forked from Minki/linux
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
@ -15,6 +15,10 @@ pound := \#
|
||||
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
|
||||
dot-target = $(dir $@).$(notdir $@)
|
||||
|
||||
###
|
||||
# Name of target with a '.tmp_' as filename prefix. foo/bar.o => foo/.tmp_bar.o
|
||||
tmp-target = $(dir $@).tmp_$(notdir $@)
|
||||
|
||||
###
|
||||
# The temporary file to save gcc -MMD generated dependencies must not
|
||||
# contain a comma
|
||||
|
@ -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)
|
||||
|
@ -225,13 +225,6 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \
|
||||
$(addprefix -I,$(DTC_INCLUDE)) \
|
||||
-undef -D__DTS__
|
||||
|
||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
||||
# With CONFIG_LTO_CLANG, .o files in modules might be LLVM bitcode, so we
|
||||
# need to run LTO to compile them into native code (.lto.o) before further
|
||||
# processing.
|
||||
mod-prelink-ext := .prelink
|
||||
endif
|
||||
|
||||
# Useful for describing the dependency of composite objects
|
||||
# Usage:
|
||||
# $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add)
|
||||
|
@ -9,7 +9,7 @@ __modfinal:
|
||||
include include/config/auto.conf
|
||||
include $(srctree)/scripts/Kbuild.include
|
||||
|
||||
# for c_flags and mod-prelink-ext
|
||||
# for c_flags
|
||||
include $(srctree)/scripts/Makefile.lib
|
||||
|
||||
# find all modules listed in modules.order
|
||||
@ -54,9 +54,8 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
|
||||
$(cmd); \
|
||||
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
|
||||
|
||||
|
||||
# Re-generate module BTFs if either module's .ko or vmlinux changed
|
||||
$(modules): %.ko: %$(mod-prelink-ext).o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
|
||||
$(modules): %.ko: %.o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE
|
||||
+$(call if_changed_except,ld_ko_o,vmlinux)
|
||||
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
|
||||
+$(if $(newer-prereqs),$(call cmd,btf_ko))
|
||||
|
@ -41,9 +41,6 @@ __modpost:
|
||||
include include/config/auto.conf
|
||||
include $(srctree)/scripts/Kbuild.include
|
||||
|
||||
# for mod-prelink-ext
|
||||
include $(srctree)/scripts/Makefile.lib
|
||||
|
||||
MODPOST = scripts/mod/modpost \
|
||||
$(if $(CONFIG_MODVERSIONS),-m) \
|
||||
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
|
||||
@ -117,8 +114,6 @@ $(input-symdump):
|
||||
@echo >&2 ' Modules may not have dependencies or modversions.'
|
||||
@echo >&2 ' You may get many unresolved symbol warnings.'
|
||||
|
||||
modules := $(sort $(shell cat $(MODORDER)))
|
||||
|
||||
# KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined symbols
|
||||
ifneq ($(KBUILD_MODPOST_WARN)$(filter-out $(existing-input-symdump), $(input-symdump)),)
|
||||
MODPOST += -w
|
||||
@ -127,9 +122,9 @@ endif
|
||||
# Read out modules.order to pass in modpost.
|
||||
# Otherwise, allmodconfig would fail with "Argument list too long".
|
||||
quiet_cmd_modpost = MODPOST $@
|
||||
cmd_modpost = sed 's/\.ko$$/$(mod-prelink-ext)\.o/' $< | $(MODPOST) -T -
|
||||
cmd_modpost = sed 's/ko$$/o/' $< | $(MODPOST) -T -
|
||||
|
||||
$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(mod-prelink-ext).o) FORCE
|
||||
$(output-symdump): $(MODORDER) $(input-symdump) FORCE
|
||||
$(call if_changed,modpost)
|
||||
|
||||
targets += $(output-symdump)
|
||||
|
@ -1903,10 +1903,6 @@ static char *remove_dot(char *s)
|
||||
size_t m = strspn(s + n + 1, "0123456789");
|
||||
if (m && (s[n + m + 1] == '.' || s[n + m + 1] == 0))
|
||||
s[n] = 0;
|
||||
|
||||
/* strip trailing .prelink */
|
||||
if (strends(s, ".prelink"))
|
||||
s[strlen(s) - 8] = '\0';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -2028,9 +2024,6 @@ static void read_symbols(const char *modname)
|
||||
/* strip trailing .o */
|
||||
tmp = NOFAIL(strdup(modname));
|
||||
tmp[strlen(tmp) - 2] = '\0';
|
||||
/* strip trailing .prelink */
|
||||
if (strends(tmp, ".prelink"))
|
||||
tmp[strlen(tmp) - 8] = '\0';
|
||||
mod = new_module(tmp);
|
||||
free(tmp);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user