kbuild: do not create *.prelink.o for Clang LTO or IBT
When CONFIG_LTO_CLANG=y, additional intermediate *.prelink.o is created
for each module. Also, objtool is postponed until LLVM IR is converted
to ELF.
CONFIG_X86_KERNEL_IBT works in a similar way to postpone objtool until
objects are merged together.
This commit stops generating *.prelink.o, so the build flow will look
similar with/without LTO.
The following figures show how the LTO build currently works, and
how this commit is changing it.
Current build flow
==================
[1] single-object module
$(LD)
$(CC) +objtool $(LD)
foo.c --------------------> foo.o -----> foo.prelink.o -----> foo.ko
(LLVM IR) (ELF) | (ELF)
|
foo.mod.o --/
(LLVM IR)
[2] multi-object module
$(LD)
$(CC) $(AR) +objtool $(LD)
foo1.c -----> foo1.o -----> foo.o -----> foo.prelink.o -----> foo.ko
| (archive) (ELF) | (ELF)
foo2.c -----> foo2.o --/ |
(LLVM IR) foo.mod.o --/
(LLVM IR)
One confusion is that foo.o in multi-object module is an archive
despite of its suffix.
New build flow
==============
[1] single-object module
Since there is only one object, there is no need to keep the LLVM IR.
Use $(CC)+$(LD) to generate an ELF object in one build rule. When LTO
is disabled, $(LD) is unneeded because $(CC) produces an ELF object.
$(CC)+$(LD)+objtool $(LD)
foo.c ----------------------------> foo.o ---------> foo.ko
(ELF) | (ELF)
|
foo.mod.o --/
(LLVM IR)
[2] multi-object module
Previously, $(AR) was used to combine LLVM IR files into an archive,
but there was no technical reason to do so. Use $(LD) to merge them
into a single ELF object.
$(LD)
$(CC) +objtool $(LD)
foo1.c ---------> foo1.o ---------> foo.o ---------> foo.ko
| (ELF) | (ELF)
foo2.c ---------> foo2.o ----/ |
(LLVM IR) foo.mod.o --/
(LLVM IR)
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
Reviewed-by: Nicolas Schier <nicolas@fjasle.eu>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com> # LLVM-14 (x86-64)
Acked-by: Josh Poimboeuf <jpoimboe@kernel.org>
This commit is contained in:
parent
0cfd90060d
commit
c25e1c5582
6 changed files with 28 additions and 67 deletions
|
|
@ -88,10 +88,6 @@ endif
|
|||
targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \
|
||||
$(patsubst %.o, %.$x, $(filter %.o, $(obj-m))))
|
||||
|
||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
||||
targets-for-modules += $(patsubst %.o, %.prelink.o, $(filter %.o, $(obj-m)))
|
||||
endif
|
||||
|
||||
ifdef need-modorder
|
||||
targets-for-modules += $(obj)/modules.order
|
||||
endif
|
||||
|
|
@ -152,8 +148,18 @@ $(obj)/%.ll: $(src)/%.c FORCE
|
|||
# The C file is compiled and updated dependency information is generated.
|
||||
# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
|
||||
|
||||
is-single-obj-m = $(and $(part-of-module),$(filter $@, $(obj-m)),y)
|
||||
|
||||
# When a module consists of a single object, there is no reason to keep LLVM IR.
|
||||
# Make $(LD) covert LLVM IR to ELF here.
|
||||
ifdef CONFIG_LTO_CLANG
|
||||
cmd_ld_single_m = $(if $(is-single-obj-m), ; $(LD) $(ld_flags) -r -o $(tmp-target) $@; mv $(tmp-target) $@)
|
||||
endif
|
||||
|
||||
quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
|
||||
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< $(cmd_objtool)
|
||||
cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< \
|
||||
$(cmd_ld_single_m) \
|
||||
$(cmd_objtool)
|
||||
|
||||
ifdef CONFIG_MODVERSIONS
|
||||
# When module versioning is enabled the following steps are executed:
|
||||
|
|
@ -219,7 +225,7 @@ objtool_args = \
|
|||
$(if $(CONFIG_STACK_VALIDATION), --stackval) \
|
||||
$(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \
|
||||
--uaccess \
|
||||
$(if $($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT)), --link) \
|
||||
$(if $(delay-objtool), --link) \
|
||||
$(if $(part-of-module), --module) \
|
||||
$(if $(CONFIG_GCOV_KERNEL), --no-unreachable)
|
||||
|
||||
|
|
@ -228,21 +234,15 @@ cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(o
|
|||
|
||||
endif # CONFIG_OBJTOOL
|
||||
|
||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
||||
|
||||
# Skip objtool for LLVM bitcode
|
||||
$(obj)/%.o: objtool-enabled :=
|
||||
|
||||
else
|
||||
|
||||
# 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory
|
||||
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file
|
||||
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
|
||||
|
||||
$(obj)/%.o: objtool-enabled = $(if $(filter-out y%, \
|
||||
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y)
|
||||
is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y)
|
||||
|
||||
endif
|
||||
delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT))
|
||||
|
||||
$(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
|
||||
|
||||
ifdef CONFIG_TRIM_UNUSED_KSYMS
|
||||
cmd_gen_ksymdeps = \
|
||||
|
|
@ -271,24 +271,6 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
|
|||
$(call if_changed_rule,cc_o_c)
|
||||
$(call cmd,force_checksrc)
|
||||
|
||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
||||
# Module .o files may contain LLVM bitcode, compile them into native code
|
||||
# before ELF processing
|
||||
quiet_cmd_cc_prelink_modules = LD [M] $@
|
||||
cmd_cc_prelink_modules = \
|
||||
$(LD) $(ld_flags) -r -o $@ \
|
||||
--whole-archive $(filter-out FORCE,$^) \
|
||||
$(cmd_objtool)
|
||||
|
||||
# objtool was skipped for LLVM bitcode, run it now that we have compiled
|
||||
# modules into native code
|
||||
$(obj)/%.prelink.o: objtool-enabled = y
|
||||
$(obj)/%.prelink.o: part-of-module := y
|
||||
|
||||
$(obj)/%.prelink.o: $(obj)/%.o FORCE
|
||||
$(call if_changed,cc_prelink_modules)
|
||||
endif
|
||||
|
||||
cmd_mod = echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)) | \
|
||||
$(AWK) -v RS='( |\n)' '!x[$$0]++' > $@
|
||||
|
||||
|
|
@ -298,7 +280,7 @@ $(obj)/%.mod: FORCE
|
|||
# List module undefined symbols
|
||||
cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@
|
||||
|
||||
$(obj)/%.usyms: $(obj)/%$(mod-prelink-ext).o FORCE
|
||||
$(obj)/%.usyms: $(obj)/%.o FORCE
|
||||
$(call if_changed,undefined_syms)
|
||||
|
||||
quiet_cmd_cc_lst_c = MKLST $@
|
||||
|
|
@ -420,16 +402,11 @@ $(obj)/modules.order: $(obj-m) FORCE
|
|||
$(obj)/lib.a: $(lib-y) FORCE
|
||||
$(call if_changed,ar)
|
||||
|
||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
||||
quiet_cmd_link_multi-m = AR [M] $@
|
||||
cmd_link_multi-m = \
|
||||
rm -f $@; \
|
||||
$(AR) cDPrsT $@ @$(patsubst %.o,%.mod,$@)
|
||||
else
|
||||
quiet_cmd_link_multi-m = LD [M] $@
|
||||
cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@)
|
||||
endif
|
||||
cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool)
|
||||
|
||||
$(multi-obj-m): objtool-enabled := $(delay-objtool)
|
||||
$(multi-obj-m): part-of-module := y
|
||||
$(multi-obj-m): %.o: %.mod FORCE
|
||||
$(call if_changed,link_multi-m)
|
||||
$(call multi_depend, $(multi-obj-m), .o, -objs -y -m)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue