On Tue 2026-03-03 13:21:01, 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)
>
> --- a/include/linux/kallsyms.h
> +++ b/include/linux/kallsyms.h
> @@ -16,10 +16,19 @@
> #include <asm/sections.h>
>
> #define KSYM_NAME_LEN 512
> +
> +#ifdef CONFIG_KALLSYMS_LINEINFO
> +/* Extra space for " (path/to/file.c:12345)" suffix */
> +#define KSYM_LINEINFO_LEN 128
> +#else
> +#define KSYM_LINEINFO_LEN 0
> +#endif
> +
> #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
I guess that this is used also in ftrace where there formatting
is delayed. We might want:
#define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s] (%s:%u)") + \
> (KSYM_NAME_LEN - 1) + \
> 2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + \
> - (BUILD_ID_SIZE_MAX * 2) + 1)
> + (BUILD_ID_SIZE_MAX * 2) + 1 + \
> + KSYM_LINEINFO_LEN)
>
> struct cred;
> struct module;
> --- a/kernel/kallsyms.c
> +++ b/kernel/kallsyms.c
> @@ -467,6 +467,62 @@ static int append_buildid(char *buffer, const char
> *modname,
>
> #endif /* CONFIG_STACKTRACE_BUILD_ID */
>
> +#ifdef CONFIG_KALLSYMS_LINEINFO
> +bool kallsyms_lookup_lineinfo(unsigned long addr, unsigned long sym_start,
> + const char **file, unsigned int *line)
> +{
> + unsigned long long raw_offset;
> + unsigned int offset, low, high, mid, file_id;
> + unsigned long line_addr;
> +
> + if (!lineinfo_num_entries)
> + return false;
> +
> + /* Compute offset from _text */
> + if (addr < (unsigned long)_text)
> + return false;
> +
> + raw_offset = addr - (unsigned long)_text;
> + if (raw_offset > UINT_MAX)
> + return false;
> + offset = (unsigned int)raw_offset;
> +
> + /* Binary search for largest entry <= offset */
> + low = 0;
> + high = lineinfo_num_entries;
> + while (low < high) {
> + mid = low + (high - low) / 2;
> + if (lineinfo_addrs[mid] <= offset)
> + low = mid + 1;
> + else
> + high = mid;
> + }
> +
> + if (low == 0)
> + return false;
> + low--;
> +
> + /*
> + * Validate that the matched lineinfo entry belongs to the same
> + * symbol. Without this check, assembly routines or other
> + * functions lacking DWARF data would inherit the file:line of
> + * a preceding C function.
> + */
> + line_addr = (unsigned long)_text + lineinfo_addrs[low];
> + if (line_addr < sym_start)
> + return false;
This is suspicious. The binary search does "low = mid + 1".
I would expect that lineinfo_addrs[low] would point to
a higher address when the exact match is not found.
Anyway, I think that we should accept only the exact match and do:
if (lineinfo_addrs[low] != offset)
return false;
Or do I miss something? (Friday evening here ;-)
> + file_id = lineinfo_file_ids[low];
> + *line = lineinfo_lines[low];
> +
> + if (file_id >= lineinfo_num_files)
> + return false;
> +
> + *file = &lineinfo_filenames[lineinfo_file_offsets[file_id]];
> + return true;
> +}
> +#endif /* CONFIG_KALLSYMS_LINEINFO */
> +
> /* Look up a kernel symbol and return it in a text buffer. */
> static int __sprint_symbol(char *buffer, unsigned long address,
> int symbol_offset, int add_offset, int add_buildid)
> @@ -497,6 +553,19 @@ static int __sprint_symbol(char *buffer, unsigned long
> address,
> len += sprintf(buffer + len, "]");
> }
>
> +#ifdef CONFIG_KALLSYMS_LINEINFO
> + if (!modname) {
> + const char *li_file;
> + unsigned int li_line;
> + unsigned long sym_start = address - offset;
> +
> + if (kallsyms_lookup_lineinfo(address, sym_start,
> + &li_file, &li_line))
> + len += snprintf(buffer + len, KSYM_SYMBOL_LEN - len,
s/KSYM_SYMBOL_LEN/KSYM_LINEINFO_LEN/
> + " (%s:%u)", li_file, li_line);
> + }
> +#endif
> +
> return len;
> }
I was rather curious how the code looked like and the mentioned things
caught my eyes. And I focused on the kernel/kallsyms code.
Unfortunately, I do not have time for a proper full review at the
moment.
The code seems to work. And it generates relative paths for me, for example:
[ 305.678609] sysrq: Show backtrace of all active CPUs
[ 305.680615] NMI backtrace for cpu 0
[ 305.680620] CPU: 0 UID: 0 PID: 1540 Comm: bash Kdump: loaded Not tainted
7.0.0-rc2-default+ #561 PREEMPT(full) 0d0ba470fd9bf64113a65472ab47c033a2658d88
[ 305.680626] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS
rel-1.17.0-2-g4f253b9b-prebuilt.qemu.org 04/01/2014
[ 305.680628] Call Trace:
[ 305.680631] <TASK>
[ 305.680640] dump_stack_lvl+0x6c/0xa0 (lib/dump_stack.c:94)
[ 305.680680] nmi_cpu_backtrace.cold+0x51/0x6a (lib/nmi_backtrace.c:113)
[ 305.680689] ? __pfx_nmi_raise_cpu_backtrace+0x10/0x10
[ 305.680702] nmi_trigger_cpumask_backtrace+0x113/0x130
(lib/nmi_backtrace.c:62)
[ 305.680720] __handle_sysrq.cold+0x9b/0xde (drivers/tty/sysrq.c:611)
[ 305.680734] write_sysrq_trigger+0x6a/0xb0 (drivers/tty/sysrq.c:1221)
[ 305.680750] proc_reg_write+0x59/0xa0 (fs/proc/inode.c:330)
[ 305.680763] vfs_write+0xd0/0x570 (fs/read_write.c:686)
[ 305.680771] ? srso_alias_return_thunk+0x5/0xfbef5
(arch/x86/lib/retpoline.S:220)
[ 305.680776] ? srso_alias_return_thunk+0x5/0xfbef5
(arch/x86/lib/retpoline.S:220)
[ 305.680779] ? __lock_release.isra.0+0x1c9/0x300
(kernel/locking/lockdep.c:342)
[ 305.680796] ? srso_alias_return_thunk+0x5/0xfbef5
(arch/x86/lib/retpoline.S:220)
[ 305.680813] ksys_write+0x70/0xf0 (fs/read_write.c:738)
[ 305.680826] do_syscall_64+0x11d/0x660 (arch/x86/entry/syscall_64.c:63)
[ 305.680832] ? irqentry_exit+0x94/0x5f0
(./include/linux/irq-entry-common.h:298)
[ 305.680846] entry_SYSCALL_64_after_hwframe+0x76/0x7e
(arch/x86/entry/entry_64.S:121)
HTH,
Petr