如果你的内核模块崩溃很幸运,你会得到一个带有大量信息的日志,例如寄存器中的值等。其中一个信息是堆栈跟踪(核心转储也是如此) ,但我最初问这个内核模块)。举个例子:
[<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>
与发生错误的函数的偏移量有关。也就是说,通过检查这个数字,或许可以查看汇编输出,我应该能够找到发生此错误的行(更好的是,指令)。这是对的吗?
我的问题是,这两个数字究竟是什么?你如何利用它们?
答案 0 :(得分:19)
skink_free_devices+0x32/0xb0
这意味着有问题的指令从函数0x32
开始是skink_free_devices()
个字节,总共0xB0
个字节。
如果您在启用-g
的情况下编译内核,那么您可以使用工具addr2line
或我们旧的gdb
像这样的东西
$ 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
,他们就会告诉您源文件中存在违规函数的行号
有关详细信息,请参阅this文章
编辑: vmlinux
是用于调试的内核的未压缩版本,如果您从源代码构建内核,则通常会找到@ /lib/modules/$(uname -r)/build/vmlinux
。您在vmlinuz
找到的/boot
是压缩内核,在调试时可能没那么有用
答案 1 :(得分:1)
对于Emacs用户,here是一种在堆栈跟踪中轻松跳转的主要模式(在内部使用addr2line
)。
免责声明:我写了:)
答案 2 :(得分:0)
反流this answer你需要使用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
并在 mainline linux kernel 中运行以下内容:
./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