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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox