18

如果你的内核模块崩溃时幸运的话,你会得到一个带有大量信息的日志的 oops,例如寄存器中的值等。其中一个信息是堆栈跟踪(核心转储也是如此,但我最初要求这个内核模块)。举个例子:

[<f97ade02>] ? skink_free_devices+0x32/0xb0 [skin_kernel]
[<f97aba45>] ? cleanup_module+0x1e5/0x550 [skin_kernel]
[<c017d0e7>] ? __stop_machine+0x57/0x70
[<c016dec0>] ? __try_stop_module+0x0/0x30
[<c016f069>] ? sys_delete_module+0x149/0x210
[<c0102f24>] ? sysenter_do_call+0x12/0x16

我的猜测是,+<number1>/<number2>这与发生错误的函数的偏移量有关。也就是说,通过检查这个数字,也许查看汇编输出,我应该能够找出发生此错误的行(更好的是指令)。那是对的吗?

我的问题是,这两个数字到底是多少?你如何利用它们?

4

3 回答 3

19
skink_free_devices+0x32/0xb0

这意味着违规指令是0x32从函数开始的字节,总共skink_free_devices()0xB0字节长。

如果您在启用的情况下编译您的内核,那么您可以使用该工具或我们的好旧-g工具获取控件跳转的函数内部的行号addr2linegdb

像这样的东西

$ addr2line -e ./vmlinux 0xc01cf0d1
/mnt/linux-2.5.26/include/asm/bitops.h:244
or
$ gdb ./vmlinux
...
(gdb) l *0xc01cf0d1
0xc01cf0d1 is in read_chan (include/asm/bitops.h:244).
(...)
244     return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
(...)

因此,只需提供您要检查的地址,addr2line或者gdb他们会告诉您源文件中存在违规函数的行号 有关完整详细信息,请参阅本文

编辑: vmlinux是用于调试的内核的未压缩版本,/lib/modules/$(uname -r)/build/vmlinux如果您从源代码构建内核,通常可以找到@。vmlinuz您发现的/boot是压缩内核,在调试中可能没有那么有用

于 2012-04-16T10:10:08.543 回答
1

对于 Emacs 用户,这里是一个主要模式,可以在堆栈跟踪中轻松跳转(addr2line内部使用)。

免责声明:我写的:)

于 2012-11-01T00:35:07.243 回答
0

反刍这个你需要使用的答案faddr2line

就我而言,我有以下截断的呼叫跟踪:

[  246.790938][   T35] Call trace:
[  246.794075][   T35]  __switch_to+0x10c/0x180
[  246.798348][   T35]  __schedule+0x278/0x6e0
[  246.802531][   T35]  schedule+0x44/0xd0
[  246.806368][   T35]  rpm_resume+0xf4/0x628
[  246.810463][   T35]  __pm_runtime_resume+0x94/0xc0
[  246.815257][   T35]  macb_open+0x30/0x2b8
[  246.819265][   T35]  __dev_open+0x10c/0x188

并在主线 linux 内核中运行以下命令:

./scripts/faddr2line vmlinux macb_open+0x30/0x2b8

给出输出

macb_open+0x30/0x2b8:
pm_runtime_get_sync at include/linux/pm_runtime.h:386
(inlined by) macb_open at drivers/net/ethernet/cadence/macb_main.c:2726
于 2021-04-07T18:15:25.163 回答