mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	kbuild: implement CONFIG_TRIM_UNUSED_KSYMS without recursion
When CONFIG_TRIM_UNUSED_KSYMS is enabled, Kbuild recursively traverses the directory tree to determine which EXPORT_SYMBOL to trim. If an EXPORT_SYMBOL turns out to be unused by anyone, Kbuild begins the second traverse, where some source files are recompiled with their EXPORT_SYMBOL() tuned into a no-op. Linus stated negative opinions about this slowness in commits: -5cf0fd591f("Kbuild: disable TRIM_UNUSED_KSYMS option") -a555bdd0c5("Kbuild: enable TRIM_UNUSED_KSYMS again, with some guarding") We can do this better now. The final data structures of EXPORT_SYMBOL are generated by the modpost stage, so modpost can selectively emit KSYMTAB entries that are really used by modules. Commitf73edc8951("kbuild: unify two modpost invocations") is another ground-work to do this in a one-pass algorithm. With the list of modules, modpost sets sym->used if it is used by a module. modpost emits KSYMTAB only for symbols with sym->used==true. BTW, Nicolas explained why the trimming was implemented with recursion: https://lore.kernel.org/all/2o2rpn97-79nq-p7s2-nq5-8p83391473r@syhkavp.arg/ Actually, we never achieved that level of optimization where the chain reaction of trimming comes into play because: - CONFIG_LTO_CLANG cannot remove any unused symbols - CONFIG_LD_DEAD_CODE_DATA_ELIMINATION is enabled only for vmlinux, but not modules If deeper trimming is required, we need to revisit this, but I guess that is unlikely to happen. Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
This commit is contained in:
		
							parent
							
								
									700c48b439
								
							
						
					
					
						commit
						5e9e95cc91
					
				
					 11 changed files with 78 additions and 264 deletions
				
			
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								Makefile
									
									
									
									
									
								
							| 
						 | 
				
			
			@ -1193,28 +1193,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 = \
 | 
			
		||||
| 
						 | 
				
			
			@ -1223,7 +1207,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
 | 
			
		||||
| 
						 | 
				
			
			@ -1279,7 +1263,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
 | 
			
		||||
| 
						 | 
				
			
			@ -2039,7 +2023,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]' \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ extern struct module __this_module;
 | 
			
		|||
	.long sym
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define ____EXPORT_SYMBOL(sym, license, ns)		\
 | 
			
		||||
#define ___EXPORT_SYMBOL(sym, license, ns)		\
 | 
			
		||||
	.section ".export_symbol","a"		ASM_NL	\
 | 
			
		||||
	__export_symbol_##sym:			ASM_NL	\
 | 
			
		||||
		.asciz license			ASM_NL	\
 | 
			
		||||
| 
						 | 
				
			
			@ -50,24 +50,6 @@ extern struct module __this_module;
 | 
			
		|||
		__EXPORT_SYMBOL_REF(sym)	ASM_NL	\
 | 
			
		||||
	.previous
 | 
			
		||||
 | 
			
		||||
#ifdef __GENKSYMS__
 | 
			
		||||
 | 
			
		||||
#define ___EXPORT_SYMBOL(sym, sec, ns)	__GENKSYMS_EXPORT_SYMBOL(sym)
 | 
			
		||||
 | 
			
		||||
#elif defined(__ASSEMBLY__)
 | 
			
		||||
 | 
			
		||||
#define ___EXPORT_SYMBOL(sym, license, ns) \
 | 
			
		||||
	____EXPORT_SYMBOL(sym, license, ns)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define ___EXPORT_SYMBOL(sym, license, ns)			\
 | 
			
		||||
	extern typeof(sym) sym;					\
 | 
			
		||||
	__ADDRESSABLE(sym)					\
 | 
			
		||||
	asm(__stringify(____EXPORT_SYMBOL(sym, license, ns)))
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS)
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			@ -77,50 +59,21 @@ extern struct module __this_module;
 | 
			
		|||
 */
 | 
			
		||||
