Merge tag 'kbuild-v5.19-3' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 5 Jun 2022 16:06:03 +0000 (09:06 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 5 Jun 2022 16:06:03 +0000 (09:06 -0700)
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()
  ...

17 files changed:
Makefile
arch/parisc/Makefile
arch/parisc/nm [deleted file]
scripts/Kbuild.include
scripts/Makefile.build
scripts/Makefile.lib
scripts/Makefile.modfinal
scripts/Makefile.modpost
scripts/Makefile.vmlinux_o [new file with mode: 0644]
scripts/check-local-export [new file with mode: 0755]
scripts/kallsyms.c
scripts/kconfig/nconf.c
scripts/link-vmlinux.sh
scripts/mod/file2alias.c
scripts/mod/modpost.c
scripts/mod/modpost.h
scripts/objdiff

index edc3f44cd96c1442d78c1a3b96ffc4a145d2e004..7011d43dff35bd31ea5f63b581c769ebd80b8537 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1490,7 +1490,7 @@ CLEAN_FILES += include/ksym vmlinux.symvers modules-only.symvers \
 
 # Directories & files removed with 'make mrproper'
 MRPROPER_FILES += include/config include/generated          \
-                 arch/$(SRCARCH)/include/generated .tmp_objdiff \
+                 arch/$(SRCARCH)/include/generated .objdiff \
                  debian snap tar-install \
                  .config .config.old .version \
                  Module.symvers \
@@ -1857,7 +1857,7 @@ clean: $(clean-dirs)
                -o -name '*.lex.c' -o -name '*.tab.[ch]' \
                -o -name '*.asn1.[ch]' \
                -o -name '*.symtypes' -o -name 'modules.order' \
-               -o -name '.tmp_*.o.*' \
+               -o -name '.tmp_*' \
                -o -name '*.c.[012]*.*' \
                -o -name '*.ll' \
                -o -name '*.gcno' \
index aca1710fd658736a4a9f478d3ecd2f1ce5179bc6..e38d993d87f2166abc60d883eddc1e1426889aa8 100644 (file)
@@ -18,7 +18,6 @@
 boot := arch/parisc/boot
 KBUILD_IMAGE := $(boot)/bzImage
 
-NM             = sh $(srctree)/arch/parisc/nm
 CHECKFLAGS     += -D__hppa__=1
 
 ifdef CONFIG_64BIT
diff --git a/arch/parisc/nm b/arch/parisc/nm
deleted file mode 100644 (file)
index c788308..0000000
+++ /dev/null
@@ -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]*$'
index 3514c2149e9d38e12f6888e17dac6cbe8df443ed..ece44b735061348a385070ba782f797abf5d4b80 100644 (file)
@@ -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
@@ -138,9 +142,11 @@ check-FORCE = $(if $(filter FORCE, $^),,$(warning FORCE prerequisite is missing)
 if-changed-cond = $(newer-prereqs)$(cmd-check)$(check-FORCE)
 
 # 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);                                                              \
-       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.
 if_changed_dep = $(if $(if-changed-cond),$(cmd_and_fixdep),@:)
index 06400504150b3ce795a780b96439b591ed639aa6..1f01ac65c0cd4c8d25ee337907f33ce98a4d19ca 100644 (file)
@@ -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:
@@ -204,54 +210,25 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)),
        $(sub_cmd_record_mcount))
 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_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
+$(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
 
 ifdef CONFIG_TRIM_UNUSED_KSYMS
 cmd_gen_ksymdeps = \
        $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
 endif
 
+cmd_check_local_export = $(srctree)/scripts/check-local-export $@
+
 define rule_cc_o_c
        $(call cmd_and_fixdep,cc_o_c)
        $(call cmd,gen_ksymdeps)
+       $(call cmd,check_local_export)
        $(call cmd,checksrc)
        $(call cmd,checkdoc)
        $(call cmd,gen_objtooldep)
@@ -262,6 +239,7 @@ endef
 define rule_as_o_S
        $(call cmd_and_fixdep,as_o_S)
        $(call cmd,gen_ksymdeps)
+       $(call cmd,check_local_export)
        $(call cmd,gen_objtooldep)
        $(call cmd,gen_symversions_S)
 endef
@@ -271,27 +249,10 @@ $(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: 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]++' > $@
+# To make this rule robust against "Argument list too long" error,
+# ensure to add $(obj)/ prefix by a shell command.
+cmd_mod = echo $(call real-search, $*.o, .o, -objs -y -m) | \
+       $(AWK) -v RS='( |\n)' '!x[$$0]++ { print("$(obj)/"$$0) }' > $@
 
 $(obj)/%.mod: FORCE
        $(call if_changed,mod)
@@ -299,7 +260,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   $@
@@ -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)
 #
