diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-07-01 09:24:31 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-07-01 09:24:31 -0700 | 
| commit | ad2885979ea6657fa8d3da51a301ec0e998ad8e7 (patch) | |
| tree | 5cd569c8fa06995febbc6cd748283f9172814e60 | |
| parent | e3c2b10d6f15640407bef3098accf10faa4ecf1b (diff) | |
| parent | f5983dab0ead92dc2690d147f0604a0badcac6a8 (diff) | |
Merge tag 'kbuild-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild
Pull Kbuild updates from Masahiro Yamada:
 - Remove the deprecated rule to build *.dtbo from *.dts
 - Refactor section mismatch detection in modpost
 - Fix bogus ARM section mismatch detections
 - Fix error of 'make gtags' with O= option
 - Add Clang's target triple to KBUILD_CPPFLAGS to fix a build error
   with the latest LLVM version
 - Rebuild the built-in initrd when KBUILD_BUILD_TIMESTAMP is changed
 - Ignore more compiler-generated symbols for kallsyms
 - Fix 'make local*config' to handle the ${CONFIG_FOO} form in Makefiles
 - Enable more kernel-doc warnings with W=2
 - Refactor <linux/export.h> by generating KSYMTAB data by modpost
 - Deprecate <asm/export.h> and <asm-generic/export.h>
 - Remove the EXPORT_DATA_SYMBOL macro
 - Move the check for static EXPORT_SYMBOL back to modpost, which makes
   the build faster
 - Re-implement CONFIG_TRIM_UNUSED_KSYMS with one-pass algorithm
 - Warn missing MODULE_DESCRIPTION when building modules with W=1
 - Make 'make clean' robust against too long argument error
 - Exclude more objects from GCOV to fix CFI failures with GCOV
 - Allow 'make modules_install' to install modules.builtin and
   modules.builtin.modinfo even when CONFIG_MODULES is disabled
 - Include modules.builtin and modules.builtin.modinfo in the
   linux-image Debian package even when CONFIG_MODULES is disabled
 - Revive "Entering directory" logging for the latest Make version
* tag 'kbuild-v6.5' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild: (72 commits)
  modpost: define more R_ARM_* for old distributions
  kbuild: revive "Entering directory" for Make >= 4.4.1
  kbuild: set correct abs_srctree and abs_objtree for package builds
  scripts/mksysmap: Ignore prefixed KCFI symbols
  kbuild: deb-pkg: remove the CONFIG_MODULES check in buildeb
  kbuild: builddeb: always make modules_install, to install modules.builtin*
  modpost: continue even with unknown relocation type
  modpost: factor out Elf_Sym pointer calculation to section_rel()
  modpost: factor out inst location calculation to section_rel()
  kbuild: Disable GCOV for *.mod.o
  kbuild: Fix CFI failures with GCOV
  kbuild: make clean rule robust against too long argument error
  script: modpost: emit a warning when the description is missing
  kbuild: make modules_install copy modules.builtin(.modinfo)
  linux/export.h: rename 'sec' argument to 'license'
  modpost: show offset from symbol for section mismatch warnings
  modpost: merge two similar section mismatch warnings
  kbuild: implement CONFIG_TRIM_UNUSED_KSYMS without recursion
  modpost: use null string instead of NULL pointer for default namespace
  modpost: squash sym_update_namespace() into sym_add_exported()
  ...
