给定如下的内核堆栈跟踪,您如何确定发生问题的特定代码行?
kernel: [<ffffffff80009a14>] __link_path_walk+0x173/0xfb9
kernel: [<ffffffff8002cbec>] mntput_no_expire+0x19/0x89
kernel: [<ffffffff8000eb94>] link_path_walk+0xa6/0xb2
kernel: [<ffffffff80063c4f>] __mutex_lock_slowpath+0x60/0x9b
kernel: [<ffffffff800238de>] __path_lookup_intent_open+0x56/0x97
kernel: [<ffffffff80063c99>] .text.lock.mutex+0xf/0x14
kernel: [<ffffffff8001b222>] open_namei+0xea/0x712
kernel: [<ffffffff8006723e>] do_page_fault+0x4fe/0x874
kernel: [<ffffffff80027660>] do_filp_open+0x1c/0x38
kernel: [<ffffffff8001a061>] do_sys_open+0x44/0xbe
kernel: [<ffffffff8005d28d>] tracesys+0xd5/0xe0
虽然我很容易找到函数调用——但是将__link_path_walk加上偏移量转换为实际的行号是困难的部分。
假设这是针对我知道确切版本和内部版本号的标准发行版提供的内核,那么获取必要的元数据并进行相应查找的过程是什么?
我手头没有 ~= RHEL5,所以显示的输出来自 Fedora 20,尽管过程应该基本相同(函数名称已更改)。
您需要
kernel-debug-debuginfo
为您的内核安装适当的软件包(假设 RHEL 或衍生发行版)。这个包提供了一个vmlinux
镜像(一个未压缩的未剥离的内核版本):该图像可以直接与
gdb
您还可以
objdump(1)
在vmlinux
图像上使用:标志是:
你可以在那里查找函数:
并将偏移量与实际的代码行匹配。
给定一个未剥离
vmlinux
的调试符号(通常包含在与您的内核版本匹配的“linux-devel”或“linux-headers”包中),您可以使用addr2line
binutils 中包含的程序将地址转换为源文件中的行。考虑这个调用跟踪:
然后
poll_select_copy_remaining
可以通过以下方式找到调用者的地址:安装内核调试信息
下载内核源代码树中的decode_stacktrace.sh 。
使堆栈转储输出再次有用。
对于少数函数偏移,请尝试
faddr2line
内核源代码中的。如果 addr2line 应该打印行号的问号或 objdump 无法内联源代码并且您有自定义内核,请务必使用 CONFIG_DEBUG_INFO 设置重新编译内核。您可能需要使用刚刚构建的内核重现错误。
使用 gdb,您还可以使用此命令快速查找行号:
(gdb) 列表 *(some_function+0x12c)