Arm Linux Kernel Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

8179
1390
307630


[리눅스커널] 임베디드 디버거 전설 TRACE32 3. 커널 디버깅과 코드 학습

<< 임베디드 디버거 전설 TRACE32 >>

TRACE32(T32)는 임베디드 소프트웨어에서 많이 사용되는 전설적인 디버깅 프로그램입니다. 다른 RTOS 개발에도 활용도가 높은 디버깅 프로그램으로서 대부분의 임베디드 개발자는 TRACE32를 사용할 줄 알고, 많은 고수 개발자들은 T32를 잘 다룹니다. 실전 개발에서 활용도가 높으니 잘 알아둘 필요가 있습니다. TRACE32는 여러 가지 강력한 디버깅 기능과 다양한 명령어를 지원합니다. 자세한 내용은 블로그에 업로드된 글을 참고하세요.

이 책에서는 TRACE32 시뮬레이터 기능을 활용해 커널 자료구조를 소개합니다. TRACE32시뮬레이터로 라즈베리 파이의 커널 이미지를 올려서 본 디버깅 정보를 TRACE32기본 명령어와 함께 소개합니다.

섹션 정보 보기

먼저 TRACE32명령어 창에서 “symbol.line.section” 명령어를 입력하면 섹션 정보를 볼 수 있습니다.

__________address________|path\section___________________________|acc|init|physical
P:80008000--8000826B|\\vmlinux\.head.text                   |R-X|L-  |
P:80100000--8078B3E3|\\vmlinux\.text                        |R-X|L-  |
P:8078B3E4--8078B3FF|\\vmlinux\.fixup                       |R-X|L-  |
D:80800000--809D288F|\\vmlinux\.rodata                      |RW-|L-  |
D:809D2890--809DA7C7|\\vmlinux\__ksymtab                    |R--|L-  |
D:809DA7C8--809E1AC7|\\vmlinux\__ksymtab_gpl                |R--|L-  |
D:809E1AC8--809E5A63|\\vmlinux\__kcrctab                    |R--|L-  |
D:809E5A64--809E93E3|\\vmlinux\__kcrctab_gpl                |R--|L-  |
D:809E93E4--80A0D5C3|\\vmlinux\__ksymtab_strings            |R--|L-  |
D:80A0D5C4--80A0EA3B|\\vmlinux\__param                      |R--|L-  |
D:80A0EA3C--80A0EFFF|\\vmlinux\__modver                     |R--|L-  |
D:80A0F000--80A0FE47|\\vmlinux\__ex_table                   |R--|L-  |
D:80A0FE48--80A4984F|\\vmlinux\.ARM.unwind_idx              |R--|L-  |
...
D:80B84000--80B8D73F|\\vmlinux\.data..percpu                |RW-|L-  |
D:80C00000--80C8BA43|\\vmlinux\.data                        |RW-|L-  |
D:80C8C000--80C8CFFF|\\vmlinux\.data..page_aligned          |RW-|L-  |
D:80C8D000--80C92F3F|\\vmlinux\__bug_table                  |RW-|L-  |
D:80C92F40--80D434B3|\\vmlinux\.bss                         |RW-|--  |
P:FFFF0000--FFFF001F|\\vmlinux\.vectors                     |R-X|L-  |
P:FFFF1000--FFFF12BF|\\vmlinux\.stubs                       |R-X|L-  |

위 섹션 정보를 참고해 주소의 속성을 파악할 수 있습니다.

주소로 코드 정보 파악

"symbol.list.line [주소]" 명령어로 주소를 입력하면 주소에 해당하는 코드의 위치를 알 수 있습니다. 예를 들어, "symbol.list.line 0x80783a78"을 입력하면 다음과 같은 결과를 확인할 수 있습니다.

_____address________|module_______________|source__________________________________|line___________|offset____|
P:80783A78--80783A8F|\\vmlinux\sched/core |.c\rasp_kernel\linux\kernel\sched\core.c|\3400--3408    |      n.f.| .ux\sched/core\schedule+0x24

여기서 0x80783a78 주소는 kernel\sched\core.c의 3400번째 줄에 있는 코드입니다.

전역 변수 확인

