51

考虑以下 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
  • 我怎样才能看到 C 代码unwind_backtrace+0x0/0xf8
  • 如何解读恐慌的内容?
4

3 回答 3

48

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

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中有更多信息。还有这个关于调试内核的优秀教程

注意:正如 Eugene 下面的建议,您可能想先尝试addr2line,但它仍然需要带有调试符号的图像,例如

addr2line -e vmlinux_with_debug_info 0019594c(+offset)

于 2012-11-20T07:30:33.877 回答
20

以下是addr2line. 假设您拥有正确的目标工具链,您可以执行以下操作之一:

使用objdump

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

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

使用gdb

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

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

有关更多信息,您可以查看以下资源:

  1. 内核调试技巧
  2. 使用 Gdb 调试 Linux 内核
于 2013-04-23T18:04:29.713 回答
14

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

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

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

于 2015-05-23T23:05:15.593 回答