Step·Next·Finish는 서로 다른 실행 범위입니다
GDB의 실행 제어 문서에서 step은 다음 소스 줄까지 진행하며 디버그 정보가 있는 호출 안으로 들어갈 수 있습니다. next는 현재 프레임의 다음 소스 줄을 목표로 합니다. finish는 선택한 프레임의 함수가 실제로 복귀한 직후까지 실행합니다. CPU의 한 명령만 실행하는 stepi와 같지 않습니다.
GUI의 Step Out이 어떤 명령에 대응하는지는 디버거 구현을 확인합니다. 실행 중 다른 중단점·신호가 먼저 멈출 수 있고 최적화·인라인·심볼 부족으로 소스 줄이 기대처럼 움직이지 않을 수 있습니다. finish와 달리 GDB의 return은 함수의 나머지 실행을 생략하는 명령이므로 같은 동작으로 사용하지 않습니다.
현재 명령·PC와 선택 프레임
LR 및 저장된 복귀 값
호출자 프레임·복귀 후 PC
LR 하나가 전체 호출 이력은 아닙니다
AAPCS32 2025Q1의 subroutine call 규칙에서 BL은 다음 복귀 위치를 LR에 남기고 호출 대상으로 분기합니다. 그 함수에서 다시 BL을 실행하면 LR 값이 바뀌므로, 호출자의 복귀 정보를 어떻게 보존했는지 생성된 명령을 확인해야 합니다. 스택에 저장될 수 있지만 모든 함수가 동일한 push/pop 형태라는 뜻은 아닙니다.
프레임 포인터 유지 여부와 저장 레지스터 배치는 컴파일러·최적화·ABI 조건에 따라 다릅니다. 현재 LR을 그대로 주소로 삼아 임의로 PC를 바꾸지 말고, 디스어셈블리와 디버거의 프레임 정보를 함께 봅니다. tail call이나 인라인된 함수는 소스의 호출 구조와 프레임 구조가 일대일로 대응하지 않을 수 있습니다.
info registers pc sp lr
bt
info frame
disassemble
finish마지막 finish는 읽기 전용 조회가 아니라 대상 실행을 재개합니다. 안전하게 실행 가능한 개발 대상에서만 사용합니다. 이 명령 목록은 예시이며 실제 보드에서 실행한 로그가 아닙니다.
예외의 LR은 일반 코드 주소가 아닐 수 있습니다
CMSIS 5.9.0의 Cortex-M3 헤더는 예외 진입 때 LR에 놓이는 EXC_RETURN 값으로 Handler/MSP, Thread/MSP, Thread/PSP 복귀를 구분합니다. 이런 값을 일반 함수 복귀 주소로 해석해 해당 주소의 코드를 찾으면 잘못된 결론에 이릅니다. 중첩 호출 도중에는 LR의 현재 용도까지 확인해야 합니다.
CMSIS의 코어 레지스터 설명에 따라 Handler 모드는 MSP를 쓰고 Thread 모드는 설정에 따라 MSP나 PSP를 사용합니다. 예외 프레임·활성 스택과 일반 함수의 프레임을 구분합니다. FPU·보안 확장이 있는 다른 Cortex-M에 Cortex-M3의 세 상수만을 완전한 목록처럼 적용하지 않습니다.
멈춘 위치와 빌드 조건을 함께 남깁니다
함수 이름, 현재 PC, LR, 활성 SP, 선택 프레임, 컴파일 옵션과 ELF를 함께 기록하면 Step Out이 예상 위치에 오지 않은 이유를 좁힐 수 있습니다. 스택 손상을 주장하기 전에 심볼·빌드 불일치와 최적화도 확인합니다. LinkedIn 535 원고를 대조한 설명이며 실제 디버깅 성공이나 메모리 안전성 검증을 주장하지 않습니다.
리셋부터 main까지 · 정적 분석과 실행 관찰의 경계
English summary. GDB finish executes until the selected function returns. LR is not a complete call history. Cortex-M exception-return tokens need a different interpretation from ordinary function return addresses.