[리눅스커널][디버깅] 크래시 유틸리티로 vmcore를 T32(Trace32)에 로딩하기

AustinKim의 이미지

소개

크래시 유틸리티는 리눅스 커널 개발에서 인기 있는 디버깅 툴입니다. 특히 search 명령어로 메모리 서치를 할 수 있는 막강한 기능을 제공합니다. 하지만 프로세스별 콜스택을 이동하면서 지역변수를 볼 수 있는 기능이 없어 조금 불편합니다.

이번 포스팅에서 vmcore에서 스택 덤프를 추출해 T32 시뮬레이터로 콜스택을 올려 보는 방법을 소개합니다.

크래시 유틸리티로 프로세스 스택 메모리 덤프하기

"./crash64 vmcore vmlinux" 명령어로 크래시 유틸리티를 실행합니다.
austindh.kim~/backup/Vmcore_dump$ ./crash64 vmcore vmlinux

crash64 7.1.9++
Copyright (C) 2002-2017 Red Hat, Inc.
Copyright (C) 2004, 2005, 2006, 2010 IBM Corporation
Copyright (C) 1999-2006 Hewlett-Packard Co
Copyright (C) 2005, 2006, 2011, 2012 Fujitsu Limited
Copyright (C) 2006, 2007 VA Linux Systems Japan K.K.
Copyright (C) 2005, 2011 NEC Corporation
Copyright (C) 1999, 2002, 2007 Silicon Graphics, Inc.
Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc.
This program is free software, covered by the GNU General Public License,
and you are welcome to change it and/or distribute copies of it under
certain conditions. Enter "help copying" to see the conditions.
This program has absolutely no warranty. Enter "help warranty" for details.

GNU gdb (GDB) 7.6
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=x86_64-unknown-linux-gnu --target=aarch64-elf-linux"...

WARNING: kernel version inconsistency between vmlinux and dumpfile

please wait... (gathering kmem slab cache data)
crash64: invalid kernel virtual address: 48773a9004 type: "array cache limit"
....
WARNING: cannot determine starting stack frame for task ffffffc87bb4cc00
KERNEL: vmlinux
DUMPFILE: vmcore
CPUS: 4
DATE: Thu Jan 15 05:02:48 1987
UPTIME: 00:02:01
LOAD AVERAGE: 0.01, 0.01, 0.01
TASKS: 107
NODENAME: Xilinx-ZCU102-2016_3
RELEASE: 4.6.0
VERSION: #1 SMP Tue Apr 4 17:38:35 KST 2017
MACHINE: aarch64 (unknown Mhz)
MEMORY: 4 GB
PANIC: "sysrq: SysRq : Trigger a crash"
PID: 0
COMMAND: "swapper/0"
TASK: ffffff8008bd3400 (1 of 4) [THREAD_INFO: ffffff8008bc4000]
CPU: 0
STATE: TASK_RUNNING (ACTIVE)

첫 메시지를 보니 "echo /proc/sysrq-trigger" 명령어로 강제 커널 패닉을 유발했습니다.

pid가 1549인 sh 프로세스의 콜스택을 보겠습니다.
crash64> bt 1549
PID: 1549 TASK: ffffffc87bae6f00 CPU: 1 COMMAND: "sh"
#0 [ffffffc87bbdbb40] __switch_to at ffffff8008086b34
#1 [ffffffc87bbdbb60] __schedule at ffffff80088778a0
#2 [ffffffc87bbdbbb0] schedule at ffffff8008877cbc
#3 [ffffffc87bbdbbd0] schedule_timeout at ffffff800887a5a8
#4 [ffffffc87bbdbc50] wait_woken at ffffff80080d273c
#5 [ffffffc87bbdbc80] n_tty_read at ffffff80084892f8
#6 [ffffffc87bbdbd90] tty_read at ffffff8008482d10
#7 [ffffffc87bbdbdd0] __vfs_read at ffffff800818add0
#8 [ffffffc87bbdbe50] vfs_read at ffffff800818bc38
#9 [ffffffc87bbdbe90] sys_read at ffffff800818d0f8
#10 [ffffffc87bbdbed0] el0_svc_naked at ffffff8008085e2c
PC: 0000007f87126bb8 LR: 00000000004a6edc SP: 0000007fc2acbf10
X29: 0000007fc2acbf10 X28: 0000007fc2acc1e0 X27: 00000000004e5000
X26: ffffffffffffffff X25: 0000000000000001 X24: 00000000004e8a84
X23: 0000000000000001 X22: 00000000004de5f4 X21: 00000000004ea000
X20: 0000007f871ae7d0 X19: 00000000004e9a38 X18: 0000000000000001
X17: 0000007f87126bd0 X16: 0000000000000000 X15: 0000000000000070
X14: 0000000000000000 X13: 0000000000000000 X12: 0000000000000000
X11: 0000000000000000 X10: 0000000000000000 X9: 0000000000000004
X8: 000000000000003f X7: 30322d3230315543 X6: 0000007f8701c01d
X5: 248290f6fb60f00d X4: 00000000004e0000 X3: 00000000004e0000
X2: 0000000000000001 X1: 0000007fc2acbf4f X0: 0000000000000000
ORIG_X0: 0000000000000000 SYSCALLNO: 3f PSTATE: 60000000

