Skip to content

Commit 67f7d2e

Browse files
committed
ops/debug: addr2line with a kernel backtrace example
1 parent e50177c commit 67f7d2e

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

docs/ops/debug.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ icon: material/bug
5151
- (U)nmount:重新挂载所有文件系统为只读模式。
5252
- re(B)oot:重启系统。
5353

54-
如果确信问题是由于某些进程占用大量内存导致的,可以使用 Alt+SysRq+F 来触发内核的 OOM Killer。其他的操作可以参考以上内核文档链接。
54+
如果确信问题是由于某些进程占用大量内存导致的,可以使用 Alt+SysRq+F 来触发内核的 OOM Killer。
55+
56+
另外,向 `/proc/sysrq-trigger` 写入字符也可以触发对应的操作。其他内容可以参考以上内核文档链接。
5557

5658
!!! lab "测试 kdump"
5759

@@ -433,6 +435,51 @@ Copyright (C) 2023 Free Software Foundation, Inc.
433435
66
434436
```
435437

438+
!!! tip "了解内核 backtrace 对应源代码文件与行号"
439+
440+
在调试与内核有关的问题时,经常需要判断内核输出的 backtrace 信息里每个函数的具体位置。例如以下是由 SysRq 的 `l` 命令触发的向 dmesg 输出所有活跃核心当前栈的信息:
441+
442+
```dmesg
443+
[ 243.860496] sysrq: Show backtrace of all active CPUs
444+
[ 243.860505] NMI backtrace for cpu 0
445+
[ 243.860507] CPU: 0 UID: 0 PID: 3660 Comm: tee Tainted: P OE 6.12.38+deb13-amd64 #1 Debian 6.12.38-1
446+
[ 243.860510] Tainted: [P]=PROPRIETARY_MODULE, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
447+
[ 243.860511] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS Arch Linux 1.17.0-1-1 04/01/2014
448+
[ 243.860514] Call Trace:
449+
[ 243.860525] <TASK>
450+
[ 243.860530] dump_stack_lvl+0x5d/0x80
451+
[ 243.860546] nmi_cpu_backtrace.cold+0x19/0x68
452+
[ 243.860548] ? __pfx_nmi_raise_cpu_backtrace+0x10/0x10
453+
[ 243.860560] nmi_trigger_cpumask_backtrace+0xed/0x100
454+
[ 243.860569] __handle_sysrq.cold+0x9c/0xe6
455+
[ 243.860577] write_sysrq_trigger+0x59/0xb0
456+
[ 243.860590] proc_reg_write+0x57/0xa0
457+
[ 243.860601] vfs_write+0xf5/0x450
458+
[ 243.860612] ksys_write+0x6d/0xf0
459+
[ 243.860614] do_syscall_64+0x82/0x190
460+
[ 243.860616] ? __count_memcg_events+0x53/0xf0
461+
[ 243.860619] ? count_memcg_events.constprop.0+0x1a/0x30
462+
[ 243.860625] ? handle_mm_fault+0x1bb/0x2c0
463+
[ 243.860628] ? do_user_addr_fault+0x36c/0x620
464+
[ 243.860630] ? exc_page_fault+0x7e/0x180
465+
[ 243.860633] entry_SYSCALL_64_after_hwframe+0x76/0x7e
466+
```
467+
468+
尽管函数名的搜索相对简单,但是怎么定位栈上的某个函数具体运行在哪一行呢?此时可以使用 Linux 内核调试符号(完整的 `vmlinux`)与 `addr2line` 工具定位。在 Debian 上需要配置调试符号源后安装当前运行内核对应的 dbg 包。注意内核调试符号很大,需要留出足够空间:
469+
470+
```shell
471+
sudo apt install linux-image-$(uname -r)-dbg
472+
```
473+
474+
之后使用 `addr2line` 即可:
475+
476+
```console
477+
$ addr2line -e /usr/lib/debug/boot/vmlinux-$(uname -r) nmi_trigger_cpumask_backtrace+0xed/0x100
478+
debian/build/build_amd64_none_amd64/lib/nmi_backtrace.c:62
479+
```
480+
481+
可以结合 `apt source` 获取到的有 Debian 补丁的内核源代码查看。
482+
436483
需要注意的是,coredump 只包含了崩溃现场的信息,导致崩溃的原因有可能并不在 coredump 中:
437484
例如在之前的执行中,程序已经向错误的位置写入数据,只是没有立刻触发问题。
438485
这就需要考虑使用其他的方法排查问题,例如在运行时使用 `valgrind` 检查内存访问,或者编译时就添加 AddressSanitizer 等工具。

0 commit comments

Comments
 (0)