如何阅读,理解,分析和debuggingLinux内核恐慌?

考虑下面的Linux内核转储堆栈跟踪,你可以通过调用panic("debugging a linux kernel panic");来触发内核源代码的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的C代码?
  • 如何解读恐慌的内容?

这只是一个普通的回溯,这些函数被调用的顺序是相反的(第一个函数被前一个函数调用,等等):

 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是符号+偏移量/长度,有关于理解内核的更多信息Oops以及如何调试内核oops。 另外还有关于调试内核的优秀教程

注意:如Eugene所建议的,您可能首先尝试使用addr2line ,但仍然需要带有调试符号的图像,例如

addr2line -e vmlinux_with_debug_info 0019594c(+offset)

这里有两个addr2line替代addr2line 。 假设你有正确的目标的工具链,你可以执行下列操作之一:

使用objdump

  1. 在内核根目录下找到你的vmlinux或者.ko文件,然后反汇编目标文件:

     objdump -dS vmlinux > /tmp/kernel.s 
  2. 打开生成的程序集文件/tmp/kernel.s 。 用一个文本编辑器如vim 。 去unwind_backtrace+0x0/0xf8 ,即搜索unwind_backtrace的地址+ offset 。 最后,你在源代码中找到了有问题的部分。

使用gdb

国际海事组织,更优雅的选择是使用唯一的gdb 。 假设你的主机上有合适的工具链:

  1. 运行gdb <path-to-vmlinux>
  2. 在gdb的提示符下执行: list *(unwind_backtrace+0x10)

有关其他信息,您可以结帐以下内容:

  1. 内核调试技巧 。
  2. 使用Gdb调试Linux内核

unwind_backtrace+0x0/0xf8 +0x0/0xf8代表什么?

第一个数字( +0x0 )是函数开始偏移量 (在这种情况下是unwind_backtrace )。 第二个数字( 0xf8 )是函数总长度 。 给出这两条信息,如果你已经对发生故障的位置有了一个预感,这可能足以证实你的怀疑(你可以粗略地说出你的功能有多远)。

为了得到相应指令的确切源代码行(通常比addr2line更好),可以在其他答案中使用addr2line或其他方法。