From: Sasha Levin <sashal@kernel.org>
To: Petr Mladek <pmladek@suse.com>
Cc: Andrew Morton <akpm@linux-foundation.org>,
Masahiro Yamada <masahiroy@kernel.org>,
Luis Chamberlain <mcgrof@kernel.org>,
Linus Torvalds <torvalds@linux-foundation.org>,
Richard Weinberger <richard@nod.at>,
Juergen Gross <jgross@suse.com>,
Geert Uytterhoeven <geert@linux-m68k.org>,
James Bottomley <James.Bottomley@hansenpartnership.com>,
Jonathan Corbet <corbet@lwn.net>,
Nathan Chancellor <nathan@kernel.org>,
Nicolas Schier <nsc@kernel.org>, Petr Pavlu <petr.pavlu@suse.com>,
Daniel Gomez <da.gomez@kernel.org>,
Greg KH <gregkh@linuxfoundation.org>,
Steven Rostedt <rostedt@goodmis.org>, Kees Cook <kees@kernel.org>,
Peter Zijlstra <peterz@infradead.org>,
Thorsten Leemhuis <linux@leemhuis.info>,
Vlastimil Babka <vbabka@kernel.org>,
linux-kernel@vger.kernel.org, linux-kbuild@vger.kernel.org,
linux-modules@vger.kernel.org, linux-doc@vger.kernel.org
Subject: Re: [PATCH 1/3] kallsyms: embed source file:line info in kernel stack traces
Date: Fri, 6 Mar 2026 12:14:45 -0500 [thread overview]
Message-ID: <aasLhbZmvcQ8sA9P@laps> (raw)
In-Reply-To: <aasClESfxETxliLB@pathway.suse.cz>
On Fri, Mar 06, 2026 at 05:36:36PM +0100, Petr Mladek wrote:
>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_LINEINFO_LEN already covers the full expansion of the path and line
number, not just the literal format characters. ftrace stores raw addresses and
formats via %pS at print time into a KSYM_SYMBOL_LEN-sized buffer, so there
shouldn't be an issue here.
>> (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 ;-)
Right, when there's no exact match, low ends up pointing to the next higher
entry. The table is sparse, with one entry per source-line transition, not per
instruction address. The correct result for a given PC is the nearest
preceding entry, so the code uses low - 1 in that case. Same semantics as
kallsyms symbol lookup.
>> + 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/
KSYM_SYMBOL_LEN - len is the remaining capacity of the output buffer. len
tracks total bytes written (symbol + offset + module + buildid), which can
easily exceed 128.
>> + " (%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)
Thanks for the review and testing! Have a great weekend!
--
Thanks,
Sasha
next prev parent reply other threads:[~2026-03-06 17:14 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-03 18:21 [PATCH 0/3] kallsyms: embed source file:line info in kernel stack traces Sasha Levin
2026-03-03 18:21 ` [PATCH 1/3] " Sasha Levin
2026-03-04 20:17 ` Helge Deller
2026-03-05 2:18 ` Sasha Levin
2026-03-05 22:26 ` Helge Deller
2026-03-06 5:31 ` Randy Dunlap
2026-03-06 17:53 ` Helge Deller
2026-03-06 5:28 ` Randy Dunlap
2026-03-06 16:36 ` Petr Mladek
2026-03-06 17:14 ` Sasha Levin [this message]
2026-03-10 15:20 ` Petr Mladek
2026-03-11 0:58 ` Sasha Levin
2026-03-03 18:21 ` [PATCH 2/3] kallsyms: extend lineinfo to loadable modules Sasha Levin
2026-03-03 18:21 ` [PATCH 3/3] kallsyms: delta-compress lineinfo tables for ~2.7x size reduction Sasha Levin
2026-03-03 21:25 ` Geert Uytterhoeven
2026-03-04 1:11 ` Sasha Levin
2026-03-11 3:34 ` Vivian Wang
2026-03-11 4:13 ` Vivian Wang
2026-03-11 14:49 ` Sasha Levin
2026-03-12 2:03 ` Vivian Wang
2026-03-12 2:18 ` Sasha Levin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=aasLhbZmvcQ8sA9P@laps \
--to=sashal@kernel.org \
--cc=James.Bottomley@hansenpartnership.com \
--cc=akpm@linux-foundation.org \
--cc=corbet@lwn.net \
--cc=da.gomez@kernel.org \
--cc=geert@linux-m68k.org \
--cc=gregkh@linuxfoundation.org \
--cc=jgross@suse.com \
--cc=kees@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kbuild@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-modules@vger.kernel.org \
--cc=linux@leemhuis.info \
--cc=masahiroy@kernel.org \
--cc=mcgrof@kernel.org \
--cc=nathan@kernel.org \
--cc=nsc@kernel.org \
--cc=peterz@infradead.org \
--cc=petr.pavlu@suse.com \
--cc=pmladek@suse.com \
--cc=richard@nod.at \
--cc=rostedt@goodmis.org \
--cc=torvalds@linux-foundation.org \
--cc=vbabka@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.