`KSYM_NAME_LEN` strikes again

Miguel Ojeda posted 1 patch 19 hours ago
include/linux/kallsyms.h            | 2 +-
kernel/livepatch/core.c             | 4 ++--
lib/tests/longest_symbol_kunit.c    | 7 +++++--
scripts/kallsyms.c                  | 2 +-
tools/include/linux/kallsyms.h      | 2 +-
tools/lib/perf/include/perf/event.h | 2 +-
tools/lib/symbol/kallsyms.h         | 2 +-
7 files changed, 12 insertions(+), 9 deletions(-)
`KSYM_NAME_LEN` strikes again
Posted by Miguel Ojeda 19 hours ago
Hi all,

In some Rust configs with -Os and doctests enabled, we are hitting
KSYM_NAME_LEN again:

    Symbol _RINvMs3_NvNtNtCs1ewLyjEZ7Le_6kernel4sync4lock1__INtB6_12___ThePinData
    NtNvNvNvCs1RN9EnoqSlC_25doctests_kernel_generated43rust_doctest_kernel_sync_lock_spinlock_rs_0
    4main52__doctest_main_rust_kernel_sync_lock_spinlock_rs_34_05InnerNtNtB8_8spinlock
    15SpinLockBackendE5stateNtNtCsb7ts3l0a5c3_4core7convert10InfallibleINtNtCs5hDniGXnib3_
    8pin_init10___internal11InitClosureNCINvMs5_NtBc_5typesINtB61_6OpaqueNtNtCse4H1uDrGHP9_
    8bindings12bindings_raw8spinlockE8ffi_initNCNCNvMs0_B8_INtB8_4LockB15_B3F_E3new0s_0E0B6c_B4j_EEB1d_
    too long for kallsyms (518 >= 512).
    Please increase KSYM_NAME_LEN both in kernel and kallsyms.c

Which expands to e.g.

    <kernel::sync::lock::_::__ThePinData<doctests_kernel_generated::rust_doctest_kernel_sync_lock_spinlock_rs_0::main::_doctest_main_rust_kernel_sync_lock_spinlock_rs_34_0::Inner,
    kernel::sync::lock::spinlock::SpinLockBackend>>::state::<core::convert::Infallible,
    pin_init::__internal::InitClosure<<kernel::types::Opaque<bindings::bindings_raw::spinlock>>::ffi_init
    <<kernel::sync::lock::Lock<doctests_kernel_generated::rust_doctest_kernel_sync_lock_spinlock_rs_0::main::_doctest_main_rust_kernel_sync_lock_spinlock_rs_34_0::Inner,
    kernel::sync::lock::spinlock::SpinLockBackend>>::new::{closure#0}::{closure#1}>::{closure#0},
    kernel::types::Opaque<bindings::bindings_raw::spinlock>, core::convert::Infallible>>

If we decide to increase KSYM_NAME_LEN again, we need to use a number
that is a multiple of 64:

    BUILD_BUG_ON(KSYM_NAME_LEN % sizeof(u64));

I first tried with 512+128, but I still saw things symbols slightly over
that:

    too long for kallsyms (645 >= 640).

So I picked 512+256 and it builds clean with a patch like the one below.
Hopefully nobody relies on it being a power of 2.

Other options:

  - Conditionally doing it only for those builds that need it, to avoid
    penalizing other builds (including normal Rust builds).

  - Building the Rust side with -O2 for now, or at least tweaking some
    of the inlining behavior under -Os.

  - Not supporting Rust for `CC_OPTIMIZE_FOR_SIZE` for now (e.g. under
    `BROKEN`).

  - Stop all this and go with a hashing approach like Willy/Linus
    discussed back then:

        https://lore.kernel.org/rust-for-linux/CAHk-=whzXv=Fu7dQshSTyd9H1-JS5=gyKwW-GMNGccAKs4Mwpg@mail.gmail.com/

Cheers,
Miguel

From: Miguel Ojeda <ojeda@kernel.org>
Date: Sun, 30 Nov 2025 17:46:29 +0100
Subject: [PATCH] kallsyms: increase KSYM_NAME_LEN to 768 (512+256)

Untested!
---
 include/linux/kallsyms.h            | 2 +-
 kernel/livepatch/core.c             | 4 ++--
 lib/tests/longest_symbol_kunit.c    | 7 +++++--
 scripts/kallsyms.c                  | 2 +-
 tools/include/linux/kallsyms.h      | 2 +-
 tools/lib/perf/include/perf/event.h | 2 +-
 tools/lib/symbol/kallsyms.h         | 2 +-
 7 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
index d5dd54c53ace..f17d335f36b2 100644
--- a/include/linux/kallsyms.h
+++ b/include/linux/kallsyms.h
@@ -15,7 +15,7 @@

 #include <asm/sections.h>

-#define KSYM_NAME_LEN 512
+#define KSYM_NAME_LEN 768
 #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
 			(KSYM_NAME_LEN - 1) + \
 			2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + \
diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
index 0e73fac55f8e..cf7f2d561386 100644
--- a/kernel/livepatch/core.c
+++ b/kernel/livepatch/core.c
@@ -210,7 +210,7 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,
 	 * we use the smallest/strictest upper bound possible (56, based on
 	 * the current definition of MODULE_NAME_LEN) to prevent overflows.
 	 */
-	BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 512);
+	BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 768);

 	relas = (Elf_Rela *) relasec->sh_addr;
 	/* For each rela in this klp relocation section */
