Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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:

- 5cf0fd591f2e ("Kbuild: disable TRIM_UNUSED_KSYMS option")
- a555bdd0c58c ("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 f73edc8951b2 ("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>

+78 -264
-2
.gitignore
··· 51 51 *.symversions 52 52 *.tab.[ch] 53 53 *.tar 54 - *.usyms 55 54 *.xz 56 55 *.zst 57 56 Module.symvers ··· 111 112 # 112 113 /include/config/ 113 114 /include/generated/ 114 - /include/ksym/ 115 115 /arch/*/include/generated/ 116 116 117 117 # stgit generated dirs
+3 -19
Makefile
··· 1193 1193 export KBUILD_VMLINUX_LIBS 1194 1194 export KBUILD_LDS := arch/$(SRCARCH)/kernel/vmlinux.lds 1195 1195 1196 - # Recurse until adjust_autoksyms.sh is satisfied 1197 - PHONY += autoksyms_recursive 1198 1196 ifdef CONFIG_TRIM_UNUSED_KSYMS 1199 1197 # For the kernel to actually contain only the needed exported symbols, 1200 1198 # 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) 1202 1199 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" 1207 1200 endif 1208 - 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 1201 1218 1202 # '$(AR) mPi' needs 'T' to workaround the bug of llvm-ar <= 14 1219 1203 quiet_cmd_ar_vmlinux.a = AR $@ ··· 1207 1223 $(AR) mPiT $$($(AR) t $@ | sed -n 1p) $@ $$($(AR) t $@ | grep -F -f $(srctree)/scripts/head-object-list.txt) 1208 1224 1209 1225 targets += vmlinux.a 1210 - vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt autoksyms_recursive FORCE 1226 + vmlinux.a: $(KBUILD_VMLINUX_OBJS) scripts/head-object-list.txt FORCE 1211 1227 $(call if_changed,ar_vmlinux.a) 1212 1228 1213 1229 PHONY += vmlinux_o ··· 1263 1279 PHONY += prepare archprepare 1264 1280 1265 1281 archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \ 1266 - asm-generic $(version_h) $(autoksyms_h) include/generated/utsrelease.h \ 1282 + asm-generic $(version_h) include/generated/utsrelease.h \ 1267 1283 include/generated/compile.h include/generated/autoconf.h remove-stale-files 1268 1284 1269 1285 prepare0: archprepare ··· 2023 2039 -o -name '*.dtb.S' -o -name '*.dtbo.S' \ 2024 2040 -o -name '*.dt.yaml' \ 2025 2041 -o -name '*.dwo' -o -name '*.lst' \ 2026 - -o -name '*.su' -o -name '*.mod' -o -name '*.usyms' \ 2042 + -o -name '*.su' -o -name '*.mod' \ 2027 2043 -o -name '.*.d' -o -name '.*.tmp' -o -name '*.mod.c' \ 2028 2044 -o -name '*.lex.c' -o -name '*.tab.[ch]' \ 2029 2045 -o -name '*.asn1.[ch]' \
+10 -57
include/linux/export.h
··· 42 42 .long sym 43 43 #endif 44 44 45 - #define ____EXPORT_SYMBOL(sym, license, ns) \ 45 + #define ___EXPORT_SYMBOL(sym, license, ns) \ 46 46 .section ".export_symbol","a" ASM_NL \ 47 47 __export_symbol_##sym: ASM_NL \ 48 48 .asciz license ASM_NL \ 49 49 .asciz ns ASM_NL \ 50 50 __EXPORT_SYMBOL_REF(sym) ASM_NL \ 51 51 .previous 52 - 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 52 71 53 #if !defined(CONFIG_MODULES) || defined(__DISABLE_EXPORTS) 72 54 ··· 59 77 */ 60 78 #define __EXPORT_SYMBOL(sym, sec, ns) 61 79 62 - #elif defined(CONFIG_TRIM_UNUSED_KSYMS) 80 + #elif defined(__GENKSYMS__) 63 81 64 - #include <generated/autoksyms.h> 82 + #define __EXPORT_SYMBOL(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym) 65 83 66 - /* 67 - * For fine grained build dependencies, we want to tell the build system 68 - * about each possible exported symbol even if they're not actually exported. 69 - * We use a symbol pattern __ksym_marker_<symbol> that the build system filters 70 - * from the $(NM) output (see scripts/gen_ksymdeps.sh). These symbols are 71 - * discarded in the final link stage. 72 - */ 84 + #elif defined(__ASSEMBLY__) 73 85 74 - #ifdef __ASSEMBLY__ 75 - 76 - #define __ksym_marker(sym) \ 77 - .section ".discard.ksym","a" ; \ 78 - __ksym_marker_##sym: ; \ 79 - .previous 86 + #define __EXPORT_SYMBOL(sym, license, ns) \ 87 + ___EXPORT_SYMBOL(sym, license, ns) 80 88 81 89 #else 82 90 83 - #define __ksym_marker(sym) \ 84 - static int __ksym_marker_##sym[0] __section(".discard.ksym") __used 85 - 86 - #endif 87 - 88 - #define __EXPORT_SYMBOL(sym, sec, ns) \ 89 - __ksym_marker(sym); \ 90 - __cond_export_sym(sym, sec, ns, __is_defined(__KSYM_##sym)) 91 - #define __cond_export_sym(sym, sec, ns, conf) \ 92 - ___cond_export_sym(sym, sec, ns, conf) 93 - #define ___cond_export_sym(sym, sec, ns, enabled) \ 94 - __cond_export_sym_##enabled(sym, sec, ns) 95 - #define __cond_export_sym_1(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) 96 - 97 - #ifdef __GENKSYMS__ 98 - #define __cond_export_sym_0(sym, sec, ns) __GENKSYMS_EXPORT_SYMBOL(sym) 99 - #else 100 - #define __cond_export_sym_0(sym, sec, ns) /* nothing */ 101 - #endif 102 - 103 - #else 104 - 105 - #define __EXPORT_SYMBOL(sym, sec, ns) ___EXPORT_SYMBOL(sym, sec, ns) 91 + #define __EXPORT_SYMBOL(sym, license, ns) \ 92 + extern typeof(sym) sym; \ 93 + __ADDRESSABLE(sym) \ 94 + asm(__stringify(___EXPORT_SYMBOL(sym, license, ns))) 106 95 107 96 #endif /* CONFIG_MODULES */ 108 97
+1 -14
scripts/Makefile.build
··· 82 82 targets-for-builtin += $(obj)/built-in.a 83 83 endif 84 84 85 - targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \ 85 + targets-for-modules := $(foreach x, o mod, \ 86 86 $(patsubst %.o, %.$x, $(filter %.o, $(obj-m)))) 87 87 88 88 ifdef need-modorder ··· 217 217 218 218 $(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y)) 219 219 220 - ifdef CONFIG_TRIM_UNUSED_KSYMS 221 - cmd_gen_ksymdeps = \ 222 - $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd 223 - endif 224 - 225 220 ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),) 226 221 cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi))) 227 222 endif 228 223 229 224 define rule_cc_o_c 230 225 $(call cmd_and_fixdep,cc_o_c) 231 - $(call cmd,gen_ksymdeps) 232 226 $(call cmd,checksrc) 233 227 $(call cmd,checkdoc) 234 228 $(call cmd,gen_objtooldep) ··· 233 239 234 240 define rule_as_o_S 235 241 $(call cmd_and_fixdep,as_o_S) 236 - $(call cmd,gen_ksymdeps) 237 242 $(call cmd,gen_objtooldep) 238 243 $(call cmd,gen_symversions_S) 239 244 $(call cmd,warn_shared_object) ··· 250 257 251 258 $(obj)/%.mod: FORCE 252 259 $(call if_changed,mod) 253 - 254 - # List module undefined symbols 255 - cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@ 256 - 257 - $(obj)/%.usyms: $(obj)/%.o FORCE 258 - $(call if_changed,undefined_syms) 259 260 260 261 quiet_cmd_cc_lst_c = MKLST $@ 261 262 cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \
+7
scripts/Makefile.modpost
··· 91 91 .vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE 92 92 $(call if_changed,vmlinux_objs) 93 93 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 + 94 101 ifeq ($(wildcard vmlinux.o),) 95 102 missing-input := vmlinux.o 96 103 output-symdump := modules-only.symvers
-73
scripts/adjust_autoksyms.sh
··· 1 - #!/bin/sh 2 - # SPDX-License-Identifier: GPL-2.0-only 3 - 4 - # Script to update include/generated/autoksyms.h and dependency files 5 - # 6 - # Copyright: (C) 2016 Linaro Limited 7 - # Created by: Nicolas Pitre, January 2016 8 - # 9 - 10 - # Update the include/generated/autoksyms.h file. 11 - # 12 - # For each symbol being added or removed, the corresponding dependency 13 - # file's timestamp is updated to force a rebuild of the affected source 14 - # file. All arguments passed to this script are assumed to be a command 15 - # to be exec'd to trigger a rebuild of those files. 16 - 17 - set -e 18 - 19 - cur_ksyms_file="include/generated/autoksyms.h" 20 - new_ksyms_file="include/generated/autoksyms.h.tmpnew" 21 - 22 - info() { 23 - if [ "$quiet" != "silent_" ]; then 24 - printf " %-7s %s\n" "$1" "$2" 25 - fi 26 - } 27 - 28 - info "CHK" "$cur_ksyms_file" 29 - 30 - # Use "make V=1" to debug this script. 31 - case "$KBUILD_VERBOSE" in 32 - *1*) 33 - set -x 34 - ;; 35 - esac 36 - 37 - # Generate a new symbol list file 38 - $CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh --modorder "$new_ksyms_file" 39 - 40 - # Extract changes between old and new list and touch corresponding 41 - # dependency files. 42 - changed=$( 43 - count=0 44 - sort "$cur_ksyms_file" "$new_ksyms_file" | uniq -u | 45 - sed -n 's/^#define __KSYM_\(.*\) 1/\1/p' | 46 - while read sympath; do 47 - if [ -z "$sympath" ]; then continue; fi 48 - depfile="include/ksym/${sympath}" 49 - mkdir -p "$(dirname "$depfile")" 50 - touch "$depfile" 51 - # Filesystems with coarse time precision may create timestamps 52 - # equal to the one from a file that was very recently built and that 53 - # needs to be rebuild. Let's guard against that by making sure our 54 - # dep files are always newer than the first file we created here. 55 - while [ ! "$depfile" -nt "$new_ksyms_file" ]; do 56 - touch "$depfile" 57 - done 58 - echo $((count += 1)) 59 - done | tail -1 ) 60 - changed=${changed:-0} 61 - 62 - if [ $changed -gt 0 ]; then 63 - # Replace the old list with tne new one 64 - old=$(grep -c "^#define __KSYM_" "$cur_ksyms_file" || true) 65 - new=$(grep -c "^#define __KSYM_" "$new_ksyms_file" || true) 66 - info "KSYMS" "symbols: before=$old, after=$new, changed=$changed" 67 - info "UPD" "$cur_ksyms_file" 68 - mv -f "$new_ksyms_file" "$cur_ksyms_file" 69 - # Then trigger a rebuild of affected source files 70 - exec $@ 71 - else 72 - rm -f "$new_ksyms_file" 73 - fi
+1 -2
scripts/basic/fixdep.c
··· 246 246 /* Ignore certain dependencies */ 247 247 static int is_ignored_file(const char *s, int len) 248 248 { 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"); 251 250 } 252 251 253 252 /* Do not parse these files */
-62
scripts/gen_autoksyms.sh
··· 1 - #!/bin/sh 2 - # SPDX-License-Identifier: GPL-2.0-only 3 - 4 - # Create an autoksyms.h header file from the list of all module's needed symbols 5 - # as recorded in *.usyms files and the user-provided symbol whitelist. 6 - 7 - set -e 8 - 9 - # Use "make V=1" to debug this script. 10 - case "$KBUILD_VERBOSE" in 11 - *1*) 12 - set -x 13 - ;; 14 - esac 15 - 16 - read_modorder= 17 - 18 - if [ "$1" = --modorder ]; then 19 - shift 20 - read_modorder=1 21 - fi 22 - 23 - output_file="$1" 24 - 25 - needed_symbols= 26 - 27 - # Special case for modversions (see modpost.c) 28 - if grep -q "^CONFIG_MODVERSIONS=y$" include/config/auto.conf; then 29 - needed_symbols="$needed_symbols module_layout" 30 - fi 31 - 32 - ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf) 33 - if [ -n "$ksym_wl" ]; then 34 - [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" 35 - if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then 36 - echo "ERROR: '$ksym_wl' whitelist file not found" >&2 37 - exit 1 38 - fi 39 - fi 40 - 41 - # Generate a new ksym list file with symbols needed by the current 42 - # set of modules. 43 - cat > "$output_file" << EOT 44 - /* 45 - * Automatically generated file; DO NOT EDIT. 46 - */ 47 - 48 - EOT 49 - 50 - { 51 - [ -n "${read_modorder}" ] && sed 's/o$/usyms/' modules.order | xargs cat 52 - echo "$needed_symbols" 53 - [ -n "$ksym_wl" ] && cat "$ksym_wl" 54 - } | sed -e 's/ /\n/g' | sed -n -e '/^$/!p' | 55 - # Remove the dot prefix for ppc64; symbol names with a dot (.) hold entry 56 - # point addresses. 57 - sed -e 's/^\.//' | 58 - sort -u | 59 - # Ignore __this_module. It's not an exported symbol, and will be resolved 60 - # when the final .ko's are linked. 61 - grep -v '^__this_module$' | 62 - sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$output_file"
-30
scripts/gen_ksymdeps.sh
··· 1 - #!/bin/sh 2 - # SPDX-License-Identifier: GPL-2.0 3 - 4 - set -e 5 - 6 - # List of exported symbols 7 - # 8 - # If the object has no symbol, $NM warns 'no symbols'. 9 - # Suppress the stderr. 10 - # TODO: 11 - # Use -q instead of 2>/dev/null when we upgrade the minimum version of 12 - # binutils to 2.37, llvm to 13.0.0. 13 - ksyms=$($NM $1 2>/dev/null | sed -n 's/.*__ksym_marker_\(.*\)/\1/p') 14 - 15 - if [ -z "$ksyms" ]; then 16 - exit 0 17 - fi 18 - 19 - echo 20 - echo "ksymdeps_$1 := \\" 21 - 22 - for s in $ksyms 23 - do 24 - printf ' $(wildcard include/ksym/%s) \\\n' "$s" 25 - done 26 - 27 - echo 28 - echo "$1: \$(ksymdeps_$1)" 29 - echo 30 - echo "\$(ksymdeps_$1):"
+52 -5
scripts/mod/modpost.c
··· 35 35 36 36 static int sec_mismatch_count; 37 37 static bool sec_mismatch_warn_only = true; 38 + /* Trim EXPORT_SYMBOLs that are unused by in-tree modules */ 39 + static bool trim_unused_exports; 40 + 38 41 /* ignore missing files */ 39 42 static bool ignore_missing_files; 40 43 /* If set to 1, only warn (instead of error) about missing ns imports */ ··· 222 219 bool weak; 223 220 bool is_func; 224 221 bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */ 222 + bool used; /* there exists a user of this symbol */ 225 223 char name[]; 226 224 }; 227 225 ··· 1830 1826 continue; 1831 1827 } 1832 1828 1829 + exp->used = true; 1833 1830 s->module = exp->module; 1834 1831 s->crc_valid = exp->crc_valid; 1835 1832 s->crc = exp->crc; ··· 1852 1847 error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n", 1853 1848 basename, exp->name); 1854 1849 } 1850 + } 1851 + 1852 + static void handle_white_list_exports(const char *white_list) 1853 + { 1854 + char *buf, *p, *name; 1855 + 1856 + buf = read_text_file(white_list); 1857 + p = buf; 1858 + 1859 + while ((name = strsep(&p, "\n"))) { 1860 + struct symbol *sym = find_symbol(name); 1861 + 1862 + if (sym) 1863 + sym->used = true; 1864 + } 1865 + 1866 + free(buf); 1855 1867 } 1856 1868 1857 1869 static void check_modname_len(struct module *mod) ··· 1941 1919 1942 1920 /* generate struct for exported symbols */ 1943 1921 buf_printf(buf, "\n"); 1944 - list_for_each_entry(sym, &mod->exported_symbols, list) 1922 + list_for_each_entry(sym, &mod->exported_symbols, list) { 1923 + if (trim_unused_exports && !sym->used) 1924 + continue; 1925 + 1945 1926 buf_printf(buf, "KSYMTAB_%s(%s, \"%s\", \"%s\");\n", 1946 1927 sym->is_func ? "FUNC" : "DATA", sym->name, 1947 1928 sym->is_gpl_only ? "_gpl" : "", sym->namespace); 1929 + } 1948 1930 1949 1931 if (!modversions) 1950 1932 return; ··· 1956 1930 /* record CRCs for exported symbols */ 1957 1931 buf_printf(buf, "\n"); 1958 1932 list_for_each_entry(sym, &mod->exported_symbols, list) { 1933 + if (trim_unused_exports && !sym->used) 1934 + continue; 1935 + 1959 1936 if (!sym->crc_valid) 1960 1937 warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" 1961 1938 "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n", ··· 2122 2093 char fname[PATH_MAX]; 2123 2094 int ret; 2124 2095 2125 - check_modname_len(mod); 2126 - check_exports(mod); 2127 - 2128 2096 add_header(&buf, mod); 2129 2097 add_exported_symbols(&buf, mod); 2130 2098 add_versions(&buf, mod); ··· 2213 2187 if (mod->from_dump) 2214 2188 continue; 2215 2189 list_for_each_entry(sym, &mod->exported_symbols, list) { 2190 + if (trim_unused_exports && !sym->used) 2191 + continue; 2192 + 2216 2193 buf_printf(&buf, "0x%08x\t%s\t%s\tEXPORT_SYMBOL%s\t%s\n", 2217 2194 sym->crc, sym->name, mod->name, 2218 2195 sym->is_gpl_only ? "_GPL" : "", ··· 2258 2229 { 2259 2230 struct module *mod; 2260 2231 char *missing_namespace_deps = NULL; 2232 + char *unused_exports_white_list = NULL; 2261 2233 char *dump_write = NULL, *files_source = NULL; 2262 2234 int opt; 2263 2235 LIST_HEAD(dump_lists); 2264 2236 struct dump_list *dl, *dl2; 2265 2237 2266 - while ((opt = getopt(argc, argv, "ei:mnT:o:aWwENd:")) != -1) { 2238 + while ((opt = getopt(argc, argv, "ei:mnT:to:au:WwENd:")) != -1) { 2267 2239 switch (opt) { 2268 2240 case 'e': 2269 2241 external_module = true; ··· 2288 2258 break; 2289 2259 case 'T': 2290 2260 files_source = optarg; 2261 + break; 2262 + case 't': 2263 + trim_unused_exports = true; 2264 + break; 2265 + case 'u': 2266 + unused_exports_white_list = optarg; 2291 2267 break; 2292 2268 case 'W': 2293 2269 extra_warn = true; ··· 2326 2290 2327 2291 if (files_source) 2328 2292 read_symbols_from_files(files_source); 2293 + 2294 + list_for_each_entry(mod, &modules, list) { 2295 + if (mod->from_dump || mod->is_vmlinux) 2296 + continue; 2297 + 2298 + check_modname_len(mod); 2299 + check_exports(mod); 2300 + } 2301 + 2302 + if (unused_exports_white_list) 2303 + handle_white_list_exports(unused_exports_white_list); 2329 2304 2330 2305 list_for_each_entry(mod, &modules, list) { 2331 2306 if (mod->from_dump)
+4
scripts/remove-stale-files
··· 33 33 rm -f scripts/bin2c 34 34 35 35 rm -f .scmversion 36 + 37 + rm -rf include/ksym 38 + 39 + find . -name '*.usyms' | xargs rm -f