mirror of
https://github.com/torvalds/linux.git
synced 2026-10-22 12:52:02 +02:00
generate_initcall_order.pl, which orders initcalls for Clang LTO, forks a child per input file, up to the job count scripts/jobserver-exec passes it in PARALLELISM. It used to run from link-vmlinux.sh, which the top-level Makefile invokes as a recursive recipe, but commit5d45950dfb("kbuild: move vmlinux.o link to scripts/Makefile.vmlinux_o") moved it into a recipe without "+". GNU Make passes the jobserver pipe only to recipes it treats as recursive, and the make 4.3 in CentOS Stream 9 also hides it in sub-makes (a backport of the fix for GNU Make bug 58232), so jobserver-exec cannot open it and prints: WARNING: Unable to reopen jobserver read-side pipe: FileNotFoundError(2, 'No such file or directory') PARALLELISM is then left unset, and the script caps its children at the number of online CPUs instead of the free job slots. Mark the recipe as recursive again (this makes "make -n" runs the script again too, as it did from link-vmlinux.sh). Masahiro posted the same change and withdrew it because the script was given only vmlinux.a, and so never ran more than one child [1]. But on arm64, LoongArch, and RISC-V with CONFIG_EFI_STUB, KBUILD_VMLINUX_LIBS also gives it the EFI stub's lib.a. Either way, the warning is silenced. Tested ARCH=x86_64 defconfig with CONFIG_LTO_CLANG_THIN=y, LLVM=1 (Clang 24.0.0git), and GNU Make 4.3 plus CentOS Stream 9's make-4.3-cloexec.patch. Fixes:5d45950dfb("kbuild: move vmlinux.o link to scripts/Makefile.vmlinux_o") Link: https://lore.kernel.org/all/CAK7LNARCM=rUm8mA8GRQ7ufeyfneGf4OEvHmESKt=zuxs2KrHw@mail.gmail.com/ [1] Assisted-by: LLM Reviewed-by: Nicolas Schier <n.schier@fritz.com> Signed-off-by: Kees Cook <kees@kernel.org> Tested-by: Paul E. McKenney <paulmck@kernel.org> Link: https://patch.msgid.link/20261010081914.540611-2-kees@kernel.org Signed-off-by: Nathan Chancellor <nathan@kernel.org>
99 lines
3.0 KiB
Makefile
99 lines
3.0 KiB
Makefile
# SPDX-License-Identifier: GPL-2.0-only
|
|
|
|
PHONY := __default
|
|
__default: vmlinux.o
|
|
|
|
include include/config/auto.conf
|
|
include $(srctree)/scripts/Kbuild.include
|
|
|
|
# for objtool
|
|
include $(srctree)/scripts/Makefile.lib
|
|
|
|
# Generate a linker script to ensure correct ordering of initcalls for Clang LTO
|
|
# ---------------------------------------------------------------------------
|
|
|
|
quiet_cmd_gen_initcalls_lds = GEN $@
|
|
cmd_gen_initcalls_lds = \
|
|
$(PYTHON3) $(srctree)/scripts/jobserver-exec \
|
|
$(PERL) $(real-prereqs) > $@
|
|
|
|
.tmp_initcalls.lds: $(srctree)/scripts/generate_initcall_order.pl \
|
|
vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
|
|
+$(call if_changed,gen_initcalls_lds)
|
|
|
|
targets := .tmp_initcalls.lds
|
|
|
|
ifdef CONFIG_LTO_CLANG
|
|
initcalls-lds := .tmp_initcalls.lds
|
|
endif
|
|
|
|
# objtool for vmlinux.o
|
|
# ---------------------------------------------------------------------------
|
|
#
|
|
# For delay-objtool (IBT or LTO), objtool doesn't run on individual translation
|
|
# units. Instead it runs on vmlinux.o.
|
|
#
|
|
# For !delay-objtool + CONFIG_NOINSTR_VALIDATION, it runs on both translation
|
|
# units and vmlinux.o, with the latter only used for noinstr/unret validation.
|
|
|
|
objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION))
|
|
|
|
ifeq ($(delay-objtool),y)
|
|
vmlinux-objtool-args-y += $(objtool-args-y)
|
|
else
|
|
vmlinux-objtool-args-$(CONFIG_OBJTOOL_WERROR) += --werror
|
|
endif
|
|
|
|
vmlinux-objtool-args-$(CONFIG_NOINSTR_VALIDATION) += --noinstr \
|
|
$(if $(or $(CONFIG_MITIGATION_UNRET_ENTRY),$(CONFIG_MITIGATION_SRSO)), --unret)
|
|
|
|
# Only used for builds initiated by klp-build
|
|
vmlinux-objtool-args-$(if $(KLP_SYMIDS),y) += --klp-symids
|
|
|
|
objtool-args = $(vmlinux-objtool-args-y) --link
|
|
|
|
# Link of vmlinux.o used for section mismatch analysis
|
|
# ---------------------------------------------------------------------------
|
|
|
|
vmlinux-o-ld-args-$(CONFIG_BUILTIN_MODULE_RANGES) += -Map=$@.map
|
|
|
|
quiet_cmd_ld_vmlinux.o = LD $@
|
|
cmd_ld_vmlinux.o = \
|
|
$(LD) ${KBUILD_LDFLAGS} -r -o $@ \
|
|
$(vmlinux-o-ld-args-y) \
|
|
$(addprefix -T , $(initcalls-lds)) \
|
|
--whole-archive vmlinux.a --no-whole-archive \
|
|
--start-group $(KBUILD_VMLINUX_LIBS) --end-group \
|
|
$(cmd_objtool)
|
|
|
|
cmd_check_function_names = $(srctree)/scripts/check-function-names.sh $@
|
|
|
|
define rule_ld_vmlinux.o
|
|
$(call cmd_and_savecmd,ld_vmlinux.o)
|
|
$(call cmd,gen_objtooldep)
|
|
$(call cmd,check_function_names)
|
|
endef
|
|
|
|
|
|
vmlinux.o: $(initcalls-lds) vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
|
|
$(call if_changed_rule,ld_vmlinux.o)
|
|
|
|
targets += vmlinux.o
|
|
|
|
# Add FORCE to the prerequisites of a target to force it to be always rebuilt.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
PHONY += FORCE
|
|
FORCE:
|
|
|
|
# Read all saved command lines and dependencies for the $(targets) we
|
|
# may be building above, using $(if_changed{,_dep}). As an
|
|
# optimization, we don't need to read them if the target does not
|
|
# exist, we will rebuild anyway in that case.
|
|
|
|
existing-targets := $(wildcard $(sort $(targets)))
|
|
|
|
-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd)
|
|
|
|
.PHONY: $(PHONY)
|