Given a kernel stack trace as below, how do you determine the specific line of code where the issue occurred?
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
While I have no trouble finding the function call -- but translating __link_path_walk plus an offset to an actual line number is the difficult part.
Assuming this is for a standard distribution-provided kernel for which I know the exact version and build number, what's the process for fetching the necessary metadata and doing the corresponding lookup?
I don't have a ~= RHEL5 at hand, so the output shown is from a Fedora 20, though the process should be mostly the same (the name of the function has changed).
You'd need to install the appropriate
kernel-debug-debuginfo
package for your kernel (assuming RHEL or derivative distro). This package provides avmlinux
image (an uncompressed not stripped version of the kernel):that image can be used directly with
gdb
You can also use
objdump(1)
on thevmlinux
image:The flags are:
You can lookup the function there:
and match the offset to the actual line of code.
Given an unstripped
vmlinux
with debugging symbols (typically included with "linux-devel" or "linux-headers" packages matching your kernel version), you can use theaddr2line
program included with binutils to translate addresses to lines in source files.Consider this call trace:
Then the address of the caller in
poll_select_copy_remaining
can be found with:Install kernel-debuginfo
Download decode_stacktrace.sh which is in the kernel source tree.
Make stack dump output useful again.
For a handful of function offsets, try
faddr2line
which is also in the kernel source.If addr2line should print a question mark for line number or objdump fails to inline source code and you have a custom kernel, be sure to recompile the kernel with CONFIG_DEBUG_INFO set. You might need to reproduce the error with the kernel just built.
With gdb, you can also use this command to find the line number quickly:
(gdb) list *(some_function+0x12c)