"var.view [전역 변수 이름]" 명령어를 입력하면 전역 변수를 볼 수 있습니다. 다음은 "var.view %l %t init_thread_union" 명령어를 실행한 결과입니다.

  (static union thread_union) [D:0x80C00000] init_thread_union = (
    (struct thread_info) [D:0x80C00000] thread_info = (
      (long unsigned int) [D:0x80C00000] flags = 0,
      (int) [D:0x80C00004] preempt_count = 1,
      (mm_segment_t) [D:0x80C00008] addr_limit = 0,
      (struct task_struct *) [D:0x80C0000C] task = 0x80C06C80,
      (__u32) [D:0x80C00010] cpu = 0,
      (__u32) [D:0x80C00014] cpu_domain = 0,

var.view 명령어를 입력할 때 %l 옵션을 지정하면 필드별 주소 정보를, %t를 지정하면 필드 타입을 출력합니다.   
  
구조체를 주소로 캐스팅

다음과 같은 형식의 명령어를 실행하면 어떤 주소든 지정한 구조체로 캐스팅할 수 있습니다.

var.view %l %t (struct 구조체_이름*)주소

var.view 명령어에 %l 인자를 지정하면 구조체를 구성하는 각 필드별 주소를 출력합니다. 또한 %t 인자를 지정하면 필드의 타입이 표시됩니다.

앞의 예제에서 init_thread_union 전역변수의 주소는 0x80C00000이고 타입은 struct thread_info였습니다. 따라서 다음 명령어를 입력해 결과를 확인해 봅시다.

var.view %l %t (struct thread_info*)0x80C00000 

예상대로 같은 결과를 출력합니다.

1  (struct thread_info *) [-] (struct thread_info*)0x80C00000 = 0x80C00000 -> (
2    (long unsigned int) [D:0x80C00000] flags = 0,
3    (int) [D:0x80C00004] preempt_count = 1,
4    (mm_segment_t) [D:0x80C00008] addr_limit = 0,
5    (struct task_struct *) [D:0x80C0000C] task = 0x80C06C80,
6    (__u32) [D:0x80C00010] cpu = 0,
7    (__u32) [D:0x80C00014] cpu_domain = 0,

먼저 2번째 줄을 보겠습니다. thread_info 구조체의 첫 번째 필드인 flags 필드는 long unsigned int 타입이고 주소는 0x80C00000입니다. 5번째 줄을 보면 task 필드의 타입은 struct task_struct 이며 주소는 0x80C0000C입니다.

어셈블리 코드 보기

"data.list 주소" 형식으로 명령어를 입력하면 주소에 해당하는 어셈블리 코드를 볼 수 있습니다. 다음은 "data.list 0x80783a78"을 입력했을 때 결과 화면입니다.

___addr/line|code_____|label____|mnemonic________________|comment
NSR:80783A78|E5932000            ldr     r2,[r3]
NSR:80783A7C|E3520000            cmp     r2,#0x0          ; r2,#0
NSR:80783A80|0A000002            beq     0x80783A90
NSR:80783A84|E5932558            ldr     r2,[r3,#0x558]

출력 결과와 같이 0x80783a78 주소에 해당하는 어셈블리 코드를 볼 수 있습니다.

이 밖에도 TRACE32는 매우 강력한 디버깅 기능을 지원하므로 임베디드 리눅스 개발에서 굉장히 자주 활용되는 프로그램입니다. 따라서 TRACE32는 잘 익혀두면 여러모로 도움이 될 것입니다. 

TRACE32에 대한 다음과 같은 신문 기사를 소개합니다.

출처: https://www.zdnet.co.kr/view/?no=20190409144249

TRACE32는 세계 시장점유율 1위 디버깅 툴로서 독일 라우터바흐에서 1979년에 출시됐다. 다양한 최신 개발환경을 지원할 뿐만 아니라 퀄컴, 인텔, 인피니언 등 세계 주요 칩 벤더와 솔루션 업체들로부터 안정성과 신뢰성이 검증된 개발도구다. 시스템온칩(SoC)을 개발하는 단계부터 제품 검증, 최종 양산 단계까지 전체 개발 프로세스에서 사용 가능해 개발 기간의 단축과 효율성을 높여주는 개발도구다.

TRACE32에 대한 추가 자료(교육 과정, 디버깅 자료)는 다음 웹사이트에서 확인할 수 있습니다. 

https://www.trace32.com/

 
"혹시 궁금한 점이 있으면 댓글로 질문 남겨주세요. 아는 한 성실히 답변 올려드리겠습니다!" 

Thanks,
Austin Kim(austindh.kim@gmail.com)



# Reference: For more information on 'Linux Kernel';

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 1

디버깅을 통해 배우는 리눅스 커널의 구조와 원리. 2


 




핑백

덧글

  • 신입 2021/02/04 12:23 # 삭제 답글

    안녕하세요 리눅스 커널에 대해 막 배우기 시작한 신입 개발자입니다.
    요즘 선생님이 쓰신 책과 유튜브로 공부를 하고 있습니다.(아직은 너무 어렵네요...)

    다름아니라 TRACE32에대해 여쭤보려고 댓글남깁니다.
    구글링을하니 TRACE32의 경우 한컴MDS에서 제공을 하고 있는데.. 개인이 사용하긴 쉽지 않아보이네요

    혹시 라즈베리파이에서 ftrace를 이용한 debugging으로만 해도 괜찮을까요?
  • AustinKim 2021/02/04 14:38 #

    네, ftrace 메시지 분석을 통해 리눅스 커널을 충분히 배울 수 있습니다.
    우선 ftrace 메시지에 익숙해지도록 초점울 맞추셔서 진행하시면 좋을 것 같습니다.

    감사합니다.
댓글 입력 영역