如何充分利用堆栈跟踪(来自内核或核心转储)?
如果你的内核模块崩溃很幸运,你会得到一个带有大量信息的日志,例如寄存器中的值等。一个这样的信息是堆栈跟踪(核心转储也是如此,但我最初问这个内核模块)。 举个例子:
[] ? skink_free_devices+0x32/0xb0 [skin_kernel] [] ? cleanup_module+0x1e5/0x550 [skin_kernel] [] ? __stop_machine+0x57/0x70 [] ? __try_stop_module+0x0/0x30 [] ? sys_delete_module+0x149/0x210 [] ? sysenter_do_call+0x12/0x16
我的猜测是+/
与发生错误的函数的偏移量有关。 也就是说,通过检查这个数字,或许可以查看汇编输出,我应该能够找到发生此错误的行(更好的是,指令)。 那是对的吗?
我的问题是,这两个数字究竟是什么? 你如何利用它们?
skink_free_devices+0x32/0xb0
这意味着有问题的指令是从函数skink_free_devices()
开始的0x32
字节,总共为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
,它们就会告诉您源文件中存在违规函数的行号。有关详细信息,请参阅此文章
编辑: vmlinux
是用于调试的内核的未压缩版本,通常可以找到@ /lib/modules/$(uname -r)/build/vmlinux
前提是您已经从源代码构建了内核。 你在/boot
找到的vmlinuz
是压缩内核,可能在调试时没用
对于Emacs用户来说, 这是一种在堆栈跟踪中轻松跳转的主要模式( addr2line
内部使用addr2line
)。
免责声明:我写了:)