[PATCH v8 0/4] kallsyms: embed source file:line info in kernel stack traces

Sasha Levin <[email protected]> Sat, 1 Aug 2026 10:32:14 -0400
Newsgroups org.kernel.vger.linux-modules,org.kernel.vger.linux-doc,org.kernel.vger.linux-kbuild,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
CONFIG_KALLSYMS_LINEINFO embeds a compact address-to-line lookup table in
the kernel image so stack traces print source locations directly, without
decode_stacktrace.sh or a vmlinux with debug info at runtime:

  default_idle+0x9/0x10 (arch/x86/kernel/process.c:768)
  default_idle_call+0x2e/0x100 (kernel/sched/idle.c:122)
  do_idle+0x20b/0x2b0 (kernel/sched/idle.c:199)
  cpu_startup_entry+0x24/0x30 (kernel/sched/idle.c:453)
  rest_init+0xbc/0xc0 (init/main.c:717)
  common_startup_64+0x13e/0x158 (arch/x86/kernel/head_64.S:418)

Patch 2 extends this to loadable modules, patch 3 delta-compresses the
tables, patch 4 adds KUnit coverage.

Changes since v7
================

Two bugs turned up while working through Petr's review:

- Module lineinfo blobs were malformed.  emit_section_table() emitted the
  .Lhdr label before its .balign 4, so the kernel read each sub-table
  header 1-3 bytes early.  5 of the 7 modules with two covered text
  sections were affected here, kvm-intel.ko among them, which silently
  lost .exit.text annotation.  Fixed in 2/4, with IS_ALIGNED() rejects on
  the kernel side so a bad blob degrades instead of faulting in NMI
  context.

- v7's symbol-boundary check over-corrected, dropping annotation for 5017
  functions -- 1542 .cold fragments, all __probestub_*, the __ia32_sys_*
  compat wrappers -- which v6 printed correctly.  gen_lineinfo now keeps
  an entry at every symbol start and synthesizes one where the compiler
  emitted none, gated so that __pfx_* padding stubs and __SCT__*
  trampolines stay unannotated.  Costs +0.12% entries.

From Petr Pavlu's review of 1/4:

- Size figures were measured on an unstripped vmlinux.  Redone with
  x86_64_defconfig + CONFIG_DEBUG_INFO, recipe stated inline:
  51.1 -> 69.1 MiB before the compression in 3/4, 51.1 -> 59.1 MiB with it.
- Paths are made relative to $objtree/$srctree/$srcroot (read with
  getenv(), so no Makefile change) rather than by scanning for well-known
  top-level directory names; kernel_dirs[] stays as a fallback.
- Private hash map replaced with scripts/include/hashtable.h.
- xalloc.h for every allocation; the unchecked strdup() is gone.
- ELF_C_READ_MMAP, and ELF_C_READ_MMAP_PRIVATE for modules, which lets
  module mode drop O_RDWR.
- Error handling unified on warn()/error(); main() no longer unwinds.
- Statistics output moved behind -v / KBUILD_VERBOSE.
- libelf named alongside libdw everywhere; Arch package corrected.
- raw_offset/raw_min narrowed to unsigned long.
- Dropped the unused -lz from HOSTLDLIBS_gen_lineinfo.
- ARRAY_SIZE() instead of open-coded sizeof/sizeof.

Also:

- 2/4 no longer documents the delta compression that 3/4 introduces.
- scripts/kallsyms.c matches the lineinfo symbols by prefix; two of them
  had been leaking into /proc/kallsyms.
- alloc_sym_buf() asserts on allocation failure, and a new KUnit case
  pins the symbol-boundary contract the generator relies on.

Testing
=======

x86_64_defconfig + CONFIG_DEBUG_INFO, booted under QEMU/KVM:

- KUnit, CONFIG_LINEINFO_KUNIT_TEST=y builtin:
  31 passed, 0 failed, 1 skipped
- KUnit, =m with CONFIG_KALLSYMS_LINEINFO_MODULES=y:
  30 passed, 0 failed, 2 skipped
- KUnit, =m with CONFIG_KALLSYMS_LINEINFO_MODULES=n:
  12 passed, 0 failed, 20 skipped (skips rather than fails, as intended)
- SysRq-l backtraces annotated, including .S frames and header inlines
- Module frames annotated, e.g.:
    test_dump_stack_no_crash+0xd/0xe80 [lineinfo_kunit]
      (lib/tests/lineinfo_kunit.c:681)
- Every .ko sub-table header 4-byte aligned (8 modules with 2 descriptors);
  was 5 of 7 misaligned before
- Coverage cross-checked against addr2line
- Each of the four patches builds standalone (vmlinux + modules), and 1/4
  alone boots with working annotations
- ARCH=i386 W=2 build of kernel/kallsyms.o and kernel/module/kallsyms.o is
  clean, covering the 32-bit paths touched here

Sasha Levin (4):
  kallsyms: embed source file:line info in kernel stack traces
  kallsyms: extend lineinfo to loadable modules
  kallsyms: delta-compress lineinfo tables for ~2.7x size reduction
  kallsyms: add KUnit tests for lineinfo feature

 Documentation/admin-guide/index.rst           |    1 +
 .../admin-guide/kallsyms-lineinfo.rst         |   97 +
 MAINTAINERS                                   |    9 +
 include/linux/kallsyms.h                      |   18 +-
 include/linux/mod_lineinfo.h                  |  312 +++
 include/linux/module.h                        |   40 +
 init/Kconfig                                  |   35 +
 kernel/kallsyms.c                             |  103 +-
 kernel/kallsyms_internal.h                    |   11 +
 kernel/module/kallsyms.c                      |  191 ++
 kernel/module/main.c                          |   26 +
 lib/Kconfig.debug                             |   10 +
 lib/tests/Makefile                            |    3 +
 lib/tests/lineinfo_kunit.c                    | 1040 +++++++++
 scripts/.gitignore                            |    1 +
 scripts/Makefile                              |    3 +
 scripts/Makefile.modfinal                     |    6 +
 scripts/empty_lineinfo.S                      |   38 +
 scripts/gen-mod-lineinfo.sh                   |   50 +
 scripts/gen_lineinfo.c                        | 1930 +++++++++++++++++
 scripts/kallsyms.c                            |   11 +
 scripts/link-vmlinux.sh                       |   43 +-
 22 files changed, 3967 insertions(+), 11 deletions(-)
 create mode 100644 Documentation/admin-guide/kallsyms-lineinfo.rst
 create mode 100644 include/linux/mod_lineinfo.h
 create mode 100644 lib/tests/lineinfo_kunit.c
 create mode 100644 scripts/empty_lineinfo.S
 create mode 100644 scripts/gen-mod-lineinfo.sh
 create mode 100644 scripts/gen_lineinfo.c

-- 
2.53.0