Linux Kernel(4.19) Hacks

rousalome.egloos.com

포토로그 Kernel Crash


통계 위젯 (화이트)

185162
807
85253


[T32] Cortex A53: 프로세스 별 Call Stack 복원하는 방법 [Linux][ARM] Core Analysis

커널 디버깅을 하다 보면 T32 simulator를 많이 쓰게 된다. 디버깅 과정에서 콜 스택을 보고 싶을 경우가 많다.
이번에 ARM Cortex A53 Call Stack 복원 방법을 정리하도록 하자.

T32 시뮬레이터의 가장 큰 장점은 각 프로세스 별로 Call Stack을 이쁘게 볼 수 있다는 점이다.
그런데 current process는 Call Stack을 제대로 볼 수 없다. 그 이유는 실행 도중 프로세스이기 때문에 Context(Register)정보를 Task Descriptor에
제대로 저장을 할 수 없기 때문이다.

magic___________|command_________|state_____|uid___|pid___|spaceid|tty_|flags___|cpu|
FFFFFFC001624860|swapper/0       |running   |    0.|    0.| 0000  | 0  |00200000| 0.|
FFFFFFC00E690000|init            |sleeping  |    0.|    1.| 0001  | 0  |40400100| 3.|
FFFFFFC00E690AC0|kthreadd        |sleeping  |    0.|    2.| 0000  | 0  |00208040| 1.|
<생략>
FFFFFFC072900AC0|migration/7     |current(7)|    0.|   28.| 0000  | 0  |04208040| 7.|
FFFFFFC072901580|ksoftirqd/7     |sleeping  |    0.|   29.| 0000  | 0  |04208040| 7.|
FFFFFFC072902B00|kworker/7:0H    |sleeping  |    0.|   31.| 0000  | 0  |04208060| 7.|
FFFFFFC0729035C0|khelper         |sleeping  |    0.|   32.| 0000  | 0  |04208060| 4.|
FFFFFFC072904080|netns           |sleeping  |    0.|   33.| 0000  | 0  |04208060| 4.|
FFFFFFC072904B40|perf            |sleeping  |    0.|   34.| 0000  | 0  |04208060| 4.|


"migration/7" 이놈 프로세스를 선택 후 우클릭을 해서 Call Stack을 보면 아래 화면과 같이 흐름이 깨져 나온다.
-000|__switch_to()
-001|degrade_zero_ticks(asm)
 ---|end of frame

