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

Lorenzo Stoakes (ARM) ljs at kernel.org
Fri Sep 11 04:07:32 PDT 2026


On Thu, Sep 10, 2026 at 10:29:03AM +0100, David Laight wrote:
> On Tue, 08 Sep 2026 21:55:04 +0100
> "Lorenzo Stoakes (ARM)" <ljs at kernel.org> 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 at kernel.org>
> > ---
> >  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.)

Ack, will fix up in v2.

>
> David

--
Cheers, Lorenzo



More information about the linux-riscv mailing list