Re: [PATCH v11 1/4] kallsyms: embed source file:line info in kernel stack traces

From: Helge Deller

Date: Fri Nov 06 2026 - 09:52:57 EST


On 11/6/26 14:24, Sasha Levin wrote:
Add CONFIG_KALLSYMS_LINEINFO, which embeds a compact address-to-line
lookup table in the kernel image so stack traces directly print source
file and line number information:

root@localhost:~# echo c > /proc/sysrq-trigger
[ 11.201987] sysrq: Trigger a crash
[ 11.202831] Kernel panic - not syncing: sysrq triggered crash
[ 11.206218] Call Trace:
[ 11.206501] <TASK>
[ 11.206749] dump_stack_lvl+0x5d/0x80 (lib/dump_stack.c:94)
[ 11.207403] vpanic+0x36e/0x620 (kernel/panic.c:650)
[ 11.208565] ? __lock_acquire+0x465/0x2240 (kernel/locking/lockdep.c:4674)
[ 11.209324] panic+0xc9/0xd0 (kernel/panic.c:787)
[ 11.211873] ? find_held_lock+0x2b/0x80 (kernel/locking/lockdep.c:5350)
[ 11.212597] ? lock_release+0xd3/0x300 (kernel/locking/lockdep.c:5535)
[ 11.213312] sysrq_handle_crash+0x1a/0x20 (drivers/tty/sysrq.c:154)
[ 11.214005] __handle_sysrq.cold+0x66/0x256 (drivers/tty/sysrq.c:611)
[ 11.214712] write_sysrq_trigger+0x65/0x80 (drivers/tty/sysrq.c:1221)
[ 11.215424] proc_reg_write+0x1bd/0x3c0 (fs/proc/inode.c:330)
[ 11.216061] vfs_write+0x1c6/0xff0 (fs/read_write.c:686)
[ 11.218848] ksys_write+0xfa/0x200 (fs/read_write.c:740)
[ 11.222394] do_syscall_64+0xf3/0x690 (arch/x86/entry/syscall_64.c:63)
[ 11.223942] entry_SYSCALL_64_after_hwframe+0x77/0x7f (arch/x86/entry/entry_64.S:121)

At build time, a new host tool (scripts/gen_lineinfo) reads DWARF
.debug_line from vmlinux using libdw (elfutils), extracts all
address-to-file:line mappings, and generates an assembly file with
sorted parallel arrays (offsets from _text, file IDs, and line
numbers). These are linked into vmlinux as .rodata.

At runtime, kallsyms_lookup_lineinfo() does a binary search on the
table and __sprint_symbol() appends "(file:line)" to each stack frame.
The lookup uses offsets from _text so it works with KASLR, requires no
locks or allocations, and is safe in any context including panic.

The suffix is appended for every symbol variant that already prints an
offset, so %pS, %pSb and the %pB backtrace forms all carry it: arm64
prints frames with %pSb and the generic stack_trace_print() uses %pS.
sprint_symbol_no_offset(), which backs lowercase %ps, stays bare
because callers suffix it with a literal "()".

A line program emits several rows per address, and every row but the
last covers zero bytes, so the generator keeps the last row at each
address. That is the row addr2line reports, and for an inlined call it
names the inlined body rather than the call site.

Rows the compiler marks with line 0 declare that no source location
applies from there on (DWARF5 6.2.2), and the end of a line program's
sequence says the same of the bytes past it. Both are kept, as entries
whose line is zero that the lookup reads as "no annotation", so an
address the compiler deliberately left unattributed reports nothing
instead of inheriting the line above it.

The feature requires CONFIG_DEBUG_INFO (for DWARF data) and libelf
and libdw (from elfutils) on the build host.

Memory footprint, measured with:

make ARCH=x86_64 O=$B defconfig
./scripts/config --file $B/.config -e DEBUG_INFO \
-e DEBUG_INFO_DWARF_TOOLCHAIN_DEFAULT
make ARCH=x86_64 O=$B olddefconfig && make ARCH=x86_64 O=$B -j$(nproc)
strip -g $B/vmlinux -o vmlinux.nodbg && stat -c %s vmlinux.nodbg

Table: 1,657,663 entries from 4,234 source files
lineinfo_addrs[] 1,657,663 x u32 = 6.3 MiB
lineinfo_file_ids[] 1,657,663 x u16 = 3.2 MiB
lineinfo_lines[] 1,657,663 x u32 = 6.3 MiB
file_offsets + filenames = 0.1 MiB
Total .rodata increase: = 15.9 MiB

vmlinux (stripped): 52.2 MiB -> 68.2 MiB (+16.0 MiB / +30.6%)

That is the cost of the uncompressed format introduced here; the delta
compression added later in this series brings it down to +8.0 MiB
(+15.3%) on the same config.

Suggested-by: Petr Pavlu <petr.pavlu@xxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>


Tested-by: Helge Deller <deller@xxxxxx> # parisc
Acked-by: Helge Deller <deller@xxxxxx>

Example:

root@62:/# echo c > /proc/sysrq-trigger
[ 95.740284] sysrq: Trigger a crash
[ 95.745518] Kernel panic - not syncing: sysrq triggered crash
[ 95.746724] CPU: 1 UID: 0 PID: 1 Comm: bash Not tainted 7.4.0-rc1+ #3263 VOLUNTARY
[ 95.746724] Hardware name: 9000/778/B160L
[ 95.746724] Backtrace:
[ 95.746724] [<1041d778>] show_stack+0x54/0x78 (arch/parisc/kernel/traps.c:212)
[ 95.746724] [<10413404>] dump_stack_lvl+0x80/0xc8 (lib/dump_stack.c:122)
[ 95.746724] [<10413468>] dump_stack+0x1c/0x2c (lib/dump_stack.c:130)
[ 95.746724] [<10401288>] vpanic+0x14c/0x340 (kernel/panic.c:561)
[ 95.746724] [<104014b0>] panic+0x34/0x48 (kernel/panic.c:787)
[ 95.746724] [<10e6cbcc>] sysrq_handle_crash+0x20/0x34 (drivers/tty/sysrq.c:154)
[ 95.746724] [<10e6d734>] __handle_sysrq+0xb4/0x1d8 (drivers/tty/sysrq.c:635)
[ 95.746724] [<10e6e1b4>] write_sysrq_trigger+0x90/0xe0 (drivers/tty/sysrq.c:1220)
[ 95.746724] [<10977d88>] proc_reg_write+0xd4/0x120 (fs/proc/inode.c:343)
[ 95.746724] [<1088c9cc>] vfs_write+0xbc/0x468 (fs/read_write.c:690)
[ 95.746724] [<1088cf5c>] ksys_write+0x7c/0x12c (fs/read_write.c:740)
[ 95.746724] [<1088d028>] sys_write+0x1c/0x3c (fs/read_write.c:747)
[ 95.746724] [<10418334>] syscall_exit+0x0/0x10 (arch/parisc/kernel/entry.S:1722)
[ 95.746724]
[ 95.746724] ---[ end Kernel panic - not syncing: sysrq triggered crash ]---