@@ -224,7 +224,7 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,

 		/* Format: .klp.sym.sym_objname.sym_name,sympos */
 		cnt = sscanf(strtab + sym->st_name,
-			     ".klp.sym.%55[^.].%511[^,],%lu",
+			     ".klp.sym.%55[^.].%767[^,],%lu",
 			     sym_objname, sym_name, &sympos);
 		if (cnt != 3) {
 			pr_err("symbol %s has an incorrectly formatted name\n",
diff --git a/lib/tests/longest_symbol_kunit.c b/lib/tests/longest_symbol_kunit.c
index 9b4de3050ba7..ff8eed2cb4bd 100644
--- a/lib/tests/longest_symbol_kunit.c
+++ b/lib/tests/longest_symbol_kunit.c
@@ -19,8 +19,11 @@
 #define DDDDI(name) DDDI(n##name##name)
 #define DDDDDI(name) DDDDI(n##name##name)

-/*Generate a symbol whose name length is 511 */
-#define LONGEST_SYM_NAME  DDDDDI(g1h2i3j4k5l6m7n)
+#define __SUM(A, B) s##A##B
+#define SUM(A, B) __SUM(A, B)
+
+/* Generate a symbol whose name length is KSYM_NAME_LEN (including null) */
+#define LONGEST_SYM_NAME SUM(DDDDDI(g1h2i3j4k5l6m7n),DDDDI(g1h2i3j4k5l6m7n))

 #define RETURN_LONGEST_SYM 0xAAAAA

diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
index 4b0234e4b12f..c90bb90c874e 100644
--- a/scripts/kallsyms.c
+++ b/scripts/kallsyms.c
@@ -31,7 +31,7 @@

 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))