+# 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      $@
-      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
        $(call if_changed,ar_builtin)
@@ -421,18 +387,18 @@ $(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
+quiet_cmd_ld_multi_m = LD [M]  $@
+      cmd_ld_multi_m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool)
+
+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
-       $(call if_changed,link_multi-m)
+       $(call if_changed_rule,ld_multi_m)
 $(call multi_depend, $(multi-obj-m), .o, -objs -y -m)
 
 targets := $(filter-out $(PHONY), $(targets))
index 0453a1904646af35f60c7606a55058e6cb732c82..f691fb231ce52b099f268c1cd0728652eb439587 100644 (file)
@@ -225,12 +225,31 @@ 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
+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 $(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
 # Usage:
index 7f39599e9faeddcd9a1363710c0feabb2cab10d3..35100e981f4a78b8220d7ffd895e11f695d9ad46 100644 (file)
@@ -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))
index 48585c4d04ade8488c27b6e0501d433219b66141..911606496341ca66a34365dcd29f5cc0d09ff0dd 100644 (file)
@@ -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)                                        \
@@ -87,8 +84,7 @@ obj := $(KBUILD_EXTMOD)
 src := $(obj)
 
 # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
-include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \
-             $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile)
+include $(or $(wildcard $(src)/Kbuild), $(src)/Makefile)
 
 # modpost option for external modules
 MODPOST += -e
@@ -118,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
@@ -128,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)
diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o
new file mode 100644 (file)
index 0000000..3c97a15
--- /dev/null
@@ -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)
diff --git a/scripts/check-local-export b/scripts/check-local-export
new file mode 100755 (executable)
index 0000000..da745e2
--- /dev/null
@@ -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}
index e6906f79833dcf9eb10231b9c24fcf4ee39d2f6d..f18e6dfc68c58398c6f1bfa15e43d5f3101a39a7 100644 (file)
@@ -70,7 +70,7 @@ static unsigned char best_table_len[256];
 
 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");
        exit(1);
 }
index 7b371bd7fb3609600a1283a4c91a926c46c3c6ee..3ba8b1af390fdc920606c4a70e7c55a43ee947ce 100644 (file)
@@ -52,8 +52,8 @@ static const char nconf_global_help[] =
 "\n"
 "Menu navigation keys\n"
 "----------------------------------------------------------------------\n"
-"Linewise up                 <Up>\n"
-"Linewise down               <Down>\n"
+"Linewise up                 <Up>    <k>\n"
+"Linewise down               <Down>  <j>\n"
 "Pagewise up                 <Page Up>\n"
 "Pagewise down               <Page Down>\n"
 "First entry                 <Home>\n"
@@ -1105,9 +1105,11 @@ static void conf(struct menu *menu)
                                break;
                        switch (res) {
                        case KEY_DOWN:
+                       case 'j':
                                menu_driver(curses_menu, REQ_DOWN_ITEM);
                                break;
                        case KEY_UP:
+                       case 'k':
                                menu_driver(curses_menu, REQ_UP_ITEM);
                                break;
                        case KEY_NPAGE:
@@ -1287,9 +1289,11 @@ static void conf_choice(struct menu *menu)
                                break;
                        switch (res) {
                        case KEY_DOWN:
+                       case 'j':
                                menu_driver(curses_menu, REQ_DOWN_ITEM);
                                break;
                        case KEY_UP:
+                       case 'k':
                                menu_driver(curses_menu, REQ_UP_ITEM);
                                break;
                        case KEY_NPAGE:
index a7f6196c7e411c6a6cafb2ee532c7d00f7836314..eecc1863e556b95acce0222fed00760708f5c60b 100755 (executable)
@@ -45,115 +45,6 @@ info()
        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
 # ${1} - output file
 # ${2}, ${3}, ... - optional extra .o files
@@ -303,14 +194,9 @@ sorttable()
 cleanup()
 {
        rm -f .btf.*
-       rm -f .tmp_System.map
-       rm -f .tmp_initcalls.lds
-       rm -f .tmp_vmlinux*
        rm -f System.map
        rm -f vmlinux
        rm -f vmlinux.map
-       rm -f vmlinux.o
-       rm -f .vmlinux.d
        rm -f .vmlinux.objs
        rm -f .vmlinux.export.c
 }
@@ -341,12 +227,18 @@ fi;
 ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1
 
 #link vmlinux.o
-modpost_link vmlinux.o
-objtool_link vmlinux.o
+${MAKE} -f "${srctree}/scripts/Makefile.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
        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)
                ${AR} t ${f} ;;
        *)
