0xFFFF_0000
번지에 존재한다.0x00FE_E730
이다.0x00EDCF19
로 이동해보자. 만일 LR이 제대로 정보를 가지고 있다면, 이 근방에서 reset이 발생했을 것이다.0x00ED_CF18
번지에서 b
명령어로 자기자신으로 branch 하는 line을 발견할 수 있다.while(1);
무한 loop를 발생시키는 코드 때문이었다.Interrupt_Lock()
덕분에 blx
명령어가 실행돼 LR에 복귀주소가 기록되는 바람에 LR에 유용한 정보가 남아있었던 것이다.0x0000_1323
번지를 덤프해보면 다음과 같다.bl
명령어를 만나 Interrupt_Free()
를 수행한 뒤 복귀주소로 0x0000_1323
번지를 담고 있었다.pop
명령어는 R7, PC값을 반환했다. 저 PC값이 무엇이었는지 확인하기 위해 R13이 가리키는 주소 0x0116_FD3C
로 이동해보자.0x00FC_4584
는 R7, 0x00ED_CEB1
은 PC에 저장됐을 것이다.0x00ED_CEB1
번지를 덤핑해보자.while(1)
문이 들어있었음을 확인할 수 있다. 따라서 task가 끝나지 못하고 watch dog에 의한 HW reset이 발생했음을 알 수 있다.0x00ED_CF3B
로 이동해보자.blx
명령어인데, 이전까지 Thumb mode로 실행되고 있다가 이때부터 ARM mode로 실행됐다.blx
명령어를 만나고 복귀주소로 LR에 집어넣은 것 같으니 운이 좋다.memset()
함수가 보인다. 범인을 찾은 느낌이 든다.memset()
함수는 함수의 시작주소로부터 60-bytes를 0으로 초기화한다.0x0
이 들어가고, 그 주소로 branch를 해버렸으니 reset이 발생한 것이다.0x10
로 abort handler를 가리키고 있으므로 data abort가 발생했음을 알 수있다. 따라서 LR - 0x8 주소로 이동하면 된다.0x00ED_CF26
이므로 해당 주소로 이동한 뒤 0x8
을 뺀 line을 보면, STR R0,[R1]
명령어가 있다.0xFFFF_FFFF
값을 가지고 있는데, 현재 시스템의 memory map에는 해당 주소가 정의돼있지 않다.HWIO_ADDR
이라는 전역변수가 0xFFFF_FFFF
를 가리키는데 여기에 0x8
을 쓰려다가 abortion이 발생했음을 알 수 있다. 잘못된 주소를 가리키고 있으니 초기화 값을 수정해주면 오류를 해결할 수 있다.0x0C
로 prefetch handler를 가리키고 있으므로 prefetch abort가 발생했음을 알 수 있다. 따라서 LR - 0x4 주소로 이동하면 된다.0x0000_0002
라는 이상한 값을 갖고 있다. 무슨 이유에선지 LR이 corrupt 됐음을 직감할 수 있다.10011
로 이전 mode가 SVC임을 알 수 있다.0xFFFF_FFFF
를 가리키고 있다. 이쪽도 LR이 corrupt 됐다.0x0116_FD24
를 가리키고 있으니 그쪽으로 가보자.0xFF
로 가득찬 것을 보아하니 심상치 않은 일이 발생했음을 알 수 있다.0x00ED_D0FD
이므로 우선 이 주소로 이동해보자.bl 0xEDCE52
명령어가 보인다. bl
명령어를 만나 복귀할 주소를 LR에 남겨놓은 흔적을 볼 수 있다. ([※] 근데 왜 LR이 stack에 저장돼있었는지는 모르겠네요.)0xEDCE52
로 이동해보자. void chaos(void)
라는 함수가 시작되는 부분이다.memset((void *)(LocalBuffer - 10), 0xFF, 40)
을 호출하는 것을 알 수 있다.LocalBuffer[10]
을 선언하고LocalBuffer
시작주소로부터 20-bytes 밑(void * type이 2-byte 크기라고 가정하자)에서부터 40-bytes만큼을 0xFF로 초기화한다.11111
로 이전 mode가 SYS였다. 즉, 이번 abortion은 ISR을 처리하다가 발생했음을 눈치챌 수 있다.0x476A
로 이동해보니 역시 clock_tick_ISR()
이라는 ISR을 처리하다가 abortion이 발생했다.0x0000_4762
부터 바라보니 심상치 않은 어셈블리를 볼 수 있다.ldmia
명령어가 계속 반복되며 딱 봐도 C 코드와 일치하지 않는 mnemonic이다.0x0000_4762
번지에 write breakpoint를 걸어 누군가 이쪽 주소에 데이터를 쓰려고 시도하면 break가 걸리도록 해보자.memset((void *)(functionsMarcel.HWIO_init), 0xABCD, 10);
이라는 함수가 원인임을 발견했다.functionsMarcel.HWIO_init
이 어떻게 초기화 됐는지 확인해보니functionsMarcel = {clock_io, clock_tick_isr};
로 clock_tick_isr
이 HWIO_init
함수 포인터가 가리키는 함수로 초기화 돼있음을 확인할 수 있다.memset()
에 의해 clock_tick_isr()
ISR의 시작주소로부터 10-bytes의 영역이 0xABCD
로 초기화 됐고,CDAB
로 채워져있었음을 알 수 있다.0xFD
인 규칙성이 보인다.0xFF
이면 1111_1111
인데, 0xFD
는 1111_1101
이다.