Skip to content

Commit 5e9e95c

Browse files
committed
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: - 5cf0fd5 ("Kbuild: disable TRIM_UNUSED_KSYMS option") - a555bdd ("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. Commit f73edc8 ("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/[email protected]/ 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 <[email protected]>
1 parent 700c48b commit 5e9e95c

11 files changed

Lines changed: 78 additions & 264 deletions

File tree

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@
5151
*.symversions
5252
*.tab.[ch]
5353
*.tar
54-
*.usyms
5554
*.xz
5655
*.zst
5756
Module.symvers
@@ -112,7 +111,6 @@ modules.order
112111
#
113112
/include/config/
114113
/include/generated/
115-
/include/ksym/
116114
/arch/*/include/generated/
117115

118116
# stgit generated dirs

Makefile

Lines changed: 3 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,28 +1193,12 @@ endif
11931193
export KBUILD_VMLINUX_LIBS
11941194
export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds
11951195

1196-
# Recurse until adjust_autoksyms.sh is satisfied
1197-
PHONY += autoksyms_recursive
11981196
ifdef CONFIG_TRIM_UNUSED_KSYMS
11991197
# For the kernel to actually contain only the needed exported symbols,
12001198
# we have to build modules as well to determine what those symbols are.
1201-
# (this can be evaluated only once include/config/auto.conf has been included)
12021199
KBUILD_MODULES := 1
1203-
1204-
autoksyms_recursive: $(build-dir) modules.order
1205-
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \
1206-
"$(MAKE) -f $(srctree)/Makefile autoksyms_recursive"
12071200
endif
12081201

1209-
autoksyms_h := $(if $(CONFIG_TRIM_UNUSED_KSYMS), include/generated/autoksyms.h)
1210-
1211-
quiet_cmd_autoksyms_h = GEN $@
1212-
cmd_autoksyms_h = mkdir -p $(dir $@); \
1213-
$(CONFIG_SHELL) $(srctree)/scripts/gen_autoksyms.sh $@
1214-
1215-
$(autoksyms_h):
1216-
$(call cmd,autoksyms_h)
1217-
12181202
# '$(AR) mPi' needs 'T' to workaround the bug of llvm-ar <= 14
12191203
quiet_cmd_ar_vmlinux.a = AR $@
12201204
cmd_ar_vmlinux.a = \
@@ -1223,7 +1207,7 @@ quiet_cmd_ar_vmlinux.a = AR $@
12231207
$(AR) mPiT $$($(AR) t $@ | sed -n 1p) $@ $$($(AR) t $@ | grep -F -f $(srctree)/scripts/head-object-list.txt)
12241208

12251209
targets += vmlinux.a
1226-
vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt autoksyms_recursive FORCE
1210+
vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt FORCE
12271211
$(call if_changed,ar_vmlinux.a)
12281212

12291213
PHONY += vmlinux_o
@@ -1279,7 +1263,7 @@ scripts: scripts_basic scripts_dtc
12791263
PHONY += prepare archprepare
12801264

12811265
archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \
1282-
asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
1266+
asm-generic $(version_h) include/generated/utsrelease.h \
12831267
include/generated/compile.h include/generated/autoconf.h remove-stale-files
12841268

12851269
prepare0: archprepare
@@ -2039,7 +2023,7 @@ clean: $(clean-dirs)
20392023
-o -name '*.dtb.S' -o -name '*.dtbo.S' \
20402024
-o -name '*.dt.yaml' \
20412025
-o -name '*.dwo' -o -name '*.lst' \
2042-
-o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \
2026+
-o -name '*.su' -o -name '*.mod' \
20432027
-o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \
20442028
-o -name '*.lex.c' -o -name '*.tab.[ch]' \
20452029
-o -name '*.asn1.[ch]' \

include/linux/export.h

Lines changed: 10 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -42,32 +42,14 @@ extern struct module __this_module;
4242
.long sym
4343
#endif
4444

45-
#define ____EXPORT_SYMBOL(sym, license, ns) \
45+
#define ___EXPORT_SYMBOL(sym, license, ns) \
4646
.section ".export_symbol","a" ASM_NL \
4747
__export_symbol_##sym: ASM_NL \
4848
.asciz license ASM_NL \
4949
.asciz ns ASM_NL \
5050
__EXPORT_SYMBOL_REF(sym) ASM_NL \
5151
.previous
5252

53-
#ifdef __GENKSYMS__
54-
55-
#define ___EXPORT_SYMBOL(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym)
56-
57-
#elif defined(__ASSEMBLY__)
58-
59-
#define ___EXPORT_SYMBOL(sym, license, ns) \
60-
____EXPORT_SYMBOL(sym, license, ns)
61-
62-
#else
63-
64-
#define ___EXPORT_SYMBOL(sym, license, ns) \
65-
extern typeof(sym) sym; \
66-
__ADDRESSABLE(sym) \
67-
asm(__stringify(____EXPORT_SYMBOL(sym, license, ns)))
68-
69-
#endif
70-
7153
#if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS)
7254

7355
/*
@@ -77,50 +59,21 @@ extern struct module __this_module;
7759
*/
7860
#define __EXPORT_SYMBOL(sym, sec, ns)
7961

80-
#elif defined(CONFIG_TRIM_UNUSED_KSYMS)
62+
#elif defined(__GENKSYMS__)
8163

82-
#include <generated/autoksyms.h>
64+
#define __EXPORT_SYMBOL(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym)
8365

84-
/*
85-
* For fine grained build dependencies, we want to tell the build system
86-
* about each possible exported symbol even if they're not actually exported.
87-
* We use a symbol pattern __ksym_marker_<symbol> that the build system filters
88-
* from the $(NM) output (see scripts/gen_ksymdeps.sh). These symbols are
89-
* discarded in the final link stage.
90-
*/
91-
92-
#ifdef __ASSEMBLY__
93-
94-
#define __ksym_marker(sym) \
95-
.section ".discard.ksym","a" ; \
96-
__ksym_marker_##sym: ; \
97-
.previous
98-
99-
#else
100-
101-
#define __ksym_marker(sym) \
102-
static int __ksym_marker_##sym[0] __section(".discard.ksym") __used
103-
104-
#endif
66+
#elif defined(__ASSEMBLY__)
10567

106-
#define __EXPORT_SYMBOL(sym, sec, ns) \
107-
__ksym_marker(sym); \
108-
__cond_export_sym(sym, sec, ns, __is_defined(__KSYM_##sym))
109-
#define __cond_export_sym(sym, sec, ns, conf) \
110-
___cond_export_sym(sym, sec, ns, conf)
111-
#define ___cond_export_sym(sym, sec, ns, enabled) \
112-
__cond_export_sym_##enabled(sym, sec, ns)
113-
#define __cond_export_sym_1(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns)
114-
115-
#ifdef __GENKSYMS__
116-
#define __cond_export_sym_0(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym)
117-
#else
118-
#define __cond_export_sym_0(sym, sec, ns) /* nothing */
119-
#endif
68+
#define __EXPORT_SYMBOL(sym, license, ns) \
69+
___EXPORT_SYMBOL(sym, license, ns)
12070

12171
#else
12272

123-
#define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns)
73+
#define __EXPORT_SYMBOL(sym, license, ns) \
74+
extern typeof(sym) sym; \
75+
__ADDRESSABLE(sym) \
76+
asm(__stringify(___EXPORT_SYMBOL(sym, license, ns)))
12477

12578
#endif /* CONFIG_MODULES */
12679

scripts/Makefile.build

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ ifdef need-builtin
8282
targets-for-builtin += $(obj)/built-in.a
8383
endif
8484

85-
targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \
85+
targets-for-modules := $(foreach x, o mod, \
8686
$(patsubst %.o, %.$x, $(filter %.o, $(obj-m))))
8787

8888
ifdef need-modorder
@@ -217,18 +217,12 @@ is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetar
217217

218218
$(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y))
219219

220-
ifdef CONFIG_TRIM_UNUSED_KSYMS
221-
cmd_gen_ksymdeps = \
222-
$(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd
223-
endif
224-
225220
ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
226221
cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi)))
227222
endif
228223