index d9d6a31446eaa66320850652a2a50a5ca0d5e7c5..cbd6b0f48b4edb111c1e53ea995120e1283486ab 100644 (file)
@@ -734,8 +734,6 @@ static int do_vio_entry(const char *filename, void *symval,
        return 1;
 }
 
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
 static void do_input(char *alias,
                     kernel_ulong_t *arr, unsigned int min, unsigned int max)
 {
index 42e949cbc255c6494c7c85e8e5e0ce4c678c8d8c..29d5a841e21501869530472d7f0667a0548facf2 100644 (file)
@@ -13,6 +13,7 @@
 
 #define _GNU_SOURCE
 #include <elf.h>
+#include <fnmatch.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <string.h>
@@ -172,11 +173,11 @@ static struct module *find_module(const char *modname)
        return NULL;
 }
 
-static struct module *new_module(const char *modname)
+static struct module *new_module(const char *name, size_t namelen)
 {
        struct module *mod;
 
-       mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1));
+       mod = NOFAIL(malloc(sizeof(*mod) + namelen + 1));
        memset(mod, 0, sizeof(*mod));
 
        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->imported_namespaces);
 
-       strcpy(mod->name, modname);
-       mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0);
+       memcpy(mod->name, name, namelen);
+       mod->name[namelen] = '\0';
+       mod->is_vmlinux = (strcmp(mod->name, "vmlinux") == 0);
 
        /*
         * Set mod->is_gpl_compatible to true by default. If MODULE_LICENSE()
@@ -212,7 +214,6 @@ struct symbol {
        unsigned int crc;
        bool crc_valid;
        bool weak;
-       bool is_static;         /* true if symbol is not global */
        bool is_gpl_only;       /* exported by EXPORT_SYMBOL_GPL */
        char name[];
 };
@@ -242,7 +243,7 @@ static struct symbol *alloc_symbol(const char *name)
 
        memset(s, 0, sizeof(*s));
        strcpy(s->name, name);
-       s->is_static = true;
+
        return s;
 }
 
@@ -710,29 +711,6 @@ static char *get_modinfo(struct elf_info *info, const char *tag)
        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)
 {
        if (sym)
@@ -741,48 +719,22 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym)
                return "(unknown)";
 }
 
-/* The pattern is an array of simple patterns.
- * "foo" will match an exact string equal to "foo"
- * "*foo" will match a string that ends with "foo"
- * "foo*" will match a string that begins with "foo"
- * "*foo*" will match a string that contains "foo"
+/*
+ * Check whether the 'string' argument matches one of the 'patterns',
+ * an array of shell wildcard patterns (glob).
+ *
+ * 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;
-       while (*pat) {
-               const char *endp;
-
-               p = *pat++;
-               endp = p + strlen(p) - 1;
+       const char *pattern;
 
-               /* "*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;
-               }
+       while ((pattern = *patterns++)) {
+               if (!fnmatch(pattern, string, 0))
+                       return true;
        }
-       /* no match */
-       return 0;
+
+       return false;
 }
 
 /* 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)
 {
        int i;
-       int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck);
-       const struct sectioncheck *check = &sectioncheck[0];
 
        /*
         * 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')
                return NULL;
 
-       for (i = 0; i < elems; i++) {
+       for (i = 0; i < ARRAY_SIZE(sectioncheck); i++) {
+               const struct sectioncheck *check = &sectioncheck[i];
+
                if (match(fromsec, check->fromsec)) {
                        if (check->bad_tosec[0] && match(tosec, check->bad_tosec))
                                return check;
                        if (check->good_tosec[0] && !match(tosec, check->good_tosec))
                                return check;
                }
-               check++;
        }
        return NULL;
 }
@@ -1180,7 +1131,8 @@ static int secref_whitelist(const struct sectioncheck *mismatch,
 
 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] == '.');
 }
 
@@ -1270,13 +1222,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr,
                        continue;
                if (!is_valid_name(elf, sym))
                        continue;
-               if (sym->st_value <= addr) {
-                       if ((addr - sym->st_value) < distance) {
-                               distance = addr - sym->st_value;
-                               near = sym;
-                       } else if ((addr - sym->st_value) == distance) {
-                               near = sym;
-                       }
+               if (sym->st_value <= addr && addr - sym->st_value <= distance) {
+                       distance = addr - sym->st_value;
+                       near = sym;
                }
        }
        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
  * be discarded and warns about it.
  **/
