考虑以下linux内核转储堆栈跟踪,您可以通过调用panic("debugging a linux kernel panic");
从内核源代码触发恐慌:
[<001360ac>] (unwind_backtrace+0x0/0xf8) from [<00147b7c>] (warn_slowpath_common+0x50/0x60)
[<00147b7c>] (warn_slowpath_common+0x50/0x60) from [<00147c40>] (warn_slowpath_null+0x1c/0x24)
[<00147c40>] (warn_slowpath_null+0x1c/0x24) from [<0014de44>] (local_bh_enable_ip+0xa0/0xac)
[<0014de44>] (local_bh_enable_ip+0xa0/0xac) from [<0019594c>] (bdi_register+0xec/0x150)
unwind_backtrace+0x0/0xf8
+0x0/0xf8
代表什么?unwind_backtrace+0x0/0xf8
?答案 0 :(得分:43)
这只是一个普通的回溯,这些函数以相反的顺序调用(第一个调用被前一个调用,依此类推):
unwind_backtrace+0x0/0xf8
warn_slowpath_common+0x50/0x60
warn_slowpath_null+0x1c/0x24
ocal_bh_enable_ip+0xa0/0xac
bdi_register+0xec/0x150
bdi_register+0xec/0x150
是符号+偏移量/长度,Understanding a Kernel Oops中有关于它的更多信息,以及如何调试内核oops。还有关于Debugging the Kernel
注意:正如Eugene下面建议的那样,您可能首先尝试addr2line,但它仍然需要带有调试符号的图像,例如
addr2line -e vmlinux_with_debug_info 0019594c(+offset)
答案 1 :(得分:21)
以下是addr2line
的两种选择。假设您拥有正确的目标工具链,则可以执行以下操作之一:
使用objdump
:
在内核根目录下找到您的vmlinux
或.ko
文件,然后反汇编目标文件:
objdump -dS vmlinux > /tmp/kernel.s
打开生成的程序集文件/tmp/kernel.s
。使用vim
等文本编辑器。去
unwind_backtrace+0x0/0xf8
,即搜索unwind_backtrace
+ offset
的地址。最后,您已在源代码中找到有问题的部分。
使用gdb
:
IMO,更优雅的选择是使用唯一的gdb
。假设您的主机上有合适的工具链:
gdb <path-to-vmlinux>
。list *(unwind_backtrace+0x10)
。有关其他信息,您可以查看以下内容:
答案 2 :(得分:12)
unwind_backtrace+0x0/0xf8
+0x0/0xf8
代表什么?
第一个数字(+0x0
)是从函数开头的偏移(在这种情况下为unwind_backtrace
)。第二个数字(0xf8
)是函数的总长度。鉴于这两条信息,如果您已经预先确定了故障发生的位置,那么这可能足以证实您的怀疑(您可以(大致)告诉您功能有多远。)
要获得相应指令的确切源代码行(通常优于预测),请使用addr2line
或其他答案中的其他方法。