mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-06 10:58:48 +09:00
Merge tag 'kbuild-v5.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild
Pull more Kbuild updates from Masahiro Yamada: - Fix build regressions for parisc, csky, nios2, openrisc - Simplify module builds for CONFIG_LTO_CLANG and CONFIG_X86_KERNEL_IBT - Remove arch/parisc/nm, which was presumably a workaround for old tools - Check the odd combination of EXPORT_SYMBOL and 'static' precisely - Make external module builds robust against "too long argument error" - Support j, k keys for moving the cursor in nconfig * tag 'kbuild-v5.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (25 commits) kbuild: Allow to select bash in a modified environment scripts: kconfig: nconf: make nconfig accept jk keybindings modpost: use fnmatch() to simplify match() modpost: simplify mod->name allocation kbuild: factor out the common objtool arguments kbuild: move vmlinux.o link to scripts/Makefile.vmlinux_o kbuild: clean .tmp_* pattern by make clean kbuild: remove redundant cleanups in scripts/link-vmlinux.sh kbuild: rebuild multi-object modules when objtool is updated kbuild: add cmd_and_savecmd macro kbuild: make *.mod rule robust against too long argument error kbuild: make built-in.a rule robust against too long argument error kbuild: check static EXPORT_SYMBOL* by script instead of modpost parisc: remove arch/parisc/nm kbuild: do not create *.prelink.o for Clang LTO or IBT kbuild: replace $(linked-object) with CONFIG options kbuild: do not try to parse *.cmd files for objects provided by compiler kbuild: replace $(if A,A,B) with $(or A,B) in scripts/Makefile.modpost modpost: squash if...else-if in find_elf_symbol2() modpost: reuse ARRAY_SIZE() macro for section_mismatch() ...
This commit is contained in:
4
Makefile
4
Makefile
@@ -1490,7 +1490,7 @@ CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \
|
|||||||
|
|
||||||
# Directories & files removed with 'make mrproper'
|
# Directories & files removed with 'make mrproper'
|
||||||
MRPROPER_FILES += include/config include/generated \
|
MRPROPER_FILES += include/config include/generated \
|
||||||
arch/$(SRCARCH)/include/generated .tmp_objdiff \
|
arch/$(SRCARCH)/include/generated .objdiff \
|
||||||
debian snap tar-install \
|
debian snap tar-install \
|
||||||
.config .config.old .version \
|
.config .config.old .version \
|
||||||
Module.symvers \
|
Module.symvers \
|
||||||
@@ -1857,7 +1857,7 @@ clean: $(clean-dirs)
|
|||||||
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
|
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
|
||||||
-o -name '*.asn1.[ch]' \
|
-o -name '*.asn1.[ch]' \
|
||||||
-o -name '*.symtypes' -o -name 'modules.order' \
|
-o -name '*.symtypes' -o -name 'modules.order' \
|
||||||
-o -name '.tmp_*.o.*' \
|
-o -name '.tmp_*' \
|
||||||
-o -name '*.c.[012]*.*' \
|
-o -name '*.c.[012]*.*' \
|
||||||
-o -name '*.ll' \
|
-o -name '*.ll' \
|
||||||
-o -name '*.gcno' \
|
-o -name '*.gcno' \
|
||||||
|
|||||||
@@ -18,7 +18,6 @@
|
|||||||
boot := arch/parisc/boot
|
boot := arch/parisc/boot
|
||||||
KBUILD_IMAGE := $(boot)/bzImage
|
KBUILD_IMAGE := $(boot)/bzImage
|
||||||
|
|
||||||
NM = sh $(srctree)/arch/parisc/nm
|
|
||||||
CHECKFLAGS += -D__hppa__=1
|
CHECKFLAGS += -D__hppa__=1
|
||||||
|
|
||||||
ifdef CONFIG_64BIT
|
ifdef CONFIG_64BIT
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
##
|
|
||||||
# Hack to have an nm which removes the local symbols. We also rely
|
|
||||||
# on this nm being hidden out of the ordinarily executable path
|
|
||||||
##
|
|
||||||
${CROSS_COMPILE}nm $* | grep -v '.LC*[0-9]*$'
|
|
||||||
@@ -15,6 +15,10 @@ pound := \#
|
|||||||
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
|
# Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o
|
||||||
dot-target = $(dir $@).$(notdir $@)
|
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
|
# The temporary file to save gcc -MMD generated dependencies must not
|
||||||
# contain a comma
|
# contain a comma
|
||||||
@@ -138,9 +142,11 @@ check-FORCE = $(if $(filter FORCE, $^),,$(warning FORCE prerequisite is missing)
|
|||||||
if-changed-cond = $(newer-prereqs)$(cmd-check)$(check-FORCE)
|
if-changed-cond = $(newer-prereqs)$(cmd-check)$(check-FORCE)
|
||||||
|
|
||||||
# Execute command if command has changed or prerequisite(s) are updated.
|
# Execute command if command has changed or prerequisite(s) are updated.
|
||||||
if_changed = $(if $(if-changed-cond), \
|
if_changed = $(if $(if-changed-cond),$(cmd_and_savecmd),@:)
|
||||||
|
|
||||||
|
cmd_and_savecmd = \
|
||||||
$(cmd); \
|
$(cmd); \
|
||||||
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
|
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd
|
||||||
|
|
||||||
# Execute the command and also postprocess generated .d dependencies file.
|
# Execute the command and also postprocess generated .d dependencies file.
|
||||||
if_changed_dep = $(if $(if-changed-cond),$(cmd_and_fixdep),@:)
|
if_changed_dep = $(if $(if-changed-cond),$(cmd_and_fixdep),@:)
|
||||||
|
|||||||
@@ -88,10 +88,6 @@ endif
|
|||||||
targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \
|
targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \
|
||||||
$(patsubst %.o, %.$x, $(filter %.o, $(obj-m))))
|
$(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
|
ifdef need-modorder
|
||||||
targets-for-modules += $(obj)/modules.order
|
targets-for-modules += $(obj)/modules.order
|
||||||
endif
|
endif
|
||||||
@@ -152,8 +148,18 @@ $(obj)/%.ll: $(src)/%.c FORCE
|
|||||||
# The C file is compiled and updated dependency information is generated.
|
# The C file is compiled and updated dependency information is generated.
|
||||||
# (See cmd_cc_o_c + relevant part of rule_cc_o_c)
|
# (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) $@
|
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
|
ifdef CONFIG_MODVERSIONS
|
||||||
# When module versioning is enabled the following steps are executed:
|
# When module versioning is enabled the following steps are executed:
|
||||||
@@ -204,54 +210,25 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),
|
|||||||
$(sub_cmd_record_mcount))
|
$(sub_cmd_record_mcount))
|
||||||
endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
|
endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT
|
||||||
|
|
||||||
ifdef CONFIG_OBJTOOL
|
|
||||||
|
|
||||||
objtool := $(objtree)/tools/objtool/objtool
|
|
||||||
|
|
||||||
objtool_args = \
|
|
||||||
$(if $(CONFIG_HAVE_JUMP_LABEL_HACK), --hacks=jump_label) \
|
|
||||||
$(if $(CONFIG_HAVE_NOINSTR_HACK), --hacks=noinstr) \
|
|
||||||
$(if $(CONFIG_X86_KERNEL_IBT), --ibt) \
|
|
||||||
$(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \
|
|
||||||
$(if $(CONFIG_UNWINDER_ORC), --orc) \
|
|
||||||
$(if $(CONFIG_RETPOLINE), --retpoline) \
|
|
||||||
$(if $(CONFIG_SLS), --sls) \
|
|
||||||
$(if $(CONFIG_STACK_VALIDATION), --stackval) \
|
|
||||||
$(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \
|
|
||||||
--uaccess \
|
|
||||||
$(if $(linked-object), --link) \
|
|
||||||
$(if $(part-of-module), --module) \
|
|
||||||
$(if $(CONFIG_GCOV_KERNEL), --no-unreachable)
|
|
||||||
|
|
||||||
cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@)
|
|
||||||
cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd)
|
|
||||||
|
|
||||||
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 := 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 := 'y': skip objtool checking for a file
|
||||||
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
|
# 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file
|
||||||
|
|
||||||
$(obj)/%.o: objtool-enabled = $(if $(filter-out y%, \
|
is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y)
|
||||||
$(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y)
|
|
||||||
|
|
||||||
endif
|
$(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
|
||||||
|
|
||||||
ifdef CONFIG_TRIM_UNUSED_KSYMS
|
ifdef CONFIG_TRIM_UNUSED_KSYMS
|
||||||
cmd_gen_ksymdeps = \
|
cmd_gen_ksymdeps = \
|
||||||
$(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
|
$(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
cmd_check_local_export = $(srctree)/scripts/check-local-export $@
|
||||||
|
|
||||||
define rule_cc_o_c
|
define rule_cc_o_c
|
||||||
$(call cmd_and_fixdep,cc_o_c)
|
$(call cmd_and_fixdep,cc_o_c)
|
||||||
$(call cmd,gen_ksymdeps)
|
$(call cmd,gen_ksymdeps)
|
||||||
|
$(call cmd,check_local_export)
|
||||||
$(call cmd,checksrc)
|
$(call cmd,checksrc)
|
||||||
$(call cmd,checkdoc)
|
$(call cmd,checkdoc)
|
||||||
$(call cmd,gen_objtooldep)
|
$(call cmd,gen_objtooldep)
|
||||||
@@ -262,6 +239,7 @@ endef
|
|||||||
define rule_as_o_S
|
define rule_as_o_S
|
||||||
$(call cmd_and_fixdep,as_o_S)
|
$(call cmd_and_fixdep,as_o_S)
|
||||||
$(call cmd,gen_ksymdeps)
|
$(call cmd,gen_ksymdeps)
|
||||||
|
$(call cmd,check_local_export)
|
||||||
$(call cmd,gen_objtooldep)
|
$(call cmd,gen_objtooldep)
|
||||||
$(call cmd,gen_symversions_S)
|
$(call cmd,gen_symversions_S)
|
||||||
endef
|
endef
|
||||||
@@ -271,27 +249,10 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE
|
|||||||
$(call if_changed_rule,cc_o_c)
|
$(call if_changed_rule,cc_o_c)
|
||||||
$(call cmd,force_checksrc)
|
$(call cmd,force_checksrc)
|
||||||
|
|
||||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
# To make this rule robust against "Argument list too long" error,
|
||||||
# Module .o files may contain LLVM bitcode, compile them into native code
|
# ensure to add $(obj)/ prefix by a shell command.
|
||||||
# before ELF processing
|
cmd_mod = echo $(call real-search, $*.o, .o, -objs -y -m) | \
|
||||||
quiet_cmd_cc_prelink_modules = LD [M] $@
|
$(AWK) -v RS='( |\n)' '!x[$$0]++ { print("$(obj)/"$$0) }' > $@
|
||||||
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: linked-object := 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]++' > $@
|
|
||||||
|
|
||||||
$(obj)/%.mod: FORCE
|
$(obj)/%.mod: FORCE
|
||||||
$(call if_changed,mod)
|
$(call if_changed,mod)
|
||||||
@@ -299,7 +260,7 @@ $(obj)/%.mod: FORCE
|
|||||||
# List module undefined symbols
|
# List module undefined symbols
|
||||||
cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@
|
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)
|
$(call if_changed,undefined_syms)
|
||||||
|
|
||||||
quiet_cmd_cc_lst_c = MKLST $@
|
quiet_cmd_cc_lst_c = MKLST $@
|
||||||
@@ -392,9 +353,14 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ;
|
|||||||
#
|
#
|
||||||
# Rule to compile a set of .o files into one .a file (without symbol table)
|
# Rule to compile a set of .o files into one .a file (without symbol table)
|
||||||
#
|
#
|
||||||
|
# To make this rule robust against "Argument list too long" error,
|
||||||
|
# remove $(obj)/ prefix, and restore it by a shell command.
|
||||||
|
|
||||||
quiet_cmd_ar_builtin = AR $@
|
quiet_cmd_ar_builtin = AR $@
|
||||||
cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs)
|
cmd_ar_builtin = rm -f $@; \
|
||||||
|
echo $(patsubst $(obj)/%,%,$(real-prereqs)) | \
|
||||||
|
sed -E 's:([^ ]+):$(obj)/\1:g' | \
|
||||||
|
xargs $(AR) cDPrST $@
|
||||||
|
|
||||||
$(obj)/built-in.a: $(real-obj-y) FORCE
|
$(obj)/built-in.a: $(real-obj-y) FORCE
|
||||||
$(call if_changed,ar_builtin)
|
$(call if_changed,ar_builtin)
|
||||||
@@ -421,18 +387,18 @@ $(obj)/modules.order: $(obj-m) FORCE
|
|||||||
$(obj)/lib.a: $(lib-y) FORCE
|
$(obj)/lib.a: $(lib-y) FORCE
|
||||||
$(call if_changed,ar)
|
$(call if_changed,ar)
|
||||||
|
|
||||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
quiet_cmd_ld_multi_m = LD [M] $@
|
||||||
quiet_cmd_link_multi-m = AR [M] $@
|
cmd_ld_multi_m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool)
|
||||||
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
|
|
||||||
|
|
||||||
|
define rule_ld_multi_m
|
||||||
|
$(call cmd_and_savecmd,ld_multi_m)
|
||||||
|
$(call cmd,gen_objtooldep)
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(multi-obj-m): objtool-enabled := $(delay-objtool)
|
||||||
|
$(multi-obj-m): part-of-module := y
|
||||||
$(multi-obj-m): %.o: %.mod FORCE
|
$(multi-obj-m): %.o: %.mod FORCE
|
||||||
$(call if_changed,link_multi-m)
|
$(call if_changed_rule,ld_multi_m)
|
||||||
$(call multi_depend, $(multi-obj-m), .o, -objs -y -m)
|
$(call multi_depend, $(multi-obj-m), .o, -objs -y -m)
|
||||||
|
|
||||||
targets := $(filter-out $(PHONY), $(targets))
|
targets := $(filter-out $(PHONY), $(targets))
|
||||||
|
|||||||
@@ -225,12 +225,31 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \
|
|||||||
$(addprefix -I,$(DTC_INCLUDE)) \
|
$(addprefix -I,$(DTC_INCLUDE)) \
|
||||||
-undef -D__DTS__
|
-undef -D__DTS__
|
||||||
|
|
||||||
ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),)
|
ifdef CONFIG_OBJTOOL
|
||||||
# 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
|
objtool := $(objtree)/tools/objtool/objtool
|
||||||
# processing.
|
|
||||||
mod-prelink-ext := .prelink
|
objtool_args = \
|
||||||
endif
|
$(if $(CONFIG_HAVE_JUMP_LABEL_HACK), --hacks=jump_label) \
|
||||||
|
$(if $(CONFIG_HAVE_NOINSTR_HACK), --hacks=noinstr) \
|
||||||
|
$(if $(CONFIG_X86_KERNEL_IBT), --ibt) \
|
||||||
|
$(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \
|
||||||
|
$(if $(CONFIG_UNWINDER_ORC), --orc) \
|
||||||
|
$(if $(CONFIG_RETPOLINE), --retpoline) \
|
||||||
|
$(if $(CONFIG_SLS), --sls) \
|
||||||
|
$(if $(CONFIG_STACK_VALIDATION), --stackval) \
|
||||||
|
$(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \
|
||||||
|
--uaccess \
|
||||||
|
$(if $(delay-objtool), --link) \
|
||||||
|
$(if $(part-of-module), --module) \
|
||||||
|
$(if $(CONFIG_GCOV_KERNEL), --no-unreachable)
|
||||||
|
|
||||||
|
delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT))
|
||||||
|
|
||||||
|
cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@)
|
||||||
|
cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd)
|
||||||
|
|
||||||
|
endif # CONFIG_OBJTOOL
|
||||||
|
|
||||||
# Useful for describing the dependency of composite objects
|
# Useful for describing the dependency of composite objects
|
||||||
# Usage:
|
# Usage:
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ __modfinal:
|
|||||||
include include/config/auto.conf
|
include include/config/auto.conf
|
||||||
include $(srctree)/scripts/Kbuild.include
|
include $(srctree)/scripts/Kbuild.include
|
||||||
|
|
||||||
# for c_flags and mod-prelink-ext
|
# for c_flags
|
||||||
include $(srctree)/scripts/Makefile.lib
|
include $(srctree)/scripts/Makefile.lib
|
||||||
|
|
||||||
# find all modules listed in modules.order
|
# find all modules listed in modules.order
|
||||||
@@ -54,9 +54,8 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
|
|||||||
$(cmd); \
|
$(cmd); \
|
||||||
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
|
printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
|
||||||
|
|
||||||
|
|
||||||
# Re-generate module BTFs if either module's .ko or vmlinux changed
|
# 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)
|
+$(call if_changed_except,ld_ko_o,vmlinux)
|
||||||
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
|
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
|
||||||
+$(if $(newer-prereqs),$(call cmd,btf_ko))
|
+$(if $(newer-prereqs),$(call cmd,btf_ko))
|
||||||
|
|||||||
@@ -41,9 +41,6 @@ __modpost:
|
|||||||
include include/config/auto.conf
|
include include/config/auto.conf
|
||||||
include $(srctree)/scripts/Kbuild.include
|
include $(srctree)/scripts/Kbuild.include
|
||||||
|
|
||||||
# for mod-prelink-ext
|
|
||||||
include $(srctree)/scripts/Makefile.lib
|
|
||||||
|
|
||||||
MODPOST = scripts/mod/modpost \
|
MODPOST = scripts/mod/modpost \
|
||||||
$(if $(CONFIG_MODVERSIONS),-m) \
|
$(if $(CONFIG_MODVERSIONS),-m) \
|
||||||
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
|
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
|
||||||
@@ -87,8 +84,7 @@ obj := $(KBUILD_EXTMOD)
|
|||||||
src := $(obj)
|
src := $(obj)
|
||||||
|
|
||||||
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
|
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
|
||||||
include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
|
include $(or $(wildcard $(src)/Kbuild), $(src)/Makefile)
|
||||||
$(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
|
|
||||||
|
|
||||||
# modpost option for external modules
|
# modpost option for external modules
|
||||||
MODPOST += -e
|
MODPOST += -e
|
||||||
@@ -118,8 +114,6 @@ $(input-symdump):
|
|||||||
@echo >&2 ' Modules may not have dependencies or modversions.'
|
@echo >&2 ' Modules may not have dependencies or modversions.'
|
||||||
@echo >&2 ' You may get many unresolved symbol warnings.'
|
@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
|
# 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)),)
|
ifneq ($(KBUILD_MODPOST_WARN)$(filter-out $(existing-input-symdump), $(input-symdump)),)
|
||||||
MODPOST += -w
|
MODPOST += -w
|
||||||
@@ -128,9 +122,9 @@ endif
|
|||||||
# Read out modules.order to pass in modpost.
|
# Read out modules.order to pass in modpost.
|
||||||
# Otherwise, allmodconfig would fail with "Argument list too long".
|
# Otherwise, allmodconfig would fail with "Argument list too long".
|
||||||
quiet_cmd_modpost = MODPOST $@
|
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)
|
$(call if_changed,modpost)
|
||||||
|
|
||||||
targets += $(output-symdump)
|
targets += $(output-symdump)
|
||||||
|
|||||||
87
scripts/Makefile.vmlinux_o
Normal file
87
scripts/Makefile.vmlinux_o
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
# 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 \
|
||||||
|
$(KBUILD_VMLINUX_OBJS) $(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 LTO and IBT, objtool doesn't run on individual translation units.
|
||||||
|
# Run everything on vmlinux instead.
|
||||||
|
|
||||||
|
objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION))
|
||||||
|
|
||||||
|
# Reuse objtool_args defined in scripts/Makefile.lib if LTO or IBT is enabled.
|
||||||
|
#
|
||||||
|
# Add some more flags as needed.
|
||||||
|
# --no-unreachable and --link might be added twice, but it is fine.
|
||||||
|
#
|
||||||
|
# Expand objtool_args to a simple variable to avoid circular reference.
|
||||||
|
|
||||||
|
objtool_args := \
|
||||||
|
$(if $(delay-objtool),$(objtool_args)) \
|
||||||
|
$(if $(CONFIG_NOINSTR_VALIDATION), --noinstr) \
|
||||||
|
$(if $(CONFIG_GCOV_KERNEL), --no-unreachable) \
|
||||||
|
--link
|
||||||
|
|
||||||
|
# Link of vmlinux.o used for section mismatch analysis
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
quiet_cmd_ld_vmlinux.o = LD $@
|
||||||
|
cmd_ld_vmlinux.o = \
|
||||||
|
$(LD) ${KBUILD_LDFLAGS} -r -o $@ \
|
||||||
|
$(addprefix -T , $(initcalls-lds)) \
|
||||||
|
--whole-archive $(KBUILD_VMLINUX_OBJS) --no-whole-archive \
|
||||||
|
--start-group $(KBUILD_VMLINUX_LIBS) --end-group \
|
||||||
|
$(cmd_objtool)
|
||||||
|
|
||||||
|
define rule_ld_vmlinux.o
|
||||||
|
$(call cmd_and_savecmd,ld_vmlinux.o)
|
||||||
|
$(call cmd,gen_objtooldep)
|
||||||
|
endef
|
||||||
|
|
||||||
|
vmlinux.o: $(initcalls-lds) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) FORCE
|
||||||
|
$(call if_changed_rule,ld_vmlinux.o)
|
||||||
|
|
||||||
|
targets += vmlinux.o
|
||||||
|
|
||||||
|
# Add FORCE to the prequisites 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)
|
||||||
65
scripts/check-local-export
Executable file
65
scripts/check-local-export
Executable file
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#
|
||||||
|
# Copyright (C) 2022 Masahiro Yamada <masahiroy@kernel.org>
|
||||||
|
#
|
||||||
|
# Exit with error if a local exported symbol is found.
|
||||||
|
# EXPORT_SYMBOL should be used for global symbols.
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
declare -A symbol_types
|
||||||
|
declare -a export_symbols
|
||||||
|
|
||||||
|
exit_code=0
|
||||||
|
|
||||||
|
while read value type name
|
||||||
|
do
|
||||||
|
# Skip the line if the number of fields is less than 3.
|
||||||
|
#
|
||||||
|
# case 1)
|
||||||
|
# For undefined symbols, the first field (value) is empty.
|
||||||
|
# The outout looks like this:
|
||||||
|
# " U _printk"
|
||||||
|
# It is unneeded to record undefined symbols.
|
||||||
|
#
|
||||||
|
# case 2)
|
||||||
|
# For Clang LTO, llvm-nm outputs a line with type 't' but empty name:
|
||||||
|
# "---------------- t"
|
||||||
|
if [[ -z ${name} ]]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# save (name, type) in the associative array
|
||||||
|
symbol_types[${name}]=${type}
|
||||||
|
|
||||||
|
# append the exported symbol to the array
|
||||||
|
if [[ ${name} == __ksymtab_* ]]; then
|
||||||
|
export_symbols+=(${name#__ksymtab_})
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If there is no symbol in the object, ${NM} (both GNU nm and llvm-nm)
|
||||||
|
# shows 'no symbols' diagnostic (but exits with 0). It is harmless and
|
||||||
|
# hidden by '2>/dev/null'. However, it suppresses real error messages
|
||||||
|
# as well. Add a hand-crafted error message here.
|
||||||
|
#
|
||||||
|
# Use --quiet instead of 2>/dev/null when we upgrade the minimum version
|
||||||
|
# of binutils to 2.37, llvm to 13.0.0.
|
||||||
|
#
|
||||||
|
# Then, the following line will be really simple:
|
||||||
|
# done < <(${NM} --quiet ${1})
|
||||||
|
done < <(${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; false; } )
|
||||||
|
|
||||||
|
# Catch error in the process substitution
|
||||||
|
wait $!
|
||||||
|
|
||||||
|
for name in "${export_symbols[@]}"
|
||||||
|
do
|
||||||
|
# nm(3) says "If lowercase, the symbol is usually local"
|
||||||
|
if [[ ${symbol_types[$name]} =~ [a-z] ]]; then
|
||||||
|
echo "$@: error: local symbol '${name}' was exported" >&2
|
||||||
|
exit_code=1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
exit ${exit_code}
|
||||||
@@ -70,7 +70,7 @@ static unsigned char best_table_len[256];
|
|||||||
|
|
||||||
static void usage(void)
|
static void usage(void)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: kallsyms [--all-symbols] "
|
fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] "
|
||||||
"[--base-relative] < in.map > out.S\n");
|
"[--base-relative] < in.map > out.S\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,8 +52,8 @@ static const char nconf_global_help[] =
|
|||||||
"\n"
|
"\n"
|
||||||
"Menu navigation keys\n"
|
"Menu navigation keys\n"
|
||||||
"----------------------------------------------------------------------\n"
|
"----------------------------------------------------------------------\n"
|
||||||
"Linewise up <Up>\n"
|
"Linewise up <Up> <k>\n"
|
||||||
"Linewise down <Down>\n"
|
"Linewise down <Down> <j>\n"
|
||||||
"Pagewise up <Page Up>\n"
|
"Pagewise up <Page Up>\n"
|
||||||
"Pagewise down <Page Down>\n"
|
"Pagewise down <Page Down>\n"
|
||||||
"First entry <Home>\n"
|
"First entry <Home>\n"
|
||||||
@@ -1105,9 +1105,11 @@ static void conf(struct menu *menu)
|
|||||||
break;
|
break;
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
|
case 'j':
|
||||||
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
|
case 'k':
|
||||||
menu_driver(curses_menu, REQ_UP_ITEM);
|
menu_driver(curses_menu, REQ_UP_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_NPAGE:
|
case KEY_NPAGE:
|
||||||
@@ -1287,9 +1289,11 @@ static void conf_choice(struct menu *menu)
|
|||||||
break;
|
break;
|
||||||
switch (res) {
|
switch (res) {
|
||||||
case KEY_DOWN:
|
case KEY_DOWN:
|
||||||
|
case 'j':
|
||||||
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
menu_driver(curses_menu, REQ_DOWN_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_UP:
|
case KEY_UP:
|
||||||
|
case 'k':
|
||||||
menu_driver(curses_menu, REQ_UP_ITEM);
|
menu_driver(curses_menu, REQ_UP_ITEM);
|
||||||
break;
|
break;
|
||||||
case KEY_NPAGE:
|
case KEY_NPAGE:
|
||||||
|
|||||||
@@ -45,115 +45,6 @@ info()
|
|||||||
printf " %-7s %s\n" "${1}" "${2}"
|
printf " %-7s %s\n" "${1}" "${2}"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Generate a linker script to ensure correct ordering of initcalls.
|
|
||||||
gen_initcalls()
|
|
||||||
{
|
|
||||||
info GEN .tmp_initcalls.lds
|
|
||||||
|
|
||||||
${PYTHON3} ${srctree}/scripts/jobserver-exec \
|
|
||||||
${PERL} ${srctree}/scripts/generate_initcall_order.pl \
|
|
||||||
${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \
|
|
||||||
> .tmp_initcalls.lds
|
|
||||||
}
|
|
||||||
|
|
||||||
# Link of vmlinux.o used for section mismatch analysis
|
|
||||||
# ${1} output file
|
|
||||||
modpost_link()
|
|
||||||
{
|
|
||||||
local objects
|
|
||||||
local lds=""
|
|
||||||
|
|
||||||
objects="--whole-archive \
|
|
||||||
${KBUILD_VMLINUX_OBJS} \
|
|
||||||
--no-whole-archive \
|
|
||||||
--start-group \
|
|
||||||
${KBUILD_VMLINUX_LIBS} \
|
|
||||||
--end-group"
|
|
||||||
|
|
||||||
if is_enabled CONFIG_LTO_CLANG; then
|
|
||||||
gen_initcalls
|
|
||||||
lds="-T .tmp_initcalls.lds"
|
|
||||||
|
|
||||||
# This might take a while, so indicate that we're doing
|
|
||||||
# an LTO link
|
|
||||||
info LTO ${1}
|
|
||||||
else
|
|
||||||
info LD ${1}
|
|
||||||
fi
|
|
||||||
|
|
||||||
${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects}
|
|
||||||
}
|
|
||||||
|
|
||||||
objtool_link()
|
|
||||||
{
|
|
||||||
local objtoolcmd;
|
|
||||||
local objtoolopt;
|
|
||||||
|
|
||||||
if ! is_enabled CONFIG_OBJTOOL; then
|
|
||||||
return;
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT; then
|
|
||||||
|
|
||||||
# For LTO and IBT, objtool doesn't run on individual
|
|
||||||
# translation units. Run everything on vmlinux instead.
|
|
||||||
|
|
||||||
if is_enabled CONFIG_HAVE_JUMP_LABEL_HACK; then
|
|
||||||
objtoolopt="${objtoolopt} --hacks=jump_label"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_HAVE_NOINSTR_HACK; then
|
|
||||||
objtoolopt="${objtoolopt} --hacks=noinstr"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_X86_KERNEL_IBT; then
|
|
||||||
objtoolopt="${objtoolopt} --ibt"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then
|
|
||||||
objtoolopt="${objtoolopt} --mcount"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_UNWINDER_ORC; then
|
|
||||||
objtoolopt="${objtoolopt} --orc"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_RETPOLINE; then
|
|
||||||
objtoolopt="${objtoolopt} --retpoline"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_SLS; then
|
|
||||||
objtoolopt="${objtoolopt} --sls"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_STACK_VALIDATION; then
|
|
||||||
objtoolopt="${objtoolopt} --stackval"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_HAVE_STATIC_CALL_INLINE; then
|
|
||||||
objtoolopt="${objtoolopt} --static-call"
|
|
||||||
fi
|
|
||||||
|
|
||||||
objtoolopt="${objtoolopt} --uaccess"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if is_enabled CONFIG_NOINSTR_VALIDATION; then
|
|
||||||
objtoolopt="${objtoolopt} --noinstr"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -n "${objtoolopt}" ]; then
|
|
||||||
|
|
||||||
if is_enabled CONFIG_GCOV_KERNEL; then
|
|
||||||
objtoolopt="${objtoolopt} --no-unreachable"
|
|
||||||
fi
|
|
||||||
|
|
||||||
objtoolopt="${objtoolopt} --link"
|
|
||||||
|
|
||||||
info OBJTOOL ${1}
|
|
||||||
tools/objtool/objtool ${objtoolopt} ${1}
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
# Link of vmlinux
|
# Link of vmlinux
|
||||||
# ${1} - output file
|
# ${1} - output file
|
||||||
# ${2}, ${3}, ... - optional extra .o files
|
# ${2}, ${3}, ... - optional extra .o files
|
||||||
@@ -303,14 +194,9 @@ sorttable()
|
|||||||
cleanup()
|
cleanup()
|
||||||
{
|
{
|
||||||
rm -f .btf.*
|
rm -f .btf.*
|
||||||
rm -f .tmp_System.map
|
|
||||||
rm -f .tmp_initcalls.lds
|
|
||||||
rm -f .tmp_vmlinux*
|
|
||||||
rm -f System.map
|
rm -f System.map
|
||||||
rm -f vmlinux
|
rm -f vmlinux
|
||||||
rm -f vmlinux.map
|
rm -f vmlinux.map
|
||||||
rm -f vmlinux.o
|
|
||||||
rm -f .vmlinux.d
|
|
||||||
rm -f .vmlinux.objs
|
rm -f .vmlinux.objs
|
||||||
rm -f .vmlinux.export.c
|
rm -f .vmlinux.export.c
|
||||||
}
|
}
|
||||||
@@ -341,12 +227,18 @@ fi;
|
|||||||
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
|
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
|
||||||
|
|
||||||
#link vmlinux.o
|
#link vmlinux.o
|
||||||
modpost_link vmlinux.o
|
${MAKE} -f "${srctree}/scripts/Makefile.vmlinux_o"
|
||||||
objtool_link vmlinux.o
|
|
||||||
|
|
||||||
# Generate the list of objects in vmlinux
|
# Generate the list of in-tree objects in vmlinux
|
||||||
|
#
|
||||||
|
# This is used to retrieve symbol versions generated by genksyms.
|
||||||
for f in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
|
for f in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do
|
||||||
case ${f} in
|
case ${f} in
|
||||||
|
*libgcc.a)
|
||||||
|
# Some architectures do '$(CC) --print-libgcc-file-name' to
|
||||||
|
# borrow libgcc.a from the toolchain.
|
||||||
|
# There is no EXPORT_SYMBOL in external objects. Ignore this.
|
||||||
|
;;
|
||||||
*.a)
|
*.a)
|
||||||
${AR} t ${f} ;;
|
${AR} t ${f} ;;
|
||||||
*)
|
*)
|
||||||
|
|||||||
@@ -734,8 +734,6 @@ static int do_vio_entry(const char *filename, void *symval,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
|
||||||
|
|
||||||
static void do_input(char *alias,
|
static void do_input(char *alias,
|
||||||
kernel_ulong_t *arr, unsigned int min, unsigned int max)
|
kernel_ulong_t *arr, unsigned int min, unsigned int max)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
#include <elf.h>
|
#include <elf.h>
|
||||||
|
#include <fnmatch.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -172,11 +173,11 @@ static struct module *find_module(const char *modname)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct module *new_module(const char *modname)
|
static struct module *new_module(const char *name, size_t namelen)
|
||||||
{
|
{
|
||||||
struct module *mod;
|
struct module *mod;
|
||||||
|
|
||||||
mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1));
|
mod = NOFAIL(malloc(sizeof(*mod) + namelen + 1));
|
||||||
memset(mod, 0, sizeof(*mod));
|
memset(mod, 0, sizeof(*mod));
|
||||||
|
|
||||||
INIT_LIST_HEAD(&mod->exported_symbols);
|
INIT_LIST_HEAD(&mod->exported_symbols);
|
||||||
@@ -184,8 +185,9 @@ static struct module *new_module(const char *modname)
|
|||||||
INIT_LIST_HEAD(&mod->missing_namespaces);
|
INIT_LIST_HEAD(&mod->missing_namespaces);
|
||||||
INIT_LIST_HEAD(&mod->imported_namespaces);
|
INIT_LIST_HEAD(&mod->imported_namespaces);
|
||||||
|
|
||||||
strcpy(mod->name, modname);
|
memcpy(mod->name, name, namelen);
|
||||||
mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0);
|
mod->name[namelen] = '\0';
|
||||||
|
mod->is_vmlinux = (strcmp(mod->name, "vmlinux") == 0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set mod->is_gpl_compatible to true by default. If MODULE_LICENSE()
|
* Set mod->is_gpl_compatible to true by default. If MODULE_LICENSE()
|
||||||
@@ -212,7 +214,6 @@ struct symbol {
|
|||||||
unsigned int crc;
|
unsigned int crc;
|
||||||
bool crc_valid;
|
bool crc_valid;
|
||||||
bool weak;
|
bool weak;
|
||||||
bool is_static; /* true if symbol is not global */
|
|
||||||
bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */
|
bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */
|
||||||
char name[];
|
char name[];
|
||||||
};
|
};
|
||||||
@@ -242,7 +243,7 @@ static struct symbol *alloc_symbol(const char *name)
|
|||||||
|
|
||||||
memset(s, 0, sizeof(*s));
|
memset(s, 0, sizeof(*s));
|
||||||
strcpy(s->name, name);
|
strcpy(s->name, name);
|
||||||
s->is_static = true;
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,29 +711,6 @@ static char *get_modinfo(struct elf_info *info, const char *tag)
|
|||||||
return get_next_modinfo(info, tag, NULL);
|
return get_next_modinfo(info, tag, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Test if string s ends in string sub
|
|
||||||
* return 0 if match
|
|
||||||
**/
|
|
||||||
static int strrcmp(const char *s, const char *sub)
|
|
||||||
{
|
|
||||||
int slen, sublen;
|
|
||||||
|
|
||||||
if (!s || !sub)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
slen = strlen(s);
|
|
||||||
sublen = strlen(sub);
|
|
||||||
|
|
||||||
if ((slen == 0) || (sublen == 0))
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
if (sublen > slen)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return memcmp(s + slen - sublen, sub, sublen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
|
static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
|
||||||
{
|
{
|
||||||
if (sym)
|
if (sym)
|
||||||
@@ -741,48 +719,22 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
|
|||||||
return "(unknown)";
|
return "(unknown)";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The pattern is an array of simple patterns.
|
/*
|
||||||
* "foo" will match an exact string equal to "foo"
|
* Check whether the 'string' argument matches one of the 'patterns',
|
||||||
* "*foo" will match a string that ends with "foo"
|
* an array of shell wildcard patterns (glob).
|
||||||
* "foo*" will match a string that begins with "foo"
|
*
|
||||||
* "*foo*" will match a string that contains "foo"
|
* Return true is there is a match.
|
||||||
*/
|
*/
|
||||||
static int match(const char *sym, const char * const pat[])
|
static bool match(const char *string, const char *const patterns[])
|
||||||
{
|
{
|
||||||
const char *p;
|
const char *pattern;
|
||||||
while (*pat) {
|
|
||||||
const char *endp;
|
|
||||||
|
|
||||||
p = *pat++;
|
while ((pattern = *patterns++)) {
|
||||||
endp = p + strlen(p) - 1;
|
if (!fnmatch(pattern, string, 0))
|
||||||
|
return true;
|
||||||
/* "*foo*" */
|
|
||||||
if (*p == '*' && *endp == '*') {
|
|
||||||
char *bare = NOFAIL(strndup(p + 1, strlen(p) - 2));
|
|
||||||
char *here = strstr(sym, bare);
|
|
||||||
|
|
||||||
free(bare);
|
|
||||||
if (here != NULL)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* "*foo" */
|
|
||||||
else if (*p == '*') {
|
|
||||||
if (strrcmp(sym, p + 1) == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* "foo*" */
|
|
||||||
else if (*endp == '*') {
|
|
||||||
if (strncmp(sym, p, strlen(p) - 1) == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* no wildcards */
|
|
||||||
else {
|
|
||||||
if (strcmp(p, sym) == 0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/* no match */
|
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* sections that we do not want to do full section mismatch check on */
|
/* sections that we do not want to do full section mismatch check on */
|
||||||
@@ -1049,8 +1001,6 @@ static const struct sectioncheck *section_mismatch(
|
|||||||
const char *fromsec, const char *tosec)
|
const char *fromsec, const char *tosec)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
|
|
||||||
const struct sectioncheck *check = §ioncheck[0];
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The target section could be the SHT_NUL section when we're
|
* The target section could be the SHT_NUL section when we're
|
||||||
@@ -1061,14 +1011,15 @@ static const struct sectioncheck *section_mismatch(
|
|||||||
if (*tosec == '\0')
|
if (*tosec == '\0')
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
for (i = 0; i < elems; i++) {
|
for (i = 0; i < ARRAY_SIZE(sectioncheck); i++) {
|
||||||
|
const struct sectioncheck *check = §ioncheck[i];
|
||||||
|
|
||||||
if (match(fromsec, check->fromsec)) {
|
if (match(fromsec, check->fromsec)) {
|
||||||
if (check->bad_tosec[0] && match(tosec, check->bad_tosec))
|
if (check->bad_tosec[0] && match(tosec, check->bad_tosec))
|
||||||
return check;
|
return check;
|
||||||
if (check->good_tosec[0] && !match(tosec, check->good_tosec))
|
if (check->good_tosec[0] && !match(tosec, check->good_tosec))
|
||||||
return check;
|
return check;
|
||||||
}
|
}
|
||||||
check++;
|
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -1180,7 +1131,8 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
|
|||||||
|
|
||||||
static inline int is_arm_mapping_symbol(const char *str)
|
static inline int is_arm_mapping_symbol(const char *str)
|
||||||
{
|
{
|
||||||
return str[0] == '$' && strchr("axtd", str[1])
|
return str[0] == '$' &&
|
||||||
|
(str[1] == 'a' || str[1] == 'd' || str[1] == 't' || str[1] == 'x')
|
||||||
&& (str[2] == '\0' || str[2] == '.');
|
&& (str[2] == '\0' || str[2] == '.');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1270,13 +1222,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
|
|||||||
continue;
|
continue;
|
||||||
if (!is_valid_name(elf, sym))
|
if (!is_valid_name(elf, sym))
|
||||||
continue;
|
continue;
|
||||||
if (sym->st_value <= addr) {
|
if (sym->st_value <= addr && addr - sym->st_value <= distance) {
|
||||||
if ((addr - sym->st_value) < distance) {
|
distance = addr - sym->st_value;
|
||||||
distance = addr - sym->st_value;
|
near = sym;
|
||||||
near = sym;
|
|
||||||
} else if ((addr - sym->st_value) == distance) {
|
|
||||||
near = sym;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return near;
|
return near;
|
||||||
@@ -1883,8 +1831,7 @@ static void section_rel(const char *modname, struct elf_info *elf,
|
|||||||
* to find all references to a section that reference a section that will
|
* to find all references to a section that reference a section that will
|
||||||
* be discarded and warns about it.
|
* be discarded and warns about it.
|
||||||
**/
|
**/
|
||||||
static void check_sec_ref(struct module *mod, const char *modname,
|
static void check_sec_ref(const char *modname, struct elf_info *elf)
|
||||||
struct elf_info *elf)
|
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
Elf_Shdr *sechdrs = elf->sechdrs;
|
Elf_Shdr *sechdrs = elf->sechdrs;
|
||||||
@@ -1906,12 +1853,8 @@ static char *remove_dot(char *s)
|
|||||||
|
|
||||||
if (n && s[n]) {
|
if (n && s[n]) {
|
||||||
size_t m = strspn(s + n + 1, "0123456789");
|
size_t m = strspn(s + n + 1, "0123456789");
|
||||||
if (m && (s[n + m] == '.' || s[n + m] == 0))
|
if (m && (s[n + m + 1] == '.' || s[n + m + 1] == 0))
|
||||||
s[n] = 0;
|
s[n] = 0;
|
||||||
|
|
||||||
/* strip trailing .prelink */
|
|
||||||
if (strends(s, ".prelink"))
|
|
||||||
s[strlen(s) - 8] = '\0';
|
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -2027,19 +1970,14 @@ static void read_symbols(const char *modname)
|
|||||||
if (!parse_elf(&info, modname))
|
if (!parse_elf(&info, modname))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
{
|
if (!strends(modname, ".o")) {
|
||||||
char *tmp;
|
error("%s: filename must be suffixed with .o\n", modname);
|
||||||
|
return;
|
||||||
/* 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* strip trailing .o */
|
||||||
|
mod = new_module(modname, strlen(modname) - strlen(".o"));
|
||||||
|
|
||||||
if (!mod->is_vmlinux) {
|
if (!mod->is_vmlinux) {
|
||||||
license = get_modinfo(&info, "license");
|
license = get_modinfo(&info, "license");
|
||||||
if (!license)
|
if (!license)
|
||||||
@@ -2076,21 +2014,7 @@ static void read_symbols(const char *modname)
|
|||||||
sym_get_data(&info, sym));
|
sym_get_data(&info, sym));
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for static EXPORT_SYMBOL_* functions && global vars
|
check_sec_ref(modname, &info);
|
||||||
for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {
|
|
||||||
unsigned char bind = ELF_ST_BIND(sym->st_info);
|
|
||||||
|
|
||||||
if (bind == STB_GLOBAL || bind == STB_WEAK) {
|
|
||||||
struct symbol *s =
|
|
||||||
find_symbol(remove_dot(info.strtab +
|
|
||||||
sym->st_name));
|
|
||||||
|
|
||||||
if (s)
|
|
||||||
s->is_static = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
check_sec_ref(mod, modname, &info);
|
|
||||||
|
|
||||||
if (!mod->is_vmlinux) {
|
if (!mod->is_vmlinux) {
|
||||||
version = get_modinfo(&info, "version");
|
version = get_modinfo(&info, "version");
|
||||||
@@ -2515,11 +2439,10 @@ static void read_dump(const char *fname)
|
|||||||
|
|
||||||
mod = find_module(modname);
|
mod = find_module(modname);
|
||||||
if (!mod) {
|
if (!mod) {
|
||||||
mod = new_module(modname);
|
mod = new_module(modname, strlen(modname));
|
||||||
mod->from_dump = true;
|
mod->from_dump = true;
|
||||||
}
|
}
|
||||||
s = sym_add_exported(symname, mod, gpl_only);
|
s = sym_add_exported(symname, mod, gpl_only);
|
||||||
s->is_static = false;
|
|
||||||
sym_set_crc(s, crc);
|
sym_set_crc(s, crc);
|
||||||
sym_update_namespace(symname, namespace);
|
sym_update_namespace(symname, namespace);
|
||||||
}
|
}
|
||||||
@@ -2584,7 +2507,6 @@ int main(int argc, char **argv)
|
|||||||
char *missing_namespace_deps = NULL;
|
char *missing_namespace_deps = NULL;
|
||||||
char *dump_write = NULL, *files_source = NULL;
|
char *dump_write = NULL, *files_source = NULL;
|
||||||
int opt;
|
int opt;
|
||||||
int n;
|
|
||||||
LIST_HEAD(dump_lists);
|
LIST_HEAD(dump_lists);
|
||||||
struct dump_list *dl, *dl2;
|
struct dump_list *dl, *dl2;
|
||||||
|
|
||||||
@@ -2660,15 +2582,6 @@ int main(int argc, char **argv)
|
|||||||
if (sec_mismatch_count && !sec_mismatch_warn_only)
|
if (sec_mismatch_count && !sec_mismatch_warn_only)
|
||||||
error("Section mismatches detected.\n"
|
error("Section mismatches detected.\n"
|
||||||
"Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
|
"Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n");
|
||||||
for (n = 0; n < SYMBOL_HASH_SIZE; n++) {
|
|
||||||
struct symbol *s;
|
|
||||||
|
|
||||||
for (s = symbolhash[n]; s; s = s->next) {
|
|
||||||
if (s->is_static)
|
|
||||||
error("\"%s\" [%s] is a static EXPORT_SYMBOL\n",
|
|
||||||
s->name, s->module->name);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nr_unresolved > MAX_UNRESOLVED_REPORTS)
|
if (nr_unresolved > MAX_UNRESOLVED_REPORTS)
|
||||||
warn("suppressed %u unresolved symbol warnings because there were too many)\n",
|
warn("suppressed %u unresolved symbol warnings because there were too many)\n",
|
||||||
|
|||||||
@@ -97,6 +97,9 @@ static inline void __endian(const void *src, void *dest, unsigned int size)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NOFAIL(ptr) do_nofail((ptr), #ptr)
|
#define NOFAIL(ptr) do_nofail((ptr), #ptr)
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||||
|
|
||||||
void *do_nofail(void *ptr, const char *expr);
|
void *do_nofail(void *ptr, const char *expr);
|
||||||
|
|
||||||
struct buffer {
|
struct buffer {
|
||||||
|
|||||||
@@ -20,10 +20,10 @@
|
|||||||
# $ ./scripts/objdiff diff COMMIT_A COMMIT_B
|
# $ ./scripts/objdiff diff COMMIT_A COMMIT_B
|
||||||
# $
|
# $
|
||||||
|
|
||||||
# And to clean up (everything is in .tmp_objdiff/*)
|
# And to clean up (everything is in .objdiff/*)
|
||||||
# $ ./scripts/objdiff clean all
|
# $ ./scripts/objdiff clean all
|
||||||
#
|
#
|
||||||
# Note: 'make mrproper' will also remove .tmp_objdiff
|
# Note: 'make mrproper' will also remove .objdiff
|
||||||
|
|
||||||
SRCTREE=$(cd $(git rev-parse --show-toplevel 2>/dev/null); pwd)
|
SRCTREE=$(cd $(git rev-parse --show-toplevel 2>/dev/null); pwd)
|
||||||
|
|
||||||
@@ -32,7 +32,7 @@ if [ -z "$SRCTREE" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
TMPD=$SRCTREE/.tmp_objdiff
|
TMPD=$SRCTREE/.objdiff
|
||||||
|
|
||||||
usage() {
|
usage() {
|
||||||
echo >&2 "Usage: $0 <command> <args>"
|
echo >&2 "Usage: $0 <command> <args>"
|
||||||
|
|||||||
Reference in New Issue
Block a user