-static void check_sec_ref(struct module *mod, const char *modname,
-                         struct elf_info *elf)
+static void check_sec_ref(const char *modname, struct elf_info *elf)
 {
        int i;
        Elf_Shdr *sechdrs = elf->sechdrs;
@@ -1906,12 +1853,8 @@ static char *remove_dot(char *s)
 
        if (n && s[n]) {
                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;
-
-               /* strip trailing .prelink */
-               if (strends(s, ".prelink"))
-                       s[strlen(s) - 8] = '\0';
        }
        return s;
 }
@@ -2027,19 +1970,14 @@ static void read_symbols(const char *modname)
        if (!parse_elf(&info, modname))
                return;
 
-       {
-               char *tmp;
-
-               /* 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);
+       if (!strends(modname, ".o")) {
+               error("%s: filename must be suffixed with .o\n", modname);
+               return;
        }
 
+       /* strip trailing .o */
+       mod = new_module(modname, strlen(modname) - strlen(".o"));
+
        if (!mod->is_vmlinux) {
                license = get_modinfo(&info, "license");
                if (!license)
@@ -2076,21 +2014,7 @@ static void read_symbols(const char *modname)
                                             sym_get_data(&info, sym));
        }
 
-       // check for static EXPORT_SYMBOL_* functions && global vars
-       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);
+       check_sec_ref(modname, &info);
 
        if (!mod->is_vmlinux) {
                version = get_modinfo(&info, "version");
@@ -2515,11 +2439,10 @@ static void read_dump(const char *fname)
 
                mod = find_module(modname);
                if (!mod) {
-                       mod = new_module(modname);
+                       mod = new_module(modname, strlen(modname));
                        mod->from_dump = true;
                }
                s = sym_add_exported(symname, mod, gpl_only);
-               s->is_static = false;
                sym_set_crc(s, crc);
                sym_update_namespace(symname, namespace);
        }
@@ -2584,7 +2507,6 @@ int main(int argc, char **argv)
        char *missing_namespace_deps = NULL;
        char *dump_write = NULL, *files_source = NULL;
        int opt;
-       int n;
        LIST_HEAD(dump_lists);
        struct dump_list *dl, *dl2;
 
@@ -2660,15 +2582,6 @@ int main(int argc, char **argv)
        if (sec_mismatch_count && !sec_mismatch_warn_only)
                error("Section mismatches detected.\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)
                warn("suppressed %u unresolved symbol warnings because there were too many)\n",
index d9daeff07b83ccffc77e687f94bde7814adac1d8..044bdfb894b720fcefb786512f2d8b6728d9f6a8 100644 (file)
@@ -97,6 +97,9 @@ static inline void __endian(const void *src, void *dest, unsigned int size)
 #endif
 
 #define NOFAIL(ptr)   do_nofail((ptr), #ptr)
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
 void *do_nofail(void *ptr, const char *expr);
 
 struct buffer {
index 72b0b63c3fe13454d820877d09953419973f1db4..0685bc3ce3df2737469c0e4d632c54ad70126b96 100755 (executable)
 # $ ./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
 #
-# 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)
 
@@ -32,7 +32,7 @@ if [ -z "$SRCTREE" ]; then
        exit 1
 fi
 
-TMPD=$SRCTREE/.tmp_objdiff
+TMPD=$SRCTREE/.objdiff
 
 usage() {
        echo >&2 "Usage: $0 <command> <args>"