-#define KSYM_NAME_LEN		512
+#define KSYM_NAME_LEN		768

 struct sym_entry {
 	unsigned long long addr;
diff --git a/tools/include/linux/kallsyms.h b/tools/include/linux/kallsyms.h
index f61a01dd7eb7..089b59906641 100644
--- a/tools/include/linux/kallsyms.h
+++ b/tools/include/linux/kallsyms.h
@@ -6,7 +6,7 @@
 #include <stdio.h>
 #include <unistd.h>

-#define KSYM_NAME_LEN 512
+#define KSYM_NAME_LEN 768

 struct module;

diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h
index aa1e91c97a22..ea3debf97db9 100644
--- a/tools/lib/perf/include/perf/event.h
+++ b/tools/lib/perf/include/perf/event.h
@@ -104,7 +104,7 @@ struct perf_record_throttle {
 };

 #ifndef KSYM_NAME_LEN
-#define KSYM_NAME_LEN 512
+#define KSYM_NAME_LEN 768
 #endif

 struct perf_record_ksymbol {
diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h
index 542f9b059c3b..435f626c92d1 100644
--- a/tools/lib/symbol/kallsyms.h
+++ b/tools/lib/symbol/kallsyms.h
@@ -7,7 +7,7 @@
 #include <linux/types.h>

 #ifndef KSYM_NAME_LEN
-#define KSYM_NAME_LEN 512
+#define KSYM_NAME_LEN 768
 #endif

 static inline u8 kallsyms2elf_binding(char type)

base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
--
2.52.0
Re: `KSYM_NAME_LEN` strikes again
Posted by david laight 12 hours ago
On Mon,  1 Dec 2025 03:16:59 +0100
Miguel Ojeda <ojeda@kernel.org> wrote:

> Hi all,
> 
> In some Rust configs with -Os and doctests enabled, we are hitting
> KSYM_NAME_LEN again:
> 
>     Symbol _RINvMs3_NvNtNtCs1ewLyjEZ7Le_6kernel4sync4lock1__INtB6_12___ThePinData
>     NtNvNvNvCs1RN9EnoqSlC_25doctests_kernel_generated43rust_doctest_kernel_sync_lock_spinlock_rs_0
>     4main52__doctest_main_rust_kernel_sync_lock_spinlock_rs_34_05InnerNtNtB8_8spinlock
>     15SpinLockBackendE5stateNtNtCsb7ts3l0a5c3_4core7convert10InfallibleINtNtCs5hDniGXnib3_
>     8pin_init10___internal11InitClosureNCINvMs5_NtBc_5typesINtB61_6OpaqueNtNtCse4H1uDrGHP9_
>     8bindings12bindings_raw8spinlockE8ffi_initNCNCNvMs0_B8_INtB8_4LockB15_B3F_E3new0s_0E0B6c_B4j_EEB1d_
>     too long for kallsyms (518 >= 512).
>     Please increase KSYM_NAME_LEN both in kernel and kallsyms.c
> 
> Which expands to e.g.
> 
>     <kernel::sync::lock::_::__ThePinData<doctests_kernel_generated::rust_doctest_kernel_sync_lock_spinlock_rs_0::main::_doctest_main_rust_kernel_sync_lock_spinlock_rs_34_0::Inner,
>     kernel::sync::lock::spinlock::SpinLockBackend>>::state::<core::convert::Infallible,  
>     pin_init::__internal::InitClosure<<kernel::types::Opaque<bindings::bindings_raw::spinlock>>::ffi_init
>     <<kernel::sync::lock::Lock<doctests_kernel_generated::rust_doctest_kernel_sync_lock_spinlock_rs_0::main::_doctest_main_rust_kernel_sync_lock_spinlock_rs_34_0::Inner,
>     kernel::sync::lock::spinlock::SpinLockBackend>>::new::{closure#0}::{closure#1}>::{closure#0},  
>     kernel::types::Opaque<bindings::bindings_raw::spinlock>, core::convert::Infallible>>

Given that is even more unreadable than a typical C++ name is it actually worth printing?
Looking at it, perhaps some of the inner <...> could be replaced with a hash
(possibly with the last real name added) with the ability to look up the hash
in a separate table if needed.
I think that is equivalent to using a short name for a type?

If rust is using the same ELF symbol resolution as C uses in shared libraries
you really don't want long symbols at all.
Clearly no one thought about the performance of dynamic linking.

	David


> 
> If we decide to increase KSYM_NAME_LEN again, we need to use a number
> that is a multiple of 64:
> 
>     BUILD_BUG_ON(KSYM_NAME_LEN % sizeof(u64));
> 
> I first tried with 512+128, but I still saw things symbols slightly over
> that:
> 
>     too long for kallsyms (645 >= 640).
> 
> So I picked 512+256 and it builds clean with a patch like the one below.
> Hopefully nobody relies on it being a power of 2.
> 
> Other options:
> 
>   - Conditionally doing it only for those builds that need it, to avoid
>     penalizing other builds (including normal Rust builds).
> 
>   - Building the Rust side with -O2 for now, or at least tweaking some
>     of the inlining behavior under -Os.
> 
>   - Not supporting Rust for `CC_OPTIMIZE_FOR_SIZE` for now (e.g. under
>     `BROKEN`).
> 
>   - Stop all this and go with a hashing approach like Willy/Linus
>     discussed back then:
> 
>         https://lore.kernel.org/rust-for-linux/CAHk-=whzXv=Fu7dQshSTyd9H1-JS5=gyKwW-GMNGccAKs4Mwpg@mail.gmail.com/
> 
> Cheers,
> Miguel
> 
> From: Miguel Ojeda <ojeda@kernel.org>
> Date: Sun, 30 Nov 2025 17:46:29 +0100
> Subject: [PATCH] kallsyms: increase KSYM_NAME_LEN to 768 (512+256)
> 
> Untested!
> ---
>  include/linux/kallsyms.h            | 2 +-
>  kernel/livepatch/core.c             | 4 ++--
>  lib/tests/longest_symbol_kunit.c    | 7 +++++--
>  scripts/kallsyms.c                  | 2 +-
>  tools/include/linux/kallsyms.h      | 2 +-
>  tools/lib/perf/include/perf/event.h | 2 +-
>  tools/lib/symbol/kallsyms.h         | 2 +-
>  7 files changed, 12 insertions(+), 9 deletions(-)
> 
> diff --git a/include/linux/kallsyms.h b/include/linux/kallsyms.h
> index d5dd54c53ace..f17d335f36b2 100644
> --- a/include/linux/kallsyms.h
> +++ b/include/linux/kallsyms.h
> @@ -15,7 +15,7 @@
> 
>  #include <asm/sections.h>
> 
> -#define KSYM_NAME_LEN 512
> +#define KSYM_NAME_LEN 768
>  #define KSYM_SYMBOL_LEN (sizeof("%s+%#lx/%#lx [%s %s]") + \
>  			(KSYM_NAME_LEN - 1) + \
>  			2*(BITS_PER_LONG*3/10) + (MODULE_NAME_LEN - 1) + \
> diff --git a/kernel/livepatch/core.c b/kernel/livepatch/core.c
> index 0e73fac55f8e..cf7f2d561386 100644
> --- a/kernel/livepatch/core.c
> +++ b/kernel/livepatch/core.c
> @@ -210,7 +210,7 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,
>  	 * we use the smallest/strictest upper bound possible (56, based on
>  	 * the current definition of MODULE_NAME_LEN) to prevent overflows.
>  	 */
> -	BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 512);
> +	BUILD_BUG_ON(MODULE_NAME_LEN < 56 || KSYM_NAME_LEN != 768);
> 
>  	relas = (Elf_Rela *) relasec->sh_addr;
>  	/* For each rela in this klp relocation section */
> @@ -224,7 +224,7 @@ static int klp_resolve_symbols(Elf_Shdr *sechdrs, const char *strtab,
> 
>  		/* Format: .klp.sym.sym_objname.sym_name,sympos */
>  		cnt = sscanf(strtab + sym->st_name,
> -			     ".klp.sym.%55[^.].%511[^,],%lu",
> +			     ".klp.sym.%55[^.].%767[^,],%lu",
>  			     sym_objname, sym_name, &sympos);
>  		if (cnt != 3) {
>  			pr_err("symbol %s has an incorrectly formatted name\n",
> diff --git a/lib/tests/longest_symbol_kunit.c b/lib/tests/longest_symbol_kunit.c
> index 9b4de3050ba7..ff8eed2cb4bd 100644
> --- a/lib/tests/longest_symbol_kunit.c
> +++ b/lib/tests/longest_symbol_kunit.c
> @@ -19,8 +19,11 @@
>  #define DDDDI(name) DDDI(n##name##name)
>  #define DDDDDI(name) DDDDI(n##name##name)
> 
> -/*Generate a symbol whose name length is 511 */
> -#define LONGEST_SYM_NAME  DDDDDI(g1h2i3j4k5l6m7n)
> +#define __SUM(A, B) s##A##B
> +#define SUM(A, B) __SUM(A, B)
> +
> +/* Generate a symbol whose name length is KSYM_NAME_LEN (including null) */
> +#define LONGEST_SYM_NAME SUM(DDDDDI(g1h2i3j4k5l6m7n),DDDDI(g1h2i3j4k5l6m7n))
> 
>  #define RETURN_LONGEST_SYM 0xAAAAA
> 
> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 4b0234e4b12f..c90bb90c874e 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
> @@ -31,7 +31,7 @@
> 
>  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
> 
> -#define KSYM_NAME_LEN		512
> +#define KSYM_NAME_LEN		768
> 
>  struct sym_entry {
>  	unsigned long long addr;
> diff --git a/tools/include/linux/kallsyms.h b/tools/include/linux/kallsyms.h
> index f61a01dd7eb7..089b59906641 100644
> --- a/tools/include/linux/kallsyms.h
> +++ b/tools/include/linux/kallsyms.h
> @@ -6,7 +6,7 @@
>  #include <stdio.h>
>  #include <unistd.h>
> 
> -#define KSYM_NAME_LEN 512
> +#define KSYM_NAME_LEN 768
> 
>  struct module;
> 
> diff --git a/tools/lib/perf/include/perf/event.h b/tools/lib/perf/include/perf/event.h
> index aa1e91c97a22..ea3debf97db9 100644
> --- a/tools/lib/perf/include/perf/event.h
> +++ b/tools/lib/perf/include/perf/event.h
> @@ -104,7 +104,7 @@ struct perf_record_throttle {
>  };
> 
>  #ifndef KSYM_NAME_LEN
> -#define KSYM_NAME_LEN 512
> +#define KSYM_NAME_LEN 768
>  #endif
> 
>  struct perf_record_ksymbol {
> diff --git a/tools/lib/symbol/kallsyms.h b/tools/lib/symbol/kallsyms.h
> index 542f9b059c3b..435f626c92d1 100644
> --- a/tools/lib/symbol/kallsyms.h
> +++ b/tools/lib/symbol/kallsyms.h
> @@ -7,7 +7,7 @@
>  #include <linux/types.h>
> 
>  #ifndef KSYM_NAME_LEN
> -#define KSYM_NAME_LEN 512
> +#define KSYM_NAME_LEN 768
>  #endif
> 
>  static inline u8 kallsyms2elf_binding(char type)
> 
> base-commit: 7d0a66e4bb9081d75c82ec4957c50034cb0ea449
> --
> 2.52.0
>
Re: `KSYM_NAME_LEN` strikes again
Posted by Miguel Ojeda 5 hours ago
On Mon, Dec 1, 2025 at 10:15 AM david laight <david.laight@runbox.com> wrote:
>
> Given that is even more unreadable than a typical C++ name is it actually worth printing?
> Looking at it, perhaps some of the inner <...> could be replaced with a hash
> (possibly with the last real name added) with the ability to look up the hash
> in a separate table if needed.

For printing, yeah, parts could be skipped. But if we are looking into
replacing parts of the mangling scheme, then at that point we could go
with the single hash (although, yes, at least seeing "something" could
perhaps clarify in some cases).

> I think that is equivalent to using a short name for a type?

Do you mean skipping the paths and/or the generics etc.?

(That expansion I showed is actually already a "short" version in at
least one way: it doesn't print add the actual crate hash, which e.g.
the GNU c++filt prints without `--no-verbose`, and typically appears
between brackets, e.g. `kernel[e6083e32b3c2ec6]::sync::lock...).

Cheers,
Miguel
Re: `KSYM_NAME_LEN` strikes again
Posted by John Hubbard 16 hours ago
On 11/30/25 6:16 PM, Miguel Ojeda wrote:
> Hi all,
> 
> In some Rust configs with -Os and doctests enabled, we are hitting
> KSYM_NAME_LEN again:
...
> Other options:
> 
>    - Conditionally doing it only for those builds that need it, to avoid
>      penalizing other builds (including normal Rust builds).
> 
>    - Building the Rust side with -O2 for now, or at least tweaking some
>      of the inlining behavior under -Os.
> 
>    - Not supporting Rust for `CC_OPTIMIZE_FOR_SIZE` for now (e.g. under
>      `BROKEN`).
> 
>    - Stop all this and go with a hashing approach like Willy/Linus
>      discussed back then:
> 
>          https://lore.kernel.org/rust-for-linux/CAHk-=whzXv=Fu7dQshSTyd9H1-JS5=gyKwW-GMNGccAKs4Mwpg@mail.gmail.com/
  
I'm impressed that you listed this last one, because it seems like a
somewhat extensive project!

But if it's actually an option, it seems like a very nice one:
a durable and long-lasting fix.

Maybe we would also get demangled backtraces at runtime as a side
effect, which would remove another minor bit of unhappiness too.
  

thanks,
-- 
John Hubbard
Re: `KSYM_NAME_LEN` strikes again
Posted by Miguel Ojeda 5 hours ago
On Mon, Dec 1, 2025 at 5:57 AM John Hubbard <jhubbard@nvidia.com> wrote:
>
> But if it's actually an option, it seems like a very nice one:
> a durable and long-lasting fix.

Unless something has changed that I am not aware of, it is still an
option and it would avoid us having to play these games.

So if someone has time to implement it, then that would be great.

Cheers,
Miguel