그럼 이제 좀 시작해 볼까.
"migration/7" 이놈 프로세스의 Task Descriptor를 보자. 아래 stack 주소가 보인다.
  (struct task_struct)*0xFFFFFFC072900AC0 = (
    state = 0,
    stack = 0xFFFFFFC07290C000,
    usage = (counter = 3),
    flags = 69238848,
    ptrace = 0,
    wake_entry = (next = 0x0),
    on_cpu = 1,

아래 명령어로 스택 Base 주소로 접근하자. 64비트 ARM CortexA53 아키텍처의 스택 사이즈는 0x4000이다.
(참고로 ARM32 비트 아키텍처에서는 d.v %y.l [주소] 를 입력해야 함)
d.v %y.q 0xFFFFFFC07290C000+0x4000
________________address|_data____________________|value_____________|symbol
   NSD:FFFFFFC07290BD78| A4 2A 29 00 C0 FF FF FF  0xFFFFFFC000292AA4 \\vmlinux\watchdog\__touch_watchdog+0x1C
   NSD:FFFFFFC07290BD80| 90 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BD90
   NSD:FFFFFFC07290BD88| 6C 0B 25 00 C0 FF FF FF  0xFFFFFFC000250B6C \\vmlinux\sched/clock\sched_clock_cpu+0x1C
   NSD:FFFFFFC07290BD90| A0 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BDA0
   NSD:FFFFFFC07290BD98| 98 0B 25 00 C0 FF FF FF  0xFFFFFFC000250B98 \\vmlinux\sched/clock\local_clock+0x10
   NSD:FFFFFFC07290BDA0| B0 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BDB0
   NSD:FFFFFFC07290BDA8| A4 2A 29 00 C0 FF FF FF  0xFFFFFFC000292AA4 \\vmlinux\watchdog\__touch_watchdog+0x1C
   NSD:FFFFFFC07290BDB0| E0 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BDE0
   NSD:FFFFFFC07290BDB8| BC 3D 24 00 C0 FF FF FF  0xFFFFFFC000243DBC \\vmlinux\smpboot\smpboot_thread_fn+0x118
   NSD:FFFFFFC07290BDC0| C0 DE 8B 72 C0 FF FF FF  0xFFFFFFC0728BDEC0
   NSD:FFFFFFC07290BDC8| 00 80 90 72 C0 FF FF FF  0xFFFFFFC072908000
   NSD:FFFFFFC07290BDD0| E0 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BDE0
   NSD:FFFFFFC07290BDD8| 50 3E 24 00 C0 FF FF FF  0xFFFFFFC000243E50 \\vmlinux\smpboot\smpboot_thread_fn+0x1AC
   NSD:FFFFFFC07290BDE0| 30 BE 90 72 C0 FF FF FF  0xFFFFFFC07290BE30
   NSD:FFFFFFC07290BDE8| 40 D3 23 00 C0 FF FF FF  0xFFFFFFC00023D340 \\vmlinux\kthread\kthread+0xB0
   NSD:FFFFFFC07290BDF0| 70 BC 69 0E C0 FF FF FF  0xFFFFFFC00E69BC70
   NSD:FFFFFFC07290BDF8| 38 78 7F 01 C0 FF FF FF  0xFFFFFFC0017F7838 \\vmlinux\kthread\kthread_create_lock
   NSD:FFFFFFC07290BE00| 93 07 17 01 C0 FF FF FF  0xFFFFFFC001170793 \\vmlinux\Global\kallsyms_token_index+0x4A93
   NSD:FFFFFFC07290BE08| C0 DE 8B 72 C0 FF FF FF  0xFFFFFFC0728BDEC0
   NSD:FFFFFFC07290BE10| A4 3C 24 00 C0 FF FF FF  0xFFFFFFC000243CA4 \\vmlinux\smpboot\smpboot_thread_fn
   NSD:FFFFFFC07290BE18| 00 00 00 00 00 00 00 00  0x0
   NSD:FFFFFFC07290BE20| 00 00 00 00 00 00 00 00  0x0
   NSD:FFFFFFC07290BE28| 24 D3 23 00 C0 FF FF FF  0xFFFFFFC00023D324 \\vmlinux\kthread\kthread+0x94


위 스택 덤프에서 볼드체로 되어 있는 부분을 참고하자. 함수를 호출한 주소가 위치해있는 주소이다.
ARM CortexA53은 정말 함수 흐름을 잘 확인할 수 있는 Calling Convention인 것 같다. (Cortex A7은 좀 거시기 하지.)
그럼 가장 많은 정보를 볼 수 있는 Call Stack을 복원하기 위해 Stack을 0xFFFFFFC072E07D90, Program Counter를 0xFFFFFFC00023D로 지정해보자.

________________address|_data____________________|value_____________|symbol
   NSD:FFFFFFC07290BD78| A4 2A 29 00 C0 FF FF FF  0xFFFFFFC000292AA4 \\vmlinux\watchdog\__touch_watchdog+0x1C
   NSD:FFFFFFC07290BD80| 90 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BD90
   NSD:FFFFFFC07290BD88| 6C 0B 25 00 C0 FF FF FF  0xFFFFFFC000250B6C \\vmlinux\sched/clock\sched_clock_cpu+0x1C
   NSD:FFFFFFC07290BD90| A0 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BDA0
   NSD:FFFFFFC07290BD98| 98 0B 25 00 C0 FF FF FF  0xFFFFFFC000250B98 \\vmlinux\sched/clock\local_clock+0x10
   NSD:FFFFFFC07290BDA0| B0 BD 90 72 C0 FF FF FF  0xFFFFFFC07290BDB0


아래 명령어를 사용하자.
r.s sp 0xFFFFFFC07290BD90
r.s pc 0xFFFFFFC000250B6C

이후 v.f 명령어를 입력하여 콜 스택을 보면 아래와 같이 이쁘게 복원이 된다.
-000|sched_clock_cpu(cpu = ?)
-001|local_clock()
-002|get_timestamp(inline)
-002|__touch_watchdog()
-003|smpboot_thread_fn(data = 0xFFFFFFC0728BDEC0)
-004|smpboot_thread_fn(data = 0xFFFFFFC07290BE30)
-005|test_bit(inline)
-005|kthread(_create = 0x0)
 ---|end of frame




Reference(프로세스 관리)
4.9 프로세스 컨택스트 정보는 어떻게 저장할까?
 4.9.1 컨택스트 소개
 4.9.2 인터럽트 컨택스트 정보 확인하기
 4.9.3 Soft IRQ 컨택스트 정보 확인하기
 4.9.4 선점 스케줄링 여부 정보 저장
4.10 프로세스 디스크립터 접근 매크로 함수
 4.10.1 current_thread_info()
 4.10.2 current 매크로란
4.11 프로세스 디버깅
 4.11.1 glibc fork 함수 gdb 디버깅
 4.11.2 유저 프로그램 실행 추적 

    핑백

    덧글

    댓글 입력 영역