Re: [PATCH 04/23] kallsyms: output binary data to speed output and kallsyms assembly

From: David Laight

Date: Thu Sep 10 2026 - 05:58:22 EST


On Tue, 08 Sep 2026 21:55:04 +0100
"Lorenzo Stoakes (ARM)" <ljs@xxxxxxxxxx> wrote:

> kallsyms generates an assembly file that consists mostly of .byte entries
> containing compressed names, token strings and name-sorted sequence
> numbers.
>
> For an x86-64 build with 158k symbols that is a 37 MiB .S file which takes
> 0.57s to assemble each of the two to three times it is built over a kernel
> build.
>
> Each time it is generated it also takes kallsyms a similar amount of time
> to output it.
>
> Avoid this overhead by instead outputting this data as binary and importing
> it into the assembly using the .incbin directive.
>
> Tables that are wider than a byte remain part of the assembly to ensure
> endianness and relative relocations are performed correctly.
>
> With this change, the output assembly file shrinks from 37 MiB to 9.8 MiB,
> with a 2.6 MiB binary data file alongside it, and the object remains
> identical.
>
> The generated binary file is deleted correctly on build clean along with
> all other ephemeral data.
>
> On an x86-64 system with CONFIG_KALLSYMS_ALL set:
>
> before after delta
> scripts/kallsyms 0.24s 0.18s 0.06s
> assemble 0.57s 0.16s 0.41s
>
> Per kallsyms invocation/assembly, for a total of 0.47s time saving upon
> invocation.
>
> An incremental build on the same system was reduced from 11.15s to 9.65s,
> indicating a total of 1.5 seconds saved over the build.
>
> The kallsyms runs and their assembly are on the serial tail of every build
> that links vmlinux, no-op builds are unchanged.
>
> Whole build, 128-thread Threadripper 9980X, best of N runs:
>
> before after delta
> -------------------------------
> x86 defconfig, touch mm/vma.c, gcc 10.8s 9.9s -0.92s (-8%)
> x86 defconfig, touch mm/vma.c, clang 10.7s 9.5s -1.2s (-11%)
> x86 defconfig, clean, gcc 29.5s 28.7s -0.81s (-3%)
> x86 defconfig, clean, clang 29.7s 28.6s -1.1s (-4%)
> x86 allmodconfig, touch mm/vma.c, gcc 45.3s 44.0s -1.3s (-3%)
> x86 allmodconfig, touch mm/vma.c, clang 42.9s 40.2s -2.7s (-6%)
>
> Assisted-by: LLM
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>
> ---
> scripts/kallsyms.c | 97 ++++++++++++++++++++++++++++++++++++++-----------
> scripts/link-vmlinux.sh | 2 +-
> 2 files changed, 77 insertions(+), 22 deletions(-)
>
> diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c
> index 350d118c3b9e..61c5eb537ed4 100644
> --- a/scripts/kallsyms.c
> +++ b/scripts/kallsyms.c
> @@ -5,7 +5,10 @@
> * This software may be used and distributed according to the terms
> * of the GNU General Public License, incorporated herein by reference.
> *
> - * Usage: kallsyms [--all-symbols] in.map > out.S
> + * Usage: kallsyms [--all-symbols] [--pc-relative] in.map out.bin > out.S
> + *
> + * The byte tables go to out.bin and are pulled into out.S with .incbin;
> + * wider tables stay assembler source for endianness and relocations.
> *
> * Table compression uses all the unused char codes on the symbols and
> * maps these to the most used substrings (tokens). For instance, it might
> @@ -102,7 +105,7 @@ static void sym_arr_free(struct sym_arr *arr)
>
> static void usage(void)
> {
> - fprintf(stderr, "Usage: kallsyms [--all-symbols] in.map > out.S\n");
> + fprintf(stderr, "Usage: kallsyms [--all-symbols] [--pc-relative] in.map out.bin > out.S\n");
> exit(1);
> }
>
> @@ -319,6 +322,40 @@ static void output_label(const char *label)
> printf("%s:\n", label);
> }
>
> +static void write_bin(FILE *file, const void *data, size_t len)
> +{
> + if (fwrite(data, 1, len, file) == len)
> + return;
> +
> + perror("kallsyms: write");
> + exit(EXIT_FAILURE);
> +}

It is pretty pointless checking the return value from fwrite().
Most of the time it is just doing a memcpy().
Instead call fflush() and the ferror() prior to the fclose().
(Or just rely on fclose() giving you that error status.)

David