pid가 1549인 "sh" 프로세스의 태스크 디스크립터 정보를 보겠습니다.
crash64> task 1549
PID: 1549 TASK: ffffffc87bae6f00 CPU: 1 COMMAND: "sh"
struct task_struct {
state = 0x1,
stack = 0xffffffc87bbd8000, //<<--
usage = {
...
thread = {
cpu_context = {
x19 = 0xffffffc87bac4680,
x20 = 0xffffffc87bae6f00,
x21 = 0xffffffc87bae6f00,
x22 = 0xffffffc879160100,
x23 = 0xffffffc87bae7398,
x24 = 0xffffff8008bca000,
x25 = 0x0,
x26 = 0xffffff80092a6000,
x27 = 0x0,
x28 = 0xffffffc87b16d400,
fp = 0xffffffc87bbdbb40,
sp = 0xffffffc87bbdbb40,
pc = 0xffffff8008086b38
},

프로세스 스택 최상단 주소가 0xffffffc87bbd8000이고 마지막 실행 레지스터 세트 정보는 x19~pc 필드에서 볼 수 있습니다.

프로세스 스택을 덤프해보겠습니다. Aarch64 비트 아키텍처이니 스택 사이즈는 0x4000입니다.
따라서 다음 주소 범위 스택을 덤프하면 됩니다.
0xffffffc87bbd8000--0xffffffc87bbd8000+0x4000

크래시 유틸리티에서 지원하는 rd 명령어를 활용해 메모리 덤프를 뽑아냅니다.
crash64> rd 0xffffffc87bbd8000 -e 0xffffffc87bbdd000 -r stack_dump.bin
20480 bytes copied from 0xffffffc87bbd8000 to stack_dump.bin

0xffffffc87bbd8000 주소는 메모리 시작 주소, 0xffffffc87bbdd000는 메모리 끝 주소입니다.
이 범위 메모리 덤프를 stack_dump.bin 파일로 저장합니다.

Trace32(T32)로 스택 덤프 로딩해 콜스택 복원하기

이제 T32 시뮬레이터가 등장할 차례입니다.

먼저 다음 명령어로 시스템 초기화를 합시다.
sys.cpu cortexa53
sys.u

다음 stack_dump.bin 덤프를 T32로 로딩합니다.
d.load.bin stack_dump.bin /noclear 0xffffffc87bbd8000

/noclear 옵션은 이전 메모리 덤프를 무시하고 덮어쓰지 않는 옵션이고 0xffffffc87bbd8000는 메모리 오프셋 주소입니다.

크래시 유틸리티에서 0xffffffc87bbd8000 메모리 주소 덤프를 추출했으니 T32에서 0xffffffc87bbd8000는 주소 오프셋을 줍니다.
crash64> rd 0xffffffc87bbd8000 -e 0xffffffc87bbdd000 -r stack_dump.bin
20480 bytes copied from 0xffffffc87bbd8000 to stack_dump.bin

다음 vmlinux를 로딩합시다.
Data.LOAD.elf vmlinux /nocode /noclear

프로세스 스택 덤프를 로딩했으니 이제는 T32로 콜스택을 볼 차례입니다.
먼저 크래시 유틸리티에서 본 프로세스 레지스터 정보를 떠올립시다.
thread = {
cpu_context = {
x19 = 0xffffffc87bac4680,
x20 = 0xffffffc87bae6f00,
x21 = 0xffffffc87bae6f00,
x22 = 0xffffffc879160100,
x23 = 0xffffffc87bae7398,
x24 = 0xffffff8008bca000,
x25 = 0x0,
x26 = 0xffffff80092a6000,
x27 = 0x0,
x28 = 0xffffffc87b16d400,
fp = 0xffffffc87bbdbb40,
sp = 0xffffffc87bbdbb40,
pc = 0xffffff8008086b38
},

위 레지스터 세트 정보를 참고해서 pc부터 x28까지 레지스터를 T32에서 로딩합시다.
다음 명령어를 T32 시뮬레이터에서 입력합시다.
r.s pc 0xffffff8008086b38
r.s sp 0xffffffc87bbdbb40
r.s x29 0xffffffc87bbdbb40
r.s x28 0xffffffc87b16d400
...

T32에서 "v.f" 명령어를 입력해 콜스택을 봅시다.
-000|__switch_to(prev = 0x0, next = 0x0)
-001|__schedule(preempt = FALSE)
-002|test_bit(inline)
-002|test_ti_thread_flag(inline)
-002|need_resched(inline)
-002|schedule()
-003|schedule_timeout(timeout = 9223372036854775807)
-004|wait_woken(wait = 0xFFFFFFC87BBDBD68, ?, ?)
-005|test_ti_thread_flag(inline)
-005|test_tsk_thread_flag(inline)
-005|signal_pending(inline)
-005|n_tty_read(tty = 0xFFFFFFC87B16D400, file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, nr = 18446743524089577028)
-006|tty_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, count = 1, ?)
-007|__vfs_read(file = 0x0000007FC2ACBF4F, buf = ???, count = ???, pos = ???)
-008|vfs_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, ?, pos = 0xFFFFFFC87BBDBEC8)
-009|SYSC_read(inline)
-009|sys_read(?, buf = 548726947663, count = 1)
-010|el0_svc_naked(asm)
---|end of frame

v.f 창에서 보이는 Up 아이콘을 눌러서 콜스택을 이동합시다.
-006|tty_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, count = 1, ?)
-007|__vfs_read(file = 0x0000007FC2ACBF4F, buf = ???, count = ???, pos = ???)
-008|vfs_read(file = 0xFFFFFFC87BA05000, buf = 0x0000007FC2ACBF4F, ?, pos = 0xFFFFFFC87BBDBEC8)
-009|SYSC_read(inline)
-009|sys_read(?, buf = 548726947663, count = 1)
-010|el0_svc_naked(asm)
---|end of frame

vmcore에서 프로세스 스택만 덤프해 T32에서 콜스택을 보는 방법을 소개했습니다.
이 방식을 쓰면 vmcore에 있는 메모리 덤프를 T32에서 볼 수 있습니다.

(개인블로그)
http://rousalome.egloos.com/

Forums: 

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.