Customer Support
Your Key to Embedded Innovations
TRACE32 를 이용한 Process Freezing Debuging 기법
작성자 이원건
조회수 8402
안녕하세요.
결론부터 이야기 하면..
chip set(AP) 내부에서 ram 에서 L1 cache 로 arm instruction 을 복사할때 간헐적으로 누락되는 문제가 있었습니다.
이러한 문제는 trace32 가 아니면 분석이 거의 불가능한 문제 입니다.
제가 고안해낸 process freezing debugging 기법과 trace32 의 강력한 기능을 결합한 디버깅 know-how를 공유하고자 합니다.
이렇게 어려운 문제도 해결 할 수 있도록 도와준 trace32 는 저의 개발인생의 보물이자 저의 힘 이라고 생각합니다.
* process freezing debugging 기법은 다음과 같은 문제 상황에서 유용합니다.
1. 문제현상이 발생하면 device 의 상태가 변경되어 debugging infomation 을 구하기 어려운 경우
2. 매우 적은 확율로 재현되는 문제
3. 단순 code level debugging 으로 분석되지 않는 문제.
* 참고 : linux base 의 system 입니다.
1. 문제 현상 : device power off중 불특정 application 들이 SIGSEGV 와 SIGILL 이 발생하며 비정상 종료 함.
- 문제 발생 시료를 다시 실행하면 문제 발생하지 않음
2. 문제 시료를 trace32 로 dump 를 떠서 죽은 부분의 ARM instruction 을 검사
- ram의 data 와 연관된 arm asm instruction(push/pop 이나 STR/LSD등) 이 아닌 cache 만 사용하는 연산에서도 SIGLL 이 발생하며 죽은경우가 있음
- 문제 발생 이후 device가 power off 되어 버려서 debuging 이 불가능 함.
3. trace 를 사용한 분석
1) SIGILL 이나 SIGSEGV interrupt 가 발생했을때 process freezing 시키도록 handler 수정
** process freezing 방법 **
-> system interrupt handler 에 h/w s/w watchdog disable 후 무한 loop 수행함.
-> 문제가 발생하였을때 무한 loop 에 빠져서 다음 sequence 로 넘어가지 않으므로 문제가 발생한 process 의 정보를 그대로 보존한 debugging semple 을 얻을 수 있음.
-> 문제가 발생한 시점의 arm register 를 얻을 수 있어서 이후 debugging 의 모든 실마리를 재공해 줌. (arm register value, neon state, sequence 진행으로 인해 값이 변경되지 않은 문제상태 그대로의 stack, running process info, MMU, L1 / L2 cache, sysmmu, interrupt handler 등..)
2) 문제가 발생한 이후 system interroup handler 에서 freezing 된 상태로 trace32 연결함 -> 이후 trace32 의 강력한 core debugging 기능을 마음껏 사용 가능.
3) Trace32 에서 Process debugging 기능을 사용해서 동작중인 application 을 symbol mapping 함.
4) interrupt handler 의 param 중 sigcontext 를 분석하여 ARM register 복원
struct sigcontext {
unsigned long trap_no; // 0000000E
unsigned long error_code; // 00000005
unsigned long oldmask; // 00000005
unsigned long arm_r0; // 2A0912F0
unsigned long arm_r1; // 00000000
unsigned long arm_r2; // 0000006C
unsigned long arm_r3; // 00000070
unsigned long arm_r4; // 2A0912F0
unsigned long arm_r5; // BEF8CAF4
unsigned long arm_r6; // 6A08C7C8
unsigned long arm_r7; // 00000000
unsigned long arm_r8; // 2A046F18
unsigned long arm_r9; // 00000000
unsigned long arm_r10; // 00000000
unsigned long arm_fp; // BEF8C97C
unsigned long arm_ip; // 40366248
unsigned long arm_sp; // BEF8C960
unsigned long arm_lr; // 402AEAF4
unsigned long arm_pc; // 40036924 -> 문제가 발생한 ARM instruction address
unsigned long arm_cpsr; // 20000010
unsigned long fault_address; // 6A08C838 -> access fail address
};
5) 복원한 ARM register 를 기반으로 문제 발생때 실행된 code address 와 access 하다가 fail 발생한 address 를 찾음
< 마지막 instruction >
ldr r1, [r6, r3]
해석 : r1 = *(r6 + r3)
r6 + r3 = 0x6A08C838 // 맵핑되어 있지 않은 주소를 접근하다 SIGILL 이나 SIGSEGV 발생 -> 비정상 동작시에만 저 값이 발생함.
6) ARM instruction 을 문제가 발생한 지점부터 arm asm 을 역 계산(steck 풀기)하면서 문제 잘못된 address 에 접근한 원인 분석
->결과 : code area 에서 전단계 함수에서 문제 발생 함수로 bl 을 이용해 jump 한 이후 최초 3개의 arm instruction 이 수행되지 않았을때 문제가 발생한 fail address 값이 생성됨.
4. 문제 원인 분석 완료.
arm instruction 이 수행되기 위해서는 일반적으로 다음의 과정을 거침
i. code instruction 수행
ii. 아직 ram 에 road 되지 않은 operation area 도달
iii. hit 발생하여 nand 에서 ram 으로 code 영역 복사
iiii. L1 cache -> L2 cache를 통해서 cpu 에 적재됨
code 가 수행될때 trace32 를 이용하여 ram 에서 L1 cache 로 복사된 메모리를 dump 해서 비교함
문제 발생시 nand 에서 ram 으로 정상적으로 arm instruction 이 복사 되었으나 L1 cache 로 복사중 누락이 발생하는 문제임
-> chip set 사에 불량 수정 요청함 : 디버깅 종료
감사합니다.
추가 문의 사항은 제 메일 및 운영중인 블로그 http://decdream.tistory.com/로 연락 바랍니다.