229224
define rule_cc_o_c
230225
$(call cmd_and_fixdep,cc_o_c)
231-
$(call cmd,gen_ksymdeps)
232226
$(call cmd,checksrc)
233227
$(call cmd,checkdoc)
234228
$(call cmd,gen_objtooldep)
@@ -239,7 +233,6 @@ endef
239233

240234
define rule_as_o_S
241235
$(call cmd_and_fixdep,as_o_S)
242-
$(call cmd,gen_ksymdeps)
243236
$(call cmd,gen_objtooldep)
244237
$(call cmd,gen_symversions_S)
245238
$(call cmd,warn_shared_object)
@@ -258,12 +251,6 @@ cmd_mod = printf '%s\n' $(call real-search, $*.o, .o, -objs -y -m) | \
258251
$(obj)/%.mod: FORCE
259252
$(call if_changed,mod)
260253

261-
# List module undefined symbols
262-
cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@
263-
264-
$(obj)/%.usyms: $(obj)/%.o FORCE
265-
$(call if_changed,undefined_syms)
266-
267254
quiet_cmd_cc_lst_c = MKLST $@
268255
cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
269256
$(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \

scripts/Makefile.modpost

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ targets += .vmlinux.objs
9191
.vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE
9292
$(call if_changed,vmlinux_objs)
9393

94+
ifdef CONFIG_TRIM_UNUSED_KSYMS
95+
ksym-wl := $(CONFIG_UNUSED_KSYMS_WHITELIST)
96+
ksym-wl := $(if $(filter-out /%, $(ksym-wl)),$(srctree)/)$(ksym-wl)
97+
modpost-args += -t $(addprefix -u , $(ksym-wl))
98+
modpost-deps += $(ksym-wl)
99+
endif
100+
94101
ifeq ($(wildcard vmlinux.o),)
95102
missing-input := vmlinux.o
96103
output-symdump := modules-only.symvers

scripts/adjust_autoksyms.sh

Lines changed: 0 additions & 73 deletions
This file was deleted.

scripts/basic/fixdep.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,8 +246,7 @@ static void *read_file(const char *filename)
246246
/* Ignore certain dependencies */
247247
static int is_ignored_file(const char *s, int len)
248248
{
249-
return str_ends_with(s, len, "include/generated/autoconf.h") ||
250-
str_ends_with(s, len, "include/generated/autoksyms.h");
249+
return str_ends_with(s, len, "include/generated/autoconf.h");
251250
}
252251

253252
/* Do not parse these files */

scripts/gen_autoksyms.sh

Lines changed: 0 additions & 62 deletions
This file was deleted.

0 commit comments

Comments
 (0)