如何阅读,理解,分析和调试Linux内核恐慌?

时间:2012-11-20 07:17:56

标签: c linux debugging linux-kernel panic

考虑以下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
  • 的C代码
  • 如何解释恐慌的内容?

3 个答案:

答案 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

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

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

  3. 使用gdb

    IMO,更优雅的选择是使用唯一的gdb。假设您的主机上有合适的工具链:

    1. 运行gdb <path-to-vmlinux>
    2. 在gdb的提示符中执行:list *(unwind_backtrace+0x10)
    3. 有关其他信息,您可以查看以下内容:

      1. Kernel Debugging Tricks
      2. Debugging The Linux Kernel Using Gdb

答案 2 :(得分:12)

  

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

第一个数字(+0x0)是从函数开头的偏移(在这种情况下为unwind_backtrace)。第二个数字(0xf8)是函数的总长度。鉴于这两条信息,如果您已经预先确定了故障发生的位置,那么这可能足以证实您的怀疑(您可以(大致)告诉您功能有多远。)

要获得相应指令的确切源代码行(通常优于预测),请使用addr2line或其他答案中的其他方法。