Re: [PATCH 06/23] kbuild: only emit vmlinux relocations when required
From: Nathan Chancellor
Date: Thu Sep 10 2026 - 00:22:55 EST
> A kernel build consists of more than one linking pass on vmlinux.o and
> vmlinux, at minimum two, and with CONFIG_KALLSYMS and BTF enabled on x86-64
> for example there are 5 such stages.
>
> For architectures that build their own relocation tables (x86, riscv, mips,
> s390), vmlinux is linked with the --emit-relocs parameter specified.
>
> However, this is only required on the final vmlinux link.
>
> Symbol tables of trial links preceding it don't need it because they
> already check that System.map matches kallsyms symbols on each build.
>
> GNU ld is slow at emitting relocation tables, so this results in a
> reduction in build time.
>
> Whole build, 128-thread Threadripper 9980X, best of N runs:
>
> before after delta
> -------------------------------
> x86 defconfig, touch mm/vma.c, gcc 9.8s 9.4s -0.43s (-4%)
> x86 defconfig, clean, gcc 28.6s 28.1s -0.47s (-2%)
> x86 allmodconfig, touch mm/vma.c, gcc 44.0s 42.7s -1.3s (-3%)
>
> Note that this has little impact on LLVM ld which performs this operation
> more efficiently.
>
> Assisted-by: LLM
> Signed-off-by: Lorenzo Stoakes (ARM) <ljs@xxxxxxxxxx>
>
> diff --git a/Makefile b/Makefile
> index 9bd226726358..de095b11e20a 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -1266,8 +1266,10 @@ LDFLAGS_vmlinux += --orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL)
> endif
>
> ifneq ($(CONFIG_ARCH_VMLINUX_NEEDS_RELOCS),)
> -LDFLAGS_vmlinux += --emit-relocs --discard-none
> +LDFLAGS_vmlinux += --discard-none
> +LDFLAGS_vmlinux_relocs := --emit-relocs
> endif
> +export LDFLAGS_vmlinux_relocs
>
> # Align the architecture of userspace programs with the kernel
> USERFLAGS_FROM_KERNEL := --target=%
> diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
> index fcae1e432d9a..4b54aaeca65d 100644
> --- a/scripts/Makefile.vmlinux
> +++ b/scripts/Makefile.vmlinux
> @@ -64,7 +64,8 @@ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink)
>
> # Final link of vmlinux with optional arch pass after final link
> cmd_link_vmlinux = \
> - $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)" "$@"; \
> + $< "$(LD)" "$(KBUILD_LDFLAGS)" "$(LDFLAGS_vmlinux)" "$@" \
> + "$(LDFLAGS_vmlinux_relocs)"; \
> $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
>
> targets += vmlinux.unstripped .vmlinux.export.o
> diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
> index 970ca10f8fa9..09c5222ccb94 100755
> --- a/scripts/link-vmlinux.sh
> +++ b/scripts/link-vmlinux.sh
> @@ -32,6 +32,7 @@ LD="$1"
> KBUILD_LDFLAGS="$2"
> LDFLAGS_vmlinux="$3"
> VMLINUX="$4"
> +LDFLAGS_vmlinux_relocs="$5"
>
> is_enabled() {
> grep -q "^$1=y" include/config/auto.conf
> @@ -96,6 +97,11 @@ vmlinux_link()
> ldflags="${ldflags} ${wl}--strip-debug"
> fi
>
> + # Only the final link actually requires the relocations.
> + if [ "${output}" = "${VMLINUX}" ] && [ -n "${LDFLAGS_vmlinux_relocs}" ]; then
> + ldflags="${ldflags} ${wl}${LDFLAGS_vmlinux_relocs}"
> + fi
> +
We don't use LDFLAGS_vmlinux_relocs anywhere else, so do we even need
this whole dance to just end up with the equivalent of
if [ "${output}" = "${VMLINUX}" ] && is_enabled CONFIG_ARCH_VMLINUX_NEEDS_RELOCS; then
ldflags="${ldflags} ${wl}--emit-relocs"
fi
which would make this diff much simpler?
That being said, Sashiko makes a comment that may be relevant, have not
verified though:
https://sashiko.dev/#/message/20260908-build-speedup-v1-6-5dc1ac01672d@xxxxxxxxxx
--
Cheers,
Nathan