44 files changed, 662 insertions, 998 deletions
diff --git a/.gitignore b/.gitignore index 7f86e0837909..c3ce78ca20d2 100644 --- a/.gitignore +++ b/.gitignore @@ -51,7 +51,6 @@  *.symversions  *.tab.[ch]  *.tar -*.usyms  *.xz  *.zst  Module.symvers @@ -112,7 +111,6 @@ modules.order  #  /include/config/  /include/generated/ -/include/ksym/  /arch/*/include/generated/  # stgit generated dirs diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst index 2a22ddb1b848..bd906407e307 100644 --- a/Documentation/kbuild/kbuild.rst +++ b/Documentation/kbuild/kbuild.rst @@ -150,6 +150,12 @@ the UTS_MACHINE variable, and on some architectures also the kernel config.  The value of KBUILD_DEBARCH is assumed (not checked) to be a valid Debian  architecture. +KDOCFLAGS +--------- +Specify extra (warning/error) flags for kernel-doc checks during the build, +see scripts/kernel-doc for which flags are supported. Note that this doesn't +(currently) apply to documentation builds. +  ARCH  ----  Set ARCH to the architecture to be built. diff --git a/Documentation/process/changes.rst b/Documentation/process/changes.rst index 5cf6a5f8ca57..5561dae94f85 100644 --- a/Documentation/process/changes.rst +++ b/Documentation/process/changes.rst @@ -60,6 +60,8 @@ openssl & libcrypto    1.0.0            openssl version  bc                     1.06.95          bc --version  Sphinx\ [#f1]_         1.7              sphinx-build --version  cpio                   any              cpio --version +GNU tar                1.28             tar --version +gtags (optional)       6.6.5            gtags --version  ====================== ===============  ========================================  .. [#f1] Sphinx is needed only to build the Kernel documentation @@ -174,6 +176,18 @@ You will need openssl to build kernels 3.7 and higher if module signing is  enabled.  You will also need openssl development packages to build kernels 4.3  and higher. +Tar +--- + +GNU tar is needed if you want to enable access to the kernel headers via sysfs +(CONFIG_IKHEADERS). + +gtags / GNU GLOBAL (optional) +----------------------------- + +The kernel build requires GNU GLOBAL version 6.6.5 or later to generate +tag files through ``make gtags``.  This is due to its use of the gtags +``-C (--directory)`` flag.  System utilities  **************** @@ -38,6 +38,10 @@ __all:  # descending is started. They are now explicitly listed as the  # prepare rule. +this-makefile := $(lastword $(MAKEFILE_LIST)) +export abs_srctree := $(realpath $(dir $(this-makefile))) +export abs_objtree := $(CURDIR) +  ifneq ($(sub_make_done),1)  # Do not use make's built-in rules and variables @@ -185,20 +189,8 @@ $(if $(abs_objtree),, \  # $(realpath ...) resolves symlinks  abs_objtree := $(realpath $(abs_objtree)) -else -abs_objtree := $(CURDIR)  endif # ifneq ($(KBUILD_OUTPUT),) -ifeq ($(abs_objtree),$(CURDIR)) -# Suppress "Entering directory ..." unless we are changing the work directory. -MAKEFLAGS += --no-print-directory -else -need-sub-make := 1 -endif - -this-makefile := $(lastword $(MAKEFILE_LIST)) -abs_srctree := $(realpath $(dir $(this-makefile))) -  ifneq ($(words $(subst :, ,$(abs_srctree))), 1)  $(error source directory cannot contain spaces or colons)  endif @@ -211,9 +203,25 @@ need-sub-make := 1  $(this-makefile): ;  endif -export abs_srctree abs_objtree  export sub_make_done := 1 +endif # sub_make_done + +ifeq ($(abs_objtree),$(CURDIR)) +# Suppress "Entering directory ..." if we are at the final work directory. +no-print-directory := --no-print-directory +else +# Recursion to show "Entering directory ..." +need-sub-make := 1 +endif + +ifeq ($(filter --no-print-directory, $(MAKEFLAGS)),) +# If --no-print-directory is unset, recurse once again to set it. +# You may end up recursing into __sub-make twice. This is needed due to the +# behavior change in GNU Make 4.4.1. +need-sub-make := 1 +endif +  ifeq ($(need-sub-make),1)  PHONY += $(MAKECMDGOALS) __sub-make @@ -223,18 +231,12 @@ $(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make  # Invoke a second make in the output directory, passing relevant variables  __sub-make: -	$(Q)$(MAKE) -C $(abs_objtree) -f $(abs_srctree)/Makefile $(MAKECMDGOALS) +	$(Q)$(MAKE) $(no-print-directory) -C $(abs_objtree) \ +	-f $(abs_srctree)/Makefile $(MAKECMDGOALS) -endif # need-sub-make -endif # sub_make_done +else # need-sub-make  # We process the rest of the Makefile if this is the final invocation of make -ifeq ($(need-sub-make),) - -# Do not print "Entering directory ...", -# but we want to display it when entering to the output directory -# so that IDEs/editors are able to understand relative filenames. -MAKEFLAGS += --no-print-directory  ifeq ($(abs_srctree),$(abs_objtree))          # building in the source tree @@ -1199,28 +1201,12 @@ endif  export KBUILD_VMLINUX_LIBS  export KBUILD_LDS          := arch/$(SRCARCH)/kernel/vmlinux.lds -# Recurse until adjust_autoksyms.sh is satisfied -PHONY += autoksyms_recursive  ifdef CONFIG_TRIM_UNUSED_KSYMS  # For the kernel to actually contain only the needed exported symbols,  # we have to build modules as well to determine what those symbols are. -# (this can be evaluated only once include/config/auto.conf has been included)  KBUILD_MODULES := 1 - -autoksyms_recursive: $(build-dir) modules.order -	$(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \ -	  "$(MAKE) -f $(srctree)/Makefile autoksyms_recursive"  endif -autoksyms_h := $(if $(CONFIG_TRIM_UNUSED_KSYMS), include/generated/autoksyms.h) - -quiet_cmd_autoksyms_h = GEN     $@ -      cmd_autoksyms_h = mkdir -p $(dir $@); \ -			$(CONFIG_SHELL) $(srctree)/scripts/gen_autoksyms.sh $@ - -$(autoksyms_h): -	$(call cmd,autoksyms_h) -  # '$(AR) mPi' needs 'T' to workaround the bug of llvm-ar <= 14  quiet_cmd_ar_vmlinux.a = AR      $@        cmd_ar_vmlinux.a = \ @@ -1229,7 +1215,7 @@ quiet_cmd_ar_vmlinux.a = AR      $@  	$(AR) mPiT $$($(AR) t $@ | sed -n 1p) $@ $$($(AR) t $@ | grep -F -f $(srctree)/scripts/head-object-list.txt)  targets += vmlinux.a -vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt autoksyms_recursive FORCE +vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt FORCE  	$(call if_changed,ar_vmlinux.a)  PHONY += vmlinux_o @@ -1285,7 +1271,7 @@ scripts: scripts_basic scripts_dtc  PHONY += prepare archprepare  archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \ -	asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h \ +	asm-generic $(version_h) include/generated/utsrelease.h \  	include/generated/compile.h include/generated/autoconf.h remove-stale-files  prepare0: archprepare @@ -1567,6 +1553,8 @@ modules_sign_only := y  endif  endif +endif # CONFIG_MODULES +  modinst_pre :=  ifneq ($(filter modules_install,$(MAKECMDGOALS)),)  modinst_pre := __modinst_pre @@ -1577,18 +1565,18 @@ PHONY += __modinst_pre  __modinst_pre:  	@rm -rf $(MODLIB)/kernel  	@rm -f $(MODLIB)/source -	@mkdir -p $(MODLIB)/kernel +	@mkdir -p $(MODLIB) +ifdef CONFIG_MODULES  	@ln -s $(abspath $(srctree)) $(MODLIB)/source  	@if [ ! $(objtree) -ef  $(MODLIB)/build ]; then \  		rm -f $(MODLIB)/build ; \  		ln -s $(CURDIR) $(MODLIB)/build ; \  	fi  	@sed 's:^\(.*\)\.o$$:kernel/\1.ko:' modules.order > $(MODLIB)/modules.order +endif  	@cp -f modules.builtin $(MODLIB)/  	@cp -f $(objtree)/modules.builtin.modinfo $(MODLIB)/ -endif # CONFIG_MODULES -  ###  # Cleaning is done on three levels.  # make clean     Delete most generated files @@ -1930,6 +1918,13 @@ help:  	@echo  '  clean           - remove generated files in module directory only'  	@echo  '' +__external_modules_error: +	@echo >&2 '***' +	@echo >&2 '*** The present kernel disabled CONFIG_MODULES.' +	@echo >&2 '*** You cannot build or install external modules.' +	@echo >&2 '***' +	@false +  endif # KBUILD_EXTMOD  # --------------------------------------------------------------------------- @@ -1966,13 +1961,10 @@ else # CONFIG_MODULES  # Modules not configured  # --------------------------------------------------------------------------- -modules modules_install: -	@echo >&2 '***' -	@echo >&2 '*** The present kernel configuration has modules disabled.' -	@echo >&2 '*** To use the module feature, please run "make menuconfig" etc.' -	@echo >&2 '*** to enable CONFIG_MODULES.' -	@echo >&2 '***' -	@exit 1 +PHONY += __external_modules_error + +modules modules_install: __external_modules_error +	@:  KBUILD_MODULES := @@ -2045,7 +2037,7 @@ clean: $(clean-dirs)  		-o -name '*.dtb.S' -o -name '*.dtbo.S' \  		-o -name '*.dt.yaml' \  		-o -name '*.dwo' -o -name '*.lst' \ -		-o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \ +		-o -name '*.su' -o -name '*.mod' \  		-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \  		-o -name '*.lex.c' -o -name '*.tab.[ch]' \  		-o -name '*.asn1.[ch]' \ diff --git a/arch/arc/include/asm/linkage.h b/arch/arc/include/asm/linkage.h index c9434ff3aa4c..8a3fb71e9cfa 100644 --- a/arch/arc/include/asm/linkage.h +++ b/arch/arc/include/asm/linkage.h @@ -8,6 +8,10 @@  #include <asm/dwarf.h> +#define ASM_NL		 `	/* use '`' to mark new line in macro */ +#define __ALIGN		.align 4 +#define __ALIGN_STR	__stringify(__ALIGN) +  #ifdef __ASSEMBLY__  .macro ST2 e, o, off @@ -28,10 +32,6 @@  #endif  .endm -#define ASM_NL		 `	/* use '`' to mark new line in macro */ -#define __ALIGN		.align 4 -#define __ALIGN_STR	__stringify(__ALIGN) -  /* annotation for data we want in DCCM - if enabled in .config */  .macro ARCFP_DATA nm  #ifdef CONFIG_ARC_HAS_DCCM diff --git a/arch/ia64/include/asm/Kbuild b/arch/ia64/include/asm/Kbuild index aefae2efde9f..33733245f42b 100644 --- a/arch/ia64/include/asm/Kbuild +++ b/arch/ia64/include/asm/Kbuild @@ -1,6 +1,7 @@  # SPDX-License-Identifier: GPL-2.0  generated-y += syscall_table.h  generic-y += agp.h +generic-y += export.h  generic-y += kvm_para.h  generic-y += mcs_spinlock.h  generic-y += vtime.h diff --git a/arch/ia64/include/asm/export.h b/arch/ia64/include/asm/export.h deleted file mode 100644 index ad18c6583252..000000000000 --- a/arch/ia64/include/asm/export.h +++ /dev/null @@ -1,3 +0,0 @@ -/* EXPORT_DATA_SYMBOL != EXPORT_SYMBOL here */ -#define KSYM_FUNC(name) @fptr(name) -#include <asm-generic/export.h> diff --git a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S index f22469f1c1fc..c096500590e9 100644 --- a/arch/ia64/kernel/head.S +++ b/arch/ia64/kernel/head.S @@ -170,7 +170,7 @@ RestRR:											\  	__PAGE_ALIGNED_DATA  	.global empty_zero_page -EXPORT_DATA_SYMBOL_GPL(empty_zero_page) +EXPORT_SYMBOL_GPL(empty_zero_page)  empty_zero_page:  	.skip PAGE_SIZE diff --git a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S index d6d4229b28db..7a418e324d30 100644 --- a/arch/ia64/kernel/ivt.S +++ b/arch/ia64/kernel/ivt.S @@ -87,7 +87,7 @@  	.align 32768	// align on 32KB boundary  	.global ia64_ivt -	EXPORT_DATA_SYMBOL(ia64_ivt) +	EXPORT_SYMBOL(ia64_ivt)  ia64_ivt:  /////////////////////////////////////////////////////////////////////////////////////////  // 0x0000 Entry 0 (size 64 bundles) VHPT Translation (8,20,47) diff --git a/arch/mips/Makefile b/arch/mips/Makefile index a7a4ee66a9d3..ef7b05ae92ce 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile @@ -346,7 +346,7 @@ KBUILD_CFLAGS += -fno-asynchronous-unwind-tables  KBUILD_LDFLAGS		+= -m $(ld-emul)  ifdef CONFIG_MIPS -CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ +CHECKFLAGS += $(shell $(CC) $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \  	grep -E -vw '__GNUC_(MINOR_|PATCHLEVEL_)?_' | \  	sed -e "s/^\#define /-D'/" -e "s/ /'='/" -e "s/$$/'/" -e 's/\$$/&&/g')  endif diff --git a/arch/powerpc/kernel/vdso/Makefile b/arch/powerpc/kernel/vdso/Makefile index 23ee96106537..0c7d82c270c3 100644 --- a/arch/powerpc/kernel/vdso/Makefile +++ b/arch/powerpc/kernel/vdso/Makefile @@ -54,7 +54,7 @@ KASAN_SANITIZE := n  KCSAN_SANITIZE := n  ccflags-y := -fno-common -fno-builtin -ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack +ldflags-y := -Wl,--hash-style=both -nostdlib -shared -z noexecstack $(CLANG_FLAGS)  ldflags-$(CONFIG_LD_IS_LLD) += $(call cc-option,--ld-path=$(LD),-fuse-ld=lld)  ldflags-$(CONFIG_LD_ORPHAN_WARN) += -Wl,--orphan-handling=$(CONFIG_LD_ORPHAN_WARN_LEVEL) diff --git a/arch/um/os-Linux/user_syms.c b/arch/um/os-Linux/user_syms.c index 9b62a9d352b3..a310ae27b479 100644 --- a/arch/um/os-Linux/user_syms.c +++ b/arch/um/os-Linux/user_syms.c @@ -37,13 +37,6 @@ EXPORT_SYMBOL(vsyscall_ehdr);  EXPORT_SYMBOL(vsyscall_end);  #endif -/* Export symbols used by GCC for the stack protector. */ -extern void __stack_smash_handler(void *) __attribute__((weak)); -EXPORT_SYMBOL(__stack_smash_handler); - -extern long __guard __attribute__((weak)); -EXPORT_SYMBOL(__guard); -  #ifdef _FORTIFY_SOURCE  extern int __sprintf_chk(char *str, int flag, size_t len, const char *format);  EXPORT_SYMBOL(__sprintf_chk); diff --git a/include/asm-generic/export.h b/include/asm-generic/export.h index 5e4b1f2369d2..570cd4da7210 100644 --- a/include/asm-generic/export.h +++ b/include/asm-generic/export.h @@ -3,86 +3,9 @@  #define __ASM_GENERIC_EXPORT_H  /* - * This comment block is used by fixdep. Please do not remove. - * - * When CONFIG_MODVERSIONS is changed from n to y, all source files having - * EXPORT_SYMBOL variants must be re-compiled because genksyms is run as a - * side effect of the *.o build rule. + * <asm/export.h> and <asm-generic/export.h> are deprecated. + * Please include <linux/export.h> directly.   */ - -#ifndef KSYM_FUNC -#define KSYM_FUNC(x) x -#endif -#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS -#define KSYM_ALIGN 4 -#elif defined(CONFIG_64BIT) -#define KSYM_ALIGN 8 -#else -#define KSYM_ALIGN 4 -#endif - -.macro __put, val, name -#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS -	.long	\val - ., \name - ., 0 -#elif defined(CONFIG_64BIT) -	.quad	\val, \name, 0 -#else -	.long	\val, \name, 0 -#endif -.endm - -/* - * note on .section use: we specify progbits since usage of the "M" (SHF_MERGE) - * section flag requires it. Use '%progbits' instead of '@progbits' since the - * former apparently works on all arches according to the binutils source. - */ - -.macro ___EXPORT_SYMBOL name,val,sec -#if defined(CONFIG_MODULES) && !defined(__DISABLE_EXPORTS) -	.section ___ksymtab\sec+\name,"a" -	.balign KSYM_ALIGN -__ksymtab_\name: -	__put \val, __kstrtab_\name -	.previous -	.section __ksymtab_strings,"aMS",%progbits,1 -__kstrtab_\name: -	.asciz "\name" -	.previous -#endif -.endm - -#if defined(CONFIG_TRIM_UNUSED_KSYMS) - -#include <linux/kconfig.h> -#include <generated/autoksyms.h> - -.macro __ksym_marker sym -	.section ".discard.ksym","a" -__ksym_marker_\sym: -	 .previous -.endm - -#define __EXPORT_SYMBOL(sym, val, sec)				\ -	__ksym_marker sym;					\ -	__cond_export_sym(sym, val, sec, __is_defined(__KSYM_##sym)) -#define __cond_export_sym(sym, val, sec, conf)			\ -	___cond_export_sym(sym, val, sec, conf) -#define ___cond_export_sym(sym, val, sec, enabled)		\ -	__cond_export_sym_##enabled(sym, val, sec) -#define __cond_export_sym_1(sym, val, sec) ___EXPORT_SYMBOL sym, val, sec -#define __cond_export_sym_0(sym, val, sec) /* nothing */ - -#else -#define __EXPORT_SYMBOL(sym, val, sec) ___EXPORT_SYMBOL sym, val, sec -#endif - -#define EXPORT_SYMBOL(name)					\ -	__EXPORT_SYMBOL(name, KSYM_FUNC(name),) -#define EXPORT_SYMBOL_GPL(name) 				\ -	__EXPORT_SYMBOL(name, KSYM_FUNC(name), _gpl) -#define EXPORT_DATA_SYMBOL(name)				\ -	__EXPORT_SYMBOL(name, name,) -#define EXPORT_DATA_SYMBOL_GPL(name)				\ -	__EXPORT_SYMBOL(name, name,_gpl) +#include <linux/export.h>  #endif diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index da9e5629ea43..45401f7a3548 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -1016,6 +1016,7 @@  	PATCHABLE_DISCARDS						\  	*(.discard)							\  	*(.discard.*)							\ +	*(.export_symbol)						\  	*(.modinfo)							\  	/* ld.bfd warns about .gnu.version* even when not emitted */	\  	*(.gnu.version*)						\ diff --git a/include/linux/export-internal.h b/include/linux/export-internal.h index fe7e6ba918f1..1c849db953a5 100644 --- a/include/linux/export-internal.h +++ b/include/linux/export-internal.h @@ -10,6 +10,55 @@  #include <linux/compiler.h>  #include <linux/types.h> +#if defined(CONFIG_HAVE_ARCH_PREL32_RELOCATIONS) +/* + * relative reference: this reduces the size by half on 64-bit architectures, + * and eliminates the need for absolute relocations that require runtime + * processing on relocatable kernels. + */ +#define __KSYM_REF(sym)		".long " #sym "- ." +#elif defined(CONFIG_64BIT) +#define __KSYM_REF(sym)		".quad " #sym +#else +#define __KSYM_REF(sym)		".long " #sym +#endif + +/* + * For every exported symbol, do the following: + * + * - Put the name of the symbol and namespace (empty string "" for none) in + *   __ksymtab_strings. + * - Place a struct kernel_symbol entry in the __ksymtab section. + * + * Note on .section use: we specify progbits since usage of the "M" (SHF_MERGE) + * section flag requires it. Use '%progbits' instead of '@progbits' since the + * former apparently works on all arches according to the binutils source. + */ +#define __KSYMTAB(name, sym, sec, ns)						\ +	asm("	.section \"__ksymtab_strings\",\"aMS\",%progbits,1"	"\n"	\ +	    "__kstrtab_" #name ":"					"\n"	\ +	    "	.asciz \"" #name "\""					"\n"	\ +	    "__kstrtabns_" #name ":"					"\n"	\ +	    "	.asciz \"" ns "\""					"\n"	\ +	    "	.previous"						"\n"	\ +	    "	.section \"___ksymtab" sec "+" #name "\", \"a\""	"\n"	\ +	    "	.balign	4"						"\n"	\ +	    "__ksymtab_" #name ":"					"\n"	\ +		__KSYM_REF(sym)						"\n"	\ +		__KSYM_REF(__kstrtab_ ##name)				"\n"	\ +		__KSYM_REF(__kstrtabns_ ##name)				"\n"	\ +	    "	.previous"						"\n"	\ +	) + +#ifdef CONFIG_IA64 +#define KSYM_FUNC(name)		@fptr(name) +#else +#define KSYM_FUNC(name)		name +#endif + +#define KSYMTAB_FUNC(name, sec, ns)	__KSYMTAB(name, KSYM_FUNC(name), sec, ns) +#define KSYMTAB_DATA(name, sec, ns)	__KSYMTAB(name, name, sec, ns) +  #define SYMBOL_CRC(sym, crc, sec)   \  	asm(".section \"___kcrctab" sec "+" #sym "\",\"a\""	"\n" \  	    "__crc_" #sym ":"					"\n" \ diff --git a/include/linux/export.h b/include/linux/export.h index 3f31ced0d977..beed8387e0a4 100644 --- a/include/linux/export.h +++ b/include/linux/export.h @@ -2,6 +2,8 @@  #ifndef _LINUX_EXPORT_H  #define _LINUX_EXPORT_H +#include <linux/compiler.h> +#include <linux/linkage.h>  #include <linux/stringify.h>  /* @@ -28,74 +30,25 @@ extern struct module __this_module;  #else  #define THIS_MODULE ((struct module *)0)  #endif +#endif /* __ASSEMBLY__ */ -#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS -#include <linux/compiler.h> -/* - * Emit the ksymtab entry as a pair of relative references: this reduces - * the size by half on 64-bit architectures, and eliminates the need for - * absolute relocations that require runtime processing on relocatable - * kernels. - */ -#define __KSYMTAB_ENTRY(sym, sec)					\ -	__ADDRESSABLE(sym)						\ -	asm("	.section \"___ksymtab" sec "+" #sym "\", \"a\"	\n"	\ -	    "	.balign	4					\n"	\ -	    "__ksymtab_" #sym ":				\n"	\ -	    "	.long	" #sym "- .				\n"	\ -	    "	.long	__kstrtab_" #sym "- .			\n"	\ -	    "	.long	__kstrtabns_" #sym "- .			\n"	\ -	    "	.previous					\n") - -struct kernel_symbol { -	int value_offset; -	int name_offset; -	int namespace_offset; -}; +#ifdef CONFIG_64BIT +#define __EXPORT_SYMBOL_REF(sym)			\ +	.balign 8				ASM_NL	\ +	.quad sym  #else -#define __KSYMTAB_ENTRY(sym, sec)					\ -	static const struct kernel_symbol __ksymtab_##sym		\ -	__attribute__((section("___ksymtab" sec "+" #sym), used))	\ -	__aligned(sizeof(void *))					\ -	= { (unsigned long)&sym, __kstrtab_##sym, __kstrtabns_##sym } - -struct kernel_symbol { -	unsigned long value; -	const char *name; -	const char *namespace; -}; +#define __EXPORT_SYMBOL_REF(sym)			\ +	.balign 4				ASM_NL	\ +	.long sym  #endif -#ifdef __GENKSYMS__ - -#define ___EXPORT_SYMBOL(sym, sec, ns)	__GENKSYMS_EXPORT_SYMBOL(sym) - -#else - -/* - * For every exported symbol, do the following: - * - * - Put the name of the symbol and namespace (empty string "" for none) in - *   __ksymtab_strings. - * - Place a struct kernel_symbol entry in the __ksymtab section. - * - * note on .section use: we specify progbits since usage of the "M" (SHF_MERGE) - * section flag requires it. Use '%progbits' instead of '@progbits' since the - * former apparently works on all arches according to the binutils source. - */ -#define ___EXPORT_SYMBOL(sym, sec, ns)						\ -	extern typeof(sym) sym;							\ -	extern const char __kstrtab_##sym[];					\ -	extern const char __kstrtabns_##sym[];					\ -	asm("	.section \"__ksymtab_strings\",\"aMS\",%progbits,1	\n"	\ -	    "__kstrtab_" #sym ":					\n"	\ -	    "	.asciz 	\"" #sym "\"					\n"	\ -	    "__kstrtabns_" #sym ":					\n"	\ -	    "	.asciz 	\"" ns "\"					\n"	\ -	    "	.previous						\n");	\ -	__KSYMTAB_ENTRY(sym, sec) - -#endif +#define ___EXPORT_SYMBOL(sym, license, ns)		\ +	.section ".export_symbol","a"		ASM_NL	\ +	__export_symbol_##sym:			ASM_NL	\ +		.asciz license			ASM_NL	\ +		.asciz ns			ASM_NL	\ +		__EXPORT_SYMBOL_REF(sym)	ASM_NL	\ +	.previous  #if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS) @@ -104,54 +57,35 @@ struct kernel_symbol {   * be reused in other execution contexts such as the UEFI stub or the   * decompressor.   */ -#define __EXPORT_SYMBOL(sym, sec, ns) +#define __EXPORT_SYMBOL(sym, license, ns) -#elif defined(CONFIG_TRIM_UNUSED_KSYMS) +#elif defined(__GENKSYMS__) -#include <generated/autoksyms.h> +#define __EXPORT_SYMBOL(sym, license, ns)	__GENKSYMS_EXPORT_SYMBOL(sym) -/* - * For fine grained build dependencies, we want to tell the build system - * about each possible exported symbol even if they're not actually exported. - * We use a symbol pattern __ksym_marker_<symbol> that the build system filters - * from the $(NM) output (see scripts/gen_ksymdeps.sh). These symbols are - * discarded in the final link stage. - */ -#define __ksym_marker(sym)	\ -	static int __ksym_marker_##sym[0] __section(".discard.ksym") __used +#elif defined(__ASSEMBLY__) -#define __EXPORT_SYMBOL(sym, sec, ns)					\ -	__ksym_marker(sym);						\ -	__cond_export_sym(sym, sec, ns, __is_defined(__KSYM_##sym)) -#define __cond_export_sym(sym, sec, ns, conf)				\ -	___cond_export_sym(sym, sec, ns, conf) -#define ___cond_export_sym(sym, sec, ns, enabled)			\ -	__cond_export_sym_##enabled(sym, sec, ns) -#define __cond_export_sym_1(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) +#define __EXPORT_SYMBOL(sym, license, ns) \ +	___EXPORT_SYMBOL(sym, license, ns) -#ifdef __GENKSYMS__ -#define __cond_export_sym_0(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym)  #else -#define __cond_export_sym_0(sym, sec, ns) /* nothing */ -#endif -#else - -#define __EXPORT_SYMBOL(sym, sec, ns)	___EXPORT_SYMBOL(sym, sec, ns) +#define __EXPORT_SYMBOL(sym, license, ns)			\ +	extern typeof(sym) sym;					\ +	__ADDRESSABLE(sym)					\ +	asm(__stringify(___EXPORT_SYMBOL(sym, license, ns)))  #endif /* CONFIG_MODULES */  #ifdef DEFAULT_SYMBOL_NAMESPACE -#define _EXPORT_SYMBOL(sym, sec)	__EXPORT_SYMBOL(sym, sec, __stringify(DEFAULT_SYMBOL_NAMESPACE)) +#define _EXPORT_SYMBOL(sym, license)	__EXPORT_SYMBOL(sym, license, __stringify(DEFAULT_SYMBOL_NAMESPACE))  #else -#define _EXPORT_SYMBOL(sym, sec)	__EXPORT_SYMBOL(sym, sec, "") +#define _EXPORT_SYMBOL(sym, license)	__EXPORT_SYMBOL(sym, license, "")  #endif  #define EXPORT_SYMBOL(sym)		_EXPORT_SYMBOL(sym, "") -#define EXPORT_SYMBOL_GPL(sym)		_EXPORT_SYMBOL(sym, "_gpl") +#define EXPORT_SYMBOL_GPL(sym)		_EXPORT_SYMBOL(sym, "GPL")  #define EXPORT_SYMBOL_NS(sym, ns)	__EXPORT_SYMBOL(sym, "", __stringify(ns)) -#define EXPORT_SYMBOL_NS_GPL(sym, ns)	__EXPORT_SYMBOL(sym, "_gpl", __stringify(ns)) - -#endif /* !__ASSEMBLY__ */ +#define EXPORT_SYMBOL_NS_GPL(sym, ns)	__EXPORT_SYMBOL(sym, "GPL", __stringify(ns))  #endif /* _LINUX_EXPORT_H */ diff --git a/include/linux/pm.h b/include/linux/pm.h index 035d9649eba4..badad7d11f4f 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -375,23 +375,23 @@ const struct dev_pm_ops name = { \  }  #ifdef CONFIG_PM -#define _EXPORT_DEV_PM_OPS(name, sec, ns)				\ +#define _EXPORT_DEV_PM_OPS(name, license, ns)				\  	const struct dev_pm_ops name;					\ -	__EXPORT_SYMBOL(name, sec, ns);					\ +	__EXPORT_SYMBOL(name, license, ns);				\  	const struct dev_pm_ops name  #define EXPORT_PM_FN_GPL(name)		EXPORT_SYMBOL_GPL(name)  #define EXPORT_PM_FN_NS_GPL(name, ns)	EXPORT_SYMBOL_NS_GPL(name, ns)  #else -#define _EXPORT_DEV_PM_OPS(name, sec, ns)				\ +#define _EXPORT_DEV_PM_OPS(name, license, ns)				\  	static __maybe_unused const struct dev_pm_ops __static_##name  #define EXPORT_PM_FN_GPL(name)  #define EXPORT_PM_FN_NS_GPL(name, ns)  #endif  #define EXPORT_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "", "") -#define EXPORT_GPL_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "_gpl", "") +#define EXPORT_GPL_DEV_PM_OPS(name) _EXPORT_DEV_PM_OPS(name, "GPL", "")  #define EXPORT_NS_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "", #ns) -#define EXPORT_NS_GPL_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "_gpl", #ns) +#define EXPORT_NS_GPL_DEV_PM_OPS(name, ns) _EXPORT_DEV_PM_OPS(name, "GPL", #ns)  /*   * Use this if you want to use the same suspend and resume callbacks for suspend diff --git a/init/Makefile b/init/Makefile index 26de459006c4..ec557ada3c12 100644 --- a/init/Makefile +++ b/init/Makefile @@ -60,3 +60,4 @@ include/generated/utsversion.h: FORCE  $(obj)/version-timestamp.o: include/generated/utsversion.h  CFLAGS_version-timestamp.o := -include include/generated/utsversion.h  KASAN_SANITIZE_version-timestamp.o := n +GCOV_PROFILE_version-timestamp.o := n diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh index 1ef9a87511f5..6d443ea22bb7 100755 --- a/kernel/gen_kheaders.sh +++ b/kernel/gen_kheaders.sh @@ -83,12 +83,9 @@ find $cpio_dir -type f -print0 |  	xargs -0 -P8 -n1 perl -pi -e 'BEGIN {undef $/;}; s/\/\*((?!SPDX).)*?\*\///smg;'  # Create archive and try to normalize metadata for reproducibility. -# For compatibility with older versions of tar, files are fed to tar -# pre-sorted, as --sort=name might not be available. -find $cpio_dir -printf "./%P\n" | LC_ALL=C sort | \ -    tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ -    --owner=0 --group=0 --numeric-owner --no-recursion \ -    -I $XZ -cf $tarfile -C $cpio_dir/ -T - > /dev/null +tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \ +    --owner=0 --group=0 --sort=name --numeric-owner \ +    -I $XZ -cf $tarfile -C $cpio_dir/ . > /dev/null  echo $headers_md5 > kernel/kheaders.md5  echo "$this_file_md5" >> kernel/kheaders.md5 diff --git a/kernel/module/internal.h b/kernel/module/internal.h index dc7b0160c480..c8b7b4dcf782 100644 --- a/kernel/module/internal.h +++ b/kernel/module/internal.h @@ -32,6 +32,18 @@  /* Maximum number of characters written by module_flags() */  #define MODULE_FLAGS_BUF_SIZE (TAINT_FLAGS_COUNT + 4) +struct kernel_symbol { +#ifdef CONFIG_HAVE_ARCH_PREL32_RELOCATIONS +	int value_offset; +	int name_offset; +	int namespace_offset; +#else +	unsigned long value; +	const char *name; +	const char *namespace; +#endif +}; +  extern struct mutex module_mutex;  extern struct list_head modules; diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 78175231c969..6413342a03f4 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -82,7 +82,7 @@ ifdef need-builtin  targets-for-builtin += $(obj)/built-in.a  endif -targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \ +targets-for-modules := $(foreach x, o mod, \  				$(patsubst %.o, %.$x, $(filter %.o, $(obj-m))))  ifdef need-modorder @@ -101,7 +101,9 @@ else ifeq ($(KBUILD_CHECKSRC),2)  endif  ifneq ($(KBUILD_EXTRA_WARN),) -  cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $< +  cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $(KDOCFLAGS) \ +        $(if $(findstring 2, $(KBUILD_EXTRA_WARN)), -Wall) \ +        $<  endif  # Compile C sources (.c) @@ -161,7 +163,7 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag)  $@  ifdef CONFIG_MODVERSIONS  # When module versioning is enabled the following steps are executed:  # o compile a <file>.o from <file>.c -# o if <file>.o doesn't contain a __ksymtab version, i.e. does +# o if <file>.o doesn't contain a __export_symbol_*, i.e. does  #   not export symbols, it's done.  # o otherwise, we calculate symbol versions using the good old  #   genksyms on the preprocessed source and dump them into the .cmd file. @@ -169,7 +171,7 @@ ifdef CONFIG_MODVERSIONS  #   be compiled and linked to the kernel and/or modules.  gen_symversions =								\ -	if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then			\ +	if $(NM) $@ 2>/dev/null | grep -q ' __export_symbol_'; then		\  		$(call cmd_gensymtypes_$(1),$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \  			>> $(dot-target).cmd;					\  	fi @@ -215,21 +217,12 @@ is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetar  $(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 $@ -  ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)  cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi)))  endif  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) @@ -240,8 +233,6 @@ 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)  	$(call cmd,warn_shared_object) @@ -260,12 +251,6 @@ cmd_mod = printf '%s\n' $(call real-search, $*.o, .o, -objs -y -m) | \  $(obj)/%.mod: FORCE  	$(call if_changed,mod) -# List module undefined symbols -cmd_undefined_syms = $(NM) $< | sed -n 's/^  *U //p' > $@ - -$(obj)/%.usyms: $(obj)/%.o FORCE -	$(call if_changed,undefined_syms) -  quiet_cmd_cc_lst_c = MKLST   $@        cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \  		     $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \ @@ -340,9 +325,7 @@ $(obj)/%.ll: $(src)/%.rs FORCE  cmd_gensymtypes_S =                                                         \     { echo "\#include <linux/kernel.h>" ;                                    \       echo "\#include <asm/asm-prototypes.h>" ;                              \ -    $(CPP) $(a_flags) $< |                                                  \ -     grep "\<___EXPORT_SYMBOL\>" |                                          \ -     sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \ +     $(NM) $@ | sed -n 's/.* __export_symbol_\(.*\)/EXPORT_SYMBOL(\1);/p' ; } | \      $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms)  quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@ diff --git a/scripts/Makefile.clang b/scripts/Makefile.clang index 9a0aebf2ae60..6c23c6af797f 100644 --- a/scripts/Makefile.clang +++ b/scripts/Makefile.clang @@ -35,6 +35,5 @@ CLANG_FLAGS	+= -Werror=unknown-warning-option  CLANG_FLAGS	+= -Werror=ignored-optimization-argument  CLANG_FLAGS	+= -Werror=option-ignored  CLANG_FLAGS	+= -Werror=unused-command-line-argument -KBUILD_CFLAGS	+= $(CLANG_FLAGS) -KBUILD_AFLAGS	+= $(CLANG_FLAGS) +KBUILD_CPPFLAGS	+= $(CLANG_FLAGS)  export CLANG_FLAGS diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 3649900696dd..f2cb4d7ffd96 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -37,8 +37,10 @@ __clean-files   := $(wildcard $(addprefix $(obj)/, $(__clean-files)))  # ========================================================================== +# To make this rule robust against "Argument list too long" error, +# remove $(obj)/ prefix, and restore it by a shell command.  quiet_cmd_clean = CLEAN   $(obj) -      cmd_clean = rm -rf $(__clean-files) +      cmd_clean = printf '$(obj)/%s ' $(patsubst $(obj)/%,%,$(__clean-files)) | xargs rm -rf  __clean: $(subdir-ymn)  ifneq ($(strip $(__clean-files)),) diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler index 1279c5fd6e76..8fcb427405a6 100644 --- a/scripts/Makefile.compiler +++ b/scripts/Makefile.compiler @@ -32,13 +32,13 @@ try-run = $(shell set -e;		\  # Usage: aflags-y += $(call as-option,-Wa$(comma)-isa=foo,)  as-option = $(call try-run,\ -	$(CC) -Werror $(KBUILD_AFLAGS) $(1) -c -x assembler-with-cpp /dev/null -o "$$TMP",$(1),$(2)) +	$(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(1) -c -x assembler-with-cpp /dev/null -o "$$TMP",$(1),$(2))  # as-instr  # Usage: aflags-y += $(call as-instr,instr,option1,option2)  as-instr = $(call try-run,\ -	printf "%b\n" "$(1)" | $(CC) -Werror $(KBUILD_AFLAGS) -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3)) +	printf "%b\n" "$(1)" | $(CC) -Werror $(CLANG_FLAGS) $(KBUILD_AFLAGS) -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3))  # __cc-option  # Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 100a386fcd71..68d0134bdbf9 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -418,9 +418,6 @@ endif  $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE  	$(call if_changed_dep,dtb) -$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE -	$(call if_changed_dep,dtc) -  $(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE  	$(call if_changed_dep,dtc) diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 4703f652c009..fc19f67039bd 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -23,7 +23,7 @@ modname = $(notdir $(@:.mod.o=))  part-of-module = y  quiet_cmd_cc_o_c = CC [M]  $@ -      cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI), $(c_flags)) -c -o $@ $< +      cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV), $(c_flags)) -c -o $@ $<  %.mod.o: %.mod.c FORCE  	$(call if_changed_dep,cc_o_c) diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 0980c58d8afc..39472e834b63 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -47,6 +47,7 @@ modpost-args =										\  	$(if $(KBUILD_MODPOST_WARN),-w)							\  	$(if $(KBUILD_NSDEPS),-d $(MODULES_NSDEPS))					\  	$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N)	\ +	$(if $(findstring 1, $(KBUILD_EXTRA_WARN)),-W)					\  	-o $@  modpost-deps := $(MODPOST) @@ -90,6 +91,13 @@ targets += .vmlinux.objs  .vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE  	$(call if_changed,vmlinux_objs) +ifdef CONFIG_TRIM_UNUSED_KSYMS +ksym-wl := $(CONFIG_UNUSED_KSYMS_WHITELIST) +ksym-wl := $(if $(filter-out /%, $(ksym-wl)),$(srctree)/)$(ksym-wl) +modpost-args += -t $(addprefix -u , $(ksym-wl)) +modpost-deps += $(ksym-wl) +endif +  ifeq ($(wildcard vmlinux.o),)  missing-input := vmlinux.o  output-symdump := modules-only.symvers diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux index 10176dec97ea..3cd6ca15f390 100644 --- a/scripts/Makefile.vmlinux +++ b/scripts/Makefile.vmlinux @@ -19,6 +19,7 @@ quiet_cmd_cc_o_c = CC      $@  ifdef CONFIG_MODULES  KASAN_SANITIZE_.vmlinux.export.o := n +GCOV_PROFILE_.vmlinux.export.o := n  targets += .vmlinux.export.o  vmlinux: .vmlinux.export.o  endif diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh deleted file mode 100755 index f1b5ac818411..000000000000 --- a/scripts/adjust_autoksyms.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0-only - -# Script to update include/generated/autoksyms.h and dependency files -# -# Copyright:	(C) 2016  Linaro Limited -# Created by:	Nicolas Pitre, January 2016 -# - -# Update the include/generated/autoksyms.h file. -# -# For each symbol being added or removed, the corresponding dependency -# file's timestamp is updated to force a rebuild of the affected source -# file. All arguments passed to this script are assumed to be a command -# to be exec'd to trigger a rebuild of those files. - -set -e - -cur_ksyms_file="include/generated/autoksyms.h" -new_ksyms_file="include/generated/autoksyms.h.tmpnew" - -info() { -	if [ "$quiet" != "silent_" ]; then -		printf "  %-7s %s\n" "$1" "$2" -	fi -} - -info "CHK" "$cur_ksyms_file" - -# Use "make V=1" to debug this script. -case "$KBUILD_VERBOSE" in -*1*) -	set -x -	;; -esac - -# Generate a new symbol list file -$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh --modorder "$new_ksyms_file" - -# Extract changes between old and new list and touch corresponding -# dependency files. -changed=$( -count=0 -sort "$cur_ksyms_file" "$new_ksyms_file" | uniq -u | -sed -n 's/^#define __KSYM_\(.*\) 1/\1/p' | -while read sympath; do -	if [ -z "$sympath" ]; then continue; fi -	depfile="include/ksym/${sympath}" -	mkdir -p "$(dirname "$depfile")" -	touch "$depfile" -	# Filesystems with coarse time precision may create timestamps -	# equal to the one from a file that was very recently built and that -	# needs to be rebuild. Let's guard against that by making sure our -	# dep files are always newer than the first file we created here. -	while [ ! "$depfile" -nt "$new_ksyms_file" ]; do -		touch "$depfile" -	done -	echo $((count += 1)) -done | tail -1 ) -changed=${changed:-0} - -if [ $changed -gt 0 ]; then -	# Replace the old list with tne new one -	old=$(grep -c "^#define __KSYM_" "$cur_ksyms_file" || true) -	new=$(grep -c "^#define __KSYM_" "$new_ksyms_file" || true) -	info "KSYMS" "symbols: before=$old, after=$new, changed=$changed" -	info "UPD" "$cur_ksyms_file" -	mv -f "$new_ksyms_file" "$cur_ksyms_file" -	# Then trigger a rebuild of affected source files -	exec $@ -else -	rm -f "$new_ksyms_file" -fi diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index fa562806c2be..84b6efa849f4 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -246,8 +246,7 @@ static void *read_file(const char *filename)  /* Ignore certain dependencies */  static int is_ignored_file(const char *s, int len)  { -	return str_ends_with(s, len, "include/generated/autoconf.h") || -	       str_ends_with(s, len, "include/generated/autoksyms.h"); +	return str_ends_with(s, len, "include/generated/autoconf.h");  }  /* Do not parse these files */ diff --git a/scripts/check-local-export b/scripts/check-local-export deleted file mode 100755 index f90b5a9c67b3..000000000000 --- a/scripts/check-local-export +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0-only -# -# Copyright (C) 2022 Masahiro Yamada <masahiroy@kernel.org> -# Copyright (C) 2022 Owen Rafferty <owen@owenrafferty.com> -# -# Exit with error if a local exported symbol is found. -# EXPORT_SYMBOL should be used for global symbols. - -set -e -pid=$$ - -# 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. -# -# TODO: -# 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 simpler: -#   { ${NM} --quiet ${1} || kill 0; } | - -{ ${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; kill $pid; } } | -${AWK} -v "file=${1}" ' -BEGIN { -	i = 0 -} - -# 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" -!length($3) { -	next -} - -# save (name, type) in the associative array -{ symbol_types[$3]=$2 } - -# append the exported symbol to the array -($3 ~ /^__ksymtab_/) { -	export_symbols[i] = $3 -	sub(/^__ksymtab_/, "", export_symbols[i]) -	i++ -} - -END { -	exit_code = 0 -	for (j = 0; j < i; ++j) { -		name = export_symbols[j] -		# nm(3) says "If lowercase, the symbol is usually local" -		if (symbol_types[name] ~ /[a-z]/) { -			printf "%s: error: local symbol %s was exported\n", -				file, name | "cat 1>&2" -			exit_code = 1 -		} -	} - -	exit exit_code -}' - -exit $? diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh deleted file mode 100755 index 12bcfae940ee..000000000000 --- a/scripts/gen_autoksyms.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0-only - -# Create an autoksyms.h header file from the list of all module's needed symbols -# as recorded in *.usyms files and the user-provided symbol whitelist. - -set -e - -# Use "make V=1" to debug this script. -case "$KBUILD_VERBOSE" in -*1*) -	set -x -	;; -esac - -read_modorder= - -if [ "$1" = --modorder ]; then -	shift -	read_modorder=1 -fi - -output_file="$1" - -needed_symbols= - -# Special case for modversions (see modpost.c) -if grep -q "^CONFIG_MODVERSIONS=y$" include/config/auto.conf; then -	needed_symbols="$needed_symbols module_layout" -fi - -ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf) -if [ -n "$ksym_wl" ]; then -	[ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" -	if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then -		echo "ERROR: '$ksym_wl' whitelist file not found" >&2 -		exit 1 -	fi -fi - -# Generate a new ksym list file with symbols needed by the current -# set of modules. -cat > "$output_file" << EOT -/* - * Automatically generated file; DO NOT EDIT. - */ - -EOT - -{ -	[ -n "${read_modorder}" ] && sed 's/o$/usyms/' modules.order | xargs cat -	echo "$needed_symbols" -	[ -n "$ksym_wl" ] && cat "$ksym_wl" -} | sed -e 's/ /\n/g' | sed -n -e '/^$/!p' | -# Remove the dot prefix for ppc64; symbol names with a dot (.) hold entry -# point addresses. -sed -e 's/^\.//' | -sort -u | -# Ignore __this_module. It's not an exported symbol, and will be resolved -# when the final .ko's are linked. -grep -v '^__this_module$' | -sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$output_file" diff --git a/scripts/gen_ksymdeps.sh b/scripts/gen_ksymdeps.sh deleted file mode 100755 index 8ee533f33659..000000000000 --- a/scripts/gen_ksymdeps.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -set -e - -# List of exported symbols -# -# If the object has no symbol, $NM warns 'no symbols'. -# Suppress the stderr. -# TODO: -#   Use -q instead of 2>/dev/null when we upgrade the minimum version of -#   binutils to 2.37, llvm to 13.0.0. -ksyms=$($NM $1 2>/dev/null | sed -n 's/.*__ksym_marker_\(.*\)/\1/p') - -if [ -z "$ksyms" ]; then -	exit 0 -fi - -echo -echo "ksymdeps_$1 := \\" - -for s in $ksyms -do -	printf '    $(wildcard include/ksym/%s) \\\n' "$s" -done - -echo -echo "$1: \$(ksymdeps_$1)" -echo -echo "\$(ksymdeps_$1):" diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 0d2db41177b2..d387c9381650 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -19,6 +19,7 @@   *   */ +#include <errno.h>  #include <getopt.h>  #include <stdbool.h>  #include <stdio.h> @@ -29,24 +30,8 @@  #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) -#define _stringify_1(x)	#x -#define _stringify(x)	_stringify_1(x) -  #define KSYM_NAME_LEN		512 -/* - * A substantially bigger size than the current maximum. - * - * It cannot be defined as an expression because it gets stringified - * for the fscanf() format string. Therefore, a _Static_assert() is - * used instead to maintain the relationship with KSYM_NAME_LEN. - */ -#define KSYM_NAME_LEN_BUFFER	2048 -_Static_assert( -	KSYM_NAME_LEN_BUFFER == KSYM_NAME_LEN * 4, -	"Please keep KSYM_NAME_LEN_BUFFER in sync with KSYM_NAME_LEN" -); -  struct sym_entry {  	unsigned long long addr;  	unsigned int len; @@ -136,24 +121,40 @@ static void check_symbol_range(const char *sym, unsigned long long addr,  	}  } -static struct sym_entry *read_symbol(FILE *in) +static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len)  { -	char name[KSYM_NAME_LEN_BUFFER+1], type; +	char *name, type, *p;  	unsigned long long addr; -	unsigned int len; +	size_t len; +	ssize_t readlen;  	struct sym_entry *sym; -	int rc; -	rc = fscanf(in, "%llx %c %" _stringify(KSYM_NAME_LEN_BUFFER) "s\n", &addr, &type, name); -	if (rc != 3) { -		if (rc != EOF && fgets(name, ARRAY_SIZE(name), in) == NULL) -			fprintf(stderr, "Read error or end of file.\n"); +	readlen = getline(buf, buf_len, in); +	if (readlen < 0) { +		if (errno) { +			perror("read_symbol"); +			exit(EXIT_FAILURE); +		}  		return NULL;  	} -	if (strlen(name) >= KSYM_NAME_LEN) { + +	if ((*buf)[readlen - 1] == '\n') +		(*buf)[readlen - 1] = 0; + +	addr = strtoull(*buf, &p, 16); + +	if (*buf == p || *p++ != ' ' || !isascii((type = *p++)) || *p++ != ' ') { +		fprintf(stderr, "line format error\n"); +		exit(EXIT_FAILURE); +	} + +	name = p; +	len = strlen(name); + +	if (len >= KSYM_NAME_LEN) {  		fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n"  				"Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n", -			name, strlen(name), KSYM_NAME_LEN); +			name, len, KSYM_NAME_LEN);  		return NULL;  	} @@ -169,8 +170,7 @@ static struct sym_entry *read_symbol(FILE *in)  	/* include the type field in the symbol name, so that it gets  	 * compressed together */ - -	len = strlen(name) + 1; +	len++;  	sym = malloc(sizeof(*sym) + len + 1);  	if (!sym) { @@ -257,6 +257,8 @@ static void read_map(const char *in)  {  	FILE *fp;  	struct sym_entry *sym; +	char *buf = NULL; +	size_t buflen = 0;  	fp = fopen(in, "r");  	if (!fp) { @@ -265,7 +267,7 @@ static void read_map(const char *in)  	}  	while (!feof(fp)) { -		sym = read_symbol(fp); +		sym = read_symbol(fp, &buf, &buflen);  		if (!sym)  			continue; @@ -284,6 +286,7 @@ static void read_map(const char *in)  		table[table_cnt++] = sym;  	} +	free(buf);  	fclose(fp);  } @@ -806,7 +809,7 @@ static void record_relative_base(void)  int main(int argc, char **argv)  {  	while (1) { -		static struct option long_options[] = { +		static const struct option long_options[] = {  			{"all-symbols",     no_argument, &all_symbols,     1},  			{"absolute-percpu", no_argument, &absolute_percpu, 1},  			{"base-relative",   no_argument, &base_relative,   1}, diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 3387ad7508f7..d51cd7ac15d2 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -317,7 +317,7 @@ foreach my $makefile (@makefiles) {  	$_ = convert_vars($_, %make_vars);  	# collect objects after obj-$(CONFIG_FOO_BAR) -	if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) { +	if (/obj-\$[({](CONFIG_[^})]*)[)}]\s*[+:]?=\s*(.*)/) {  	    $var = $1;  	    $objs = $2; diff --git a/scripts/kernel-doc b/scripts/kernel-doc index eb70c1fd4e86..8c392fb75049 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -23,7 +23,7 @@ kernel-doc - Print formatted kernel documentation to stdout  =head1 SYNOPSIS - kernel-doc [-h] [-v] [-Werror] + kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-description] [-Wcontents-before-sections]     [ -man |       -rst [-sphinx-version VERSION] [-enable-lineno] |       -none @@ -133,6 +133,9 @@ my $dohighlight = "";  my $verbose = 0;  my $Werror = 0; +my $Wreturn = 0; +my $Wshort_desc = 0; +my $Wcontents_before_sections = 0;  my $output_mode = "rst";  my $output_preformatted = 0;  my $no_doc_sections = 0; @@ -187,9 +190,14 @@ if (defined($ENV{'KCFLAGS'})) {  	}  } +# reading this variable is for backwards compat just in case +# someone was calling it with the variable from outside the +# kernel's build system  if (defined($ENV{'KDOC_WERROR'})) {  	$Werror = "$ENV{'KDOC_WERROR'}";  } +# other environment variables are converted to command-line +# arguments in cmd_checkdoc in the build system  # Generated docbook code is inserted in a template at a point where  # docbook v3.1 requires a non-zero sequence of RefEntry's; see: @@ -318,6 +326,16 @@ while ($ARGV[0] =~ m/^--?(.*)/) {  	$verbose = 1;      } elsif ($cmd eq "Werror") {  	$Werror = 1; +    } elsif ($cmd eq "Wreturn") { +	$Wreturn = 1; +    } elsif ($cmd eq "Wshort-desc") { +	$Wshort_desc = 1; +    } elsif ($cmd eq "Wcontents-before-sections") { +	$Wcontents_before_sections = 1; +    } elsif ($cmd eq "Wall") { +        $Wreturn = 1; +        $Wshort_desc = 1; +        $Wcontents_before_sections = 1;      } elsif (($cmd eq "h") || ($cmd eq "help")) {  		pod2usage(-exitval => 0, -verbose => 2);      } elsif ($cmd eq 'no-doc-sections') { @@ -1748,9 +1766,9 @@ sub dump_function($$) {      # This check emits a lot of warnings at the moment, because many      # functions don't have a 'Return' doc section. So until the number      # of warnings goes sufficiently down, the check is only performed in -    # verbose mode. +    # -Wreturn mode.      # TODO: always perform the check. -    if ($verbose && !$noret) { +    if ($Wreturn && !$noret) {  	    check_return_section($file, $declaration_name, $return_type);      } @@ -2054,7 +2072,7 @@ sub process_name($$) {  	    $state = STATE_NORMAL;  	} -	if (($declaration_purpose eq "") && $verbose) { +	if (($declaration_purpose eq "") && $Wshort_desc) {  	    emit_warning("${file}:$.", "missing initial short description on line:\n$_");  	} @@ -2103,7 +2121,7 @@ sub process_body($$) {  	}  	if (($contents ne "") && ($contents ne "\n")) { -	    if (!$in_doc_sect && $verbose) { +	    if (!$in_doc_sect && $Wcontents_before_sections) {  		emit_warning("${file}:$.", "contents before sections\n");  	    }  	    dump_section($file, $section, $contents); diff --git a/scripts/mksysmap b/scripts/mksysmap index cb3b1fff3eee..9ba1c9da0a40 100755 --- a/scripts/mksysmap +++ b/scripts/mksysmap @@ -32,7 +32,7 @@ ${NM} -n ${1} | sed >${2} -e "  #  (do not forget a space before each pattern)  # local symbols for ARM, MIPS, etc. -/ \$/d +/ \\$/d  # local labels, .LBB, .Ltmpxxx, .L__unnamed_xx, .LASANPC, etc.  / \.L/d @@ -40,8 +40,12 @@ ${NM} -n ${1} | sed >${2} -e "  # arm64 EFI stub namespace  / __efistub_/d +# arm64 local symbols in PIE namespace +/ __pi_\\$/d +/ __pi_\.L/d +  # arm64 local symbols in non-VHE KVM namespace -/ __kvm_nvhe_\$/d +/ __kvm_nvhe_\\$/d  / __kvm_nvhe_\.L/d  # arm64 lld @@ -58,6 +62,8 @@ ${NM} -n ${1} | sed >${2} -e "  # CFI type identifiers  / __kcfi_typeid_/d +/ __kvm_nvhe___kcfi_typeid_/d +/ __pi___kcfi_typeid_/d  # CRC from modversions  / __crc_/d diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c12150f96b88..b29b29707f10 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -35,6 +35,9 @@ static bool warn_unresolved;  static int sec_mismatch_count;  static bool sec_mismatch_warn_only = true; +/* Trim EXPORT_SYMBOLs that are unused by in-tree modules */ +static bool trim_unused_exports; +  /* ignore missing files */  static bool ignore_missing_files;  /* If set to 1, only warn (instead of error) about missing ns imports */ @@ -42,6 +45,8 @@ static bool allow_missing_ns_imports;  static bool error_occurred; +static bool extra_warn; +  /*   * Cut off the warnings when there are too many. This typically occurs when   * vmlinux is missing. ('make modules' without building vmlinux.) @@ -215,7 +220,9 @@ struct symbol {  	unsigned int crc;  	bool crc_valid;  	bool weak; +	bool is_func;  	bool is_gpl_only;	/* exported by EXPORT_SYMBOL_GPL */ +	bool used;		/* there exists a user of this symbol */  	char name[];  }; @@ -297,6 +304,13 @@ static bool contains_namespace(struct list_head *head, const char *namespace)  {  	struct namespace_list *list; +	/* +	 * The default namespace is null string "", which is always implicitly +	 * contained. +	 */ +	if (!namespace[0]) +		return true; +  	list_for_each_entry(list, head, list) {  		if (!strcmp(list->namespace, namespace))  			return true; @@ -352,26 +366,8 @@ static const char *sec_name(const struct elf_info *info, unsigned int secindex)  #define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) -static void sym_update_namespace(const char *symname, const char *namespace) -{ -	struct symbol *s = find_symbol(symname); - -	/* -	 * That symbol should have been created earlier and thus this is -	 * actually an assertion. -	 */ -	if (!s) { -		error("Could not update namespace(%s) for symbol %s\n", -		      namespace, symname); -		return; -	} - -	free(s->namespace); -	s->namespace = namespace[0] ? NOFAIL(strdup(namespace)) : NULL; -} -  static struct symbol *sym_add_exported(const char *name, struct module *mod, -				       bool gpl_only) +				       bool gpl_only, const char *namespace)  {  	struct symbol *s = find_symbol(name); @@ -384,6 +380,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod,  	s = alloc_symbol(name);  	s->module = mod;  	s->is_gpl_only = gpl_only; +	s->namespace = NOFAIL(strdup(namespace));  	list_add_tail(&s->list, &mod->exported_symbols);  	hash_add_symbol(s); @@ -531,6 +528,8 @@ static int parse_elf(struct elf_info *info, const char *filename)  				fatal("%s has NOBITS .modinfo\n", filename);  			info->modinfo = (void *)hdr + sechdrs[i].sh_offset;  			info->modinfo_len = sechdrs[i].sh_size; +		} else if (!strcmp(secname, ".export_symbol")) { +			info->export_symbol_secndx = i;  		}  		if (sechdrs[i].sh_type == SHT_SYMTAB) { @@ -653,18 +652,6 @@ static void handle_symbol(struct module *mod, struct elf_info *info,  				   ELF_ST_BIND(sym->st_info) == STB_WEAK);  		break;  	default: -		/* All exported symbols */ -		if (strstarts(symname, "__ksymtab_")) { -			const char *name, *secname; - -			name = symname + strlen("__ksymtab_"); -			secname = sec_name(info, get_secindex(info, sym)); - -			if (strstarts(secname, "___ksymtab_gpl+")) -				sym_add_exported(name, mod, true); -			else if (strstarts(secname, "___ksymtab+")) -				sym_add_exported(name, mod, false); -		}  		if (strcmp(symname, "init_module") == 0)  			mod->has_init = true;  		if (strcmp(symname, "cleanup_module") == 0) @@ -838,34 +825,14 @@ static void check_section(const char *modname, struct elf_info *elf,  #define ALL_TEXT_SECTIONS  ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \  		TEXT_SECTIONS, OTHER_TEXT_SECTIONS -/* init data sections */ -static const char *const init_data_sections[] = -	{ ALL_INIT_DATA_SECTIONS, NULL }; - -/* all init sections */ -static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL }; - -/* all text sections */ -static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL }; - -/* data section */ -static const char *const data_sections[] = { DATA_SECTIONS, NULL }; - -static const char *const head_sections[] = { ".head.text*", NULL }; -static const char *const linker_symbols[] = -	{ "__init_begin", "_sinittext", "_einittext", NULL }; -static const char *const optim_symbols[] = { "*.constprop.*", NULL }; -  enum mismatch {  	TEXT_TO_ANY_INIT,  	DATA_TO_ANY_INIT, -	TEXT_TO_ANY_EXIT, -	DATA_TO_ANY_EXIT, +	TEXTDATA_TO_ANY_EXIT,  	XXXINIT_TO_SOME_INIT,  	XXXEXIT_TO_SOME_EXIT,  	ANY_INIT_TO_ANY_EXIT,  	ANY_EXIT_TO_ANY_INIT, -	EXPORT_TO_INIT_EXIT,  	EXTABLE_TO_NON_TEXT,  }; @@ -881,27 +848,14 @@ enum mismatch {   * targeting sections in this array (white-list).  Can be empty.   *   * @mismatch: Type of mismatch. - * - * @handler: Specific handler to call when a match is found.  If NULL, - * default_mismatch_handler() will be called. - *   */  struct sectioncheck {  	const char *fromsec[20];  	const char *bad_tosec[20];  	const char *good_tosec[20];  	enum mismatch mismatch; -	void (*handler)(const char *modname, struct elf_info *elf, -			const struct sectioncheck* const mismatch, -			Elf_Rela *r, Elf_Sym *sym, const char *fromsec); -  }; -static void extable_mismatch_handler(const char *modname, struct elf_info *elf, -				     const struct sectioncheck* const mismatch, -				     Elf_Rela *r, Elf_Sym *sym, -				     const char *fromsec); -  static const struct sectioncheck sectioncheck[] = {  /* Do not reference init/exit code/data from   * normal code and data @@ -913,23 +867,13 @@ static const struct sectioncheck sectioncheck[] = {  },  {  	.fromsec = { DATA_SECTIONS, NULL }, -	.bad_tosec = { ALL_XXXINIT_SECTIONS, NULL }, +	.bad_tosec = { ALL_XXXINIT_SECTIONS, INIT_SECTIONS, NULL },  	.mismatch = DATA_TO_ANY_INIT,  },  { -	.fromsec = { DATA_SECTIONS, NULL }, -	.bad_tosec = { INIT_SECTIONS, NULL }, -	.mismatch = DATA_TO_ANY_INIT, -}, -{ -	.fromsec = { TEXT_SECTIONS, NULL }, +	.fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL },  	.bad_tosec = { ALL_EXIT_SECTIONS, NULL }, -	.mismatch = TEXT_TO_ANY_EXIT, -}, -{ -	.fromsec = { DATA_SECTIONS, NULL }, -	.bad_tosec = { ALL_EXIT_SECTIONS, NULL }, -	.mismatch = DATA_TO_ANY_EXIT, +	.mismatch = TEXTDATA_TO_ANY_EXIT,  },  /* Do not reference init code/data from meminit code/data */  { @@ -960,12 +904,6 @@ static const struct sectioncheck sectioncheck[] = {  	.bad_tosec = { INIT_SECTIONS, NULL },  	.mismatch = ANY_INIT_TO_ANY_EXIT,  }, -/* Do not export init/exit functions or data */ -{ -	.fromsec = { "___ksymtab*", NULL }, -	.bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, -	.mismatch = EXPORT_TO_INIT_EXIT, -},  {  	.fromsec = { "__ex_table", NULL },  	/* If you're adding any new black-listed sections in here, consider @@ -974,7 +912,6 @@ static const struct sectioncheck sectioncheck[] = {  	.bad_tosec = { ".altinstr_replacement", NULL },  	.good_tosec = {ALL_TEXT_SECTIONS , NULL},  	.mismatch = EXTABLE_TO_NON_TEXT, -	.handler = extable_mismatch_handler,  }  }; @@ -1048,28 +985,19 @@ static const struct sectioncheck *section_mismatch(   *   fromsec = text section   *   refsymname = *.constprop.*   * - * Pattern 6: - *   Hide section mismatch warnings for ELF local symbols.  The goal - *   is to eliminate false positive modpost warnings caused by - *   compiler-generated ELF local symbol names such as ".LANCHOR1". - *   Autogenerated symbol names bypass modpost's "Pattern 2" - *   whitelisting, which relies on pattern-matching against symbol - *   names to work.  (One situation where gcc can autogenerate ELF - *   local symbols is when "-fsection-anchors" is used.)   **/ -static int secref_whitelist(const struct sectioncheck *mismatch, -			    const char *fromsec, const char *fromsym, +static int secref_whitelist(const char *fromsec, const char *fromsym,  			    const char *tosec, const char *tosym)  {  	/* Check for pattern 1 */ -	if (match(tosec, init_data_sections) && -	    match(fromsec, data_sections) && +	if (match(tosec, PATTERNS(ALL_INIT_DATA_SECTIONS)) && +	    match(fromsec, PATTERNS(DATA_SECTIONS)) &&  	    strstarts(fromsym, "__param"))  		return 0;  	/* Check for pattern 1a */  	if (strcmp(tosec, ".init.text") == 0 && -	    match(fromsec, data_sections) && +	    match(fromsec, PATTERNS(DATA_SECTIONS)) &&  	    strstarts(fromsym, "__param_ops_"))  		return 0; @@ -1092,22 +1020,18 @@ static int secref_whitelist(const struct sectioncheck *mismatch,  		return 0;  	/* Check for pattern 3 */ -	if (match(fromsec, head_sections) && -	    match(tosec, init_sections)) +	if (strstarts(fromsec, ".head.text") && +	    match(tosec, PATTERNS(ALL_INIT_SECTIONS)))  		return 0;  	/* Check for pattern 4 */ -	if (match(tosym, linker_symbols)) +	if (match(tosym, PATTERNS("__init_begin", "_sinittext", "_einittext")))  		return 0;  	/* Check for pattern 5 */ -	if (match(fromsec, text_sections) && -	    match(tosec, init_sections) && -	    match(fromsym, optim_symbols)) -		return 0; - -	/* Check for pattern 6 */ -	if (strstarts(fromsym, ".L")) +	if (match(fromsec, PATTERNS(ALL_TEXT_SECTIONS)) && +	    match(tosec, PATTERNS(ALL_INIT_SECTIONS)) && +	    match(fromsym, PATTERNS("*.constprop.*")))  		return 0;  	return 1; @@ -1131,303 +1055,210 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym)  	return !is_mapping_symbol(name);  } -/** - * Find symbol based on relocation record info. - * In some cases the symbol supplied is a valid symbol so - * return refsym. If st_name != 0 we assume this is a valid symbol. - * In other cases the symbol needs to be looked up in the symbol table - * based on section and address. - *  **/ -static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, -				Elf_Sym *relsym) +/* Look up the nearest symbol based on the section and the address */ +static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr, +				 unsigned int secndx, bool allow_negative, +				 Elf_Addr min_distance)  {  	Elf_Sym *sym;  	Elf_Sym *near = NULL; -	Elf64_Sword distance = 20; -	Elf64_Sword d; -	unsigned int relsym_secindex; +	Elf_Addr sym_addr, distance; +	bool is_arm = (elf->hdr->e_machine == EM_ARM); -	if (relsym->st_name != 0) -		return relsym; - -	relsym_secindex = get_secindex(elf, relsym);  	for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { -		if (get_secindex(elf, sym) != relsym_secindex) -			continue; -		if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) +		if (get_secindex(elf, sym) != secndx)  			continue;  		if (!is_valid_name(elf, sym))  			continue; -		if (sym->st_value == addr) -			return sym; -		/* Find a symbol nearby - addr are maybe negative */ -		d = sym->st_value - addr; -		if (d < 0) -			d = addr - sym->st_value; -		if (d < distance) { -			distance = d; -			near = sym; -		} -	} -	/* We need a close match */ -	if (distance < 20) -		return near; -	else -		return NULL; -} -/* - * Find symbols before or equal addr and after addr - in the section sec. - * If we find two symbols with equal offset prefer one with a valid name. - * The ELF format may have a better way to detect what type of symbol - * it is, but this works for now. - **/ -static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, -				 const char *sec) -{ -	Elf_Sym *sym; -	Elf_Sym *near = NULL; -	Elf_Addr distance = ~0; +		sym_addr = sym->st_value; -	for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { -		const char *symsec; +		/* +		 * For ARM Thumb instruction, the bit 0 of st_value is set +		 * if the symbol is STT_FUNC type. Mask it to get the address. +		 */ +		if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC) +			 sym_addr &= ~1; -		if (is_shndx_special(sym->st_shndx)) -			continue; -		symsec = sec_name(elf, get_secindex(elf, sym)); -		if (strcmp(symsec, sec) != 0) -			continue; -		if (!is_valid_name(elf, sym)) +		if (addr >= sym_addr) +			distance = addr - sym_addr; +		else if (allow_negative) +			distance = sym_addr - addr; +		else  			continue; -		if (sym->st_value <= addr && addr - sym->st_value <= distance) { -			distance = addr - sym->st_value; + +		if (distance <= min_distance) { +			min_distance = distance;  			near = sym;  		} + +		if (min_distance == 0) +			break;  	}  	return near;  } -static int is_function(Elf_Sym *sym) +static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr, +			     unsigned int secndx)  { -	if (sym) -		return ELF_ST_TYPE(sym->st_info) == STT_FUNC; -	else -		return -1; +	return find_nearest_sym(elf, addr, secndx, false, ~0);  } -static inline void get_pretty_name(int is_func, const char** name, const char** name_p) +static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym)  { -	switch (is_func) { -	case 0:	*name = "variable"; *name_p = ""; break; -	case 1:	*name = "function"; *name_p = "()"; break; -	default: *name = "(unknown reference)"; *name_p = ""; break; -	} +	/* If the supplied symbol has a valid name, return it */ +	if (is_valid_name(elf, sym)) +		return sym; + +	/* +	 * Strive to find a better symbol name, but the resulting name may not +	 * match the symbol referenced in the original code. +	 */ +	return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20);  } -/* - * Print a warning about a section mismatch. - * Try to find symbols near it so user can find it. - * Check whitelist before warning - it may be a false positive. - */ -static void report_sec_mismatch(const char *modname, -				const struct sectioncheck *mismatch, -				const char *fromsec, -				const char *fromsym, -				const char *tosec, const char *tosym) +static bool is_executable_section(struct elf_info *elf, unsigned int secndx)  { -	sec_mismatch_count++; +	if (secndx >= elf->num_sections) +		return false; -	switch (mismatch->mismatch) { -	case TEXT_TO_ANY_INIT: -	case DATA_TO_ANY_INIT: -	case TEXT_TO_ANY_EXIT: -	case DATA_TO_ANY_EXIT: -	case XXXINIT_TO_SOME_INIT: -	case XXXEXIT_TO_SOME_EXIT: -	case ANY_INIT_TO_ANY_EXIT: -	case ANY_EXIT_TO_ANY_INIT: -		warn("%s: section mismatch in reference: %s (section: %s) -> %s (section: %s)\n", -		     modname, fromsym, fromsec, tosym, tosec); -		break; -	case EXPORT_TO_INIT_EXIT: -		warn("%s: EXPORT_SYMBOL used for init/exit symbol: %s (section: %s)\n", -		     modname, tosym, tosec); -		break; -	case EXTABLE_TO_NON_TEXT: -		fatal("There's a special handler for this mismatch type, we should never get here.\n"); -		break; -	} +	return (elf->sechdrs[secndx].sh_flags & SHF_EXECINSTR) != 0;  }  static void default_mismatch_handler(const char *modname, struct elf_info *elf,  				     const struct sectioncheck* const mismatch, -				     Elf_Rela *r, Elf_Sym *sym, const char *fromsec) +				     Elf_Sym *tsym, +				     unsigned int fsecndx, const char *fromsec, Elf_Addr faddr, +				     const char *tosec, Elf_Addr taddr)  { -	const char *tosec; -	Elf_Sym *to;  	Elf_Sym *from;  	const char *tosym;  	const char *fromsym; -	from = find_elf_symbol2(elf, r->r_offset, fromsec); +	from = find_fromsym(elf, faddr, fsecndx);  	fromsym = sym_name(elf, from); -	tosec = sec_name(elf, get_secindex(elf, sym)); -	to = find_elf_symbol(elf, r->r_addend, sym); -	tosym = sym_name(elf, to); +	tsym = find_tosym(elf, taddr, tsym); +	tosym = sym_name(elf, tsym);  	/* check whitelist - we may ignore it */ -	if (secref_whitelist(mismatch, -			     fromsec, fromsym, tosec, tosym)) { -		report_sec_mismatch(modname, mismatch, -				    fromsec, fromsym, tosec, tosym); -	} -} +	if (!secref_whitelist(fromsec, fromsym, tosec, tosym)) +		return; -static int is_executable_section(struct elf_info* elf, unsigned int section_index) -{ -	if (section_index > elf->num_sections) -		fatal("section_index is outside elf->num_sections!\n"); +	sec_mismatch_count++; -	return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR); -} +	warn("%s: section mismatch in reference: %s+0x%x (section: %s) -> %s (section: %s)\n", +	     modname, fromsym, (unsigned int)(faddr - from->st_value), fromsec, tosym, tosec); -/* - * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size() - * to know the sizeof(struct exception_table_entry) for the target architecture. - */ -static unsigned int extable_entry_size = 0; -static void find_extable_entry_size(const char* const sec, const Elf_Rela* r) -{ -	/* -	 * If we're currently checking the second relocation within __ex_table, -	 * that relocation offset tells us the offsetof(struct -	 * exception_table_entry, fixup) which is equal to sizeof(struct -	 * exception_table_entry) divided by two.  We use that to our advantage -	 * since there's no portable way to get that size as every architecture -	 * seems to go with different sized types.  Not pretty but better than -	 * hard-coding the size for every architecture.. -	 */ -	if (!extable_entry_size) -		extable_entry_size = r->r_offset * 2; +	if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) { +		if (match(tosec, mismatch->bad_tosec)) +			fatal("The relocation at %s+0x%lx references\n" +			      "section \"%s\" which is black-listed.\n" +			      "Something is seriously wrong and should be fixed.\n" +			      "You might get more information about where this is\n" +			      "coming from by using scripts/check_extable.sh %s\n", +			      fromsec, (long)faddr, tosec, modname); +		else if (is_executable_section(elf, get_secindex(elf, tsym))) +			warn("The relocation at %s+0x%lx references\n" +			     "section \"%s\" which is not in the list of\n" +			     "authorized sections.  If you're adding a new section\n" +			     "and/or if this reference is valid, add \"%s\" to the\n" +			     "list of authorized sections to jump to on fault.\n" +			     "This can be achieved by adding \"%s\" to\n" +			     "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n", +			     fromsec, (long)faddr, tosec, tosec, tosec); +		else +			error("%s+0x%lx references non-executable section '%s'\n", +			      fromsec, (long)faddr, tosec); +	}  } -static inline bool is_extable_fault_address(Elf_Rela *r) +static void check_export_symbol(struct module *mod, struct elf_info *elf, +				Elf_Addr faddr, const char *secname, +				Elf_Sym *sym)  { -	/* -	 * extable_entry_size is only discovered after we've handled the -	 * _second_ relocation in __ex_table, so only abort when we're not -	 * handling the first reloc and extable_entry_size is zero. -	 */ -	if (r->r_offset && extable_entry_size == 0) -		fatal("extable_entry size hasn't been discovered!\n"); - -	return ((r->r_offset == 0) || -		(r->r_offset % extable_entry_size == 0)); -} - -#define is_second_extable_reloc(Start, Cur, Sec)			\ -	(((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0)) +	static const char *prefix = "__export_symbol_"; +	const char *label_name, *name, *data; +	Elf_Sym *label; +	struct symbol *s; +	bool is_gpl; -static void report_extable_warnings(const char* modname, struct elf_info* elf, -				    const struct sectioncheck* const mismatch, -				    Elf_Rela* r, Elf_Sym* sym, -				    const char* fromsec, const char* tosec) -{ -	Elf_Sym* fromsym = find_elf_symbol2(elf, r->r_offset, fromsec); -	const char* fromsym_name = sym_name(elf, fromsym); -	Elf_Sym* tosym = find_elf_symbol(elf, r->r_addend, sym); -	const char* tosym_name = sym_name(elf, tosym); -	const char* from_pretty_name; -	const char* from_pretty_name_p; -	const char* to_pretty_name; -	const char* to_pretty_name_p; +	label = find_fromsym(elf, faddr, elf->export_symbol_secndx); +	label_name = sym_name(elf, label); -	get_pretty_name(is_function(fromsym), -			&from_pretty_name, &from_pretty_name_p); -	get_pretty_name(is_function(tosym), -			&to_pretty_name, &to_pretty_name_p); +	if (!strstarts(label_name, prefix)) { +		error("%s: .export_symbol section contains strange symbol '%s'\n", +		      mod->name, label_name); +		return; +	} -	warn("%s(%s+0x%lx): Section mismatch in reference from the %s %s%s to the %s %s:%s%s\n", -	     modname, fromsec, (long)r->r_offset, from_pretty_name, -	     fromsym_name, from_pretty_name_p, -	     to_pretty_name, tosec, tosym_name, to_pretty_name_p); +	if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && +	    ELF_ST_BIND(sym->st_info) != STB_WEAK) { +		error("%s: local symbol '%s' was exported\n", mod->name, +		      label_name + strlen(prefix)); +		return; +	} -	if (!match(tosec, mismatch->bad_tosec) && -	    is_executable_section(elf, get_secindex(elf, sym))) -		fprintf(stderr, -			"The relocation at %s+0x%lx references\n" -			"section \"%s\" which is not in the list of\n" -			"authorized sections.  If you're adding a new section\n" -			"and/or if this reference is valid, add \"%s\" to the\n" -			"list of authorized sections to jump to on fault.\n" -			"This can be achieved by adding \"%s\" to \n" -			"OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n", -			fromsec, (long)r->r_offset, tosec, tosec, tosec); -} +	name = sym_name(elf, sym); +	if (strcmp(label_name + strlen(prefix), name)) { +		error("%s: .export_symbol section references '%s', but it does not seem to be an export symbol\n", +		      mod->name, name); +		return; +	} -static void extable_mismatch_handler(const char* modname, struct elf_info *elf, -				     const struct sectioncheck* const mismatch, -				     Elf_Rela* r, Elf_Sym* sym, -				     const char *fromsec) -{ -	const char* tosec = sec_name(elf, get_secindex(elf, sym)); +	data = sym_get_data(elf, label);	/* license */ +	if (!strcmp(data, "GPL")) { +		is_gpl = true; +	} else if (!strcmp(data, "")) { +		is_gpl = false; +	} else { +		error("%s: unknown license '%s' was specified for '%s'\n", +		      mod->name, data, name); +		return; +	} -	sec_mismatch_count++; +	data += strlen(data) + 1;	/* namespace */ +	s = sym_add_exported(name, mod, is_gpl, data); -	report_extable_warnings(modname, elf, mismatch, r, sym, fromsec, tosec); +	/* +	 * We need to be aware whether we are exporting a function or +	 * a data on some architectures. +	 */ +	s->is_func = (ELF_ST_TYPE(sym->st_info) == STT_FUNC); -	if (match(tosec, mismatch->bad_tosec)) -		fatal("The relocation at %s+0x%lx references\n" -		      "section \"%s\" which is black-listed.\n" -		      "Something is seriously wrong and should be fixed.\n" -		      "You might get more information about where this is\n" -		      "coming from by using scripts/check_extable.sh %s\n", -		      fromsec, (long)r->r_offset, tosec, modname); -	else if (!is_executable_section(elf, get_secindex(elf, sym))) { -		if (is_extable_fault_address(r)) -			fatal("The relocation at %s+0x%lx references\n" -			      "section \"%s\" which is not executable, IOW\n" -			      "it is not possible for the kernel to fault\n" -			      "at that address.  Something is seriously wrong\n" -			      "and should be fixed.\n", -			      fromsec, (long)r->r_offset, tosec); -		else -			fatal("The relocation at %s+0x%lx references\n" -			      "section \"%s\" which is not executable, IOW\n" -			      "the kernel will fault if it ever tries to\n" -			      "jump to it.  Something is seriously wrong\n" -			      "and should be fixed.\n", -			      fromsec, (long)r->r_offset, tosec); -	} +	if (match(secname, PATTERNS(INIT_SECTIONS))) +		warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n", +		     mod->name, name); +	else if (match(secname, PATTERNS(EXIT_SECTIONS))) +		warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n", +		     mod->name, name);  } -static void check_section_mismatch(const char *modname, struct elf_info *elf, -				   Elf_Rela *r, Elf_Sym *sym, const char *fromsec) +static void check_section_mismatch(struct module *mod, struct elf_info *elf, +				   Elf_Sym *sym, +				   unsigned int fsecndx, const char *fromsec, +				   Elf_Addr faddr, Elf_Addr taddr)  {  	const char *tosec = sec_name(elf, get_secindex(elf, sym)); -	const struct sectioncheck *mismatch = section_mismatch(fromsec, tosec); +	const struct sectioncheck *mismatch; -	if (mismatch) { -		if (mismatch->handler) -			mismatch->handler(modname, elf,  mismatch, -					  r, sym, fromsec); -		else -			default_mismatch_handler(modname, elf, mismatch, -						 r, sym, fromsec); +	if (elf->export_symbol_secndx == fsecndx) { +		check_export_symbol(mod, elf, faddr, tosec, sym); +		return;  	} -} -static unsigned int *reloc_location(struct elf_info *elf, -				    Elf_Shdr *sechdr, Elf_Rela *r) -{ -	return sym_get_data_by_offset(elf, sechdr->sh_info, r->r_offset); +	mismatch = section_mismatch(fromsec, tosec); +	if (!mismatch) +		return; + +	default_mismatch_handler(mod->name, elf, mismatch, sym, +				 fsecndx, fromsec, faddr, +				 tosec, taddr);  } -static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) +static int addend_386_rel(uint32_t *location, Elf_Rela *r)  {  	unsigned int r_typ = ELF_R_TYPE(r->r_info); -	unsigned int *location = reloc_location(elf, sechdr, r);  	switch (r_typ) {  	case R_386_32: @@ -1436,6 +1267,8 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  	case R_386_PC32:  		r->r_addend = TO_NATIVE(*location) + 4;  		break; +	default: +		r->r_addend = (Elf_Addr)(-1);  	}  	return 0;  } @@ -1453,45 +1286,131 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  #ifndef	R_ARM_THM_JUMP24  #define	R_ARM_THM_JUMP24	30  #endif + +#ifndef R_ARM_MOVW_ABS_NC +#define R_ARM_MOVW_ABS_NC	43 +#endif + +#ifndef R_ARM_MOVT_ABS +#define R_ARM_MOVT_ABS		44 +#endif + +#ifndef R_ARM_THM_MOVW_ABS_NC +#define R_ARM_THM_MOVW_ABS_NC	47 +#endif + +#ifndef R_ARM_THM_MOVT_ABS +#define R_ARM_THM_MOVT_ABS	48 +#endif +  #ifndef	R_ARM_THM_JUMP19  #define	R_ARM_THM_JUMP19	51  #endif -static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) +static int32_t sign_extend32(int32_t value, int index) +{ +	uint8_t shift = 31 - index; + +	return (int32_t)(value << shift) >> shift; +} + +static int addend_arm_rel(void *loc, Elf_Sym *sym, Elf_Rela *r)  {  	unsigned int r_typ = ELF_R_TYPE(r->r_info); +	uint32_t inst, upper, lower, sign, j1, j2; +	int32_t offset;  	switch (r_typ) {  	case R_ARM_ABS32: -		/* From ARM ABI: (S + A) | T */ -		r->r_addend = (int)(long) -			      (elf->symtab_start + ELF_R_SYM(r->r_info)); +	case R_ARM_REL32: +		inst = TO_NATIVE(*(uint32_t *)loc); +		r->r_addend = inst + sym->st_value; +		break; +	case R_ARM_MOVW_ABS_NC: +	case R_ARM_MOVT_ABS: +		inst = TO_NATIVE(*(uint32_t *)loc); +		offset = sign_extend32(((inst & 0xf0000) >> 4) | (inst & 0xfff), +				       15); +		r->r_addend = offset + sym->st_value;  		break;  	case R_ARM_PC24:  	case R_ARM_CALL:  	case R_ARM_JUMP24: +		inst = TO_NATIVE(*(uint32_t *)loc); +		offset = sign_extend32((inst & 0x00ffffff) << 2, 25); +		r->r_addend = offset + sym->st_value + 8; +		break; +	case R_ARM_THM_MOVW_ABS_NC: +	case R_ARM_THM_MOVT_ABS: +		upper = TO_NATIVE(*(uint16_t *)loc); +		lower = TO_NATIVE(*((uint16_t *)loc + 1)); +		offset = sign_extend32(((upper & 0x000f) << 12) | +				       ((upper & 0x0400) << 1) | +				       ((lower & 0x7000) >> 4) | +				       (lower & 0x00ff), +				       15); +		r->r_addend = offset + sym->st_value; +		break; +	case R_ARM_THM_JUMP19: +		/* +		 * Encoding T3: +		 * S     = upper[10] +		 * imm6  = upper[5:0] +		 * J1    = lower[13] +		 * J2    = lower[11] +		 * imm11 = lower[10:0] +		 * imm32 = SignExtend(S:J2:J1:imm6:imm11:'0') +		 */ +		upper = TO_NATIVE(*(uint16_t *)loc); +		lower = TO_NATIVE(*((uint16_t *)loc + 1)); + +		sign = (upper >> 10) & 1; +		j1 = (lower >> 13) & 1; +		j2 = (lower >> 11) & 1; +		offset = sign_extend32((sign << 20) | (j2 << 19) | (j1 << 18) | +				       ((upper & 0x03f) << 12) | +				       ((lower & 0x07ff) << 1), +				       20); +		r->r_addend = offset + sym->st_value + 4; +		break;  	case R_ARM_THM_CALL:  	case R_ARM_THM_JUMP24: -	case R_ARM_THM_JUMP19: -		/* From ARM ABI: ((S + A) | T) - P */ -		r->r_addend = (int)(long)(elf->hdr + -			      sechdr->sh_offset + -			      (r->r_offset - sechdr->sh_addr)); +		/* +		 * Encoding T4: +		 * S     = upper[10] +		 * imm10 = upper[9:0] +		 * J1    = lower[13] +		 * J2    = lower[11] +		 * imm11 = lower[10:0] +		 * I1    = NOT(J1 XOR S) +		 * I2    = NOT(J2 XOR S) +		 * imm32 = SignExtend(S:I1:I2:imm10:imm11:'0') +		 */ +		upper = TO_NATIVE(*(uint16_t *)loc); +		lower = TO_NATIVE(*((uint16_t *)loc + 1)); + +		sign = (upper >> 10) & 1; +		j1 = (lower >> 13) & 1; +		j2 = (lower >> 11) & 1; +		offset = sign_extend32((sign << 24) | +				       ((~(j1 ^ sign) & 1) << 23) | +				       ((~(j2 ^ sign) & 1) << 22) | +				       ((upper & 0x03ff) << 12) | +				       ((lower & 0x07ff) << 1), +				       24); +		r->r_addend = offset + sym->st_value + 4;  		break;  	default: -		return 1; +		r->r_addend = (Elf_Addr)(-1);  	}  	return 0;  } -static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) +static int addend_mips_rel(uint32_t *location, Elf_Rela *r)  {  	unsigned int r_typ = ELF_R_TYPE(r->r_info); -	unsigned int *location = reloc_location(elf, sechdr, r); -	unsigned int inst; +	uint32_t inst; -	if (r_typ == R_MIPS_HI16) -		return 1;	/* skip this */  	inst = TO_NATIVE(*location);  	switch (r_typ) {  	case R_MIPS_LO16: @@ -1503,6 +1422,8 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  	case R_MIPS_32:  		r->r_addend = inst;  		break; +	default: +		r->r_addend = (Elf_Addr)(-1);  	}  	return 0;  } @@ -1523,19 +1444,17 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)  #define R_LARCH_SUB32		55  #endif -static void section_rela(const char *modname, struct elf_info *elf, +static void section_rela(struct module *mod, struct elf_info *elf,  			 Elf_Shdr *sechdr)  { -	Elf_Sym  *sym;  	Elf_Rela *rela;  	Elf_Rela r;  	unsigned int r_sym; -	const char *fromsec; - +	unsigned int fsecndx = sechdr->sh_info; +	const char *fromsec = sec_name(elf, fsecndx);  	Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset;  	Elf_Rela *stop  = (void *)start + sechdr->sh_size; -	fromsec = sec_name(elf, sechdr->sh_info);  	/* if from section (name) is know good then skip it */  	if (match(fromsec, section_white_list))  		return; @@ -1570,34 +1489,31 @@ static void section_rela(const char *modname, struct elf_info *elf,  				continue;  			break;  		} -		sym = elf->symtab_start + r_sym; -		/* Skip special sections */ -		if (is_shndx_special(sym->st_shndx)) -			continue; -		if (is_second_extable_reloc(start, rela, fromsec)) -			find_extable_entry_size(fromsec, &r); -		check_section_mismatch(modname, elf, &r, sym, fromsec); + +		check_section_mismatch(mod, elf, elf->symtab_start + r_sym, +				       fsecndx, fromsec, r.r_offset, r.r_addend);  	}  } -static void section_rel(const char *modname, struct elf_info *elf, +static void section_rel(struct module *mod, struct elf_info *elf,  			Elf_Shdr *sechdr)  { -	Elf_Sym *sym;  	Elf_Rel *rel;  	Elf_Rela r;  	unsigned int r_sym; -	const char *fromsec; - +	unsigned int fsecndx = sechdr->sh_info; +	const char *fromsec = sec_name(elf, fsecndx);  	Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset;  	Elf_Rel *stop  = (void *)start + sechdr->sh_size; -	fromsec = sec_name(elf, sechdr->sh_info);  	/* if from section (name) is know good then skip it */  	if (match(fromsec, section_white_list))  		return;  	for (rel = start; rel < stop; rel++) { +		Elf_Sym *tsym; +		void *loc; +  		r.r_offset = TO_NATIVE(rel->r_offset);  #if KERNEL_ELFCLASS == ELFCLASS64  		if (elf->hdr->e_machine == EM_MIPS) { @@ -1615,27 +1531,26 @@ static void section_rel(const char *modname, struct elf_info *elf,  		r_sym = ELF_R_SYM(r.r_info);  #endif  		r.r_addend = 0; + +		loc = sym_get_data_by_offset(elf, fsecndx, r.r_offset); +		tsym = elf->symtab_start + r_sym; +  		switch (elf->hdr->e_machine) {  		case EM_386: -			if (addend_386_rel(elf, sechdr, &r)) -				continue; +			addend_386_rel(loc, &r);  			break;  		case EM_ARM: -			if (addend_arm_rel(elf, sechdr, &r)) -				continue; +			addend_arm_rel(loc, tsym, &r);  			break;  		case EM_MIPS: -			if (addend_mips_rel(elf, sechdr, &r)) -				continue; +			addend_mips_rel(loc, &r);  			break; +		default: +			fatal("Please add code to calculate addend for this architecture\n");  		} -		sym = elf->symtab_start + r_sym; -		/* Skip special sections */ -		if (is_shndx_special(sym->st_shndx)) -			continue; -		if (is_second_extable_reloc(start, rel, fromsec)) -			find_extable_entry_size(fromsec, &r); -		check_section_mismatch(modname, elf, &r, sym, fromsec); + +		check_section_mismatch(mod, elf, tsym, +				       fsecndx, fromsec, r.r_offset, r.r_addend);  	}  } @@ -1651,19 +1566,19 @@ 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(const char *modname, struct elf_info *elf) +static void check_sec_ref(struct module *mod, struct elf_info *elf)  {  	int i;  	Elf_Shdr *sechdrs = elf->sechdrs;  	/* Walk through all sections */  	for (i = 0; i < elf->num_sections; i++) { -		check_section(modname, elf, &elf->sechdrs[i]); +		check_section(mod->name, elf, &elf->sechdrs[i]);  		/* We want to process only relocation sections and not .init */  		if (sechdrs[i].sh_type == SHT_RELA) -			section_rela(modname, elf, &elf->sechdrs[i]); +			section_rela(mod, elf, &elf->sechdrs[i]);  		else if (sechdrs[i].sh_type == SHT_REL) -			section_rel(modname, elf, &elf->sechdrs[i]); +			section_rel(mod, elf, &elf->sechdrs[i]);  	}  } @@ -1818,6 +1733,8 @@ static void read_symbols(const char *modname)  		}  	} +	if (extra_warn && !get_modinfo(&info, "description")) +		warn("missing MODULE_DESCRIPTION() in %s\n", modname);  	for (sym = info.symtab_start; sym < info.symtab_stop; sym++) {  		symname = remove_dot(info.strtab + sym->st_name); @@ -1825,16 +1742,7 @@ static void read_symbols(const char *modname)  		handle_moddevtable(mod, &info, sym, symname);  	} -	for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { -		symname = remove_dot(info.strtab + sym->st_name); - -		/* Apply symbol namespaces from __kstrtabns_<symbol> entries. */ -		if (strstarts(symname, "__kstrtabns_")) -			sym_update_namespace(symname + strlen("__kstrtabns_"), -					     sym_get_data(&info, sym)); -	} - -	check_sec_ref(modname, &info); +	check_sec_ref(mod, &info);  	if (!mod->is_vmlinux) {  		version = get_modinfo(&info, "version"); @@ -1925,6 +1833,7 @@ static void check_exports(struct module *mod)  			continue;  		} +		exp->used = true;  		s->module = exp->module;  		s->crc_valid = exp->crc_valid;  		s->crc = exp->crc; @@ -1935,8 +1844,7 @@ static void check_exports(struct module *mod)  		else  			basename = mod->name; -		if (exp->namespace && -		    !contains_namespace(&mod->imported_namespaces, exp->namespace)) { +		if (!contains_namespace(&mod->imported_namespaces, exp->namespace)) {  			modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR,  				    "module %s uses symbol %s from namespace %s, but does not import it.\n",  				    basename, exp->name, exp->namespace); @@ -1949,6 +1857,23 @@ static void check_exports(struct module *mod)  	}  } +static void handle_white_list_exports(const char *white_list) +{ +	char *buf, *p, *name; + +	buf = read_text_file(white_list); +	p = buf; + +	while ((name = strsep(&p, "\n"))) { +		struct symbol *sym = find_symbol(name); + +		if (sym) +			sym->used = true; +	} + +	free(buf); +} +  static void check_modname_len(struct module *mod)  {  	const char *mod_name; @@ -2022,12 +1947,26 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod)  {  	struct symbol *sym; +	/* generate struct for exported symbols */ +	buf_printf(buf, "\n"); +	list_for_each_entry(sym, &mod->exported_symbols, list) { +		if (trim_unused_exports && !sym->used) +			continue; + +		buf_printf(buf, "KSYMTAB_%s(%s, \"%s\", \"%s\");\n", +			   sym->is_func ? "FUNC" : "DATA", sym->name, +			   sym->is_gpl_only ? "_gpl" : "", sym->namespace); +	} +  	if (!modversions)  		return;  	/* record CRCs for exported symbols */  	buf_printf(buf, "\n");  	list_for_each_entry(sym, &mod->exported_symbols, list) { +		if (trim_unused_exports && !sym->used) +			continue; +  		if (!sym->crc_valid)  			warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n"  			     "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n", @@ -2191,9 +2130,6 @@ static void write_mod_c_file(struct module *mod)  	char fname[PATH_MAX];  	int ret; -	check_modname_len(mod); -	check_exports(mod); -  	add_header(&buf, mod);  	add_exported_symbols(&buf, mod);  	add_versions(&buf, mod); @@ -2265,9 +2201,8 @@ static void read_dump(const char *fname)  			mod = new_module(modname, strlen(modname));  			mod->from_dump = true;  		} -		s = sym_add_exported(symname, mod, gpl_only); +		s = sym_add_exported(symname, mod, gpl_only, namespace);  		sym_set_crc(s, crc); -		sym_update_namespace(symname, namespace);  	}  	free(buf);  	return; @@ -2286,10 +2221,13 @@ static void write_dump(const char *fname)  		if (mod->from_dump)  			continue;  		list_for_each_entry(sym, &mod->exported_symbols, list) { +			if (trim_unused_exports && !sym->used) +				continue; +  			buf_printf(&buf, "0x%08x\t%s\t%s\tEXPORT_SYMBOL%s\t%s\n",  				   sym->crc, sym->name, mod->name,  				   sym->is_gpl_only ? "_GPL" : "", -				   sym->namespace ?: ""); +				   sym->namespace);  		}  	}  	write_buf(&buf, fname); @@ -2328,12 +2266,13 @@ int main(int argc, char **argv)  {  	struct module *mod;  	char *missing_namespace_deps = NULL; +	char *unused_exports_white_list = NULL;  	char *dump_write = NULL, *files_source = NULL;  	int opt;  	LIST_HEAD(dump_lists);  	struct dump_list *dl, *dl2; -	while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) { +	while ((opt = getopt(argc, argv, "ei:mnT:to:au:WwENd:")) != -1) {  		switch (opt) {  		case 'e':  			external_module = true; @@ -2358,6 +2297,15 @@ int main(int argc, char **argv)  		case 'T':  			files_source = optarg;  			break; +		case 't': +			trim_unused_exports = true; +			break; +		case 'u': +			unused_exports_white_list = optarg; +			break; +		case 'W': +			extra_warn = true; +			break;  		case 'w':  			warn_unresolved = true;  			break; @@ -2388,6 +2336,17 @@ int main(int argc, char **argv)  		read_symbols_from_files(files_source);  	list_for_each_entry(mod, &modules, list) { +		if (mod->from_dump || mod->is_vmlinux) +			continue; + +		check_modname_len(mod); +		check_exports(mod); +	} + +	if (unused_exports_white_list) +		handle_white_list_exports(unused_exports_white_list); + +	list_for_each_entry(mod, &modules, list) {  		if (mod->from_dump)  			continue; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 1178f40a73f3..dfdb9484e325 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -137,6 +137,7 @@ struct elf_info {  	Elf_Shdr     *sechdrs;  	Elf_Sym      *symtab_start;  	Elf_Sym      *symtab_stop; +	unsigned int export_symbol_secndx;	/* .export_symbol section */  	char         *strtab;  	char	     *modinfo;  	unsigned int modinfo_len; @@ -151,11 +152,6 @@ struct elf_info {  	Elf32_Word   *symtab_shndx_stop;  }; -static inline int is_shndx_special(unsigned int i) -{ -	return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; -} -  /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */  static inline unsigned int get_secindex(const struct elf_info *info,  					const Elf_Sym *sym) diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 252faaa5561c..032774eb061e 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -62,18 +62,14 @@ install_linux_image () {  		${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install  	fi -	if is_enabled CONFIG_MODULES; then -		${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install -		rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build" -		rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source" -		if [ "${SRCARCH}" = um ] ; then -			mkdir -p "${pdir}/usr/lib/uml/modules" -			mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}" -		fi -	fi +	${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install +	rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build" +	rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source"  	# Install the kernel  	if [ "${ARCH}" = um ] ; then +		mkdir -p "${pdir}/usr/lib/uml/modules" +		mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}"  		mkdir -p "${pdir}/usr/bin" "${pdir}/usr/share/doc/${pname}"  		cp System.map "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}/System.map"  		cp ${KCONFIG_CONFIG} "${pdir}/usr/share/doc/${pname}/config" diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files index 7f432900671a..f3659ea0335b 100755 --- a/scripts/remove-stale-files +++ b/scripts/remove-stale-files @@ -33,3 +33,7 @@ rm -f rust/target.json  rm -f scripts/bin2c  rm -f .scmversion + +rm -rf include/ksym + +find . -name '*.usyms' | xargs rm -f diff --git a/scripts/tags.sh b/scripts/tags.sh index ea31640b2671..f6b3c7cd39c7 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -32,6 +32,13 @@ else  	tree=${srctree}/  fi +# gtags(1) refuses to index any file outside of its current working dir. +# If gtags indexing is requested and the build output directory is not +# the kernel source tree, index all files in absolute-path form. +if [[ "$1" == "gtags" && -n "${tree}" ]]; then +	tree=$(realpath "$tree")/ +fi +  # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH  if [ "${ALLSOURCE_ARCHS}" = "" ]; then  	ALLSOURCE_ARCHS=${SRCARCH} @@ -131,7 +138,7 @@ docscope()  dogtags()  { -	all_target_sources | gtags -i -f - +	all_target_sources | gtags -i -C "${tree:-.}" -f - "$PWD"  }  # Basic regular expressions with an optional /kind-spec/ for ctags and diff --git a/usr/Makefile b/usr/Makefile index 59d9e8b07a01..f8e1ad19e05c 100644 --- a/usr/Makefile +++ b/usr/Makefile @@ -64,6 +64,7 @@ quiet_cmd_initfs = GEN     $@  	$(CONFIG_SHELL) $< -o $@ -l $(obj)/.initramfs_data.cpio.d \  	$(if $(CONFIG_INITRAMFS_ROOT_UID), -u $(CONFIG_INITRAMFS_ROOT_UID)) \  	$(if $(CONFIG_INITRAMFS_ROOT_GID), -g $(CONFIG_INITRAMFS_ROOT_GID)) \ +	$(if $(KBUILD_BUILD_TIMESTAMP), -d "$(KBUILD_BUILD_TIMESTAMP)") \  	$(ramfs-input)  # We rebuild initramfs_data.cpio if: diff --git a/usr/gen_initramfs.sh b/usr/gen_initramfs.sh index 63476bb70b41..14b5782f961a 100755 --- a/usr/gen_initramfs.sh +++ b/usr/gen_initramfs.sh @@ -23,6 +23,7 @@ $0 [-o <file>] [-l <dep_list>] [-u <uid>] [-g <gid>] {-d | <cpio_source>} ...  	-g <gid>       Group ID to map to group ID 0 (root).  		       <gid> is only meaningful if <cpio_source> is a  		       directory.  "squash" forces all files to gid 0. +	-d <date>      Use date for all file mtime values  	<cpio_source>  File list or directory for cpio archive.  		       If <cpio_source> is a .cpio file it will be used  		       as direct input to initramfs. @@ -190,6 +191,7 @@ prog=$0  root_uid=0  root_gid=0  dep_list= +timestamp=  cpio_list=$(mktemp ${TMPDIR:-/tmp}/cpiolist.XXXXXX)  output="/dev/stdout" @@ -218,6 +220,13 @@ while [ $# -gt 0 ]; do  			[ "$root_gid" = "-1" ] && root_gid=$(id -g || echo 0)  			shift  			;; +		"-d")	# date for file mtimes +			timestamp="$(date -d"$1" +%s || :)" +			if test -n "$timestamp"; then +				timestamp="-t $timestamp" +			fi +			shift +			;;  		"-h")  			usage  			exit 0 @@ -237,11 +246,4 @@ done  # If output_file is set we will generate cpio archive  # we are careful to delete tmp files -timestamp= -if test -n "$KBUILD_BUILD_TIMESTAMP"; then -	timestamp="$(date -d"$KBUILD_BUILD_TIMESTAMP" +%s || :)" -	if test -n "$timestamp"; then -		timestamp="-t $timestamp" -	fi -fi  usr/gen_init_cpio $timestamp $cpio_list > $output  | 
