Vector Table 분석할 때 이상한 걸 발견했다.
Reset_Handler: 0x08002801
주소가 홀수다. Flash는 2바이트 정렬인데?
Thumb 비트
Cortex-M은 Thumb 모드만 지원한다. ARM 모드 없음.
그래서 분기할 때 주소 LSB로 모드를 표시한다:
- LSB = 0: ARM 모드
- LSB = 1: Thumb 모드
실제 주소는 0x08002800이고, +1은 “Thumb으로 실행해라"라는 의미.
Ghidra에서 헷갈리는 부분
void (*func)(void) = (void (*)(void))0x08002801;
func();
디컴파일러가 이렇게 보여주면 실제 함수 위치는 0x08002800이다.
라벨 달 때 주의:
0x08002801에 라벨 달면 안 됨0x08002800에 달아야 함
BX LR
함수 끝에 자주 보이는 명령:
bx lr
LR (Link Register)로 분기하면서 모드 전환. LR의 LSB 보고 Thumb/ARM 결정.
Cortex-M은 항상 Thumb이라 사실 의미 없지만, 호환성 때문에 남아있다.
삽질 사례
처음에 Vector Table 파싱할 때:
reset_handler = struct.unpack('<I', data[4:8])[0]
# 0x08002801
이 주소로 Ghidra에서 Go to 하면 엉뚱한 데 간다.
reset_handler = struct.unpack('<I', data[4:8])[0] & ~1
# 0x08002800
& ~1로 LSB 지워야 실제 주소.
다음 글에서 구조체 크기 추정 삽질.