#define __EXPORT_SYMBOL(sym, sec, ns)
 | 
			
		||||
 | 
			
		||||
#elif defined(CONFIG_TRIM_UNUSED_KSYMS)
 | 
			
		||||
#elif defined(__GENKSYMS__)
 | 
			
		||||
 | 
			
		||||
#include <generated/autoksyms.h>
 | 
			
		||||
#define __EXPORT_SYMBOL(sym, sec, 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.
 | 
			
		||||
 */
 | 
			
		||||
#elif defined(__ASSEMBLY__)
 | 
			
		||||
 | 
			
		||||
#ifdef __ASSEMBLY__
 | 
			
		||||
 | 
			
		||||
#define __ksym_marker(sym)					\
 | 
			
		||||
	.section ".discard.ksym","a" ;				\
 | 
			
		||||
__ksym_marker_##sym: ;						\
 | 
			
		||||
	.previous
 | 
			
		||||
#define __EXPORT_SYMBOL(sym, license, ns) \
 | 
			
		||||
	___EXPORT_SYMBOL(sym, license, ns)
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
 | 
			
		||||
#define __ksym_marker(sym)	\
 | 
			
		||||
	static int __ksym_marker_##sym[0] __section(".discard.ksym") __used
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#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)
 | 
			
		||||
 | 
			
		||||
#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 */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -217,18 +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
 | 
			
		||||
 | 
			
		||||
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,checksrc)
 | 
			
		||||
	$(call cmd,checkdoc)
 | 
			
		||||
	$(call cmd,gen_objtooldep)
 | 
			
		||||
| 
						 | 
				
			
			@ -239,7 +233,6 @@ endef
 | 
			
		|||
 | 
			
		||||
define rule_as_o_S
 | 
			
		||||
	$(call cmd_and_fixdep,as_o_S)
 | 
			
		||||
	$(call cmd,gen_ksymdeps)
 | 
			
		||||
	$(call cmd,gen_objtooldep)
 | 
			
		||||
	$(call cmd,gen_symversions_S)
 | 
			
		||||
	$(call cmd,warn_shared_object)
 | 
			
		||||
| 
						 | 
				
			
			@ -258,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 \
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -91,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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			@ -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):"
 | 
			
		||||
| 
						 | 
				
			
			@ -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 */
 | 
			
		||||
| 
						 | 
				
			
			@ -219,6 +222,7 @@ struct symbol {
 | 
			
		|||
	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[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1826,6 +1830,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1849,6 +1854,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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1919,10 +1941,14 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod)
 | 
			
		|||
 | 
			
		||||
	/* generate struct for exported symbols */
 | 
			
		||||
	buf_printf(buf, "\n");
 | 
			
		||||
	list_for_each_entry(sym, &mod->exported_symbols, list)
 | 
			
		||||
	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;
 | 
			
		||||
| 
						 | 
				
			
			@ -1930,6 +1956,9 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod)
 | 
			
		|||
	/* 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",
 | 
			
		||||
| 
						 | 
				
			
			@ -2093,9 +2122,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);
 | 
			
		||||
| 
						 | 
				
			
			@ -2187,6 +2213,9 @@ 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" : "",
 | 
			
		||||
| 
						 | 
				
			
			@ -2229,12 +2258,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:aWwENd:")) != -1) {
 | 
			
		||||
	while ((opt = getopt(argc, argv, "ei:mnT:to:au:WwENd:")) != -1) {
 | 
			
		||||
		switch (opt) {
 | 
			
		||||
		case 'e':
 | 
			
		||||
			external_module = true;
 | 
			
		||||
| 
						 | 
				
			
			@ -2259,6 +2289,12 @@ 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;
 | 
			
		||||
| 
						 | 
				
			
			@ -2291,6 +2327,17 @@ int main(int argc, char **argv)
 | 
			
		|||
	if (files_source)
 | 
			
		||||
		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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue