From d5ea4fece4508bf8e72b659cd22fa4840d8d61e5 Mon Sep 17 00:00:00 2001 From: Chun-Tse Shao Date: Fri, 1 Apr 2022 23:18:02 +0000 Subject: kbuild: Allow kernel installation packaging to override pkg-config Add HOSTPKG_CONFIG to allow tooling that builds the kernel to override what pkg-config and parameters are used. Signed-off-by: Chun-Tse Shao Reviewed-by: Nick Desaulniers Signed-off-by: Masahiro Yamada --- scripts/Makefile | 4 ++-- scripts/kconfig/gconf-cfg.sh | 12 ++++++------ scripts/kconfig/mconf-cfg.sh | 16 ++++++++-------- scripts/kconfig/nconf-cfg.sh | 16 ++++++++-------- scripts/kconfig/qconf-cfg.sh | 14 +++++++------- 5 files changed, 31 insertions(+), 31 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile b/scripts/Makefile index ce5aa9030b74..f084f08ed176 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -14,8 +14,8 @@ hostprogs-always-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert HOSTCFLAGS_sorttable.o = -I$(srctree)/tools/include HOSTLDLIBS_sorttable = -lpthread HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include -HOSTCFLAGS_sign-file.o = $(shell pkg-config --cflags libcrypto 2> /dev/null) -HOSTLDLIBS_sign-file = $(shell pkg-config --libs libcrypto 2> /dev/null || echo -lcrypto) +HOSTCFLAGS_sign-file.o = $(shell $(HOSTPKG_CONFIG) --cflags libcrypto 2> /dev/null) +HOSTLDLIBS_sign-file = $(shell $(HOSTPKG_CONFIG) --libs libcrypto 2> /dev/null || echo -lcrypto) ifdef CONFIG_UNWINDER_ORC ifeq ($(ARCH),x86_64) diff --git a/scripts/kconfig/gconf-cfg.sh b/scripts/kconfig/gconf-cfg.sh index 480ecd8b9f41..cbd90c28c05f 100755 --- a/scripts/kconfig/gconf-cfg.sh +++ b/scripts/kconfig/gconf-cfg.sh @@ -3,14 +3,14 @@ PKG="gtk+-2.0 gmodule-2.0 libglade-2.0" -if [ -z "$(command -v pkg-config)" ]; then +if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then echo >&2 "*" - echo >&2 "* 'make gconfig' requires 'pkg-config'. Please install it." + echo >&2 "* 'make gconfig' requires '${HOSTPKG_CONFIG}'. Please install it." echo >&2 "*" exit 1 fi -if ! pkg-config --exists $PKG; then +if ! ${HOSTPKG_CONFIG} --exists $PKG; then echo >&2 "*" echo >&2 "* Unable to find the GTK+ installation. Please make sure that" echo >&2 "* the GTK+ 2.0 development package is correctly installed." @@ -19,12 +19,12 @@ if ! pkg-config --exists $PKG; then exit 1 fi -if ! pkg-config --atleast-version=2.0.0 gtk+-2.0; then +if ! ${HOSTPKG_CONFIG} --atleast-version=2.0.0 gtk+-2.0; then echo >&2 "*" echo >&2 "* GTK+ is present but version >= 2.0.0 is required." echo >&2 "*" exit 1 fi -echo cflags=\"$(pkg-config --cflags $PKG)\" -echo libs=\"$(pkg-config --libs $PKG)\" +echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\" +echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" diff --git a/scripts/kconfig/mconf-cfg.sh b/scripts/kconfig/mconf-cfg.sh index b520e407a8eb..025b565e0b7c 100755 --- a/scripts/kconfig/mconf-cfg.sh +++ b/scripts/kconfig/mconf-cfg.sh @@ -4,16 +4,16 @@ PKG="ncursesw" PKG2="ncurses" -if [ -n "$(command -v pkg-config)" ]; then - if pkg-config --exists $PKG; then - echo cflags=\"$(pkg-config --cflags $PKG)\" - echo libs=\"$(pkg-config --libs $PKG)\" +if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then + if ${HOSTPKG_CONFIG} --exists $PKG; then + echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\" + echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" exit 0 fi - if pkg-config --exists $PKG2; then - echo cflags=\"$(pkg-config --cflags $PKG2)\" - echo libs=\"$(pkg-config --libs $PKG2)\" + if ${HOSTPKG_CONFIG} --exists $PKG2; then + echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\" + echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\" exit 0 fi fi @@ -46,7 +46,7 @@ echo >&2 "* Unable to find the ncurses package." echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev" echo >&2 "* depending on your distribution)." echo >&2 "*" -echo >&2 "* You may also need to install pkg-config to find the" +echo >&2 "* You may also need to install ${HOSTPKG_CONFIG} to find the" echo >&2 "* ncurses installed in a non-default location." echo >&2 "*" exit 1 diff --git a/scripts/kconfig/nconf-cfg.sh b/scripts/kconfig/nconf-cfg.sh index c212255070c0..3a10bac2adb3 100755 --- a/scripts/kconfig/nconf-cfg.sh +++ b/scripts/kconfig/nconf-cfg.sh @@ -4,16 +4,16 @@ PKG="ncursesw menuw panelw" PKG2="ncurses menu panel" -if [ -n "$(command -v pkg-config)" ]; then - if pkg-config --exists $PKG; then - echo cflags=\"$(pkg-config --cflags $PKG)\" - echo libs=\"$(pkg-config --libs $PKG)\" +if [ -n "$(command -v ${HOSTPKG_CONFIG})" ]; then + if ${HOSTPKG_CONFIG} --exists $PKG; then + echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG)\" + echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" exit 0 fi - if pkg-config --exists $PKG2; then - echo cflags=\"$(pkg-config --cflags $PKG2)\" - echo libs=\"$(pkg-config --libs $PKG2)\" + if ${HOSTPKG_CONFIG} --exists $PKG2; then + echo cflags=\"$(${HOSTPKG_CONFIG} --cflags $PKG2)\" + echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG2)\" exit 0 fi fi @@ -44,7 +44,7 @@ echo >&2 "* Unable to find the ncurses package." echo >&2 "* Install ncurses (ncurses-devel or libncurses-dev" echo >&2 "* depending on your distribution)." echo >&2 "*" -echo >&2 "* You may also need to install pkg-config to find the" +echo >&2 "* You may also need to install ${HOSTPKG_CONFIG} to find the" echo >&2 "* ncurses installed in a non-default location." echo >&2 "*" exit 1 diff --git a/scripts/kconfig/qconf-cfg.sh b/scripts/kconfig/qconf-cfg.sh index fa564cd795b7..9b695e5cd9b3 100755 --- a/scripts/kconfig/qconf-cfg.sh +++ b/scripts/kconfig/qconf-cfg.sh @@ -3,22 +3,22 @@ PKG="Qt5Core Qt5Gui Qt5Widgets" -if [ -z "$(command -v pkg-config)" ]; then +if [ -z "$(command -v ${HOSTPKG_CONFIG})" ]; then echo >&2 "*" - echo >&2 "* 'make xconfig' requires 'pkg-config'. Please install it." + echo >&2 "* 'make xconfig' requires '${HOSTPKG_CONFIG}'. Please install it." echo >&2 "*" exit 1 fi -if pkg-config --exists $PKG; then - echo cflags=\"-std=c++11 -fPIC $(pkg-config --cflags $PKG)\" - echo libs=\"$(pkg-config --libs $PKG)\" - echo moc=\"$(pkg-config --variable=host_bins Qt5Core)/moc\" +if ${HOSTPKG_CONFIG} --exists $PKG; then + echo cflags=\"-std=c++11 -fPIC $(${HOSTPKG_CONFIG} --cflags $PKG)\" + echo libs=\"$(${HOSTPKG_CONFIG} --libs $PKG)\" + echo moc=\"$(${HOSTPKG_CONFIG} --variable=host_bins Qt5Core)/moc\" exit 0 fi echo >&2 "*" -echo >&2 "* Could not find Qt5 via pkg-config." +echo >&2 "* Could not find Qt5 via ${HOSTPKG_CONFIG}." echo >&2 "* Please install Qt5 and make sure it's in PKG_CONFIG_PATH" echo >&2 "*" exit 1 -- cgit From f43e31d5cb7859189a8be5699f4347e07b07c1df Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:49 +0900 Subject: kbuild: factor out genksyms command from cmd_gensymtypes_{c,S} The genksyms command part in cmd_gensymtypes_{c,S} is duplicated. Factor it out into the 'genksyms' macro. For the readability, I slightly refactor the arguments to genksyms. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers Reviewed-by: Nicolas Schier --- scripts/Makefile.build | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 9717e6f6fb31..31e0e33dfe5d 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -125,13 +125,14 @@ cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $< $(obj)/%.i: $(src)/%.c FORCE $(call if_changed_dep,cpp_i_c) +genksyms = scripts/genksyms/genksyms \ + $(if $(1), -T $(2)) \ + $(if $(CONFIG_MODULE_REL_CRCS), -R) \ + $(if $(KBUILD_PRESERVE), -p) \ + -r $(or $(wildcard $(2:.symtypes=.symref)), /dev/null) + # These mirror gensymtypes_S and co below, keep them in synch. -cmd_gensymtypes_c = \ - $(CPP) -D__GENKSYMS__ $(c_flags) $< | \ - scripts/genksyms/genksyms $(if $(1), -T $(2)) \ - $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \ - $(if $(KBUILD_PRESERVE),-p) \ - -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) +cmd_gensymtypes_c = $(CPP) -D__GENKSYMS__ $(c_flags) $< | $(genksyms) quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ cmd_cc_symtypes_c = \ @@ -344,11 +345,7 @@ cmd_gensymtypes_S = \ $(CPP) $(a_flags) $< | \ grep "\<___EXPORT_SYMBOL\>" | \ sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \ - $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | \ - scripts/genksyms/genksyms $(if $(1), -T $(2)) \ - $(patsubst y,-R,$(CONFIG_MODULE_REL_CRCS)) \ - $(if $(KBUILD_PRESERVE),-p) \ - -r $(firstword $(wildcard $(2:.symtypes=.symref) /dev/null)) + $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms) quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@ cmd_cc_symtypes_S = \ -- cgit From dc6dc3e7a73fc09c9ce773bc23bc2864d4c13284 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:50 +0900 Subject: kbuild: do not remove empty *.symtypes explicitly Presumably, 'test -s $@ || rm -f $@' intends to remove the output when the genksyms command fails. It is unneeded because .DELETE_ON_ERROR automatically removes the output on failure. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers Reviewed-by: Nicolas Schier --- scripts/Makefile.build | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 31e0e33dfe5d..3ef2373f0a57 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -135,9 +135,7 @@ genksyms = scripts/genksyms/genksyms \ cmd_gensymtypes_c = $(CPP) -D__GENKSYMS__ $(c_flags) $< | $(genksyms) quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@ -cmd_cc_symtypes_c = \ - $(call cmd_gensymtypes_c,true,$@) >/dev/null; \ - test -s $@ || rm -f $@ + cmd_cc_symtypes_c = $(call cmd_gensymtypes_c,true,$@) >/dev/null $(obj)/%.symtypes : $(src)/%.c FORCE $(call cmd,cc_symtypes_c) @@ -348,9 +346,7 @@ cmd_gensymtypes_S = \ $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms) quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@ -cmd_cc_symtypes_S = \ - $(call cmd_gensymtypes_S,true,$@) >/dev/null; \ - test -s $@ || rm -f $@ + cmd_cc_symtypes_S = $(call cmd_gensymtypes_S,true,$@) >/dev/null $(obj)/%.symtypes : $(src)/%.S FORCE $(call cmd,cc_symtypes_S) -- cgit From 5b5bfecaa333fb6a0cce1bfc4852a622dacfed1d Mon Sep 17 00:00:00 2001 From: SeongJae Park Date: Tue, 19 Apr 2022 12:16:36 +0000 Subject: scripts/get_abi: Fix wrong script file name in the help message The help message of 'get_abi.pl' is mistakenly saying it's 'abi_book.pl'. This commit fixes the wrong name in the help message. Fixes: bbc249f2b859 ("scripts: add an script to parse the ABI files") Signed-off-by: SeongJae Park Link: https://lore.kernel.org/r/20220419121636.290407-1-sj@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 1389db76cff3..0ffd5531242a 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -981,11 +981,11 @@ __END__ =head1 NAME -abi_book.pl - parse the Linux ABI files and produce a ReST book. +get_abi.pl - parse the Linux ABI files and produce a ReST book. =head1 SYNOPSIS -B [--debug ] [--enable-lineno] [--man] [--help] +B [--debug ] [--enable-lineno] [--man] [--help] [--(no-)rst-source] [--dir=] [--show-hints] [--search-string ] [] -- cgit From 73f1d07e5f8a1dec989a5ec964f5f2ce5b6f8825 Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Tue, 26 Apr 2022 00:32:12 -0500 Subject: checkpatch: add new alloc functions to alloc with multiplies check kvmalloc() and kvzalloc() functions have now 2-factor multiplication argument forms kvmalloc_array() and kvcalloc(), correspondingly. Add alloc-with-multiplies checks for these new functions. Link: https://github.com/KSPP/linux/issues/187 Signed-off-by: Gustavo A. R. Silva --- scripts/checkpatch.pl | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 577e02998701..503e8abbb2c1 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -7033,14 +7033,16 @@ sub process { "Prefer $3(sizeof(*$1)...) over $3($4...)\n" . $herecurr); } -# check for k[mz]alloc with multiplies that could be kmalloc_array/kcalloc +# check for (kv|k)[mz]alloc with multiplies that could be kmalloc_array/kvmalloc_array/kvcalloc/kcalloc if ($perl_version_ok && defined $stat && - $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { + $stat =~ /^\+\s*($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)\s*,/) { my $oldfunc = $3; my $a1 = $4; my $a2 = $10; my $newfunc = "kmalloc_array"; + $newfunc = "kvmalloc_array" if ($oldfunc eq "kvmalloc"); + $newfunc = "kvcalloc" if ($oldfunc eq "kvzalloc"); $newfunc = "kcalloc" if ($oldfunc eq "kzalloc"); my $r1 = $a1; my $r2 = $a2; @@ -7057,7 +7059,7 @@ sub process { "Prefer $newfunc over $oldfunc with multiply\n" . $herectx) && $cnt == 1 && $fix) { - $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*(k[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; + $fixed[$fixlinenr] =~ s/\b($Lval)\s*\=\s*(?:$balanced_parens)?\s*((?:kv|k)[mz]alloc)\s*\(\s*($FuncArg)\s*\*\s*($FuncArg)/$1 . ' = ' . "$newfunc(" . trim($r1) . ', ' . trim($r2)/e; } } } -- cgit From c268c0a8a33047cd957fecc1349d09a68eb6ad9e Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Tue, 5 Apr 2022 19:27:54 +0530 Subject: bus: mhi: ep: Add uevent support for module autoloading Add uevent support to MHI endpoint bus so that the client drivers can be autoloaded by udev when the MHI endpoint devices gets created. The client drivers are expected to provide MODULE_DEVICE_TABLE with the MHI id_table struct so that the alias can be exported. The MHI endpoint reused the mhi_device_id structure of the MHI bus. Reviewed-by: Alex Elder Signed-off-by: Manivannan Sadhasivam Link: https://lore.kernel.org/r/20220405135754.6622-19-manivannan.sadhasivam@linaro.org Signed-off-by: Greg Kroah-Hartman --- scripts/mod/file2alias.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'scripts') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 5258247d78ac..d9d6a31446ea 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -1391,6 +1391,15 @@ static int do_mhi_entry(const char *filename, void *symval, char *alias) return 1; } +/* Looks like: mhi_ep:S */ +static int do_mhi_ep_entry(const char *filename, void *symval, char *alias) +{ + DEF_FIELD_ADDR(symval, mhi_device_id, chan); + sprintf(alias, MHI_EP_DEVICE_MODALIAS_FMT, *chan); + + return 1; +} + /* Looks like: ishtp:{guid} */ static int do_ishtp_entry(const char *filename, void *symval, char *alias) { @@ -1519,6 +1528,7 @@ static const struct devtable devtable[] = { {"tee", SIZE_tee_client_device_id, do_tee_entry}, {"wmi", SIZE_wmi_device_id, do_wmi_entry}, {"mhi", SIZE_mhi_device_id, do_mhi_entry}, + {"mhi_ep", SIZE_mhi_device_id, do_mhi_ep_entry}, {"auxiliary", SIZE_auxiliary_device_id, do_auxiliary_entry}, {"ssam", SIZE_ssam_device_id, do_ssam_entry}, {"dfl", SIZE_dfl_device_id, do_dfl_entry}, -- cgit From 6ccf9cb557bd32073b0d68baed97f1bd8a40ff1d Mon Sep 17 00:00:00 2001 From: Kalesh Singh Date: Wed, 20 Apr 2022 14:42:57 -0700 Subject: KVM: arm64: Symbolize the nVHE HYP addresses Reintroduce the __kvm_nvhe_ symbols in kallsyms, ignoring the local symbols in this namespace. The local symbols are not informative and can cause aliasing issues when symbolizing the addresses. With the necessary symbols now in kallsyms we can symbolize nVHE addresses using the %p print format specifier: [ 98.916444][ T426] kvm [426]: nVHE hyp panic at: [] __kvm_nvhe_overflow_stack+0x8/0x34! Signed-off-by: Kalesh Singh Tested-by: Fuad Tabba Reviewed-by: Fuad Tabba Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20220420214317.3303360-7-kaleshsingh@google.com --- scripts/kallsyms.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 8caabddf817c..e6906f79833d 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -111,7 +111,8 @@ static bool is_ignored_symbol(const char *name, char type) ".L", /* local labels, .LBB,.Ltmpxxx,.L__unnamed_xx,.LASANPC, etc. */ "__crc_", /* modversions */ "__efistub_", /* arm64 EFI stub namespace */ - "__kvm_nvhe_", /* arm64 non-VHE KVM namespace */ + "__kvm_nvhe_$", /* arm64 local symbols in non-VHE KVM namespace */ + "__kvm_nvhe_.L", /* arm64 local symbols in non-VHE KVM namespace */ "__AArch64ADRPThunk_", /* arm64 lld */ "__ARMV5PILongThunk_", /* arm lld */ "__ARMV7PILongThunk_", -- cgit From 3af8acf6aff2a98731522b52927429760f0b8006 Mon Sep 17 00:00:00 2001 From: Schspa Shi Date: Fri, 29 Apr 2022 14:37:57 -0700 Subject: scripts/decode_stacktrace.sh: support old bash version Old bash version don't support associative array variables. Avoid to use associative array variables to avoid error. Without this, old bash version will report error as fellowing [ 15.954042] Kernel panic - not syncing: sysrq triggered crash [ 15.955252] CPU: 1 PID: 167 Comm: sh Not tainted 5.18.0-rc1-00208-gb7d075db2fd5 #4 [ 15.956472] Hardware name: Hobot J5 Virtual development board (DT) [ 15.957856] Call trace: ./scripts/decode_stacktrace.sh: line 128: ,dump_backtrace: syntax error: operand expected (error token is ",dump_backtrace") Link: https://lkml.kernel.org/r/20220409180331.24047-1-schspa@gmail.com Signed-off-by: Schspa Shi Cc: Stephen Boyd Signed-off-by: Andrew Morton --- scripts/decode_stacktrace.sh | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh index 5fbad61fe490..7075e26ab2c4 100755 --- a/scripts/decode_stacktrace.sh +++ b/scripts/decode_stacktrace.sh @@ -45,8 +45,13 @@ else fi fi -declare -A cache -declare -A modcache +declare aarray_support=true +declare -A cache 2>/dev/null +if [[ $? != 0 ]]; then + aarray_support=false +else + declare -A modcache +fi find_module() { if [[ -n $debuginfod ]] ; then @@ -97,7 +102,7 @@ parse_symbol() { if [[ $module == "" ]] ; then local objfile=$vmlinux - elif [[ "${modcache[$module]+isset}" == "isset" ]]; then + elif [[ $aarray_support == true && "${modcache[$module]+isset}" == "isset" ]]; then local objfile=${modcache[$module]} else local objfile=$(find_module) @@ -105,7 +110,9 @@ parse_symbol() { echo "WARNING! Modules path isn't set, but is needed to parse this symbol" >&2 return fi - modcache[$module]=$objfile + if [[ $aarray_support == true ]]; then + modcache[$module]=$objfile + fi fi # Remove the englobing parenthesis @@ -125,7 +132,7 @@ parse_symbol() { # Use 'nm vmlinux' to figure out the base address of said symbol. # It's actually faster to call it every time than to load it # all into bash. - if [[ "${cache[$module,$name]+isset}" == "isset" ]]; then + if [[ $aarray_support == true && "${cache[$module,$name]+isset}" == "isset" ]]; then local base_addr=${cache[$module,$name]} else local base_addr=$(nm "$objfile" 2>/dev/null | awk '$3 == "'$name'" && ($2 == "t" || $2 == "T") {print $1; exit}') @@ -133,7 +140,9 @@ parse_symbol() { # address not found return fi - cache[$module,$name]="$base_addr" + if [[ $aarray_support == true ]]; then + cache[$module,$name]="$base_addr" + fi fi # Let's start doing the math to get the exact address into the # symbol. First, strip out the symbol total length. @@ -149,11 +158,13 @@ parse_symbol() { # Pass it to addr2line to get filename and line number # Could get more than one result - if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then + if [[ $aarray_support == true && "${cache[$module,$address]+isset}" == "isset" ]]; then local code=${cache[$module,$address]} else local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address" 2>/dev/null) - cache[$module,$address]=$code + if [[ $aarray_support == true ]]; then + cache[$module,$address]=$code + fi fi # addr2line doesn't return a proper error code if it fails, so -- cgit From dec81a532027a77bd52f9bd8d8b3230843533d3f Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 29 Apr 2022 14:37:57 -0700 Subject: scripts/bloat-o-meter: filter out vermagic as it is not relevant Seeing it as a false positive increase at the top is just noise: linux-head$./scripts/bloat-o-meter ../pre/vmlinux ../post/vmlinux add/remove: 0/571 grow/shrink: 1/9 up/down: 20/-64662 (-64642) Function old new delta vermagic 49 69 +20 Since it really doesn't "grow", it makes sense to filter it out. Link: https://lkml.kernel.org/r/20220428035824.7934-1-paul.gortmaker@windriver.com Signed-off-by: Paul Gortmaker Signed-off-by: Andrew Morton --- scripts/bloat-o-meter | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter index dcd8d8750b8b..4dd6a804ce41 100755 --- a/scripts/bloat-o-meter +++ b/scripts/bloat-o-meter @@ -36,6 +36,7 @@ def getsizes(file, format): if name.startswith("__se_compat_sys"): continue if name.startswith("__addressable_"): continue if name == "linux_banner": continue + if name == "vermagic": continue # statics and some other optimizations adds random .NUMBER name = re_NUMBER.sub('', name) sym[name] = sym.get(name, 0) + int(size, 16) -- cgit From 11fb48961e5250768767612da4a303fa2f5ea504 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 29 Apr 2022 14:38:00 -0700 Subject: get_maintainer: Honor mailmap for in file emails Add support to also use the mailmap for 'in file' email addresses. Link: https://lkml.kernel.org/r/20220323193645.317514-1-robh@kernel.org Signed-off-by: Rob Herring Reported-by: Marc Zyngier Acked-by: Joe Perches Signed-off-by: Andrew Morton --- scripts/get_maintainer.pl | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 6bd5221d37b8..ab123b498fd9 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -983,6 +983,7 @@ sub get_maintainers { } foreach my $email (@file_emails) { + $email = mailmap_email($email); my ($name, $address) = parse_email($email); my $tmp_email = format_email($name, $address, $email_usename); -- cgit From 7ce3e410e0188ce7ca65b49c90cff2863d6e232e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:51 +0900 Subject: modpost: remove useless export_from_sec() With commit 1743694eb235 ("modpost: stop symbol preloading for modversion CRC") applied, now export_from_sec() is useless. handle_symbol() is called for every symbol in the ELF. When 'symname' does not start with "__ksymtab", export_from_sec() is called, and the returned value is stored in 'export'. It is used in the last part of handle_symbol(): if (strstarts(symname, "__ksymtab_")) { name = symname + strlen("__ksymtab_"); sym_add_exported(name, mod, export); } 'export' is used only when 'symname' starts with "__ksymtab_". So, the value returned by export_from_sec() is never used. Remove useless export_from_sec(). This makes further cleanups possible. I put the temporary code: export = export_unknown; Otherwise, I would get the compiler warning: warning: 'export' may be used uninitialized in this function [-Wmaybe-uninitialized] This is apparently false positive because if (strstarts(symname, "__ksymtab_") ... is a stronger condition than: if (strstarts(symname, "__ksymtab") Anyway, this part will be cleaned up by the next commit. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 17 ++--------------- scripts/mod/modpost.h | 2 -- 2 files changed, 2 insertions(+), 17 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index ed9d056d2108..eebb32689816 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -369,16 +369,6 @@ static enum export export_from_secname(struct elf_info *elf, unsigned int sec) return export_unknown; } -static enum export export_from_sec(struct elf_info *elf, unsigned int sec) -{ - if (sec == elf->export_sec) - return export_plain; - else if (sec == elf->export_gpl_sec) - return export_gpl; - else - return export_unknown; -} - static const char *namespace_from_kstrtabns(const struct elf_info *info, const Elf_Sym *sym) { @@ -576,10 +566,7 @@ 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, "__ksymtab") == 0) - info->export_sec = i; - else if (strcmp(secname, "__ksymtab_gpl") == 0) - info->export_gpl_sec = i; + } if (sechdrs[i].sh_type == SHT_SYMTAB) { unsigned int sh_link_idx; @@ -703,7 +690,7 @@ static void handle_symbol(struct module *mod, struct elf_info *info, if (strstarts(symname, "__ksymtab")) export = export_from_secname(info, get_secindex(info, sym)); else - export = export_from_sec(info, get_secindex(info, sym)); + export = export_unknown; switch (sym->st_shndx) { case SHN_COMMON: diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 0c47ff95c0e2..0a940fd2e5c7 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -138,8 +138,6 @@ struct elf_info { Elf_Shdr *sechdrs; Elf_Sym *symtab_start; Elf_Sym *symtab_stop; - Elf_Section export_sec; - Elf_Section export_gpl_sec; char *strtab; char *modinfo; unsigned int modinfo_len; -- cgit From 535b3e05f435698f8f661d9e6449beb5791fff59 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:52 +0900 Subject: modpost: move export_from_secname() call to more relevant place The assigned 'export' is only used when if (strstarts(symname, "__ksymtab_")) is met. The else-part of the assignment is the dead code. Move the export_from_secname() call to where it is used. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index eebb32689816..f9e54247ae1d 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -684,14 +684,8 @@ static void handle_modversion(const struct module *mod, static void handle_symbol(struct module *mod, struct elf_info *info, const Elf_Sym *sym, const char *symname) { - enum export export; const char *name; - if (strstarts(symname, "__ksymtab")) - export = export_from_secname(info, get_secindex(info, sym)); - else - export = export_unknown; - switch (sym->st_shndx) { case SHN_COMMON: if (strstarts(symname, "__gnu_lto_")) { @@ -726,7 +720,11 @@ static void handle_symbol(struct module *mod, struct elf_info *info, default: /* All exported symbols */ if (strstarts(symname, "__ksymtab_")) { + enum export export; + name = symname + strlen("__ksymtab_"); + export = export_from_secname(info, + get_secindex(info, sym)); sym_add_exported(name, mod, export); } if (strcmp(symname, "init_module") == 0) -- cgit From b5f1a52a59eb810f68c96d1cea7cf1256c39956c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:53 +0900 Subject: modpost: remove redundant initializes for static variables These are initialized with zeros without explicit initializers. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index f9e54247ae1d..2a202764ff48 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -23,15 +23,15 @@ #include "../../include/linux/license.h" /* Are we using CONFIG_MODVERSIONS? */ -static int modversions = 0; +static int modversions; /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ -static int all_versions = 0; +static int all_versions; /* If we are modposting external module set to 1 */ -static int external_module = 0; +static int external_module; /* Only warn about unresolved symbols */ -static int warn_unresolved = 0; +static int warn_unresolved; /* How a symbol is exported */ -static int sec_mismatch_count = 0; +static int sec_mismatch_count; static int sec_mismatch_warn_only = true; /* ignore missing files */ static int ignore_missing_files; -- cgit From 79f646e8654b6b8e4f7dda456ec3eabd51052041 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:54 +0900 Subject: modpost: remove annoying namespace_from_kstrtabns() There are two call sites for sym_update_namespace(). When the symbol has no namespace, s->namespace is set to NULL, but the conversion from "" to NULL is done in two different places. [1] read_symbols() This gets the namespace from __kstrtabns_. If the symbol has no namespace, sym_get_data(info, sym) returns the empty string "". namespace_from_kstrtabns() converts it to NULL before it is passed to sym_update_namespace(). [2] read_dump() This gets the namespace from the dump file, *.symvers. If the symbol has no namespace, the 'namespace' is the empty string "", which is directly passed into sym_update_namespace(). The conversion from "" to NULL is done in sym_update_namespace(). namespace_from_kstrtabns() exists only for creating this inconsistency. Remove namespace_from_kstrtabns() so that sym_update_namespace() is consistently passed with "" instead of NULL. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2a202764ff48..522d5249d196 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -369,13 +369,6 @@ static enum export export_from_secname(struct elf_info *elf, unsigned int sec) return export_unknown; } -static const char *namespace_from_kstrtabns(const struct elf_info *info, - const Elf_Sym *sym) -{ - const char *value = sym_get_data(info, sym); - return value[0] ? value : NULL; -} - static void sym_update_namespace(const char *symname, const char *namespace) { struct symbol *s = find_symbol(symname); @@ -391,8 +384,7 @@ static void sym_update_namespace(const char *symname, const char *namespace) } free(s->namespace); - s->namespace = - namespace && namespace[0] ? NOFAIL(strdup(namespace)) : NULL; + s->namespace = namespace[0] ? NOFAIL(strdup(namespace)) : NULL; } /** @@ -2049,9 +2041,7 @@ static void read_symbols(const char *modname) /* Apply symbol namespaces from __kstrtabns_ entries. */ if (strstarts(symname, "__kstrtabns_")) sym_update_namespace(symname + strlen("__kstrtabns_"), - namespace_from_kstrtabns(&info, - sym)); - + sym_get_data(&info, sym)); if (strstarts(symname, "__crc_")) handle_modversion(mod, &info, sym, symname + strlen("__crc_")); -- cgit From 8017ce50641c303b9b5d96f3c10229ecfd770a70 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:57 +0900 Subject: kbuild: refactor cmd_modversions_c cmd_modversions_c implements two parts; run genksyms to calculate CRCs of exported symbols, run $(LD) to update the object with the CRCs. The latter is not executed for CONFIG_LTO_CLANG=y since the object is not ELF but LLVM bit code at this point. The first part can be unified because we can always use $(NM) instead of "$(OBJDUMP) -h" to dump the symbols. Split the code into the two macros, cmd_gen_symversions_c and cmd_modversions. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/Makefile.build | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 3ef2373f0a57..e1992ddc35f6 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -168,29 +168,25 @@ ifdef CONFIG_MODVERSIONS # the actual value of the checksum generated by genksyms # o remove .tmp_.o to .o -ifdef CONFIG_LTO_CLANG # Generate .o.symversions files for each .o with exported symbols, and link these # to the kernel and/or modules at the end. -cmd_modversions_c = \ +gen_symversions = \ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \ - $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ + $(call cmd_gensymtypes_$(1),$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ > $@.symversions; \ else \ rm -f $@.symversions; \ - fi; -else -cmd_modversions_c = \ - if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \ - $(call cmd_gensymtypes_c,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ - > $(@D)/.tmp_$(@F:.o=.ver); \ - \ + fi + +cmd_gen_symversions_c = $(call gen_symversions,c) + +cmd_modversions = \ + if [ -r $@.symversions ]; then \ $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \ - -T $(@D)/.tmp_$(@F:.o=.ver); \ + -T $@.symversions; \ mv -f $(@D)/.tmp_$(@F) $@; \ - rm -f $(@D)/.tmp_$(@F:.o=.ver); \ fi endif -endif ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT # compiler will not generate __mcount_loc use recordmcount or recordmcount.pl @@ -271,7 +267,8 @@ define rule_cc_o_c $(call cmd,checksrc) $(call cmd,checkdoc) $(call cmd,gen_objtooldep) - $(call cmd,modversions_c) + $(call cmd,gen_symversions_c) + $(if $(CONFIG_LTO_CLANG),,$(call cmd,modversions)) $(call cmd,record_mcount) endef -- cgit From 7cfa2fcbac167ca0ceadf25a4b600391fd01fb29 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 5 Apr 2022 20:33:58 +0900 Subject: kbuild: refactor cmd_modversions_S Split the code into two macros, cmd_gen_symversions_S for running genksyms, and cmd_modversions for running $(LD) to update the object with CRCs. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/Makefile.build | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index e1992ddc35f6..f15c245dc17e 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -276,7 +276,8 @@ define rule_as_o_S $(call cmd_and_fixdep,as_o_S) $(call cmd,gen_ksymdeps) $(call cmd,gen_objtooldep) - $(call cmd,modversions_S) + $(call cmd,gen_symversions_S) + $(call cmd,modversions) endef # Built-in and composite module parts @@ -363,16 +364,8 @@ ifdef CONFIG_ASM_MODVERSIONS # versioning matches the C process described above, with difference that # we parse asm-prototypes.h C header to get function definitions. -cmd_modversions_S = \ - if $(OBJDUMP) -h $@ | grep -q __ksymtab; then \ - $(call cmd_gensymtypes_S,$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ - > $(@D)/.tmp_$(@F:.o=.ver); \ - \ - $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \ - -T $(@D)/.tmp_$(@F:.o=.ver); \ - mv -f $(@D)/.tmp_$(@F) $@; \ - rm -f $(@D)/.tmp_$(@F:.o=.ver); \ - fi +cmd_gen_symversions_S = $(call gen_symversions,S) + endif $(obj)/%.o: $(src)/%.S FORCE -- cgit From 9eef99f7a335e4ffc6dfe65fc29c7d38dafae915 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 7 Apr 2022 00:30:17 +0900 Subject: kbuild: reuse suffix-search to refactor multi_depend The complicated part of multi_depend is the same as suffix-search. Reuse it. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 9f69ecdd7977..d56cda3c1e8a 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -238,7 +238,7 @@ endif define multi_depend $(foreach m, $(notdir $1), \ $(eval $(obj)/$m: \ - $(addprefix $(obj)/, $(foreach s, $3, $($(m:%$(strip $2)=%$(s))))))) + $(addprefix $(obj)/, $(call suffix-search, $m, $2, $3)))) endef # Copy a file -- cgit From f97cf399915bc928f5f97ce93e15ce40da514e16 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 7 Apr 2022 00:30:18 +0900 Subject: kbuild: make multi_depend work with targets in subdirectory Precisely speaking, when you get the stem of the path, you should use $(patsubst $(obj)/%,%,...) instead of $(notdir ...). I do not see this usecase, but if you create a composite object in a subdirectory, the Makefile should look like this: obj-$(CONFIG_FOO) += dir/foo.o dir/foo-objs := dir/foo1.o dir/foo2.o The member objects should be assigned to dir/foo-objs instead of foo-objs. This syntax is more consistent with commit 54b8ae66ae1a ("kbuild: change *FLAGS_.o to take the path relative to $(obj)"). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/Makefile.lib | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index d56cda3c1e8a..0453a1904646 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -236,9 +236,9 @@ endif # Usage: # $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add) define multi_depend -$(foreach m, $(notdir $1), \ - $(eval $(obj)/$m: \ - $(addprefix $(obj)/, $(call suffix-search, $m, $2, $3)))) +$(foreach m, $1, \ + $(eval $m: \ + $(addprefix $(obj)/, $(call suffix-search, $(patsubst $(obj)/%,%,$m), $2, $3)))) endef # Copy a file -- cgit From b3591e061919c837c14680c1ceff8f009ed0afb4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 7 Apr 2022 00:30:19 +0900 Subject: kbuild: reuse real-search to simplify cmd_mod The first command in cmd_mod is similar to the real-search macro. Reuse it. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/Makefile.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index f15c245dc17e..857329844789 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -306,7 +306,7 @@ $(obj)/%.prelink.o: $(obj)/%.o FORCE endif cmd_mod = { \ - echo $(if $($*-objs)$($*-y)$($*-m), $(addprefix $(obj)/, $($*-objs) $($*-y) $($*-m)), $(@:.mod=.o)); \ + echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)); \ $(undefined_syms) echo; \ } > $@ -- cgit From 9413e7640564fe70b24ea1a9ff3fb92c5bb52fcb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 7 Apr 2022 00:30:20 +0900 Subject: kbuild: split the second line of *.mod into *.usyms The *.mod files have two lines; the first line lists the member objects of the module, and the second line, if CONFIG_TRIM_UNUSED_KSYMS=y, lists the undefined symbols. Currently, we generate *.mod after constructing composite modules, otherwise, we cannot compute the second line. No prerequisite is required to print the first line. They are orthogonal. Splitting them into separate commands will ease further cleanups. This commit splits the list of undefined symbols out to *.usyms files. Previously, the list of undefined symbols ended up with a very long line, but now it has one symbol per line. Use sed like we did before commit 7d32358be8ac ("kbuild: avoid split lines in .mod files"). Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier --- scripts/Makefile.build | 17 +++++++++-------- scripts/adjust_autoksyms.sh | 2 +- scripts/gen_autoksyms.sh | 18 +++++++++++------- scripts/mod/sumversion.c | 11 ++--------- 4 files changed, 23 insertions(+), 25 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 857329844789..6ae92d119dfa 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -85,7 +85,8 @@ ifdef need-builtin targets-for-builtin += $(obj)/built-in.a endif -targets-for-modules := $(patsubst %.o, %.mod, $(filter %.o, $(obj-m))) +targets-for-modules := $(foreach x, mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \ + $(patsubst %.o, %.$x, $(filter %.o, $(obj-m)))) ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) targets-for-modules += $(patsubst %.o, %.prelink.o, $(filter %.o, $(obj-m))) @@ -256,9 +257,6 @@ endif ifdef CONFIG_TRIM_UNUSED_KSYMS cmd_gen_ksymdeps = \ $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd - -# List module undefined symbols -undefined_syms = $(NM) $< | $(AWK) '$$1 == "U" { printf("%s%s", x++ ? " " : "", $$2) }'; endif define rule_cc_o_c @@ -305,14 +303,17 @@ $(obj)/%.prelink.o: $(obj)/%.o FORCE $(call if_changed,cc_prelink_modules) endif -cmd_mod = { \ - echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)); \ - $(undefined_syms) echo; \ - } > $@ +cmd_mod = echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)) > $@ $(obj)/%.mod: $(obj)/%$(mod-prelink-ext).o FORCE $(call if_changed,mod) +# List module undefined symbols +cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@ + +$(obj)/%.usyms: $(obj)/%$(mod-prelink-ext).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 \ diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh index 59fdb875e818..f1b5ac818411 100755 --- a/scripts/adjust_autoksyms.sh +++ b/scripts/adjust_autoksyms.sh @@ -35,7 +35,7 @@ case "$KBUILD_VERBOSE" in esac # Generate a new symbol list file -$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh "$new_ksyms_file" +$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh --modorder "$new_ksyms_file" # Extract changes between old and new list and touch corresponding # dependency files. diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index 120225c541c5..faacf7062122 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -2,13 +2,10 @@ # SPDX-License-Identifier: GPL-2.0-only # Create an autoksyms.h header file from the list of all module's needed symbols -# as recorded on the second line of *.mod files and the user-provided symbol -# whitelist. +# as recorded in *.usyms files and the user-provided symbol whitelist. set -e -output_file="$1" - # Use "make V=1" to debug this script. case "$KBUILD_VERBOSE" in *1*) @@ -16,6 +13,15 @@ case "$KBUILD_VERBOSE" in ;; esac +read_modorder= + +if [ "$1" = --modorder ]; then + shift + read_modorder=1 +fi + +output_file="$1" + needed_symbols= # Special case for modversions (see modpost.c) @@ -41,10 +47,8 @@ cat > "$output_file" << EOT EOT -[ -f modules.order ] && modlist=modules.order || modlist=/dev/null - { - sed 's/ko$/mod/' $modlist | xargs -n1 sed -n -e '2p' + [ -n "${read_modorder}" ] && sed 's/ko$/usyms/' modules.order | xargs cat echo "$needed_symbols" [ -n "$ksym_wl" ] && cat "$ksym_wl" } | sed -e 's/ /\n/g' | sed -n -e '/^$/!p' | diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 905c0ec291e1..0125698f2037 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -387,7 +387,7 @@ out_file: /* Calc and record src checksum. */ void get_src_version(const char *modname, char sum[], unsigned sumlen) { - char *buf, *pos, *firstline; + char *buf; struct md4_ctx md; char *fname; char filelist[PATH_MAX + 1]; @@ -397,15 +397,8 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) buf = read_text_file(filelist); - pos = buf; - firstline = get_line(&pos); - if (!firstline) { - warn("bad ending versions file for %s\n", modname); - goto free; - } - md4_init(&md); - while ((fname = strsep(&firstline, " "))) { + while ((fname = strsep(&buf, " \n"))) { if (!*fname) continue; if (!(is_static_library(fname)) && -- cgit From 22f26f21774f838e97921952d8c5c4aab3da2ea4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 7 Apr 2022 00:30:21 +0900 Subject: kbuild: get rid of duplication in *.mod files It is allowed to add the same objects multiple times to obj-y / obj-m: obj-y += foo.o foo.o foo.o obj-m += bar.o bar.o bar.o It is also allowed to add the same objects multiple times to a composite module: obj-m += foo.o foo-y := foo1.o foo2.o foo2.o foo1.o This flexibility is useful because the same object might be selected by different CONFIG options, like this: obj-m += foo.o foo-y := foo1.o foo-$(CONFIG_FOO_X) += foo2.o foo-$(CONFIG_FOO_Y) += foo2.o The duplicated objects are omitted at link time. It works naturally in Makefiles because GNU Make removes duplication in $^ without changing the order. It is working well, almost... A small flaw I notice is, *.mod contains duplication in such a case. This is probably not a big deal. As far as I know, the only small problem is scripts/mod/sumversion.c parses the same file multiple times. I am fixing this because I plan to reuse *.mod for other purposes, where the duplication can be problematic. The code change is quite simple. We already use awk to drop duplicated lines in modules.order (see cmd_modules_order in the same file). I copied the code, but changed RS to use spaces as record separators. I also changed the file format to list one object per line. Signed-off-by: Masahiro Yamada --- scripts/Makefile.build | 3 ++- scripts/mod/sumversion.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 6ae92d119dfa..f7a30f378e20 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -303,7 +303,8 @@ $(obj)/%.prelink.o: $(obj)/%.o FORCE $(call if_changed,cc_prelink_modules) endif -cmd_mod = echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)) > $@ +cmd_mod = echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)) | \ + $(AWK) -v RS='( |\n)' '!x[$$0]++' > $@ $(obj)/%.mod: $(obj)/%$(mod-prelink-ext).o FORCE $(call if_changed,mod) diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 0125698f2037..79bb9eaa65ac 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -398,7 +398,7 @@ void get_src_version(const char *modname, char sum[], unsigned sumlen) buf = read_text_file(filelist); md4_init(&md); - while ((fname = strsep(&buf, " \n"))) { + while ((fname = strsep(&buf, "\n"))) { if (!*fname) continue; if (!(is_static_library(fname)) && -- cgit From fc93a4cdce1db7568fcdff608924324f5754efe5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 7 Apr 2022 00:30:22 +0900 Subject: kbuild: make *.mod not depend on *.o The dependency $(obj)/%.mod: $(obj)/%$(mod-prelink-ext).o ... exists because *.mod files previously contained undefined symbols, which are computed from *.o files when CONFIG_TRIM_UNUSED_KSYMS=y. Now that the undefined symbols are put into separate *.usyms files, there is no reason to make *.mod depend on *.o files. Signed-off-by: Masahiro Yamada --- scripts/Makefile.build | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index f7a30f378e20..3da731cf6978 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -85,7 +85,7 @@ ifdef need-builtin targets-for-builtin += $(obj)/built-in.a endif -targets-for-modules := $(foreach x, mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \ +targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \ $(patsubst %.o, %.$x, $(filter %.o, $(obj-m)))) ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) @@ -306,7 +306,7 @@ endif cmd_mod = echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)) | \ $(AWK) -v RS='( |\n)' '!x[$$0]++' > $@ -$(obj)/%.mod: $(obj)/%$(mod-prelink-ext).o FORCE +$(obj)/%.mod: FORCE $(call if_changed,mod) # List module undefined symbols @@ -469,7 +469,6 @@ $(multi-obj-m): FORCE $(call if_changed,link_multi-m) $(call multi_depend, $(multi-obj-m), .o, -objs -y -m) -targets += $(multi-obj-m) targets := $(filter-out $(PHONY), $(targets)) # Add intermediate targets: -- cgit From feb7d79fea1d43ddf51a09359b52e73bba0340fd Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 7 Apr 2022 00:30:23 +0900 Subject: kbuild: read *.mod to get objects passed to $(LD) or $(AR) ld and ar support @file, which command-line options are read from. Now that *.mod lists the member objects in the correct order, without duplication, it is ready to be passed to ld and ar. By using the @file syntax, people will not be worried about the pitfall described in the NOTE. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/Makefile.build | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 3da731cf6978..f6a506318795 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -450,22 +450,18 @@ quiet_cmd_ar_lib = AR $@ $(obj)/lib.a: $(lib-y) FORCE $(call if_changed,ar_lib) -# NOTE: -# Do not replace $(filter %.o,^) with $(real-prereqs). When a single object -# module is turned into a multi object module, $^ will contain header file -# dependencies recorded in the .*.cmd file. ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) quiet_cmd_link_multi-m = AR [M] $@ cmd_link_multi-m = \ $(cmd_update_lto_symversions); \ rm -f $@; \ - $(AR) cDPrsT $@ $(filter %.o,$^) + $(AR) cDPrsT $@ @$(patsubst %.o,%.mod,$@) else quiet_cmd_link_multi-m = LD [M] $@ - cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ $(filter %.o,$^) + cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) endif -$(multi-obj-m): FORCE +$(multi-obj-m): %.o: %.mod FORCE $(call if_changed,link_multi-m) $(call multi_depend, $(multi-obj-m), .o, -objs -y -m) -- cgit From c77d06e70d59cbc6e3c22bf644bb0b197a5fc182 Mon Sep 17 00:00:00 2001 From: Yann Droneaud Date: Fri, 8 Apr 2022 10:46:07 +0200 Subject: kbuild: support W=e to make build abort in case of warning When developing new code/feature, CONFIG_WERROR is most often turned off, especially for people using make W=12 to get more warnings. In such case, turning on -Werror temporarily would require switching on CONFIG_WERROR in the configuration, building, then switching off CONFIG_WERROR. For this use case, this patch introduces a new 'e' modifier to W= as a short hand for KCFLAGS+=-Werror" so that -Werror got added to the kernel (built-in) and modules' CFLAGS. Signed-off-by: Yann Droneaud Signed-off-by: Masahiro Yamada --- scripts/Makefile.extrawarn | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 650d0b8ceec3..f5f0d6f09053 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -2,8 +2,8 @@ # ========================================================================== # make W=... settings # -# There are three warning groups enabled by W=1, W=2, W=3. -# They are independent, and can be combined like W=12 or W=123. +# There are four warning groups enabled by W=1, W=2, W=3, and W=e +# They are independent, and can be combined like W=12 or W=123e. # ========================================================================== KBUILD_CFLAGS += $(call cc-disable-warning, packed-not-aligned) @@ -94,3 +94,12 @@ KBUILD_CFLAGS += $(call cc-option, -Wpacked-bitfield-compat) KBUILD_CPPFLAGS += -DKBUILD_EXTRA_WARN3 endif + +# +# W=e - error out on warnings +# +ifneq ($(findstring e, $(KBUILD_EXTRA_WARN)),) + +KBUILD_CFLAGS += -Werror + +endif -- cgit From a90bb65ae2168c8b36e53f82dc3cb35c6cff4f1e Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 19 Apr 2022 08:30:09 +0200 Subject: scripts: dummy-tools, add pahole CONFIG_PAHOLE_VERSION is a part of a config since the commit below. And when multiple people update the config, this value constantly changes. Even if they use dummy scripts. To fix this, add a pahole dummy script returning v99.99. (This is translated into 9999 later in the process.) Thereafter, this script can be invoked easily for example as: make PAHOLE=scripts/dummy-tools/pahole oldconfig Fixes: 613fe1692377 (kbuild: Add CONFIG_PAHOLE_VERSION) Signed-off-by: Jiri Slaby Signed-off-by: Masahiro Yamada --- scripts/dummy-tools/pahole | 4 ++++ 1 file changed, 4 insertions(+) create mode 100755 scripts/dummy-tools/pahole (limited to 'scripts') diff --git a/scripts/dummy-tools/pahole b/scripts/dummy-tools/pahole new file mode 100755 index 000000000000..53501a36fa71 --- /dev/null +++ b/scripts/dummy-tools/pahole @@ -0,0 +1,4 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only + +echo v99.99 -- cgit From f4d40868fc4dcfd5db4999149b13fea3902c8883 Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Sat, 23 Apr 2022 00:17:25 +0900 Subject: checksyscalls: ignore -Wunused-macros The macros defined in this file are for testing only and are purposely not used. When compiled with W=2, both gcc and clang yield some -Wunused-macros warnings. Ignore them. Signed-off-by: Vincent Mailhol Signed-off-by: Masahiro Yamada --- scripts/checksyscalls.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checksyscalls.sh b/scripts/checksyscalls.sh index 9dbab13329fa..f33e61aca93d 100755 --- a/scripts/checksyscalls.sh +++ b/scripts/checksyscalls.sh @@ -268,4 +268,4 @@ syscall_list() { } (ignore_list && syscall_list $(dirname $0)/../arch/x86/entry/syscalls/syscall_32.tbl) | \ -$* -Wno-error -E -x c - > /dev/null +$* -Wno-error -Wno-unused-macros -E -x c - > /dev/null -- cgit From 15a28c7c72917f96820e9e9ccd113606363ba3ac Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 25 Apr 2022 04:07:45 +0900 Subject: modpost: use snprintf() instead of sprintf() for safety Use snprintf() to avoid the potential buffer overflow, and also check the return value to detect the too long path. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 522d5249d196..141370ebbfd3 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2560,6 +2560,7 @@ int main(int argc, char **argv) for (mod = modules; mod; mod = mod->next) { char fname[PATH_MAX]; + int ret; if (mod->is_vmlinux || mod->from_dump) continue; @@ -2578,7 +2579,12 @@ int main(int argc, char **argv) add_moddevtable(&buf, mod); add_srcversion(&buf, mod); - sprintf(fname, "%s.mod.c", mod->name); + ret = snprintf(fname, sizeof(fname), "%s.mod.c", mod->name); + if (ret >= sizeof(fname)) { + error("%s: too long path was truncated\n", fname); + continue; + } + write_if_changed(&buf, fname); } -- cgit From c155a47d83ab0b5ee96ebe1721057cba1936d0d5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 25 Apr 2022 04:07:46 +0900 Subject: modpost: do not write out any file when error occurred If an error occurs, modpost will fail anyway. Do not write out any content (, which might be invalid). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 141370ebbfd3..f0d48f65fb33 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2333,6 +2333,9 @@ static void write_buf(struct buffer *b, const char *fname) { FILE *file; + if (error_occurred) + return; + file = fopen(fname, "w"); if (!file) { perror(fname); -- cgit From 594ade3eef3f2d458902ced2cb2614dfae8558de Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 25 Apr 2022 04:07:47 +0900 Subject: modpost: remove stale comment about sym_add_exported() The description, it may have already been added without a CRC, in this case just update the CRC ... is no longer valid. In the old days, this function was used to update the CRC as well. Commit 040fcc819a2e ("kbuild: improved modversioning support for external modules") started to use a separate function (sym_update_crc) for updating the CRC. The first part, "Add an exported symbol" is correct, but it is too obvious from the function name. Drop this comment entirely. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index f0d48f65fb33..c7cfeeb088f7 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -387,10 +387,6 @@ static void sym_update_namespace(const char *symname, const char *namespace) s->namespace = namespace[0] ? NOFAIL(strdup(namespace)) : NULL; } -/** - * Add an exported symbol - it may have already been added without a - * CRC, in this case just update the CRC - **/ static struct symbol *sym_add_exported(const char *name, struct module *mod, enum export export) { -- cgit From 23beb44a0effaad1bd627fd134f0301c622deba7 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 25 Apr 2022 04:07:48 +0900 Subject: modpost: add a separate error for exported symbols without definition It took me a while to understand the intent of "exp->module == mod". This code goes back to 2003. [1] The commit is not in this git repository, and might be worth a little explanation. You can add EXPORT_SYMBOL() without having its definition in the same file (but you need to put a declaration). This is typical when EXPORT_SYMBOL() is added in a C file, but the actual implementation is in a separate assembly file. One example is arch/arm/kernel/armksyms.c In the old days, EXPORT_SYMBOL() was only available in C files (but this limitation does not exist any more). If you forget to add the definition, this error occurs. Add a separate, clearer message for this case. It should be an error even if KBUILD_MODPOST_WARN is given. [1]: https://git.kernel.org/pub/scm/linux/kernel/git/history/history.git/commit/?id=2763b6bcb96e6a38a2fe31108fe5759ec5bcc80a Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c7cfeeb088f7..969a081dba62 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2147,13 +2147,18 @@ static void check_exports(struct module *mod) for (s = mod->unres; s; s = s->next) { const char *basename; exp = find_symbol(s->name); - if (!exp || exp->module == mod) { + if (!exp) { if (!s->weak && nr_unresolved++ < MAX_UNRESOLVED_REPORTS) modpost_log(warn_unresolved ? LOG_WARN : LOG_ERROR, "\"%s\" [%s.ko] undefined!\n", s->name, mod->name); continue; } + if (exp->module == mod) { + error("\"%s\" [%s.ko] was exported without definition\n", + s->name, mod->name); + continue; + } basename = strrchr(mod->name, '/'); if (basename) basename++; -- cgit From 4cae77ac582b430d6ad6fbf0e1b23248997ceac8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 25 Apr 2022 04:07:49 +0900 Subject: modpost: retrieve the module dependency and CRCs in check_exports() Do not repeat the similar code. It is simpler to do this in check_exports() instead of add_versions(). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 969a081dba62..f9cbb6b6b7a5 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2159,6 +2159,11 @@ static void check_exports(struct module *mod) s->name, mod->name); continue; } + + s->module = exp->module; + s->crc_valid = exp->crc_valid; + s->crc = exp->crc; + basename = strrchr(mod->name, '/'); if (basename) basename++; @@ -2251,16 +2256,7 @@ static void add_staging_flag(struct buffer *b, const char *name) **/ static void add_versions(struct buffer *b, struct module *mod) { - struct symbol *s, *exp; - - for (s = mod->unres; s; s = s->next) { - exp = find_symbol(s->name); - if (!exp || exp->module == mod) - continue; - s->module = exp->module; - s->crc_valid = exp->crc_valid; - s->crc = exp->crc; - } + struct symbol *s; if (!modversions) return; -- cgit From 70ddb48db4aaddd3c2a7d8802463e15b21ce8525 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 25 Apr 2022 04:07:56 +0900 Subject: modpost: move struct namespace_list to modpost.c There is no good reason to define struct namespace_list in modpost.h struct module has pointers to struct namespace_list, but that does not require the definition of struct namespace_list. Move it to modpost.c. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 5 +++++ scripts/mod/modpost.h | 5 ----- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index f9cbb6b6b7a5..689a34229809 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -270,6 +270,11 @@ static struct symbol *find_symbol(const char *name) return NULL; } +struct namespace_list { + struct namespace_list *next; + char namespace[]; +}; + static bool contains_namespace(struct namespace_list *list, const char *namespace) { diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 0a940fd2e5c7..7aed57fe793e 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -109,11 +109,6 @@ buf_printf(struct buffer *buf, const char *fmt, ...); void buf_write(struct buffer *buf, const char *s, int len); -struct namespace_list { - struct namespace_list *next; - char namespace[]; -}; - struct module { struct module *next; int gpl_compatible; -- cgit From 8d613a1d048c233a490d45a26d55fc2fd58d26e8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 30 Apr 2022 20:04:09 +0900 Subject: kbuild: drop $(objtree)/ prefix support for clean-files I think this hack is a bad idea. arch/powerpc/boot/Makefile is the only and last user. Let's stop doing this. Signed-off-by: Masahiro Yamada Acked-by: Michael Ellerman (powerpc) --- scripts/Makefile.clean | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 74cb1c5c3658..878cec648959 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -36,13 +36,7 @@ __clean-files := \ __clean-files := $(filter-out $(no-clean-files), $(__clean-files)) -# clean-files is given relative to the current directory, unless it -# starts with $(objtree)/ (which means "./", so do not add "./" unless -# you want to delete a file from the toplevel object directory). - -__clean-files := $(wildcard \ - $(addprefix $(obj)/, $(filter-out $(objtree)/%, $(__clean-files))) \ - $(filter $(objtree)/%, $(__clean-files))) +__clean-files := $(wildcard $(addprefix $(obj)/, $(__clean-files))) # ========================================================================== -- cgit From 58e01fcae18c9d01be701bec9e9a8ee58269c7c1 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:07 +0900 Subject: modpost: use bool type where appropriate Use 'bool' to clarify that the valid value is true or false. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 56 ++++++++++++++++++++++++------------------------ scripts/mod/modpost.h | 11 +++++----- scripts/mod/sumversion.c | 8 +++---- 3 files changed, 37 insertions(+), 38 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 689a34229809..a6035ab78cd8 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -23,20 +23,20 @@ #include "../../include/linux/license.h" /* Are we using CONFIG_MODVERSIONS? */ -static int modversions; +static bool modversions; /* Is CONFIG_MODULE_SRCVERSION_ALL set? */ -static int all_versions; +static bool all_versions; /* If we are modposting external module set to 1 */ -static int external_module; +static bool external_module; /* Only warn about unresolved symbols */ -static int warn_unresolved; +static bool warn_unresolved; /* How a symbol is exported */ static int sec_mismatch_count; -static int sec_mismatch_warn_only = true; +static bool sec_mismatch_warn_only = true; /* ignore missing files */ -static int ignore_missing_files; +static bool ignore_missing_files; /* If set to 1, only warn (instead of error) about missing ns imports */ -static int allow_missing_ns_imports; +static bool allow_missing_ns_imports; static bool error_occurred; @@ -202,11 +202,11 @@ static struct module *new_module(const char *modname) struct symbol { struct symbol *next; struct module *module; - unsigned int crc; - int crc_valid; char *namespace; - unsigned int weak:1; - unsigned int is_static:1; /* 1 if symbol is not global */ + unsigned int crc; + bool crc_valid; + bool weak; + bool is_static; /* true if symbol is not global */ enum export export; /* Type of export */ char name[]; }; @@ -230,7 +230,7 @@ static inline unsigned int tdb_hash(const char *name) * Allocate a new symbols for use in the hash of exported symbols or * the list of unresolved symbols per module **/ -static struct symbol *alloc_symbol(const char *name, unsigned int weak, +static struct symbol *alloc_symbol(const char *name, bool weak, struct symbol *next) { struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); @@ -239,7 +239,7 @@ static struct symbol *alloc_symbol(const char *name, unsigned int weak, strcpy(s->name, name); s->weak = weak; s->next = next; - s->is_static = 1; + s->is_static = true; return s; } @@ -250,7 +250,7 @@ static struct symbol *new_symbol(const char *name, struct module *module, unsigned int hash; hash = tdb_hash(name) % SYMBOL_HASH_SIZE; - symbolhash[hash] = alloc_symbol(name, 0, symbolhash[hash]); + symbolhash[hash] = alloc_symbol(name, false, symbolhash[hash]); return symbolhash[hash]; } @@ -424,7 +424,7 @@ static void sym_set_crc(const char *name, unsigned int crc) return; s->crc = crc; - s->crc_valid = 1; + s->crc_valid = true; } static void *grab_file(const char *filename, size_t *size) @@ -721,9 +721,9 @@ static void handle_symbol(struct module *mod, struct elf_info *info, sym_add_exported(name, mod, export); } if (strcmp(symname, "init_module") == 0) - mod->has_init = 1; + mod->has_init = true; if (strcmp(symname, "cleanup_module") == 0) - mod->has_cleanup = 1; + mod->has_cleanup = true; break; } } @@ -2058,7 +2058,7 @@ static void read_symbols(const char *modname) sym->st_name)); if (s) - s->is_static = 0; + s->is_static = false; } } @@ -2078,7 +2078,7 @@ static void read_symbols(const char *modname) * the automatic versioning doesn't pick it up, but it's really * important anyhow */ if (modversions) - mod->unres = alloc_symbol("module_layout", 0, mod->unres); + mod->unres = alloc_symbol("module_layout", false, mod->unres); } static void read_symbols_from_files(const char *filename) @@ -2310,7 +2310,7 @@ static void add_depends(struct buffer *b, struct module *mod) if (s->module->seen) continue; - s->module->seen = 1; + s->module->seen = true; p = strrchr(s->module->name, '/'); if (p) p++; @@ -2427,10 +2427,10 @@ static void read_dump(const char *fname) mod = find_module(modname); if (!mod) { mod = new_module(modname); - mod->from_dump = 1; + mod->from_dump = true; } s = sym_add_exported(symname, mod, export_no(export)); - s->is_static = 0; + s->is_static = false; sym_set_crc(symname, crc); sym_update_namespace(symname, namespace); } @@ -2508,7 +2508,7 @@ int main(int argc, char **argv) while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) { switch (opt) { case 'e': - external_module = 1; + external_module = true; break; case 'i': *dump_read_iter = @@ -2517,28 +2517,28 @@ int main(int argc, char **argv) dump_read_iter = &(*dump_read_iter)->next; break; case 'm': - modversions = 1; + modversions = true; break; case 'n': - ignore_missing_files = 1; + ignore_missing_files = true; break; case 'o': dump_write = optarg; break; case 'a': - all_versions = 1; + all_versions = true; break; case 'T': files_source = optarg; break; case 'w': - warn_unresolved = 1; + warn_unresolved = true; break; case 'E': sec_mismatch_warn_only = false; break; case 'N': - allow_missing_ns_imports = 1; + allow_missing_ns_imports = true; break; case 'd': missing_namespace_deps = optarg; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 7aed57fe793e..0bd8f697f94c 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -1,4 +1,5 @@ /* SPDX-License-Identifier: GPL-2.0 */ +#include #include #include #include @@ -113,11 +114,11 @@ struct module { struct module *next; int gpl_compatible; struct symbol *unres; - int from_dump; /* 1 if module was loaded from *.symvers */ - int is_vmlinux; - int seen; - int has_init; - int has_cleanup; + bool from_dump; /* true if module was loaded from *.symvers */ + bool is_vmlinux; + bool seen; + bool has_init; + bool has_cleanup; struct buffer dev_table_buf; char srcversion[25]; // Missing namespace dependencies diff --git a/scripts/mod/sumversion.c b/scripts/mod/sumversion.c index 79bb9eaa65ac..6bf9caca0968 100644 --- a/scripts/mod/sumversion.c +++ b/scripts/mod/sumversion.c @@ -290,13 +290,11 @@ static int parse_file(const char *fname, struct md4_ctx *md) return 1; } /* Check whether the file is a static library or not */ -static int is_static_library(const char *objfile) +static bool is_static_library(const char *objfile) { int len = strlen(objfile); - if (objfile[len - 2] == '.' && objfile[len - 1] == 'a') - return 1; - else - return 0; + + return objfile[len - 2] == '.' && objfile[len - 1] == 'a'; } /* We have dir/file.o. Open dir/.file.o.cmd, look for source_ and deps_ line -- cgit From 5066743e4c2f702c1da8ba00a1dc217527a0ab7c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:08 +0900 Subject: modpost: change mod->gpl_compatible to bool type Currently, mod->gpl_compatible is tristate; it is set to -1 by default, then to 1 or 0 when MODULE_LICENSE() is found. Maybe, -1 was chosen to represent the 'unknown' license, but it is not useful. The current code: if (!mod->gpl_compatible) check_for_gpl_usage(exp->export, basename, exp->name); ... only cares whether gpl_compatible is zero or not. Change it to a bool type with the initial value 'true', which has no functional change. The default value should be 'true' instead of 'false'. Since commit 1d6cd3929360 ("modpost: turn missing MODULE_LICENSE() into error"), unknown module license is an error. The error message, "missing MODULE_LICENSE()" is enough to explain the issue. It is not sensible to show another message, "GPL-incompatible module ... uses GPL-only symbol". Add comments to explain this. While I was here, I renamed gpl_compatible to is_gpl_compatible for clarification, and also slightly refactored the code. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 17 +++++++++++------ scripts/mod/modpost.h | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index a6035ab78cd8..25066dc25790 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -187,7 +187,14 @@ static struct module *new_module(const char *modname) /* add to list */ strcpy(mod->name, modname); mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0); - mod->gpl_compatible = -1; + + /* + * Set mod->is_gpl_compatible to true by default. If MODULE_LICENSE() + * is missing, do not check the use for EXPORT_SYMBOL_GPL() becasue + * modpost will exit wiht error anyway. + */ + mod->is_gpl_compatible = true; + mod->next = modules; modules = mod; @@ -2012,10 +2019,8 @@ static void read_symbols(const char *modname) if (!license) error("missing MODULE_LICENSE() in %s\n", modname); while (license) { - if (license_is_gpl_compatible(license)) - mod->gpl_compatible = 1; - else { - mod->gpl_compatible = 0; + if (!license_is_gpl_compatible(license)) { + mod->is_gpl_compatible = false; break; } license = get_next_modinfo(&info, "license", license); @@ -2183,7 +2188,7 @@ static void check_exports(struct module *mod) add_namespace(&mod->missing_namespaces, exp->namespace); } - if (!mod->gpl_compatible) + if (!mod->is_gpl_compatible) check_for_gpl_usage(exp->export, basename, exp->name); } } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 0bd8f697f94c..73c36dfbf0e1 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -112,7 +112,7 @@ buf_write(struct buffer *buf, const char *s, int len); struct module { struct module *next; - int gpl_compatible; + bool is_gpl_compatible; struct symbol *unres; bool from_dump; /* true if module was loaded from *.symvers */ bool is_vmlinux; -- cgit From 97aa4aef532aed6885e887ad6979e5ffb2667c84 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:09 +0900 Subject: modpost: import include/linux/list.h Import include/linux/list.h to use convenient list macros in modpost. I dropped kernel-space code such as {WRITE,READ}_ONCE etc. and unneeded macros. I also imported container_of() from include/linux/container_of.h and type definitions from include/linux/types.h. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/list.h | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 scripts/mod/list.h (limited to 'scripts') diff --git a/scripts/mod/list.h b/scripts/mod/list.h new file mode 100644 index 000000000000..a924a6c4aa4d --- /dev/null +++ b/scripts/mod/list.h @@ -0,0 +1,213 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef LIST_H +#define LIST_H + +#include +#include + +/* Are two types/vars the same type (ignoring qualifiers)? */ +#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) + +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + void *__mptr = (void *)(ptr); \ + _Static_assert(__same_type(*(ptr), ((type *)0)->member) || \ + __same_type(*(ptr), void), \ + "pointer type mismatch in container_of()"); \ + ((type *)(__mptr - offsetof(type, member))); }) + +#define LIST_POISON1 ((void *) 0x100) +#define LIST_POISON2 ((void *) 0x122) + +/* + * Circular doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +/** + * INIT_LIST_HEAD - Initialize a list_head structure + * @list: list_head structure to be initialized. + * + * Initializes the list_head to point to itself. If it is a list header, + * the result is an empty list. + */ +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_add(struct list_head *new, + struct list_head *prev, + struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +static inline void __list_del_entry(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +static inline void list_del(struct list_head *entry) +{ + __list_del_entry(entry); + entry->next = LIST_POISON1; + entry->prev = LIST_POISON2; +} + +/** + * list_is_head - tests whether @list is the list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_head(const struct list_head *list, const struct list_head *head) +{ + return list == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_head within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_next_entry - get the next element in list + * @pos: the type * to cursor + * @member: the name of the list_head within the struct. + */ +#define list_next_entry(pos, member) \ + list_entry((pos)->member.next, typeof(*(pos)), member) + +/** + * list_entry_is_head - test if the entry points to the head of the list + * @pos: the type * to cursor + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_entry_is_head(pos, head, member) \ + (&pos->member == (head)) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member); \ + !list_entry_is_head(pos, head, member); \ + pos = list_next_entry(pos, member)) + +/** + * list_for_each_entry_safe - iterate over list of given type. Safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_head within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_first_entry(head, typeof(*pos), member), \ + n = list_next_entry(pos, member); \ + !list_entry_is_head(pos, head, member); \ + pos = n, n = list_next_entry(n, member)) + +#endif /* LIST_H */ -- cgit From 325eba05e8ab53a9182a2734f0986c15e5f87349 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:10 +0900 Subject: modpost: traverse modules in order Currently, modpost manages modules in a singly linked list; it adds a new node to the head, and traverses the list from new to old. It works, but the error messages are shown in the reverse order. If you have a Makefile like this: obj-m += foo.o bar.o then, modpost shows error messages in bar.o, foo.o, in this order. Use a doubly linked list to keep the order in modules.order; use list_add_tail() for the node addition and list_for_each_entry() for the list traverse. Now that the kernel's list macros have been imported to modpost, I will use them actively going forward. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 17 ++++++++--------- scripts/mod/modpost.h | 3 ++- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 25066dc25790..1b9dcb44621c 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -165,16 +165,17 @@ char *get_line(char **stringp) } /* A list of all modules we processed */ -static struct module *modules; +LIST_HEAD(modules); static struct module *find_module(const char *modname) { struct module *mod; - for (mod = modules; mod; mod = mod->next) + list_for_each_entry(mod, &modules, list) { if (strcmp(mod->name, modname) == 0) - break; - return mod; + return mod; + } + return NULL; } static struct module *new_module(const char *modname) @@ -184,7 +185,6 @@ static struct module *new_module(const char *modname) mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1)); memset(mod, 0, sizeof(*mod)); - /* add to list */ strcpy(mod->name, modname); mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0); @@ -195,8 +195,7 @@ static struct module *new_module(const char *modname) */ mod->is_gpl_compatible = true; - mod->next = modules; - modules = mod; + list_add_tail(&mod->list, &modules); return mod; } @@ -2477,7 +2476,7 @@ static void write_namespace_deps_files(const char *fname) struct namespace_list *ns; struct buffer ns_deps_buf = {}; - for (mod = modules; mod; mod = mod->next) { + list_for_each_entry(mod, &modules, list) { if (mod->from_dump || !mod->missing_namespaces) continue; @@ -2568,7 +2567,7 @@ int main(int argc, char **argv) if (files_source) read_symbols_from_files(files_source); - for (mod = modules; mod; mod = mod->next) { + list_for_each_entry(mod, &modules, list) { char fname[PATH_MAX]; int ret; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 73c36dfbf0e1..69601f36d080 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -11,6 +11,7 @@ #include #include +#include "list.h" #include "elfconfig.h" /* On BSD-alike OSes elf.h defines these according to host's word size */ @@ -111,7 +112,7 @@ void buf_write(struct buffer *buf, const char *s, int len); struct module { - struct module *next; + struct list_head list; bool is_gpl_compatible; struct symbol *unres; bool from_dump; /* true if module was loaded from *.symvers */ -- cgit From e882e89bcf1d54da2e4388570325774c3e3078a9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:11 +0900 Subject: modpost: add sym_add_unresolved() helper Add a small helper, sym_add_unresolved() to ease the further refactoring. Remove the 'weak' argument from alloc_symbol() because it is sensible only for unresolved symbols. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 1b9dcb44621c..59d817692893 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -236,14 +236,12 @@ static inline unsigned int tdb_hash(const char *name) * Allocate a new symbols for use in the hash of exported symbols or * the list of unresolved symbols per module **/ -static struct symbol *alloc_symbol(const char *name, bool weak, - struct symbol *next) +static struct symbol *alloc_symbol(const char *name, struct symbol *next) { struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); memset(s, 0, sizeof(*s)); strcpy(s->name, name); - s->weak = weak; s->next = next; s->is_static = true; return s; @@ -256,11 +254,17 @@ static struct symbol *new_symbol(const char *name, struct module *module, unsigned int hash; hash = tdb_hash(name) % SYMBOL_HASH_SIZE; - symbolhash[hash] = alloc_symbol(name, false, symbolhash[hash]); + symbolhash[hash] = alloc_symbol(name, symbolhash[hash]); return symbolhash[hash]; } +static void sym_add_unresolved(const char *name, struct module *mod, bool weak) +{ + mod->unres = alloc_symbol(name, mod->unres); + mod->unres->weak = weak; +} + static struct symbol *find_symbol(const char *name) { struct symbol *s; @@ -712,9 +716,8 @@ static void handle_symbol(struct module *mod, struct elf_info *info, } } - mod->unres = alloc_symbol(symname, - ELF_ST_BIND(sym->st_info) == STB_WEAK, - mod->unres); + sym_add_unresolved(symname, mod, + ELF_ST_BIND(sym->st_info) == STB_WEAK); break; default: /* All exported symbols */ @@ -2082,7 +2085,7 @@ static void read_symbols(const char *modname) * the automatic versioning doesn't pick it up, but it's really * important anyhow */ if (modversions) - mod->unres = alloc_symbol("module_layout", false, mod->unres); + sym_add_unresolved("module_layout", mod, false); } static void read_symbols_from_files(const char *filename) -- cgit From 8a69152be9a8c1f7a02c6b8410b35c68cb200f6d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:12 +0900 Subject: modpost: traverse unresolved symbols in order Currently, modpost manages unresolved in a singly linked list; it adds a new node to the head, and traverses the list from new to old. Use a doubly linked list to keep the order in the symbol table in the ELF file. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 20 ++++++++++++++------ scripts/mod/modpost.h | 2 +- 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 59d817692893..70a66ce9ffd9 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -185,6 +185,8 @@ static struct module *new_module(const char *modname) mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1)); memset(mod, 0, sizeof(*mod)); + INIT_LIST_HEAD(&mod->unresolved_symbols); + strcpy(mod->name, modname); mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0); @@ -207,6 +209,7 @@ static struct module *new_module(const char *modname) struct symbol { struct symbol *next; + struct list_head list; /* link to module::unresolved_symbols */ struct module *module; char *namespace; unsigned int crc; @@ -261,8 +264,12 @@ static struct symbol *new_symbol(const char *name, struct module *module, static void sym_add_unresolved(const char *name, struct module *mod, bool weak) { - mod->unres = alloc_symbol(name, mod->unres); - mod->unres->weak = weak; + struct symbol *sym; + + sym = alloc_symbol(name, NULL); + sym->weak = weak; + + list_add_tail(&sym->list, &mod->unresolved_symbols); } static struct symbol *find_symbol(const char *name) @@ -2156,7 +2163,7 @@ static void check_exports(struct module *mod) { struct symbol *s, *exp; - for (s = mod->unres; s; s = s->next) { + list_for_each_entry(s, &mod->unresolved_symbols, list) { const char *basename; exp = find_symbol(s->name); if (!exp) { @@ -2277,7 +2284,7 @@ static void add_versions(struct buffer *b, struct module *mod) buf_printf(b, "static const struct modversion_info ____versions[]\n"); buf_printf(b, "__used __section(\"__versions\") = {\n"); - for (s = mod->unres; s; s = s->next) { + list_for_each_entry(s, &mod->unresolved_symbols, list) { if (!s->module) continue; if (!s->crc_valid) { @@ -2303,13 +2310,14 @@ static void add_depends(struct buffer *b, struct module *mod) int first = 1; /* Clear ->seen flag of modules that own symbols needed by this. */ - for (s = mod->unres; s; s = s->next) + list_for_each_entry(s, &mod->unresolved_symbols, list) { if (s->module) s->module->seen = s->module->is_vmlinux; + } buf_printf(b, "\n"); buf_printf(b, "MODULE_INFO(depends, \""); - for (s = mod->unres; s; s = s->next) { + list_for_each_entry(s, &mod->unresolved_symbols, list) { const char *p; if (!s->module) continue; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 69601f36d080..f06bbd0ba93c 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -113,8 +113,8 @@ buf_write(struct buffer *buf, const char *s, int len); struct module { struct list_head list; + struct list_head unresolved_symbols; bool is_gpl_compatible; - struct symbol *unres; bool from_dump; /* true if module was loaded from *.symvers */ bool is_vmlinux; bool seen; -- cgit From 4484054816cab940fc2fde23fa989174fec889d0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:13 +0900 Subject: modpost: use doubly linked list for dump_lists This looks easier to understand (just because this is a pattern in the kernel code). No functional change is intended. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 70a66ce9ffd9..a6a55f359396 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2505,7 +2505,7 @@ static void write_namespace_deps_files(const char *fname) } struct dump_list { - struct dump_list *next; + struct list_head list; const char *file; }; @@ -2517,8 +2517,8 @@ int main(int argc, char **argv) char *dump_write = NULL, *files_source = NULL; int opt; int n; - struct dump_list *dump_read_start = NULL; - struct dump_list **dump_read_iter = &dump_read_start; + LIST_HEAD(dump_lists); + struct dump_list *dl, *dl2; while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) { switch (opt) { @@ -2526,10 +2526,9 @@ int main(int argc, char **argv) external_module = true; break; case 'i': - *dump_read_iter = - NOFAIL(calloc(1, sizeof(**dump_read_iter))); - (*dump_read_iter)->file = optarg; - dump_read_iter = &(*dump_read_iter)->next; + dl = NOFAIL(malloc(sizeof(*dl))); + dl->file = optarg; + list_add_tail(&dl->list, &dump_lists); break; case 'm': modversions = true; @@ -2563,13 +2562,10 @@ int main(int argc, char **argv) } } - while (dump_read_start) { - struct dump_list *tmp; - - read_dump(dump_read_start->file); - tmp = dump_read_start->next; - free(dump_read_start); - dump_read_start = tmp; + list_for_each_entry_safe(dl, dl2, &dump_lists, list) { + read_dump(dl->file); + list_del(&dl->list); + free(dl); } while (optind < argc) -- cgit From ab489d6002fc27dc5db6d66f121da6fc0bda13ad Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:14 +0900 Subject: modpost: traverse the namespace_list in order Use the doubly linked list to traverse the list in the added order. This makes the code more consistent. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 33 +++++++++++++++------------------ scripts/mod/modpost.h | 4 ++-- 2 files changed, 17 insertions(+), 20 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index a6a55f359396..8bdde738803f 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -186,6 +186,8 @@ static struct module *new_module(const char *modname) memset(mod, 0, sizeof(*mod)); INIT_LIST_HEAD(&mod->unresolved_symbols); + INIT_LIST_HEAD(&mod->missing_namespaces); + INIT_LIST_HEAD(&mod->imported_namespaces); strcpy(mod->name, modname); mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0); @@ -288,39 +290,34 @@ static struct symbol *find_symbol(const char *name) } struct namespace_list { - struct namespace_list *next; + struct list_head list; char namespace[]; }; -static bool contains_namespace(struct namespace_list *list, - const char *namespace) +static bool contains_namespace(struct list_head *head, const char *namespace) { - for (; list; list = list->next) + struct namespace_list *list; + + list_for_each_entry(list, head, list) { if (!strcmp(list->namespace, namespace)) return true; + } return false; } -static void add_namespace(struct namespace_list **list, const char *namespace) +static void add_namespace(struct list_head *head, const char *namespace) { struct namespace_list *ns_entry; - if (!contains_namespace(*list, namespace)) { - ns_entry = NOFAIL(malloc(sizeof(struct namespace_list) + + if (!contains_namespace(head, namespace)) { + ns_entry = NOFAIL(malloc(sizeof(*ns_entry) + strlen(namespace) + 1)); strcpy(ns_entry->namespace, namespace); - ns_entry->next = *list; - *list = ns_entry; + list_add_tail(&ns_entry->list, head); } } -static bool module_imports_namespace(struct module *module, - const char *namespace) -{ - return contains_namespace(module->imported_namespaces, namespace); -} - static const struct { const char *str; enum export export; @@ -2190,7 +2187,7 @@ static void check_exports(struct module *mod) basename = mod->name; if (exp->namespace && - !module_imports_namespace(mod, exp->namespace)) { + !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); @@ -2489,12 +2486,12 @@ static void write_namespace_deps_files(const char *fname) list_for_each_entry(mod, &modules, list) { - if (mod->from_dump || !mod->missing_namespaces) + if (mod->from_dump || list_empty(&mod->missing_namespaces)) continue; buf_printf(&ns_deps_buf, "%s.ko:", mod->name); - for (ns = mod->missing_namespaces; ns; ns = ns->next) + list_for_each_entry(ns, &mod->missing_namespaces, list) buf_printf(&ns_deps_buf, " %s", ns->namespace); buf_printf(&ns_deps_buf, "\n"); diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index f06bbd0ba93c..2e13a736ab38 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -123,9 +123,9 @@ struct module { struct buffer dev_table_buf; char srcversion[25]; // Missing namespace dependencies - struct namespace_list *missing_namespaces; + struct list_head missing_namespaces; // Actual imported namespaces - struct namespace_list *imported_namespaces; + struct list_head imported_namespaces; char name[]; }; -- cgit From f841536e8c5b28e1fbf8743911ae1dc78993abd4 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:15 +0900 Subject: modpost: dump Module.symvers in the same order of modules.order modpost dumps the exported symbols into Module.symvers, but currently in random order because it iterates in the hash table. Add a linked list of exported symbols in struct module, so we can iterate on symbols per module. This commit makes Module.symvers much more readable; the outer loop in write_dump() iterates over the modules in the order of modules.order, and the inner loop dumps symbols in each module. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 29 +++++++++++++---------------- scripts/mod/modpost.h | 1 + 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8bdde738803f..cdd9098b6035 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -185,6 +185,7 @@ static struct module *new_module(const char *modname) mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1)); memset(mod, 0, sizeof(*mod)); + INIT_LIST_HEAD(&mod->exported_symbols); INIT_LIST_HEAD(&mod->unresolved_symbols); INIT_LIST_HEAD(&mod->missing_namespaces); INIT_LIST_HEAD(&mod->imported_namespaces); @@ -211,7 +212,7 @@ static struct module *new_module(const char *modname) struct symbol { struct symbol *next; - struct list_head list; /* link to module::unresolved_symbols */ + struct list_head list; /* link to module::exported_symbols or module::unresolved_symbols */ struct module *module; char *namespace; unsigned int crc; @@ -413,6 +414,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, if (!s) { s = new_symbol(name, mod, export); + list_add_tail(&s->list, &mod->exported_symbols); } else if (!external_module || s->module->is_vmlinux || s->module == mod) { warn("%s: '%s' exported twice. Previous export was in %s%s\n", @@ -2456,22 +2458,17 @@ fail: static void write_dump(const char *fname) { struct buffer buf = { }; - struct symbol *symbol; - const char *namespace; - int n; + struct module *mod; + struct symbol *sym; - for (n = 0; n < SYMBOL_HASH_SIZE ; n++) { - symbol = symbolhash[n]; - while (symbol) { - if (!symbol->module->from_dump) { - namespace = symbol->namespace; - buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", - symbol->crc, symbol->name, - symbol->module->name, - export_str(symbol->export), - namespace ? namespace : ""); - } - symbol = symbol->next; + list_for_each_entry(mod, &modules, list) { + if (mod->from_dump) + continue; + list_for_each_entry(sym, &mod->exported_symbols, list) { + buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", + sym->crc, sym->name, mod->name, + export_str(sym->export), + sym->namespace ?: ""); } } write_buf(&buf, fname); diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 2e13a736ab38..cfa127d2bb8f 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -113,6 +113,7 @@ buf_write(struct buffer *buf, const char *s, int len); struct module { struct list_head list; + struct list_head exported_symbols; struct list_head unresolved_symbols; bool is_gpl_compatible; bool from_dump; /* true if module was loaded from *.symvers */ -- cgit From b8422711080f57cdf9fb1c0cb8683a2112bed27c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:17 +0900 Subject: modpost: make multiple export error This is currently a warning, but I think modpost should stop building in this case. If the same symbol is exported multiple times and we let it keep going, the sanity check becomes difficult. Only the legitimate case is that an external module overrides the corresponding in-tree module to provide a different implementation with the same interface. Also, there exists an upstream example that exploits this feature. $ make M=tools/testing/nvdimm ... builds tools/testing/nvdimm/libnvdimm.ko. This is a mocked module that overrides the symbols from drivers/nvdimm/libnvdimm.ko. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index cdd9098b6035..841f69475247 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -417,9 +417,9 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, list_add_tail(&s->list, &mod->exported_symbols); } else if (!external_module || s->module->is_vmlinux || s->module == mod) { - warn("%s: '%s' exported twice. Previous export was in %s%s\n", - mod->name, name, s->module->name, - s->module->is_vmlinux ? "" : ".ko"); + error("%s: '%s' exported twice. Previous export was in %s%s\n", + mod->name, name, s->module->name, + s->module->is_vmlinux ? "" : ".ko"); return s; } -- cgit From e76cc48d8e6df5d949284132981db73d2dd8c6b5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:18 +0900 Subject: modpost: make sym_add_exported() always allocate a new symbol Currently, sym_add_exported() does not allocate a symbol if the same name symbol already exists in the hash table. This does not reflect the real use cases. You can let an external module override the in-tree one. In this case, the external module will export the same name symbols as the in-tree one. However, modpost simply ignores those symbols, then Module.symvers for the external module loses its symbols. sym_add_exported() should allocate a new symbol. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 841f69475247..6024c668a07c 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -412,19 +412,17 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, { struct symbol *s = find_symbol(name); - if (!s) { - s = new_symbol(name, mod, export); - list_add_tail(&s->list, &mod->exported_symbols); - } else if (!external_module || s->module->is_vmlinux || - s->module == mod) { + if (s && (!external_module || s->module->is_vmlinux || s->module == mod)) { error("%s: '%s' exported twice. Previous export was in %s%s\n", mod->name, name, s->module->name, s->module->is_vmlinux ? "" : ".ko"); - return s; } + s = new_symbol(name, mod, export); s->module = mod; s->export = export; + list_add_tail(&s->list, &mod->exported_symbols); + return s; } -- cgit From f18379a30271c0289c2d0e1074e1ed633bfd708c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 1 May 2022 17:40:19 +0900 Subject: modpost: split new_symbol() to symbol allocation and hash table addition new_symbol() does two things; allocate a new symbol and register it to the hash table. Using a separate function for each is easier to understand. Replace new_symbol() with hash_add_symbol(). Remove the second parameter of alloc_symbol(). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 6024c668a07c..085abe541280 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -242,34 +242,31 @@ static inline unsigned int tdb_hash(const char *name) * Allocate a new symbols for use in the hash of exported symbols or * the list of unresolved symbols per module **/ -static struct symbol *alloc_symbol(const char *name, struct symbol *next) +static struct symbol *alloc_symbol(const char *name) { struct symbol *s = NOFAIL(malloc(sizeof(*s) + strlen(name) + 1)); memset(s, 0, sizeof(*s)); strcpy(s->name, name); - s->next = next; s->is_static = true; return s; } /* For the hash of exported symbols */ -static struct symbol *new_symbol(const char *name, struct module *module, - enum export export) +static void hash_add_symbol(struct symbol *sym) { unsigned int hash; - hash = tdb_hash(name) % SYMBOL_HASH_SIZE; - symbolhash[hash] = alloc_symbol(name, symbolhash[hash]); - - return symbolhash[hash]; + hash = tdb_hash(sym->name) % SYMBOL_HASH_SIZE; + sym->next = symbolhash[hash]; + symbolhash[hash] = sym; } static void sym_add_unresolved(const char *name, struct module *mod, bool weak) { struct symbol *sym; - sym = alloc_symbol(name, NULL); + sym = alloc_symbol(name); sym->weak = weak; list_add_tail(&sym->list, &mod->unresolved_symbols); @@ -418,10 +415,11 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, s->module->is_vmlinux ? "" : ".ko"); } - s = new_symbol(name, mod, export); + s = alloc_symbol(name); s->module = mod; s->export = export; list_add_tail(&s->list, &mod->exported_symbols); + hash_add_symbol(s); return s; } -- cgit From f774f5bb87d132b48bc4a99598c45f35121ac054 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 3 May 2022 11:47:16 +0900 Subject: kbuild: factor out the common installation code into scripts/install.sh Many architectures have similar install.sh scripts. The first half is really generic; it verifies that the kernel image and System.map exist, then executes ~/bin/${INSTALLKERNEL} or /sbin/${INSTALLKERNEL} if available. The second half is kind of arch-specific; it copies the kernel image and System.map to the destination, but the code is slightly different. Factor out the generic part into scripts/install.sh. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier --- scripts/install.sh | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 scripts/install.sh (limited to 'scripts') diff --git a/scripts/install.sh b/scripts/install.sh new file mode 100755 index 000000000000..9bb0fb44f04a --- /dev/null +++ b/scripts/install.sh @@ -0,0 +1,40 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 1995 by Linus Torvalds +# +# Adapted from code in arch/i386/boot/Makefile by H. Peter Anvin +# Common code factored out by Masahiro Yamada + +set -e + +# Make sure the files actually exist +for file in "${KBUILD_IMAGE}" System.map +do + if [ ! -f "${file}" ]; then + echo >&2 + echo >&2 " *** Missing file: ${file}" + echo >&2 ' *** You need to run "make" before "make install".' + echo >&2 + exit 1 + fi +done + +# User/arch may have a custom install script +for file in "${HOME}/bin/${INSTALLKERNEL}" \ + "/sbin/${INSTALLKERNEL}" \ + "${srctree}/arch/${SRCARCH}/install.sh" \ + "${srctree}/arch/${SRCARCH}/boot/install.sh" +do + if [ ! -x "${file}" ]; then + continue + fi + + # installkernel(8) says the parameters are like follows: + # + # installkernel version zImage System.map [directory] + exec "${file}" "${KERNELRELEASE}" "${KBUILD_IMAGE}" System.map "${INSTALL_PATH}" +done + +echo "No install script found" >&2 +exit 1 -- cgit From 5d53508d1bae79a84840bcfd3c45094d2081d6d2 Mon Sep 17 00:00:00 2001 From: Reza Arbab Date: Wed, 4 May 2022 16:27:14 -0500 Subject: scripts/prune-kernel: Use kernel-install if available If the new-kernel-pkg utility isn't present, try using kernel-install. This is what the %preun scriptlet in scripts/package/mkspec does too. Signed-off-by: Reza Arbab Signed-off-by: Masahiro Yamada --- scripts/prune-kernel | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/prune-kernel b/scripts/prune-kernel index e8aa940bc0a9..dadfd0e47f89 100755 --- a/scripts/prune-kernel +++ b/scripts/prune-kernel @@ -16,6 +16,10 @@ do rm -f "/boot/initramfs-$f.img" "/boot/System.map-$f" rm -f "/boot/vmlinuz-$f" "/boot/config-$f" rm -rf "/lib/modules/$f" - new-kernel-pkg --remove $f + if [ -x "$(command -v new-kernel-pkg)" ]; then + new-kernel-pkg --remove $f + elif [ -x "$(command -v kernel-install)" ]; then + kernel-install remove $f + fi fi done -- cgit From 7fedac9698b3a56571064eb3b23063f09c93eb94 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 May 2022 16:22:32 +0900 Subject: modpost: merge add_{intree_flag,retpoline,staging_flag} to add_header add_intree_flag(), add_retpoline(), and add_staging_flag() are small enough to be merged into add_header(). Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor --- scripts/mod/modpost.c | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 085abe541280..8cc386346298 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2243,25 +2243,17 @@ static void add_header(struct buffer *b, struct module *mod) "#endif\n"); buf_printf(b, "\t.arch = MODULE_ARCH_INIT,\n"); buf_printf(b, "};\n"); -} -static void add_intree_flag(struct buffer *b, int is_intree) -{ - if (is_intree) + if (!external_module) buf_printf(b, "\nMODULE_INFO(intree, \"Y\");\n"); -} -/* Cannot check for assembler */ -static void add_retpoline(struct buffer *b) -{ - buf_printf(b, "\n#ifdef CONFIG_RETPOLINE\n"); - buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n"); - buf_printf(b, "#endif\n"); -} + buf_printf(b, + "\n" + "#ifdef CONFIG_RETPOLINE\n" + "MODULE_INFO(retpoline, \"Y\");\n" + "#endif\n"); -static void add_staging_flag(struct buffer *b, const char *name) -{ - if (strstarts(name, "drivers/staging")) + if (strstarts(mod->name, "drivers/staging")) buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); } @@ -2577,9 +2569,6 @@ int main(int argc, char **argv) check_exports(mod); add_header(&buf, mod); - add_intree_flag(&buf, !external_module); - add_retpoline(&buf); - add_staging_flag(&buf, mod->name); add_versions(&buf, mod); add_depends(&buf, mod); add_moddevtable(&buf, mod); -- cgit From a44abaca0e196cfeef2374ed663b97daa1ad112a Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 May 2022 16:22:33 +0900 Subject: modpost: move *.mod.c generation to write_mod_c_files() A later commit will add more code to this list_for_each_entry loop. Before that, move the loop body into a separate helper function. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor --- scripts/mod/modpost.c | 56 ++++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 8cc386346298..d9efbd5b31a6 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2390,6 +2390,34 @@ static void write_if_changed(struct buffer *b, const char *fname) write_buf(b, fname); } +/* do sanity checks, and generate *.mod.c file */ +static void write_mod_c_file(struct module *mod) +{ + struct buffer buf = { }; + char fname[PATH_MAX]; + int ret; + + check_modname_len(mod); + check_exports(mod); + + add_header(&buf, mod); + add_versions(&buf, mod); + add_depends(&buf, mod); + add_moddevtable(&buf, mod); + add_srcversion(&buf, mod); + + ret = snprintf(fname, sizeof(fname), "%s.mod.c", mod->name); + if (ret >= sizeof(fname)) { + error("%s: too long path was truncated\n", fname); + goto free; + } + + write_if_changed(&buf, fname); + +free: + free(buf.p); +} + /* parse Module.symvers file. line format: * 0x12345678symbolmoduleexportnamespace **/ @@ -2494,7 +2522,6 @@ struct dump_list { int main(int argc, char **argv) { struct module *mod; - struct buffer buf = { }; char *missing_namespace_deps = NULL; char *dump_write = NULL, *files_source = NULL; int opt; @@ -2557,30 +2584,11 @@ int main(int argc, char **argv) read_symbols_from_files(files_source); list_for_each_entry(mod, &modules, list) { - char fname[PATH_MAX]; - int ret; - - if (mod->is_vmlinux || mod->from_dump) - continue; - - buf.pos = 0; - - check_modname_len(mod); - check_exports(mod); - - add_header(&buf, mod); - add_versions(&buf, mod); - add_depends(&buf, mod); - add_moddevtable(&buf, mod); - add_srcversion(&buf, mod); - - ret = snprintf(fname, sizeof(fname), "%s.mod.c", mod->name); - if (ret >= sizeof(fname)) { - error("%s: too long path was truncated\n", fname); + if (mod->from_dump) continue; - } - write_if_changed(&buf, fname); + if (!mod->is_vmlinux) + write_mod_c_file(mod); } if (missing_namespace_deps) @@ -2606,7 +2614,5 @@ int main(int argc, char **argv) warn("suppressed %u unresolved symbol warnings because there were too many)\n", nr_unresolved - MAX_UNRESOLVED_REPORTS); - free(buf.p); - return error_occurred ? 1 : 0; } -- cgit From e493f472752000968f5b30aac10391288cfbf5b1 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 May 2022 16:22:34 +0900 Subject: kbuild: generate a list of objects in vmlinux A *.mod file lists the member objects of a module, but vmlinux does not have such a file. Generate this list to allow modpost to know all the member objects. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor --- scripts/link-vmlinux.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 20f44504a644..eceb3ee7ec06 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -311,6 +311,7 @@ cleanup() rm -f vmlinux.map rm -f vmlinux.o rm -f .vmlinux.d + rm -f .vmlinux.objs } # Use "make V=1" to debug this script @@ -342,6 +343,16 @@ ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1 modpost_link vmlinux.o objtool_link vmlinux.o +# Generate the list of objects in vmlinux +for f in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do + case ${f} in + *.a) + ${AR} t ${f} ;; + *) + echo ${f} ;; + esac +done > .vmlinux.objs + # modpost vmlinux.o to check for section mismatches ${MAKE} -f "${srctree}/scripts/Makefile.modpost" MODPOST_VMLINUX=1 -- cgit From 78e9e56af3858bf2c52c065daa6c8bee0d72048c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 5 May 2022 16:22:35 +0900 Subject: kbuild: record symbol versions in *.cmd files When CONFIG_MODVERSIONS=y, the output from genksyms is saved in separate *.symversions files, and will be used much later when CONFIG_LTO_CLANG=y because it is impossible to update LLVM bit code here. This approach is not robust because: - *.symversions may or may not exist. If *.symversions does not exist, we never know if it is missing for legitimate reason (i.e. no EXPORT_SYMBOL) or something bad has happened (for example, the user accidentally deleted it). Once it occurs, it is not self-healing because *.symversions is generated as a side effect. - stale (i.e. invalid) *.symversions might be picked up if an object is generated in a non-ordinary way, and corresponding *.symversions (, which was generated by old builds) just happen to exist. A more robust approach is to save symbol versions in *.cmd files because: - *.cmd always exists (if the object is generated by if_changed rule or friends). Even if the user accidentally deletes it, it will be regenerated in the next build. - *.cmd is always re-generated when the object is updated. This avoid stale version information being picked up. I will remove *.symversions later. Signed-off-by: Masahiro Yamada Tested-by: Nicolas Schier Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor --- scripts/Makefile.build | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index f6a506318795..a1023868775f 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -171,10 +171,17 @@ ifdef CONFIG_MODVERSIONS # Generate .o.symversions files for each .o with exported symbols, and link these # to the kernel and/or modules at the end. + +genksyms_format_rel_crc := [^_]*__crc_\([^ ]*\) = \.; LONG(\([^)]*\)).* +genksyms_format_normal := __crc_\(.*\) = \(.*\); +genksyms_format := $(if $(CONFIG_MODULE_REL_CRCS),$(genksyms_format_rel_crc),$(genksyms_format_normal)) + gen_symversions = \ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \ $(call cmd_gensymtypes_$(1),$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ > $@.symversions; \ + sed -n 's/$(genksyms_format)/$(pound)SYMVER \1 \2/p' $@.symversions \ + >> $(dot-target).cmd; \ else \ rm -f $@.symversions; \ fi -- cgit From ce79c406a24c3825a2adeaa4668f79f8d5d72e58 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 May 2022 04:06:18 +0900 Subject: modpost: remove left-over cross_compile declaration This is a remnant of commit 6543becf26ff ("mod/file2alias: make modalias generation safe for cross compiling"). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.h | 1 - 1 file changed, 1 deletion(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index cfa127d2bb8f..d9daeff07b83 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -174,7 +174,6 @@ static inline unsigned int get_secindex(const struct elf_info *info, } /* file2alias.c */ -extern unsigned int cross_build; void handle_moddevtable(struct module *mod, struct elf_info *info, Elf_Sym *sym, const char *symname); void add_moddevtable(struct buffer *buf, struct module *mod); -- cgit From 2a66c3124afd2782015d160f8bad693488ce68de Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 9 May 2022 04:06:19 +0900 Subject: modpost: change the license of EXPORT_SYMBOL to bool type There were more EXPORT_SYMBOL types in the past. The following commits removed unused ones. - f1c3d73e973c ("module: remove EXPORT_SYMBOL_GPL_FUTURE") - 367948220fce ("module: remove EXPORT_UNUSED_SYMBOL*") There are 3 remaining in enum export, but export_unknown does not make any sense because we never expect such a situation like "we do not know how it was exported". If the symbol name starts with "__ksymtab_", but the section name does not start with "___ksymtab+" or "___ksymtab_gpl+", it is not an exported symbol. It occurs when a variable starting with "__ksymtab_" is directly defined: int __ksymtab_foo; Presumably, there is no practical issue for using such a weird variable name (but there is no good reason for doing so, either). Anyway, that is not an exported symbol. Setting export_unknown is not the right thing to do. Do not call sym_add_exported() in this case. With pointless export_unknown removed, the export type finally becomes boolean (either EXPORT_SYMBOL or EXPORT_SYMBOL_GPL). I renamed the field name to is_gpl_only. EXPORT_SYMBOL_GPL sets it true. Only GPL-compatible modules can use it. I removed the orphan comment, "How a symbol is exported", which is unrelated to sec_mismatch_count. It is about enum export. See commit bd5cbcedf446 ("kbuild: export-type enhancement to modpost.c") Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor --- scripts/mod/modpost.c | 108 ++++++++++++++------------------------------------ 1 file changed, 30 insertions(+), 78 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index d9efbd5b31a6..a78b75f0eeb0 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -30,7 +30,7 @@ static bool all_versions; static bool external_module; /* Only warn about unresolved symbols */ static bool warn_unresolved; -/* How a symbol is exported */ + static int sec_mismatch_count; static bool sec_mismatch_warn_only = true; /* ignore missing files */ @@ -47,12 +47,6 @@ static bool error_occurred; #define MAX_UNRESOLVED_REPORTS 10 static unsigned int nr_unresolved; -enum export { - export_plain, - export_gpl, - export_unknown -}; - /* In kernel, this size is defined in linux/module.h; * here we use Elf_Addr instead of long for covering cross-compile */ @@ -219,7 +213,7 @@ struct symbol { bool crc_valid; bool weak; bool is_static; /* true if symbol is not global */ - enum export export; /* Type of export */ + bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */ char name[]; }; @@ -316,34 +310,6 @@ static void add_namespace(struct list_head *head, const char *namespace) } } -static const struct { - const char *str; - enum export export; -} export_list[] = { - { .str = "EXPORT_SYMBOL", .export = export_plain }, - { .str = "EXPORT_SYMBOL_GPL", .export = export_gpl }, - { .str = "(unknown)", .export = export_unknown }, -}; - - -static const char *export_str(enum export ex) -{ - return export_list[ex].str; -} - -static enum export export_no(const char *s) -{ - int i; - - if (!s) - return export_unknown; - for (i = 0; export_list[i].export != export_unknown; i++) { - if (strcmp(export_list[i].str, s) == 0) - return export_list[i].export; - } - return export_unknown; -} - static void *sym_get_data_by_offset(const struct elf_info *info, unsigned int secindex, unsigned long offset) { @@ -374,18 +340,6 @@ static const char *sec_name(const struct elf_info *info, int secindex) #define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) -static enum export export_from_secname(struct elf_info *elf, unsigned int sec) -{ - const char *secname = sec_name(elf, sec); - - if (strstarts(secname, "___ksymtab+")) - return export_plain; - else if (strstarts(secname, "___ksymtab_gpl+")) - return export_gpl; - else - return export_unknown; -} - static void sym_update_namespace(const char *symname, const char *namespace) { struct symbol *s = find_symbol(symname); @@ -405,7 +359,7 @@ static void sym_update_namespace(const char *symname, const char *namespace) } static struct symbol *sym_add_exported(const char *name, struct module *mod, - enum export export) + bool gpl_only) { struct symbol *s = find_symbol(name); @@ -417,7 +371,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, s = alloc_symbol(name); s->module = mod; - s->export = export; + s->is_gpl_only = gpl_only; list_add_tail(&s->list, &mod->exported_symbols); hash_add_symbol(s); @@ -689,8 +643,6 @@ static void handle_modversion(const struct module *mod, static void handle_symbol(struct module *mod, struct elf_info *info, const Elf_Sym *sym, const char *symname) { - const char *name; - switch (sym->st_shndx) { case SHN_COMMON: if (strstarts(symname, "__gnu_lto_")) { @@ -724,12 +676,15 @@ static void handle_symbol(struct module *mod, struct elf_info *info, default: /* All exported symbols */ if (strstarts(symname, "__ksymtab_")) { - enum export export; + const char *name, *secname; name = symname + strlen("__ksymtab_"); - export = export_from_secname(info, - get_secindex(info, sym)); - sym_add_exported(name, mod, export); + 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; @@ -2140,20 +2095,6 @@ void buf_write(struct buffer *buf, const char *s, int len) buf->pos += len; } -static void check_for_gpl_usage(enum export exp, const char *m, const char *s) -{ - switch (exp) { - case export_gpl: - error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n", - m, s); - break; - case export_plain: - case export_unknown: - /* ignore */ - break; - } -} - static void check_exports(struct module *mod) { struct symbol *s, *exp; @@ -2192,8 +2133,9 @@ static void check_exports(struct module *mod) add_namespace(&mod->missing_namespaces, exp->namespace); } - if (!mod->is_gpl_compatible) - check_for_gpl_usage(exp->export, basename, exp->name); + if (!mod->is_gpl_compatible && exp->is_gpl_only) + error("GPL-incompatible module %s.ko uses GPL-only symbol '%s'\n", + basename, exp->name); } } @@ -2437,6 +2379,7 @@ static void read_dump(const char *fname) unsigned int crc; struct module *mod; struct symbol *s; + bool gpl_only; if (!(symname = strchr(line, '\t'))) goto fail; @@ -2454,12 +2397,22 @@ static void read_dump(const char *fname) crc = strtoul(line, &d, 16); if (*symname == '\0' || *modname == '\0' || *d != '\0') goto fail; + + if (!strcmp(export, "EXPORT_SYMBOL_GPL")) { + gpl_only = true; + } else if (!strcmp(export, "EXPORT_SYMBOL")) { + gpl_only = false; + } else { + error("%s: unknown license %s. skip", symname, export); + continue; + } + mod = find_module(modname); if (!mod) { mod = new_module(modname); mod->from_dump = true; } - s = sym_add_exported(symname, mod, export_no(export)); + s = sym_add_exported(symname, mod, gpl_only); s->is_static = false; sym_set_crc(symname, crc); sym_update_namespace(symname, namespace); @@ -2481,9 +2434,9 @@ static void write_dump(const char *fname) if (mod->from_dump) continue; list_for_each_entry(sym, &mod->exported_symbols, list) { - buf_printf(&buf, "0x%08x\t%s\t%s\t%s\t%s\n", + buf_printf(&buf, "0x%08x\t%s\t%s\tEXPORT_SYMBOL%s\t%s\n", sym->crc, sym->name, mod->name, - export_str(sym->export), + sym->is_gpl_only ? "_GPL" : "", sym->namespace ?: ""); } } @@ -2604,9 +2557,8 @@ int main(int argc, char **argv) for (s = symbolhash[n]; s; s = s->next) { if (s->is_static) - error("\"%s\" [%s] is a static %s\n", - s->name, s->module->name, - export_str(s->export)); + error("\"%s\" [%s] is a static EXPORT_SYMBOL\n", + s->name, s->module->name); } } -- cgit From 149d623fbefe67b4c3cfbaae3246f559478aff4c Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:22 +0200 Subject: scripts/spdxcheck: Add percentage to statistics Files checked: 75856 Lines checked: 294516 Files with SPDX: 59410 78% Files with errors: 0 Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxcheck.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py index f3be8ed54f6d..c6ff37e935f5 100755 --- a/scripts/spdxcheck.py +++ b/scripts/spdxcheck.py @@ -285,7 +285,9 @@ if __name__ == '__main__': sys.stderr.write('\n') sys.stderr.write('Files checked: %12d\n' %parser.checked) sys.stderr.write('Lines checked: %12d\n' %parser.lines_checked) - sys.stderr.write('Files with SPDX: %12d\n' %parser.spdx_valid) + if parser.checked: + pc = int(100 * parser.spdx_valid / parser.checked) + sys.stderr.write('Files with SPDX: %12d %3d%%\n' %(parser.spdx_valid, pc)) sys.stderr.write('Files with errors: %12d\n' %parser.spdx_errors) sys.exit(0) -- cgit From a377ce75e4916da5dbb84672218a7e61e51da3ce Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:24 +0200 Subject: scripts/spdxcheck: Add directory statistics For better insights. Directories accounted: 4646 Directories complete: 2565 55% Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxcheck.py | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'scripts') diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py index c6ff37e935f5..80fade8629e7 100755 --- a/scripts/spdxcheck.py +++ b/scripts/spdxcheck.py @@ -28,6 +28,15 @@ class SPDXdata(object): self.licenses = [ ] self.exceptions = { } +class dirinfo(object): + def __init__(self): + self.missing = 0 + self.total = 0 + + def update(self, miss): + self.total += 1 + self.missing += miss + # Read the spdx data from the LICENSES directory def read_spdxdata(repo): @@ -93,6 +102,7 @@ class id_parser(object): self.checked = 0 self.spdx_valid = 0 self.spdx_errors = 0 + self.spdx_dirs = {} self.curline = 0 self.deepest = 0 @@ -167,6 +177,7 @@ class id_parser(object): def parse_lines(self, fd, maxlines, fname): self.checked += 1 self.curline = 0 + fail = 1 try: for line in fd: line = line.decode(locale.getpreferredencoding(False), errors='ignore') @@ -192,6 +203,7 @@ class id_parser(object): # Should we check for more SPDX ids in the same file and # complain if there are any? # + fail = 0 break except ParserException as pe: @@ -203,6 +215,11 @@ class id_parser(object): sys.stdout.write('%s: %d:0 %s\n' %(fname, self.curline, pe.txt)) self.spdx_errors += 1 + base = os.path.dirname(fname) + di = self.spdx_dirs.get(base, dirinfo()) + di.update(fail) + self.spdx_dirs[base] = di + def scan_git_tree(tree): for el in tree.traverse(): # Exclude stuff which would make pointless noise @@ -289,6 +306,16 @@ if __name__ == '__main__': pc = int(100 * parser.spdx_valid / parser.checked) sys.stderr.write('Files with SPDX: %12d %3d%%\n' %(parser.spdx_valid, pc)) sys.stderr.write('Files with errors: %12d\n' %parser.spdx_errors) + ndirs = len(parser.spdx_dirs) + dirsok = 0 + if ndirs: + sys.stderr.write('\n') + sys.stderr.write('Directories accounted: %8d\n' %ndirs) + for di in parser.spdx_dirs.values(): + if not di.missing: + dirsok += 1 + pc = int(100 * dirsok / ndirs) + sys.stderr.write('Directories complete: %8d %3d%%\n' %(dirsok, pc)) sys.exit(0) -- cgit From 0e7f030687efb7a6f8dddd0e967ca4377aee3001 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:26 +0200 Subject: scripts/spdxcheck: Add [sub]directory statistics Add functionality to display [sub]directory statistics. This is enabled by adding '-d' to the command line. The optional -D parameter allows to limit the directory depth. If supplied the subdirectories are accumulated # scripts/spdxcheck.py -d kernel/ Incomplete directories: SPDX in Files ./kernel : 111 of 114 97% ./kernel/bpf : 43 of 45 95% ./kernel/bpf/preload : 4 of 5 80% ./kernel/bpf/preload/iterators : 4 of 5 80% ./kernel/cgroup : 10 of 13 76% ./kernel/configs : 0 of 9 0% ./kernel/debug : 3 of 4 75% ./kernel/debug/kdb : 1 of 11 9% ./kernel/locking : 29 of 32 90% ./kernel/sched : 38 of 39 97% The result can be accumulated by restricting the depth via the new command line option '-d $DEPTH': # scripts/spdxcheck.py -d -D1 Incomplete directories: SPDX in Files ./ : 6 of 13 46% ./Documentation : 4096 of 8451 48% ./arch : 13476 of 16402 82% ./block : 100 of 101 99% ./certs : 11 of 14 78% ./crypto : 145 of 176 82% ./drivers : 24682 of 30745 80% ./fs : 1876 of 2110 88% ./include : 5175 of 5757 89% ./ipc : 12 of 13 92% ./kernel : 493 of 527 93% ./lib : 393 of 524 75% ./mm : 151 of 159 94% ./net : 1713 of 1900 90% ./samples : 211 of 273 77% ./scripts : 341 of 435 78% ./security : 241 of 250 96% ./sound : 2438 of 2503 97% ./tools : 3810 of 5462 69% ./usr : 9 of 10 90% Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxcheck.py | 67 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 57 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py index 80fade8629e7..dc605d485dca 100755 --- a/scripts/spdxcheck.py +++ b/scripts/spdxcheck.py @@ -103,9 +103,21 @@ class id_parser(object): self.spdx_valid = 0 self.spdx_errors = 0 self.spdx_dirs = {} + self.dirdepth = -1 + self.basedir = '.' self.curline = 0 self.deepest = 0 + def set_dirinfo(self, basedir, dirdepth): + if dirdepth >= 0: + self.basedir = basedir + bdir = basedir.lstrip('./').rstrip('/') + if bdir != '': + parts = bdir.split('/') + else: + parts = [] + self.dirdepth = dirdepth + len(parts) + # Validate License and Exception IDs def validate(self, tok): id = tok.value.upper() @@ -215,12 +227,29 @@ class id_parser(object): sys.stdout.write('%s: %d:0 %s\n' %(fname, self.curline, pe.txt)) self.spdx_errors += 1 + if fname == '-': + return + base = os.path.dirname(fname) + if self.dirdepth > 0: + parts = base.split('/') + i = 0 + base = '.' + while i < self.dirdepth and i < len(parts) and len(parts[i]): + base += '/' + parts[i] + i += 1 + elif self.dirdepth == 0: + base = self.basedir + else: + base = './' + base.rstrip('/') + base += '/' + di = self.spdx_dirs.get(base, dirinfo()) di.update(fail) self.spdx_dirs[base] = di -def scan_git_tree(tree): +def scan_git_tree(tree, basedir, dirdepth): + parser.set_dirinfo(basedir, dirdepth) for el in tree.traverse(): # Exclude stuff which would make pointless noise # FIXME: Put this somewhere more sensible @@ -233,15 +262,19 @@ def scan_git_tree(tree): with open(el.path, 'rb') as fd: parser.parse_lines(fd, args.maxlines, el.path) -def scan_git_subtree(tree, path): +def scan_git_subtree(tree, path, dirdepth): for p in path.strip('/').split('/'): tree = tree[p] - scan_git_tree(tree) + scan_git_tree(tree, path.strip('/'), dirdepth) if __name__ == '__main__': ap = ArgumentParser(description='SPDX expression checker') ap.add_argument('path', nargs='*', help='Check path or file. If not given full git tree scan. For stdin use "-"') + ap.add_argument('-d', '--dirs', action='store_true', + help='Show [sub]directory statistics.') + ap.add_argument('-D', '--depth', type=int, default=-1, + help='Directory depth for -d statistics. Default: unlimited') ap.add_argument('-m', '--maxlines', type=int, default=15, help='Maximum number of lines to scan in a file. Default 15') ap.add_argument('-v', '--verbose', action='store_true', help='Verbose statistics output') @@ -285,13 +318,21 @@ if __name__ == '__main__': if os.path.isfile(p): parser.parse_lines(open(p, 'rb'), args.maxlines, p) elif os.path.isdir(p): - scan_git_subtree(repo.head.reference.commit.tree, p) + scan_git_subtree(repo.head.reference.commit.tree, p, + args.depth) else: sys.stderr.write('path %s does not exist\n' %p) sys.exit(1) else: # Full git tree scan - scan_git_tree(repo.head.commit.tree) + scan_git_tree(repo.head.commit.tree, '.', args.depth) + + ndirs = len(parser.spdx_dirs) + dirsok = 0 + if ndirs: + for di in parser.spdx_dirs.values(): + if not di.missing: + dirsok += 1 if args.verbose: sys.stderr.write('\n') @@ -306,17 +347,23 @@ if __name__ == '__main__': pc = int(100 * parser.spdx_valid / parser.checked) sys.stderr.write('Files with SPDX: %12d %3d%%\n' %(parser.spdx_valid, pc)) sys.stderr.write('Files with errors: %12d\n' %parser.spdx_errors) - ndirs = len(parser.spdx_dirs) - dirsok = 0 if ndirs: sys.stderr.write('\n') sys.stderr.write('Directories accounted: %8d\n' %ndirs) - for di in parser.spdx_dirs.values(): - if not di.missing: - dirsok += 1 pc = int(100 * dirsok / ndirs) sys.stderr.write('Directories complete: %8d %3d%%\n' %(dirsok, pc)) + if ndirs and ndirs != dirsok and args.dirs: + if args.verbose: + sys.stderr.write('\n') + sys.stderr.write('Incomplete directories: SPDX in Files\n') + for f in sorted(parser.spdx_dirs.keys()): + di = parser.spdx_dirs[f] + if di.missing: + valid = di.total - di.missing + pc = int(100 * valid / di.total) + sys.stderr.write(' %-80s: %5d of %5d %3d%%\n' %(f, valid, di.total, pc)) + sys.exit(0) except Exception as ex: -- cgit From 67924b71412cd965e0d1c55c0cddb0014c8a725b Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:27 +0200 Subject: scripts/spdxcheck: Add option to display files without SPDX Makes life easier when chasing the missing ones. Is activated with '-f' on the command line. # scripts/spdxcheck.py -f kernel/ Files without SPDX: ./kernel/cpu.c ./kernel/kmod.c ./kernel/relay.c ./kernel/bpf/offload.c ./kernel/bpf/preload/.gitignore ./kernel/bpf/preload/iterators/README ./kernel/bpf/ringbuf.c ./kernel/cgroup/cgroup.c ./kernel/cgroup/cpuset.c ./kernel/cgroup/legacy_freezer.c ./kernel/debug/debug_core.h ./kernel/debug/kdb/Makefile ./kernel/debug/kdb/kdb_bp.c ./kernel/debug/kdb/kdb_bt.c ./kernel/debug/kdb/kdb_cmds ./kernel/debug/kdb/kdb_debugger.c ./kernel/debug/kdb/kdb_io.c ./kernel/debug/kdb/kdb_keyboard.c ./kernel/debug/kdb/kdb_main.c ./kernel/debug/kdb/kdb_private.h ./kernel/debug/kdb/kdb_support.c ./kernel/locking/lockdep_states.h ./kernel/locking/mutex-debug.c ./kernel/locking/spinlock_debug.c ./kernel/sched/pelt.h With the optional -D parameter the directory depth can be limited: # scripts/spdxcheck.py -f -D 0 kernel/ Files without SPDX: ./kernel/cpu.c ./kernel/kmod.c ./kernel/relay.c Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxcheck.py | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py index dc605d485dca..b9e0f1725a0a 100755 --- a/scripts/spdxcheck.py +++ b/scripts/spdxcheck.py @@ -32,10 +32,16 @@ class dirinfo(object): def __init__(self): self.missing = 0 self.total = 0 + self.files = [] - def update(self, miss): + def update(self, fname, basedir, miss): self.total += 1 self.missing += miss + if miss: + fname = './' + fname + bdir = os.path.dirname(fname) + if bdir == basedir.rstrip('/'): + self.files.append(fname) # Read the spdx data from the LICENSES directory def read_spdxdata(repo): @@ -245,7 +251,7 @@ class id_parser(object): base += '/' di = self.spdx_dirs.get(base, dirinfo()) - di.update(fail) + di.update(fname, base, fail) self.spdx_dirs[base] = di def scan_git_tree(tree, basedir, dirdepth): @@ -275,6 +281,8 @@ if __name__ == '__main__': help='Show [sub]directory statistics.') ap.add_argument('-D', '--depth', type=int, default=-1, help='Directory depth for -d statistics. Default: unlimited') + ap.add_argument('-f', '--files', action='store_true', + help='Show files without SPDX.') ap.add_argument('-m', '--maxlines', type=int, default=15, help='Maximum number of lines to scan in a file. Default 15') ap.add_argument('-v', '--verbose', action='store_true', help='Verbose statistics output') @@ -364,6 +372,15 @@ if __name__ == '__main__': pc = int(100 * valid / di.total) sys.stderr.write(' %-80s: %5d of %5d %3d%%\n' %(f, valid, di.total, pc)) + if ndirs and ndirs != dirsok and args.files: + if args.verbose or args.dirs: + sys.stderr.write('\n') + sys.stderr.write('Files without SPDX:\n') + for f in sorted(parser.spdx_dirs.keys()): + di = parser.spdx_dirs[f] + for f in sorted(di.files): + sys.stderr.write(' %s\n' %f) + sys.exit(0) except Exception as ex: -- cgit From 0509b270a358fa563946368418f8e832d9b63452 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:29 +0200 Subject: scripts/spdxcheck: Put excluded files and directories into a separate file The files and directories which are excluded from scanning are currently hard coded in the script. That's not maintainable and not accessible for external tools. Move the files and directories which should be excluded into a file. The default file is scripts/spdxexclude. This can be overridden with the '-e $FILE' command line option. The file format and syntax is similar to the .gitignore file. Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxcheck.py | 70 +++++++++++++++++++++++++++++++++++++++++++++++----- scripts/spdxexclude | 8 ++++++ 2 files changed, 72 insertions(+), 6 deletions(-) create mode 100644 scripts/spdxexclude (limited to 'scripts') diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py index b9e0f1725a0a..18cb9f5b3d3d 100755 --- a/scripts/spdxcheck.py +++ b/scripts/spdxcheck.py @@ -6,6 +6,7 @@ from argparse import ArgumentParser from ply import lex, yacc import locale import traceback +import fnmatch import sys import git import re @@ -106,6 +107,7 @@ class id_parser(object): self.parser = yacc.yacc(module = self, write_tables = False, debug = False) self.lines_checked = 0 self.checked = 0 + self.excluded = 0 self.spdx_valid = 0 self.spdx_errors = 0 self.spdx_dirs = {} @@ -254,17 +256,47 @@ class id_parser(object): di.update(fname, base, fail) self.spdx_dirs[base] = di +class pattern(object): + def __init__(self, line): + self.pattern = line + self.match = self.match_file + if line == '.*': + self.match = self.match_dot + elif line.endswith('/'): + self.pattern = line[:-1] + self.match = self.match_dir + elif line.startswith('/'): + self.pattern = line[1:] + self.match = self.match_fn + + def match_dot(self, fpath): + return os.path.basename(fpath).startswith('.') + + def match_file(self, fpath): + return os.path.basename(fpath) == self.pattern + + def match_fn(self, fpath): + return fnmatch.fnmatchcase(fpath, self.pattern) + + def match_dir(self, fpath): + if self.match_fn(os.path.dirname(fpath)): + return True + return fpath.startswith(self.pattern) + +def exclude_file(fpath): + for rule in exclude_rules: + if rule.match(fpath): + return True + return False + def scan_git_tree(tree, basedir, dirdepth): parser.set_dirinfo(basedir, dirdepth) for el in tree.traverse(): - # Exclude stuff which would make pointless noise - # FIXME: Put this somewhere more sensible - if el.path.startswith("LICENSES"): - continue - if el.path.find("license-rules.rst") >= 0: - continue if not os.path.isfile(el.path): continue + if exclude_file(el.path): + parser.excluded += 1 + continue with open(el.path, 'rb') as fd: parser.parse_lines(fd, args.maxlines, el.path) @@ -273,6 +305,20 @@ def scan_git_subtree(tree, path, dirdepth): tree = tree[p] scan_git_tree(tree, path.strip('/'), dirdepth) +def read_exclude_file(fname): + rules = [] + if not fname: + return rules + with open(fname) as fd: + for line in fd: + line = line.strip() + if line.startswith('#'): + continue + if not len(line): + continue + rules.append(pattern(line)) + return rules + if __name__ == '__main__': ap = ArgumentParser(description='SPDX expression checker') @@ -281,6 +327,8 @@ if __name__ == '__main__': help='Show [sub]directory statistics.') ap.add_argument('-D', '--depth', type=int, default=-1, help='Directory depth for -d statistics. Default: unlimited') + ap.add_argument('-e', '--exclude', + help='File containing file patterns to exclude. Default: scripts/spdxexclude') ap.add_argument('-f', '--files', action='store_true', help='Show files without SPDX.') ap.add_argument('-m', '--maxlines', type=int, default=15, @@ -316,6 +364,15 @@ if __name__ == '__main__': sys.stderr.write('%s\n' %traceback.format_exc()) sys.exit(1) + try: + fname = args.exclude + if not fname: + fname = os.path.join(os.path.dirname(__file__), 'spdxexclude') + exclude_rules = read_exclude_file(fname) + except Exception as ex: + sys.stderr.write('FAIL: Reading exclude file %s: %s\n' %(fname, ex)) + sys.exit(1) + try: if len(args.path) and args.path[0] == '-': stdin = os.fdopen(sys.stdin.fileno(), 'rb') @@ -349,6 +406,7 @@ if __name__ == '__main__': sys.stderr.write('License IDs %12d\n' %len(spdx.licenses)) sys.stderr.write('Exception IDs %12d\n' %len(spdx.exceptions)) sys.stderr.write('\n') + sys.stderr.write('Files excluded: %12d\n' %parser.excluded) sys.stderr.write('Files checked: %12d\n' %parser.checked) sys.stderr.write('Lines checked: %12d\n' %parser.lines_checked) if parser.checked: diff --git a/scripts/spdxexclude b/scripts/spdxexclude new file mode 100644 index 000000000000..5b30fe246197 --- /dev/null +++ b/scripts/spdxexclude @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +# +# Patterns for excluding files and directories + +# Ignore the license directory and the licensing documentation which would +# create lots of noise for no value +LICENSES/ +license-rules.rst -- cgit From 2fb977133684bb74d301bd86a9bb1bd2762362fc Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:30 +0200 Subject: scripts/spdxcheck: Exclude config directories Kernel configuration files like default configs are machine generated and pretty useless outside of the kernel context. Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxexclude | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts') diff --git a/scripts/spdxexclude b/scripts/spdxexclude index 5b30fe246197..4a7fb16dc823 100644 --- a/scripts/spdxexclude +++ b/scripts/spdxexclude @@ -6,3 +6,8 @@ # create lots of noise for no value LICENSES/ license-rules.rst + +# Ignore config files and snippets. The majority is generated +# by the Kconfig tools +kernel/configs/ +arch/*/configs/ -- cgit From 2ab99ce9780d3c3505db4b83669869627010307e Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:32 +0200 Subject: scripts/spdxcheck: Exclude MAINTAINERS/CREDITS Listings of maintainers and people who deserve credits are not really interesting in terms of copyright. The usage of these files outside of the kernel is pointless and the file format is trivial. No point in chasing them or slapping a SPDX identifier into them just because. Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxexclude | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts') diff --git a/scripts/spdxexclude b/scripts/spdxexclude index 4a7fb16dc823..73ef8caf5e61 100644 --- a/scripts/spdxexclude +++ b/scripts/spdxexclude @@ -11,3 +11,7 @@ license-rules.rst # by the Kconfig tools kernel/configs/ arch/*/configs/ + +# Other files without copyrightable content +/CREDITS +/MAINTAINERS -- cgit From e0208351383c19e62f5f04209ce4ecf24db64eaf Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Mon, 16 May 2022 12:27:35 +0200 Subject: scripts/spdxcheck: Exclude top-level README Nothing copyrightable to see here. Signed-off-by: Thomas Gleixner Signed-off-by: Greg Kroah-Hartman --- scripts/spdxexclude | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/spdxexclude b/scripts/spdxexclude index 73ef8caf5e61..81bdb13ed789 100644 --- a/scripts/spdxexclude +++ b/scripts/spdxexclude @@ -15,3 +15,4 @@ arch/*/configs/ # Other files without copyrightable content /CREDITS /MAINTAINERS +/README -- cgit From 7394d2ebb651a9f62e08c6ab864aac015d27c64d Mon Sep 17 00:00:00 2001 From: Cristian Ciocaltea Date: Tue, 17 May 2022 02:46:46 +0300 Subject: scripts/tags.sh: Invoke 'realpath' via 'xargs' When COMPILED_SOURCE is set, running make ARCH=x86_64 COMPILED_SOURCE=1 cscope tags could throw the following errors: scripts/tags.sh: line 98: /usr/bin/realpath: Argument list too long cscope: no source files found scripts/tags.sh: line 98: /usr/bin/realpath: Argument list too long ctags: No files specified. Try "ctags --help". This is most likely to happen when the kernel is configured to build a large number of modules, which has the consequence of passing too many arguments when calling 'realpath' in 'all_compiled_sources()'. Let's improve this by invoking 'realpath' through 'xargs', which takes care of properly limiting the argument list. Signed-off-by: Cristian Ciocaltea Link: https://lore.kernel.org/r/20220516234646.531208-1-cristian.ciocaltea@collabora.com Signed-off-by: Greg Kroah-Hartman --- scripts/tags.sh | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index 16d475b3e203..01fab3d4f90b 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -95,10 +95,13 @@ all_sources() all_compiled_sources() { - realpath -es $([ -z "$KBUILD_ABS_SRCTREE" ] && echo --relative-to=.) \ - include/generated/autoconf.h $(find $ignore -name "*.cmd" -exec \ - grep -Poh '(?(?=^source_.* \K).*|(?=^ \K\S).*(?= \\))' {} \+ | - awk '!a[$0]++') | sort -u + { + echo include/generated/autoconf.h + find $ignore -name "*.cmd" -exec \ + grep -Poh '(?(?=^source_.* \K).*|(?=^ \K\S).*(?= \\))' {} \+ | + awk '!a[$0]++' + } | xargs realpath -es $([ -z "$KBUILD_ABS_SRCTREE" ] && echo --relative-to=.) | + sort -u } all_target_sources() -- cgit From b2441b3bdce6c02cb96278d98c620d7ba1d41b7b Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 20 May 2022 22:40:56 +0200 Subject: h8300: remove stale bindings and symlink MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These four files are left over from the h8300 removal. Reported-by: Geert Uytterhoeven Reported-by: Uwe Kleine-König Signed-off-by: Arnd Bergmann --- scripts/dtc/include-prefixes/h8300 | 1 - 1 file changed, 1 deletion(-) delete mode 120000 scripts/dtc/include-prefixes/h8300 (limited to 'scripts') diff --git a/scripts/dtc/include-prefixes/h8300 b/scripts/dtc/include-prefixes/h8300 deleted file mode 120000 index 3bdaa332c54c..000000000000 --- a/scripts/dtc/include-prefixes/h8300 +++ /dev/null @@ -1 +0,0 @@ -../../../arch/h8300/boot/dts \ No newline at end of file -- cgit From 3bc253c2e652cf5f12cd8c00d80d8ec55d67d1a7 Mon Sep 17 00:00:00 2001 From: Geliang Tang Date: Thu, 19 May 2022 16:30:10 -0700 Subject: bpf: Add bpf_skc_to_mptcp_sock_proto This patch implements a new struct bpf_func_proto, named bpf_skc_to_mptcp_sock_proto. Define a new bpf_id BTF_SOCK_TYPE_MPTCP, and a new helper bpf_skc_to_mptcp_sock(), which invokes another new helper bpf_mptcp_sock_from_subflow() in net/mptcp/bpf.c to get struct mptcp_sock from a given subflow socket. v2: Emit BTF type, add func_id checks in verifier.c and bpf_trace.c, remove build check for CONFIG_BPF_JIT v5: Drop EXPORT_SYMBOL (Martin) Co-developed-by: Nicolas Rybowski Co-developed-by: Matthieu Baerts Signed-off-by: Nicolas Rybowski Signed-off-by: Matthieu Baerts Signed-off-by: Geliang Tang Signed-off-by: Mat Martineau Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20220519233016.105670-2-mathew.j.martineau@linux.intel.com --- scripts/bpf_doc.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index 096625242475..d5452f7eb996 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -633,6 +633,7 @@ class PrinterHelpers(Printer): 'struct socket', 'struct file', 'struct bpf_timer', + 'struct mptcp_sock', ] known_types = { '...', @@ -682,6 +683,7 @@ class PrinterHelpers(Printer): 'struct socket', 'struct file', 'struct bpf_timer', + 'struct mptcp_sock', } mapped_types = { 'u8': '__u8', -- cgit From 69c4cc99bbcbf3ef2e1901b569954e9226180840 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 12 May 2022 01:45:04 +0900 Subject: modpost: add sym_find_with_module() helper find_symbol() returns the first symbol found in the hash table. This table is global, so it may return a symbol from an unexpected module. There is a case where we want to search for a symbol with a given name in a specified module. Add sym_find_with_module(), which receives the module pointer as the second argument. It is equivalent to find_module() if NULL is passed as the module pointer. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/mod/modpost.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index a78b75f0eeb0..f36f02d4b79b 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -266,7 +266,7 @@ static void sym_add_unresolved(const char *name, struct module *mod, bool weak) list_add_tail(&sym->list, &mod->unresolved_symbols); } -static struct symbol *find_symbol(const char *name) +static struct symbol *sym_find_with_module(const char *name, struct module *mod) { struct symbol *s; @@ -275,12 +275,17 @@ static struct symbol *find_symbol(const char *name) name++; for (s = symbolhash[tdb_hash(name) % SYMBOL_HASH_SIZE]; s; s = s->next) { - if (strcmp(s->name, name) == 0) + if (strcmp(s->name, name) == 0 && (!mod || s->module == mod)) return s; } return NULL; } +static struct symbol *find_symbol(const char *name) +{ + return sym_find_with_module(name, NULL); +} + struct namespace_list { struct list_head list; char namespace[]; -- cgit From f292d875d0dc700b3af0bef04c5abc1dc7b3b62c Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 13 May 2022 20:39:21 +0900 Subject: modpost: extract symbol versions from *.cmd files Currently, CONFIG_MODVERSIONS needs extra link to embed the symbol versions into ELF objects. Then, modpost extracts the version CRCs from them. The following figures show how it currently works, and how I am trying to change it. Current implementation ====================== |----------| embed CRC -------------------------->| final | $(CC) $(LD) / |---------| | link for | -----> *.o -------> *.o -->| modpost | | vmlinux | / / | |-- *.mod.c -->| or | / genksyms / |---------| | module | *.c ------> *.symversions |----------| Genksyms outputs the calculated CRCs in the form of linker script (*.symversions), which is used by $(LD) to update the object. If CONFIG_LTO_CLANG=y, the build process is much more complex. Embedding the CRCs is postponed until the LLVM bitcode is converted into ELF, creating another intermediate *.prelink.o. However, this complexity is unneeded. There is no reason why we must embed version CRCs in objects so early. There is final link stage for vmlinux (scripts/link-vmlinux.sh) and modules (scripts/Makefile.modfinal). We can link CRCs at the very last moment. New implementation ================== |----------| --------------------------------------->| final | $(CC) / |---------| | link for | -----> *.o ---->| | | vmlinux | / | modpost |--- .vmlinux.export.c -->| or | / genksyms | |--- *.mod.c ------------>| module | *.c ------> *.cmd -->|---------| |----------| Pass the symbol versions to modpost as separate text data, which are available in *.cmd files. This commit changes modpost to extract CRCs from *.cmd files instead of from ELF objects. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor Reviewed-by: Sami Tolvanen Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/mod/modpost.c | 179 ++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 131 insertions(+), 48 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index f36f02d4b79b..1e2949775e1b 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -383,19 +383,10 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, return s; } -static void sym_set_crc(const char *name, unsigned int crc) +static void sym_set_crc(struct symbol *sym, unsigned int crc) { - struct symbol *s = find_symbol(name); - - /* - * Ignore stand-alone __crc_*, which might be auto-generated symbols - * such as __*_veneer in ARM ELF. - */ - if (!s) - return; - - s->crc = crc; - s->crc_valid = true; + sym->crc = crc; + sym->crc_valid = true; } static void *grab_file(const char *filename, size_t *size) @@ -618,33 +609,6 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname) return 0; } -static void handle_modversion(const struct module *mod, - const struct elf_info *info, - const Elf_Sym *sym, const char *symname) -{ - unsigned int crc; - - if (sym->st_shndx == SHN_UNDEF) { - warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" - "Is \"%s\" prototyped in ?\n", - symname, mod->name, mod->is_vmlinux ? "" : ".ko", - symname); - - return; - } - - if (sym->st_shndx == SHN_ABS) { - crc = sym->st_value; - } else { - unsigned int *crcp; - - /* symbol points to the CRC in the ELF object */ - crcp = sym_get_data(info, sym); - crc = TO_NATIVE(*crcp); - } - sym_set_crc(symname, crc); -} - static void handle_symbol(struct module *mod, struct elf_info *info, const Elf_Sym *sym, const char *symname) { @@ -1952,6 +1916,104 @@ static char *remove_dot(char *s) return s; } +/* + * The CRCs are recorded in .*.cmd files in the form of: + * #SYMVER + */ +static void extract_crcs_for_object(const char *object, struct module *mod) +{ + char cmd_file[PATH_MAX]; + char *buf, *p; + const char *base; + int dirlen, ret; + + base = strrchr(object, '/'); + if (base) { + base++; + dirlen = base - object; + } else { + dirlen = 0; + base = object; + } + + ret = snprintf(cmd_file, sizeof(cmd_file), "%.*s.%s.cmd", + dirlen, object, base); + if (ret >= sizeof(cmd_file)) { + error("%s: too long path was truncated\n", cmd_file); + return; + } + + buf = read_text_file(cmd_file); + p = buf; + + while ((p = strstr(p, "\n#SYMVER "))) { + char *name; + size_t namelen; + unsigned int crc; + struct symbol *sym; + + name = p + strlen("\n#SYMVER "); + + p = strchr(name, ' '); + if (!p) + break; + + namelen = p - name; + p++; + + if (!isdigit(*p)) + continue; /* skip this line */ + + crc = strtol(p, &p, 0); + if (*p != '\n') + continue; /* skip this line */ + + name[namelen] = '\0'; + + /* + * sym_find_with_module() may return NULL here. + * It typically occurs when CONFIG_TRIM_UNUSED_KSYMS=y. + * Since commit e1327a127703, genksyms calculates CRCs of all + * symbols, including trimmed ones. Ignore orphan CRCs. + */ + sym = sym_find_with_module(name, mod); + if (sym) + sym_set_crc(sym, crc); + } + + free(buf); +} + +/* + * The symbol versions (CRC) are recorded in the .*.cmd files. + * Parse them to retrieve CRCs for the current module. + */ +static void mod_set_crcs(struct module *mod) +{ + char objlist[PATH_MAX]; + char *buf, *p, *obj; + int ret; + + if (mod->is_vmlinux) { + strcpy(objlist, ".vmlinux.objs"); + } else { + /* objects for a module are listed in the *.mod file. */ + ret = snprintf(objlist, sizeof(objlist), "%s.mod", mod->name); + if (ret >= sizeof(objlist)) { + error("%s: too long path was truncated\n", objlist); + return; + } + } + + buf = read_text_file(objlist); + p = buf; + + while ((obj = strsep(&p, "\n")) && obj[0]) + extract_crcs_for_object(obj, mod); + + free(buf); +} + static void read_symbols(const char *modname) { const char *symname; @@ -2012,9 +2074,6 @@ static void read_symbols(const char *modname) if (strstarts(symname, "__kstrtabns_")) sym_update_namespace(symname + strlen("__kstrtabns_"), sym_get_data(&info, sym)); - if (strstarts(symname, "__crc_")) - handle_modversion(mod, &info, sym, - symname + strlen("__crc_")); } // check for static EXPORT_SYMBOL_* functions && global vars @@ -2042,12 +2101,17 @@ static void read_symbols(const char *modname) parse_elf_finish(&info); - /* Our trick to get versioning for module struct etc. - it's - * never passed as an argument to an exported function, so - * the automatic versioning doesn't pick it up, but it's really - * important anyhow */ - if (modversions) + if (modversions) { + /* + * Our trick to get versioning for module struct etc. - it's + * never passed as an argument to an exported function, so + * the automatic versioning doesn't pick it up, but it's really + * important anyhow. + */ sym_add_unresolved("module_layout", mod, false); + + mod_set_crcs(mod); + } } static void read_symbols_from_files(const char *filename) @@ -2204,6 +2268,23 @@ static void add_header(struct buffer *b, struct module *mod) buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); } +static void check_symversions(struct module *mod) +{ + struct symbol *sym; + + if (!modversions) + return; + + list_for_each_entry(sym, &mod->exported_symbols, list) { + if (!sym->crc_valid) { + warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" + "Is \"%s\" prototyped in ?\n", + sym->name, mod->name, mod->is_vmlinux ? "" : ".ko", + sym->name); + } + } +} + /** * Record CRCs for unresolved symbols **/ @@ -2419,7 +2500,7 @@ static void read_dump(const char *fname) } s = sym_add_exported(symname, mod, gpl_only); s->is_static = false; - sym_set_crc(symname, crc); + sym_set_crc(s, crc); sym_update_namespace(symname, namespace); } free(buf); @@ -2545,6 +2626,8 @@ int main(int argc, char **argv) if (mod->from_dump) continue; + check_symversions(mod); + if (!mod->is_vmlinux) write_mod_c_file(mod); } -- cgit From 97e03f521050c092919591e668107b3d69c5f426 Mon Sep 17 00:00:00 2001 From: Joanne Koong Date: Mon, 23 May 2022 14:07:07 -0700 Subject: bpf: Add verifier support for dynptrs This patch adds the bulk of the verifier work for supporting dynamic pointers (dynptrs) in bpf. A bpf_dynptr is opaque to the bpf program. It is a 16-byte structure defined internally as: struct bpf_dynptr_kern { void *data; u32 size; u32 offset; } __aligned(8); The upper 8 bits of *size* is reserved (it contains extra metadata about read-only status and dynptr type). Consequently, a dynptr only supports memory less than 16 MB. There are different types of dynptrs (eg malloc, ringbuf, ...). In this patchset, the most basic one, dynptrs to a bpf program's local memory, is added. For now only local memory that is of reg type PTR_TO_MAP_VALUE is supported. In the verifier, dynptr state information will be tracked in stack slots. When the program passes in an uninitialized dynptr (ARG_PTR_TO_DYNPTR | MEM_UNINIT), the stack slots corresponding to the frame pointer where the dynptr resides at are marked STACK_DYNPTR. For helper functions that take in initialized dynptrs (eg bpf_dynptr_read + bpf_dynptr_write which are added later in this patchset), the verifier enforces that the dynptr has been initialized properly by checking that their corresponding stack slots have been marked as STACK_DYNPTR. The 6th patch in this patchset adds test cases that the verifier should successfully reject, such as for example attempting to use a dynptr after doing a direct write into it inside the bpf program. Signed-off-by: Joanne Koong Signed-off-by: Andrii Nakryiko Acked-by: Andrii Nakryiko Acked-by: David Vernet Link: https://lore.kernel.org/bpf/20220523210712.3641569-2-joannelkoong@gmail.com --- scripts/bpf_doc.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/bpf_doc.py b/scripts/bpf_doc.py index d5452f7eb996..855b937e7585 100755 --- a/scripts/bpf_doc.py +++ b/scripts/bpf_doc.py @@ -634,6 +634,7 @@ class PrinterHelpers(Printer): 'struct file', 'struct bpf_timer', 'struct mptcp_sock', + 'struct bpf_dynptr', ] known_types = { '...', @@ -684,6 +685,7 @@ class PrinterHelpers(Printer): 'struct file', 'struct bpf_timer', 'struct mptcp_sock', + 'struct bpf_dynptr', } mapped_types = { 'u8': '__u8', -- cgit From 7b4537199a4a8480b8c3ba37a2d44765ce76cd9b Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 13 May 2022 20:39:22 +0900 Subject: kbuild: link symbol CRCs at final link, removing CONFIG_MODULE_REL_CRCS include/{linux,asm-generic}/export.h defines a weak symbol, __crc_* as a placeholder. Genksyms writes the version CRCs into the linker script, which will be used for filling the __crc_* symbols. The linker script format depends on CONFIG_MODULE_REL_CRCS. If it is enabled, __crc_* holds the offset to the reference of CRC. It is time to get rid of this complexity. Now that modpost parses text files (.*.cmd) to collect all the CRCs, it can generate C code that will be linked to the vmlinux or modules. Generate a new C file, .vmlinux.export.c, which contains the CRCs of symbols exported by vmlinux. It is compiled and linked to vmlinux in scripts/link-vmlinux.sh. Put the CRCs of symbols exported by modules into the existing *.mod.c files. No additional build step is needed for modules. As before, *.mod.c are compiled and linked to *.ko in scripts/Makefile.modfinal. No linker magic is used here. The new C implementation works in the same way, whether CONFIG_RELOCATABLE is enabled or not. CONFIG_MODULE_REL_CRCS is no longer needed. Previously, Kbuild invoked additional $(LD) to update the CRCs in objects, but this step is unneeded too. Signed-off-by: Masahiro Yamada Tested-by: Nathan Chancellor Tested-by: Nicolas Schier Reviewed-by: Nicolas Schier Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 27 ++++----------------------- scripts/Makefile.vmlinux | 32 ++++++++++++++++++++++++++++++++ scripts/genksyms/genksyms.c | 18 ++++-------------- scripts/link-vmlinux.sh | 10 +++++++++- scripts/mod/modpost.c | 28 ++++++++++++++++++++++++---- 5 files changed, 73 insertions(+), 42 deletions(-) create mode 100644 scripts/Makefile.vmlinux (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index a1023868775f..ddd9080fc028 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -128,7 +128,6 @@ $(obj)/%.i: $(src)/%.c FORCE genksyms = scripts/genksyms/genksyms \ $(if $(1), -T $(2)) \ - $(if $(CONFIG_MODULE_REL_CRCS), -R) \ $(if $(KBUILD_PRESERVE), -p) \ -r $(or $(wildcard $(2:.symtypes=.symref)), /dev/null) @@ -162,19 +161,11 @@ ifdef CONFIG_MODVERSIONS # o if .o doesn't contain a __ksymtab version, 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 postprocess them in a way -# that they are usable as a linker script -# o generate .tmp_.o from .o using the linker to -# replace the unresolved symbols __crc_exported_symbol with -# the actual value of the checksum generated by genksyms -# o remove .tmp_.o to .o +# genksyms on the preprocessed source and dump them into the .cmd file. +# o modpost will extract versions from that file and create *.c files that will +# be compiled and linked to the kernel and/or modules. -# Generate .o.symversions files for each .o with exported symbols, and link these -# to the kernel and/or modules at the end. - -genksyms_format_rel_crc := [^_]*__crc_\([^ ]*\) = \.; LONG(\([^)]*\)).* -genksyms_format_normal := __crc_\(.*\) = \(.*\); -genksyms_format := $(if $(CONFIG_MODULE_REL_CRCS),$(genksyms_format_rel_crc),$(genksyms_format_normal)) +genksyms_format := __crc_\(.*\) = \(.*\); gen_symversions = \ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \ @@ -188,12 +179,6 @@ gen_symversions = \ cmd_gen_symversions_c = $(call gen_symversions,c) -cmd_modversions = \ - if [ -r $@.symversions ]; then \ - $(LD) $(KBUILD_LDFLAGS) -r -o $(@D)/.tmp_$(@F) $@ \ - -T $@.symversions; \ - mv -f $(@D)/.tmp_$(@F) $@; \ - fi endif ifdef CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT @@ -273,7 +258,6 @@ define rule_cc_o_c $(call cmd,checkdoc) $(call cmd,gen_objtooldep) $(call cmd,gen_symversions_c) - $(if $(CONFIG_LTO_CLANG),,$(call cmd,modversions)) $(call cmd,record_mcount) endef @@ -282,7 +266,6 @@ define rule_as_o_S $(call cmd,gen_ksymdeps) $(call cmd,gen_objtooldep) $(call cmd,gen_symversions_S) - $(call cmd,modversions) endef # Built-in and composite module parts @@ -296,8 +279,6 @@ ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) quiet_cmd_cc_prelink_modules = LD [M] $@ cmd_cc_prelink_modules = \ $(LD) $(ld_flags) -r -o $@ \ - $(shell [ -s $(@:.prelink.o=.o.symversions) ] && \ - echo -T $(@:.prelink.o=.o.symversions)) \ --whole-archive $(filter-out FORCE,$^) \ $(cmd_objtool) diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux new file mode 100644 index 000000000000..7a63abf22399 --- /dev/null +++ b/scripts/Makefile.vmlinux @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: GPL-2.0-only + +include include/config/auto.conf +include $(srctree)/scripts/Kbuild.include + +# for c_flags +include $(srctree)/scripts/Makefile.lib + +quiet_cmd_cc_o_c = CC $@ + cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< + +%.o: %.c FORCE + $(call if_changed_dep,cc_o_c) + +targets := $(MAKECMDGOALS) + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +PHONY += FORCE +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +existing-targets := $(wildcard $(sort $(targets))) + +-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) + +.PHONY: $(PHONY) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 4827c5abe5b7..67b23cc0df0f 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -33,7 +33,7 @@ char *cur_filename; int in_source_file; static int flag_debug, flag_dump_defs, flag_reference, flag_dump_types, - flag_preserve, flag_warnings, flag_rel_crcs; + flag_preserve, flag_warnings; static int errors; static int nsyms; @@ -680,11 +680,7 @@ void export_symbol(const char *name) if (flag_dump_defs) fputs(">\n", debugfile); - /* Used as a linker script. */ - printf(!flag_rel_crcs ? "__crc_%s = 0x%08lx;\n" : - "SECTIONS { .rodata : ALIGN(4) { " - "__crc_%s = .; LONG(0x%08lx); } }\n", - name, crc); + printf("__crc_%s = 0x%08lx;\n", name, crc); } } @@ -733,7 +729,6 @@ static void genksyms_usage(void) " -q, --quiet Disable warnings (default)\n" " -h, --help Print this message\n" " -V, --version Print the release version\n" - " -R, --relative-crc Emit section relative symbol CRCs\n" #else /* __GNU_LIBRARY__ */ " -s Select symbol prefix\n" " -d Increment the debug level (repeatable)\n" @@ -745,7 +740,6 @@ static void genksyms_usage(void) " -q Disable warnings (default)\n" " -h Print this message\n" " -V Print the release version\n" - " -R Emit section relative symbol CRCs\n" #endif /* __GNU_LIBRARY__ */ , stderr); } @@ -766,14 +760,13 @@ int main(int argc, char **argv) {"preserve", 0, 0, 'p'}, {"version", 0, 0, 'V'}, {"help", 0, 0, 'h'}, - {"relative-crc", 0, 0, 'R'}, {0, 0, 0, 0} }; - while ((o = getopt_long(argc, argv, "s:dwqVDr:T:phR", + while ((o = getopt_long(argc, argv, "s:dwqVDr:T:ph", &long_opts[0], NULL)) != EOF) #else /* __GNU_LIBRARY__ */ - while ((o = getopt(argc, argv, "s:dwqVDr:T:phR")) != EOF) + while ((o = getopt(argc, argv, "s:dwqVDr:T:ph")) != EOF) #endif /* __GNU_LIBRARY__ */ switch (o) { case 'd': @@ -813,9 +806,6 @@ int main(int argc, char **argv) case 'h': genksyms_usage(); return 0; - case 'R': - flag_rel_crcs = 1; - break; default: genksyms_usage(); return 1; diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index eceb3ee7ec06..db34dc3163ae 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -90,7 +90,6 @@ modpost_link() if is_enabled CONFIG_MODVERSIONS; then gen_symversions - lds="${lds} -T .tmp_symversions.lds" fi # This might take a while, so indicate that we're doing @@ -183,6 +182,10 @@ vmlinux_link() libs="${KBUILD_VMLINUX_LIBS}" fi + if is_enabled CONFIG_MODULES; then + objs="${objs} .vmlinux.export.o" + fi + if [ "${SRCARCH}" = "um" ]; then wl=-Wl, ld="${CC}" @@ -312,6 +315,7 @@ cleanup() rm -f vmlinux.o rm -f .vmlinux.d rm -f .vmlinux.objs + rm -f .vmlinux.export.c } # Use "make V=1" to debug this script @@ -363,6 +367,10 @@ info GEN modules.builtin tr '\0' '\n' < modules.builtin.modinfo | sed -n 's/^[[:alnum:]:_]*\.file=//p' | tr ' ' '\n' | uniq | sed -e 's:^:kernel/:' -e 's/$/.ko/' > modules.builtin +if is_enabled CONFIG_MODULES; then + ${MAKE} -f "${srctree}/scripts/Makefile.vmlinux" .vmlinux.export.o +fi + btf_vmlinux_bin_o="" if is_enabled CONFIG_DEBUG_INFO_BTF; then btf_vmlinux_bin_o=.btf.vmlinux.bin.o diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 1e2949775e1b..42e949cbc255 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2234,6 +2234,7 @@ static void add_header(struct buffer *b, struct module *mod) buf_printf(b, "#define INCLUDE_VERMAGIC\n"); buf_printf(b, "#include \n"); buf_printf(b, "#include \n"); + buf_printf(b, "#include \n"); buf_printf(b, "#include \n"); buf_printf(b, "#include \n"); buf_printf(b, "\n"); @@ -2268,20 +2269,26 @@ static void add_header(struct buffer *b, struct module *mod) buf_printf(b, "\nMODULE_INFO(staging, \"Y\");\n"); } -static void check_symversions(struct module *mod) +static void add_exported_symbols(struct buffer *buf, struct module *mod) { struct symbol *sym; if (!modversions) return; + /* record CRCs for exported symbols */ + buf_printf(buf, "\n"); list_for_each_entry(sym, &mod->exported_symbols, list) { if (!sym->crc_valid) { warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" "Is \"%s\" prototyped in ?\n", sym->name, mod->name, mod->is_vmlinux ? "" : ".ko", sym->name); + continue; } + + buf_printf(buf, "SYMBOL_CRC(%s, 0x%08x, \"%s\");\n", + sym->name, sym->crc, sym->is_gpl_only ? "_gpl" : ""); } } @@ -2418,6 +2425,18 @@ static void write_if_changed(struct buffer *b, const char *fname) write_buf(b, fname); } +static void write_vmlinux_export_c_file(struct module *mod) +{ + struct buffer buf = { }; + + buf_printf(&buf, + "#include \n"); + + add_exported_symbols(&buf, mod); + write_if_changed(&buf, ".vmlinux.export.c"); + free(buf.p); +} + /* do sanity checks, and generate *.mod.c file */ static void write_mod_c_file(struct module *mod) { @@ -2429,6 +2448,7 @@ static void write_mod_c_file(struct module *mod) check_exports(mod); add_header(&buf, mod); + add_exported_symbols(&buf, mod); add_versions(&buf, mod); add_depends(&buf, mod); add_moddevtable(&buf, mod); @@ -2626,9 +2646,9 @@ int main(int argc, char **argv) if (mod->from_dump) continue; - check_symversions(mod); - - if (!mod->is_vmlinux) + if (mod->is_vmlinux) + write_vmlinux_export_c_file(mod); + else write_mod_c_file(mod); } -- cgit From 7375cbcf2343a9337b19846e76dfd94c3af98a27 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 13 May 2022 20:39:23 +0900 Subject: kbuild: stop merging *.symversions Now modpost reads symbol versions from .*.cmd files. The merged *.symversions are no longer needed. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 21 ++------------------- scripts/link-vmlinux.sh | 19 ------------------- 2 files changed, 2 insertions(+), 38 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index ddd9080fc028..dff9220135c4 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -390,17 +390,6 @@ $(obj)/%.asn1.c $(obj)/%.asn1.h: $(src)/%.asn1 $(objtree)/scripts/asn1_compiler $(subdir-builtin): $(obj)/%/built-in.a: $(obj)/% ; $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ; -# combine symversions for later processing -ifeq ($(CONFIG_LTO_CLANG) $(CONFIG_MODVERSIONS),y y) - cmd_update_lto_symversions = \ - rm -f $@.symversions \ - $(foreach n, $(filter-out FORCE,$^), \ - $(if $(shell test -s $(n).symversions && echo y), \ - ; cat $(n).symversions >> $@.symversions)) -else - cmd_update_lto_symversions = echo >/dev/null -endif - # # Rule to compile a set of .o files into one .a file (without symbol table) # @@ -408,11 +397,8 @@ endif quiet_cmd_ar_builtin = AR $@ cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs) -quiet_cmd_ar_and_symver = AR $@ - cmd_ar_and_symver = $(cmd_update_lto_symversions); $(cmd_ar_builtin) - $(obj)/built-in.a: $(real-obj-y) FORCE - $(call if_changed,ar_and_symver) + $(call if_changed,ar_builtin) # # Rule to create modules.order file @@ -432,16 +418,13 @@ $(obj)/modules.order: $(obj-m) FORCE # # Rule to compile a set of .o files into one .a file (with symbol table) # -quiet_cmd_ar_lib = AR $@ - cmd_ar_lib = $(cmd_update_lto_symversions); $(cmd_ar) $(obj)/lib.a: $(lib-y) FORCE - $(call if_changed,ar_lib) + $(call if_changed,ar) ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) quiet_cmd_link_multi-m = AR [M] $@ cmd_link_multi-m = \ - $(cmd_update_lto_symversions); \ rm -f $@; \ $(AR) cDPrsT $@ @$(patsubst %.o,%.mod,$@) else diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index db34dc3163ae..eb6721e2fc47 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -56,20 +56,6 @@ gen_initcalls() > .tmp_initcalls.lds } -# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into -# .tmp_symversions.lds -gen_symversions() -{ - info GEN .tmp_symversions.lds - rm -f .tmp_symversions.lds - - for o in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do - if [ -f ${o}.symversions ]; then - cat ${o}.symversions >> .tmp_symversions.lds - fi - done -} - # Link of vmlinux.o used for section mismatch analysis # ${1} output file modpost_link() @@ -88,10 +74,6 @@ modpost_link() gen_initcalls lds="-T .tmp_initcalls.lds" - if is_enabled CONFIG_MODVERSIONS; then - gen_symversions - fi - # This might take a while, so indicate that we're doing # an LTO link info LTO ${1} @@ -307,7 +289,6 @@ cleanup() rm -f .btf.* rm -f .tmp_System.map rm -f .tmp_initcalls.lds - rm -f .tmp_symversions.lds rm -f .tmp_vmlinux* rm -f System.map rm -f vmlinux -- cgit From 5ce2176b81f77366bd02c27509b83049f0020544 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 13 May 2022 20:39:24 +0900 Subject: genksyms: adjust the output format to modpost Make genksyms output symbol versions in the format modpost expects, so the 'sed' is unneeded. This commit makes *.symversions completely unneeded. I will keep *.symversions in .gitignore and 'make clean' for a while. Otherwise, 'git status' might be surprising. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 6 ------ scripts/genksyms/genksyms.c | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index dff9220135c4..461998a2ad2b 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -165,16 +165,10 @@ ifdef CONFIG_MODVERSIONS # o modpost will extract versions from that file and create *.c files that will # be compiled and linked to the kernel and/or modules. -genksyms_format := __crc_\(.*\) = \(.*\); - gen_symversions = \ if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \ $(call cmd_gensymtypes_$(1),$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ - > $@.symversions; \ - sed -n 's/$(genksyms_format)/$(pound)SYMVER \1 \2/p' $@.symversions \ >> $(dot-target).cmd; \ - else \ - rm -f $@.symversions; \ fi cmd_gen_symversions_c = $(call gen_symversions,c) diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 67b23cc0df0f..f5dfdb9d80e9 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -680,7 +680,7 @@ void export_symbol(const char *name) if (flag_dump_defs) fputs(">\n", debugfile); - printf("__crc_%s = 0x%08lx;\n", name, crc); + printf("#SYMVER %s 0x%08lx\n", name, crc); } } -- cgit From d37aa2efc89b387cda93bf15317883519683d435 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 May 2022 22:55:41 +0900 Subject: gcc-plugins: use KERNELVERSION for plugin version Commit 61f60bac8c05 ("gcc-plugins: Change all version strings match kernel") broke parallel builds. Instead of adding the dependency between GCC plugins and utsrelease.h, let's use KERNELVERSION, which does not require any build artifact. Another reason why I want to avoid utsrelease.h is because it depends on CONFIG_LOCALVERSION(_AUTO) and localversion* files. (include/generated/utsrelease.h depends on include/config/kernel.release, which is generated by scripts/setlocalversion) I want to keep host tools independent of the kernel configuration. There is no good reason to rebuild GCC plugins just because of CONFIG_LOCALVERSION being changed. We just want to associate the plugin versions with the kernel source version. KERNELVERSION should be enough for our purpose. Fixes: 61f60bac8c05 ("gcc-plugins: Change all version strings match kernel") Reported-by: kernel test robot Link: https://lore.kernel.org/linux-mm/202205230239.EZxeZ3Fv-lkp@intel.com Reported-by: Guenter Roeck Signed-off-by: Masahiro Yamada Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20220524135541.1453693-1-masahiroy@kernel.org --- scripts/gcc-plugins/Makefile | 2 +- scripts/gcc-plugins/latent_entropy_plugin.c | 2 +- scripts/gcc-plugins/randomize_layout_plugin.c | 2 +- scripts/gcc-plugins/sancov_plugin.c | 2 +- scripts/gcc-plugins/stackleak_plugin.c | 2 +- scripts/gcc-plugins/structleak_plugin.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/gcc-plugins/Makefile b/scripts/gcc-plugins/Makefile index 6f0aecad5d67..b34d11e22636 100644 --- a/scripts/gcc-plugins/Makefile +++ b/scripts/gcc-plugins/Makefile @@ -28,7 +28,7 @@ GCC_PLUGINS_DIR = $(shell $(CC) -print-file-name=plugin) plugin_cxxflags = -Wp,-MMD,$(depfile) $(KBUILD_HOSTCXXFLAGS) -fPIC \ -include $(srctree)/include/linux/compiler-version.h \ - -include $(objtree)/include/generated/utsrelease.h \ + -DPLUGIN_VERSION=$(call stringify,$(KERNELVERSION)) \ -I $(GCC_PLUGINS_DIR)/include -I $(obj) -std=gnu++11 \ -fno-rtti -fno-exceptions -fasynchronous-unwind-tables \ -ggdb -Wno-narrowing -Wno-unused-variable \ diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c index 5d415b2572a8..848918764174 100644 --- a/scripts/gcc-plugins/latent_entropy_plugin.c +++ b/scripts/gcc-plugins/latent_entropy_plugin.c @@ -82,7 +82,7 @@ __visible int plugin_is_GPL_compatible; static GTY(()) tree latent_entropy_decl; static struct plugin_info latent_entropy_plugin_info = { - .version = UTS_RELEASE, + .version = PLUGIN_VERSION, .help = "disable\tturn off latent entropy instrumentation\n", }; diff --git a/scripts/gcc-plugins/randomize_layout_plugin.c b/scripts/gcc-plugins/randomize_layout_plugin.c index ea2aea570404..951b74ba1b24 100644 --- a/scripts/gcc-plugins/randomize_layout_plugin.c +++ b/scripts/gcc-plugins/randomize_layout_plugin.c @@ -34,7 +34,7 @@ __visible int plugin_is_GPL_compatible; static int performance_mode; static struct plugin_info randomize_layout_plugin_info = { - .version = UTS_RELEASE, + .version = PLUGIN_VERSION, .help = "disable\t\t\tdo not activate plugin\n" "performance-mode\tenable cacheline-aware layout randomization\n" }; diff --git a/scripts/gcc-plugins/sancov_plugin.c b/scripts/gcc-plugins/sancov_plugin.c index f3d629555b84..b76cb9c42cec 100644 --- a/scripts/gcc-plugins/sancov_plugin.c +++ b/scripts/gcc-plugins/sancov_plugin.c @@ -26,7 +26,7 @@ __visible int plugin_is_GPL_compatible; tree sancov_fndecl; static struct plugin_info sancov_plugin_info = { - .version = UTS_RELEASE, + .version = PLUGIN_VERSION, .help = "sancov plugin\n", }; diff --git a/scripts/gcc-plugins/stackleak_plugin.c b/scripts/gcc-plugins/stackleak_plugin.c index de817d54b8af..ff91885f9470 100644 --- a/scripts/gcc-plugins/stackleak_plugin.c +++ b/scripts/gcc-plugins/stackleak_plugin.c @@ -44,7 +44,7 @@ static bool verbose = false; static GTY(()) tree track_function_decl; static struct plugin_info stackleak_plugin_info = { - .version = UTS_RELEASE, + .version = PLUGIN_VERSION, .help = "track-min-size=nn\ttrack stack for functions with a stack frame size >= nn bytes\n" "arch=target_arch\tspecify target build arch\n" "disable\t\tdo not activate the plugin\n" diff --git a/scripts/gcc-plugins/structleak_plugin.c b/scripts/gcc-plugins/structleak_plugin.c index 86b608a24ec0..8bc04068ed39 100644 --- a/scripts/gcc-plugins/structleak_plugin.c +++ b/scripts/gcc-plugins/structleak_plugin.c @@ -37,7 +37,7 @@ __visible int plugin_is_GPL_compatible; static struct plugin_info structleak_plugin_info = { - .version = UTS_RELEASE, + .version = PLUGIN_VERSION, .help = "disable\tdo not activate plugin\n" "byref\tinit structs passed by reference\n" "byref-all\tinit anything passed by reference\n" -- cgit From 23a0cb8e3225122496bfa79172005c587c2d64bf Mon Sep 17 00:00:00 2001 From: Jing Leng Date: Tue, 17 May 2022 18:51:28 +0800 Subject: kbuild: Fix include path in scripts/Makefile.modpost When building an external module, if users don't need to separate the compilation output and source code, they run the following command: "make -C $(LINUX_SRC_DIR) M=$(PWD)". At this point, "$(KBUILD_EXTMOD)" and "$(src)" are the same. If they need to separate them, they run "make -C $(KERNEL_SRC_DIR) O=$(KERNEL_OUT_DIR) M=$(OUT_DIR) src=$(PWD)". Before running the command, they need to copy "Kbuild" or "Makefile" to "$(OUT_DIR)" to prevent compilation failure. So the kernel should change the included path to avoid the copy operation. Signed-off-by: Jing Leng [masahiro: I do not think "M=$(OUT_DIR) src=$(PWD)" is the official way, but this patch is a nice clean up anyway.] Signed-off-by: Masahiro Yamada --- scripts/Makefile.modpost | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 48585c4d04ad..0273bf7375e2 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -87,8 +87,7 @@ obj := $(KBUILD_EXTMOD) src := $(obj) # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS -include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \ - $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile) +include $(if $(wildcard $(src)/Kbuild), $(src)/Kbuild, $(src)/Makefile) # modpost option for external modules MODPOST += -e -- cgit From 8d3a75078c83a26d2e637da4e8f95058a406f5e7 Mon Sep 17 00:00:00 2001 From: Yuntao Wang Date: Sun, 22 May 2022 22:12:40 +0800 Subject: scripts/kallsyms: update usage message of the kallsyms program The kallsyms program supports --absolute-percpu option but does not display it in the usage message, fix it. Signed-off-by: Yuntao Wang Signed-off-by: Masahiro Yamada --- scripts/kallsyms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index e6906f79833d..f18e6dfc68c5 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -70,7 +70,7 @@ static unsigned char best_table_len[256]; static void usage(void) { - fprintf(stderr, "Usage: kallsyms [--all-symbols] " + fprintf(stderr, "Usage: kallsyms [--all-symbols] [--absolute-percpu] " "[--base-relative] < in.map > out.S\n"); exit(1); } -- cgit From b5beffa20d83c4e15306c991ffd00de0d8628338 Mon Sep 17 00:00:00 2001 From: Alexander Lobakin Date: Tue, 24 May 2022 17:27:18 +0200 Subject: modpost: fix removing numeric suffixes With the `-z unique-symbol` linker flag or any similar mechanism, it is possible to trigger the following: ERROR: modpost: "param_set_uint.0" [vmlinux] is a static EXPORT_SYMBOL The reason is that for now the condition from remove_dot(): if (m && (s[n + m] == '.' || s[n + m] == 0)) which was designed to test if it's a dot or a '\0' after the suffix is never satisfied. This is due to that `s[n + m]` always points to the last digit of a numeric suffix, not on the symbol next to it (from a custom debug print added to modpost): param_set_uint.0, s[n + m] is '0', s[n + m + 1] is '\0' So it's off-by-one and was like that since 2014. Fix this for the sake of any potential upcoming features, but don't bother stable-backporting, as it's well hidden -- apart from that LD flag, it can be triggered only with GCC LTO which never landed upstream. Fixes: fcd38ed0ff26 ("scripts: modpost: fix compilation warning") Signed-off-by: Alexander Lobakin Reviewed-by: Petr Mladek Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 42e949cbc255..08f6989437bd 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1906,7 +1906,7 @@ static char *remove_dot(char *s) if (n && s[n]) { size_t m = strspn(s + n + 1, "0123456789"); - if (m && (s[n + m] == '.' || s[n + m] == 0)) + if (m && (s[n + m + 1] == '.' || s[n + m + 1] == 0)) s[n] = 0; /* strip trailing .prelink */ -- cgit From d6b732666a1bae0df3c3ae06925043bba34502b1 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 May 2022 01:46:22 +0900 Subject: modpost: fix undefined behavior of is_arm_mapping_symbol() The return value of is_arm_mapping_symbol() is unpredictable when "$" is passed in. strchr(3) says: The strchr() and strrchr() functions return a pointer to the matched character or NULL if the character is not found. The terminating null byte is considered part of the string, so that if c is specified as '\0', these functions return a pointer to the terminator. When str[1] is '\0', strchr("axtd", str[1]) is not NULL, and str[2] is referenced (i.e. buffer overrun). Test code --------- char str1[] = "abc"; char str2[] = "ab"; strcpy(str1, "$"); strcpy(str2, "$"); printf("test1: %d\n", is_arm_mapping_symbol(str1)); printf("test2: %d\n", is_arm_mapping_symbol(str2)); Result ------ test1: 0 test2: 1 Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 08f6989437bd..1092906867f0 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1180,7 +1180,8 @@ static int secref_whitelist(const struct sectioncheck *mismatch, static inline int is_arm_mapping_symbol(const char *str) { - return str[0] == '$' && strchr("axtd", str[1]) + return str[0] == '$' && + (str[1] == 'a' || str[1] == 'd' || str[1] == 't' || str[1] == 'x') && (str[2] == '\0' || str[2] == '.'); } -- cgit From 76954527fe05354add150737aa1b9a6baa4a6ee5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 May 2022 01:46:23 +0900 Subject: modpost: remove the unused argument of check_sec_ref() check_sec_ref() does not use the first parameter 'mod'. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 1092906867f0..2806a5c528c8 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1884,8 +1884,7 @@ static void section_rel(const char *modname, struct elf_info *elf, * to find all references to a section that reference a section that will * be discarded and warns about it. **/ -static void check_sec_ref(struct module *mod, const char *modname, - struct elf_info *elf) +static void check_sec_ref(const char *modname, struct elf_info *elf) { int i; Elf_Shdr *sechdrs = elf->sechdrs; @@ -2091,7 +2090,7 @@ static void read_symbols(const char *modname) } } - check_sec_ref(mod, modname, &info); + check_sec_ref(modname, &info); if (!mod->is_vmlinux) { version = get_modinfo(&info, "version"); -- cgit From c5c468dcc25efc0095361bb63b6255622e22f695 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 May 2022 01:46:25 +0900 Subject: modpost: reuse ARRAY_SIZE() macro for section_mismatch() Move ARRAY_SIZE() from file2alias.c to modpost.h to reuse it in section_mismatch(). Also, move the variable 'check' inside the for-loop. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/file2alias.c | 2 -- scripts/mod/modpost.c | 7 +++---- scripts/mod/modpost.h | 3 +++ 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 5258247d78ac..e8a9c6816fec 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -734,8 +734,6 @@ static int do_vio_entry(const char *filename, void *symval, return 1; } -#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) - static void do_input(char *alias, kernel_ulong_t *arr, unsigned int min, unsigned int max) { diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2806a5c528c8..fc8ba8585d23 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1049,8 +1049,6 @@ static const struct sectioncheck *section_mismatch( const char *fromsec, const char *tosec) { int i; - int elems = sizeof(sectioncheck) / sizeof(struct sectioncheck); - const struct sectioncheck *check = §ioncheck[0]; /* * The target section could be the SHT_NUL section when we're @@ -1061,14 +1059,15 @@ static const struct sectioncheck *section_mismatch( if (*tosec == '\0') return NULL; - for (i = 0; i < elems; i++) { + for (i = 0; i < ARRAY_SIZE(sectioncheck); i++) { + const struct sectioncheck *check = §ioncheck[i]; + if (match(fromsec, check->fromsec)) { if (check->bad_tosec[0] && match(tosec, check->bad_tosec)) return check; if (check->good_tosec[0] && !match(tosec, check->good_tosec)) return check; } - check++; } return NULL; } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index d9daeff07b83..044bdfb894b7 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -97,6 +97,9 @@ static inline void __endian(const void *src, void *dest, unsigned int size) #endif #define NOFAIL(ptr) do_nofail((ptr), #ptr) + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) + void *do_nofail(void *ptr, const char *expr); struct buffer { -- cgit From 68fef6704e38581f7462cb7aac349978fd4ca5cc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 May 2022 01:46:26 +0900 Subject: modpost: squash if...else-if in find_elf_symbol2() if ((addr - sym->st_value) < distance) { distance = addr - sym->st_value; near = sym; } else if ((addr - sym->st_value) == distance) { near = sym; } is equivalent to: if (addr - sym->st_value <= distance) { distance = addr - sym->st_value; near = sym; } (The else-if block can overwrite 'distance' with the same value). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index fc8ba8585d23..b70a31b4245a 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1270,13 +1270,9 @@ static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, continue; if (!is_valid_name(elf, sym)) continue; - if (sym->st_value <= addr) { - if ((addr - sym->st_value) < distance) { - distance = addr - sym->st_value; - near = sym; - } else if ((addr - sym->st_value) == distance) { - near = sym; - } + if (sym->st_value <= addr && addr - sym->st_value <= distance) { + distance = addr - sym->st_value; + near = sym; } } return near; -- cgit From c9db1884050fa6524ae851347731ba2ff9c8d734 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 24 May 2022 03:15:03 +0900 Subject: kbuild: replace $(if A,A,B) with $(or A,B) in scripts/Makefile.modpost Similar cleanup to commit 5c8166419acf ("kbuild: replace $(if A,A,B) with $(or A,B)"). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/Makefile.modpost | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 0273bf7375e2..8b343480813d 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -87,7 +87,7 @@ obj := $(KBUILD_EXTMOD) src := $(obj) # Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS -include $(if $(wildcard $(src)/Kbuild), $(src)/Kbuild, $(src)/Makefile) +include $(or $(wildcard $(src)/Kbuild), $(src)/Makefile) # modpost option for external modules MODPOST += -e -- cgit From 5f3da8c08508df82823566c32f753071c8ad36af Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Tue, 19 Apr 2022 09:05:09 -0700 Subject: objtool: Add CONFIG_HAVE_UACCESS_VALIDATION Allow an arch specify that it has objtool uaccess validation with CONFIG_HAVE_UACCESS_VALIDATION. For now, doing so unconditionally selects CONFIG_OBJTOOL. Signed-off-by: Josh Poimboeuf Signed-off-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/d393d5e2fe73aec6e8e41d5c24f4b6fe8583f2d8.1650384225.git.jpoimboe@redhat.com --- scripts/Makefile.build | 2 +- scripts/link-vmlinux.sh | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 06400504150b..6a663b27b286 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -218,7 +218,7 @@ objtool_args = \ $(if $(CONFIG_SLS), --sls) \ $(if $(CONFIG_STACK_VALIDATION), --stackval) \ $(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \ - --uaccess \ + $(if $(CONFIG_HAVE_UACCESS_VALIDATION), --uaccess) \ $(if $(linked-object), --link) \ $(if $(part-of-module), --module) \ $(if $(CONFIG_GCOV_KERNEL), --no-unreachable) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index a7f6196c7e41..fd578c380919 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -134,7 +134,9 @@ objtool_link() objtoolopt="${objtoolopt} --static-call" fi - objtoolopt="${objtoolopt} --uaccess" + if is_enabled CONFIG_HAVE_UACCESS_VALIDATION; then + objtoolopt="${objtoolopt} --uaccess" + fi fi if is_enabled CONFIG_NOINSTR_VALIDATION; then -- cgit From 0aa24a79ee3b603f6e6cd470c364edc2d746f613 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 29 May 2022 13:23:18 +0900 Subject: kbuild: do not try to parse *.cmd files for objects provided by compiler Guenter Roeck reported the build breakage for parisc and csky. I confirmed nios2 and openrisc are broken as well. The reason is that they borrow libgcc.a from the toolchains. For example, see this line in arch/parisc/Makefile: LIBGCC := $(shell $(CC) -print-libgcc-file-name) Some objects in libgcc.a are linked to vmlinux.o, but they do not have .*.cmd files. Obviously, there is no EXPORT_SYMBOL in external objects. Ignore them. (Most of the architectures import library code into the kernel tree. Perhaps those 4 architectures can do similar, but I do not know how challenging it is.) Fixes: f292d875d0dc ("modpost: extract symbol versions from *.cmd files") Link: https://lore.kernel.org/linux-kbuild/20220528224745.GA2501857@roeck-us.net/T/#mac65c20c71c3e272db0350ecfba53fcd8905b0a0 Reported-by: Guenter Roeck Signed-off-by: Masahiro Yamada Tested-by: Guenter Roeck --- scripts/link-vmlinux.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index a7f6196c7e41..68e4be463a76 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -344,9 +344,16 @@ ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1 modpost_link vmlinux.o objtool_link vmlinux.o -# Generate the list of objects in vmlinux +# Generate the list of in-tree objects in vmlinux +# +# This is used to retrieve symbol versions generated by genksyms. for f in ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS}; do case ${f} in + *libgcc.a) + # Some architectures do '$(CC) --print-libgcc-file-name' to + # borrow libgcc.a from the toolchain. + # There is no EXPORT_SYMBOL in external objects. Ignore this. + ;; *.a) ${AR} t ${f} ;; *) -- cgit From 0cfd90060d714e3d1e0d1b30cfd1c46b71f4e721 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 May 2022 19:01:48 +0900 Subject: kbuild: replace $(linked-object) with CONFIG options *.prelink.o is created when CONFIG_LTO_CLANG or CONFIG_X86_KERNEL_IBT is enabled. Replace $(linked-object) with $(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT) so you will get a quick idea of when the --link option is passed. No functional change is intended. Signed-off-by: Masahiro Yamada Acked-by: Josh Poimboeuf Reviewed-by: Nick Desaulniers Tested-by: Sedat Dilek # LLVM-14 --- scripts/Makefile.build | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 06400504150b..f80196eef03a 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -219,7 +219,7 @@ objtool_args = \ $(if $(CONFIG_STACK_VALIDATION), --stackval) \ $(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \ --uaccess \ - $(if $(linked-object), --link) \ + $(if $($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT)), --link) \ $(if $(part-of-module), --module) \ $(if $(CONFIG_GCOV_KERNEL), --no-unreachable) @@ -284,7 +284,6 @@ quiet_cmd_cc_prelink_modules = LD [M] $@ # modules into native code $(obj)/%.prelink.o: objtool-enabled = y $(obj)/%.prelink.o: part-of-module := y -$(obj)/%.prelink.o: linked-object := y $(obj)/%.prelink.o: $(obj)/%.o FORCE $(call if_changed,cc_prelink_modules) -- cgit From c25e1c55822f9b3b53ccbf88b85644317a525752 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 May 2022 19:01:49 +0900 Subject: kbuild: do not create *.prelink.o for Clang LTO or IBT When CONFIG_LTO_CLANG=y, additional intermediate *.prelink.o is created for each module. Also, objtool is postponed until LLVM IR is converted to ELF. CONFIG_X86_KERNEL_IBT works in a similar way to postpone objtool until objects are merged together. This commit stops generating *.prelink.o, so the build flow will look similar with/without LTO. The following figures show how the LTO build currently works, and how this commit is changing it. Current build flow ================== [1] single-object module $(LD) $(CC) +objtool $(LD) foo.c --------------------> foo.o -----> foo.prelink.o -----> foo.ko (LLVM IR) (ELF) | (ELF) | foo.mod.o --/ (LLVM IR) [2] multi-object module $(LD) $(CC) $(AR) +objtool $(LD) foo1.c -----> foo1.o -----> foo.o -----> foo.prelink.o -----> foo.ko | (archive) (ELF) | (ELF) foo2.c -----> foo2.o --/ | (LLVM IR) foo.mod.o --/ (LLVM IR) One confusion is that foo.o in multi-object module is an archive despite of its suffix. New build flow ============== [1] single-object module Since there is only one object, there is no need to keep the LLVM IR. Use $(CC)+$(LD) to generate an ELF object in one build rule. When LTO is disabled, $(LD) is unneeded because $(CC) produces an ELF object. $(CC)+$(LD)+objtool $(LD) foo.c ----------------------------> foo.o ---------> foo.ko (ELF) | (ELF) | foo.mod.o --/ (LLVM IR) [2] multi-object module Previously, $(AR) was used to combine LLVM IR files into an archive, but there was no technical reason to do so. Use $(LD) to merge them into a single ELF object. $(LD) $(CC) +objtool $(LD) foo1.c ---------> foo1.o ---------> foo.o ---------> foo.ko | (ELF) | (ELF) foo2.c ---------> foo2.o ----/ | (LLVM IR) foo.mod.o --/ (LLVM IR) Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor Reviewed-by: Sami Tolvanen Tested-by: Sedat Dilek # LLVM-14 (x86-64) Acked-by: Josh Poimboeuf --- scripts/Kbuild.include | 4 +++ scripts/Makefile.build | 63 +++++++++++++++-------------------------------- scripts/Makefile.lib | 7 ------ scripts/Makefile.modfinal | 5 ++-- scripts/Makefile.modpost | 9 ++----- scripts/mod/modpost.c | 7 ------ 6 files changed, 28 insertions(+), 67 deletions(-) (limited to 'scripts') diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 3514c2149e9d..455a0a6ce12d 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -15,6 +15,10 @@ pound := \# # Name of target with a '.' as filename prefix. foo/bar.o => foo/.bar.o dot-target = $(dir $@).$(notdir $@) +### +# Name of target with a '.tmp_' as filename prefix. foo/bar.o => foo/.tmp_bar.o +tmp-target = $(dir $@).tmp_$(notdir $@) + ### # The temporary file to save gcc -MMD generated dependencies must not # contain a comma diff --git a/scripts/Makefile.build b/scripts/Makefile.build index f80196eef03a..cc7061258e42 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -88,10 +88,6 @@ endif targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \ $(patsubst %.o, %.$x, $(filter %.o, $(obj-m)))) -ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) -targets-for-modules += $(patsubst %.o, %.prelink.o, $(filter %.o, $(obj-m))) -endif - ifdef need-modorder targets-for-modules += $(obj)/modules.order endif @@ -152,8 +148,18 @@ $(obj)/%.ll: $(src)/%.c FORCE # The C file is compiled and updated dependency information is generated. # (See cmd_cc_o_c + relevant part of rule_cc_o_c) +is-single-obj-m = $(and $(part-of-module),$(filter $@, $(obj-m)),y) + +# When a module consists of a single object, there is no reason to keep LLVM IR. +# Make $(LD) covert LLVM IR to ELF here. +ifdef CONFIG_LTO_CLANG +cmd_ld_single_m = $(if $(is-single-obj-m), ; $(LD) $(ld_flags) -r -o $(tmp-target) $@; mv $(tmp-target) $@) +endif + quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ - cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< $(cmd_objtool) + cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< \ + $(cmd_ld_single_m) \ + $(cmd_objtool) ifdef CONFIG_MODVERSIONS # When module versioning is enabled the following steps are executed: @@ -219,7 +225,7 @@ objtool_args = \ $(if $(CONFIG_STACK_VALIDATION), --stackval) \ $(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \ --uaccess \ - $(if $($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT)), --link) \ + $(if $(delay-objtool), --link) \ $(if $(part-of-module), --module) \ $(if $(CONFIG_GCOV_KERNEL), --no-unreachable) @@ -228,21 +234,15 @@ cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(o endif # CONFIG_OBJTOOL -ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) - -# Skip objtool for LLVM bitcode -$(obj)/%.o: objtool-enabled := - -else - # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory # 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file # 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file -$(obj)/%.o: objtool-enabled = $(if $(filter-out y%, \ - $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y) +is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y) -endif +delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT)) + +$(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y)) ifdef CONFIG_TRIM_UNUSED_KSYMS cmd_gen_ksymdeps = \ @@ -271,24 +271,6 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE $(call if_changed_rule,cc_o_c) $(call cmd,force_checksrc) -ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) -# Module .o files may contain LLVM bitcode, compile them into native code -# before ELF processing -quiet_cmd_cc_prelink_modules = LD [M] $@ - cmd_cc_prelink_modules = \ - $(LD) $(ld_flags) -r -o $@ \ - --whole-archive $(filter-out FORCE,$^) \ - $(cmd_objtool) - -# objtool was skipped for LLVM bitcode, run it now that we have compiled -# modules into native code -$(obj)/%.prelink.o: objtool-enabled = y -$(obj)/%.prelink.o: part-of-module := y - -$(obj)/%.prelink.o: $(obj)/%.o FORCE - $(call if_changed,cc_prelink_modules) -endif - cmd_mod = echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)) | \ $(AWK) -v RS='( |\n)' '!x[$$0]++' > $@ @@ -298,7 +280,7 @@ $(obj)/%.mod: FORCE # List module undefined symbols cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@ -$(obj)/%.usyms: $(obj)/%$(mod-prelink-ext).o FORCE +$(obj)/%.usyms: $(obj)/%.o FORCE $(call if_changed,undefined_syms) quiet_cmd_cc_lst_c = MKLST $@ @@ -420,16 +402,11 @@ $(obj)/modules.order: $(obj-m) FORCE $(obj)/lib.a: $(lib-y) FORCE $(call if_changed,ar) -ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) -quiet_cmd_link_multi-m = AR [M] $@ -cmd_link_multi-m = \ - rm -f $@; \ - $(AR) cDPrsT $@ @$(patsubst %.o,%.mod,$@) -else quiet_cmd_link_multi-m = LD [M] $@ - cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) -endif + cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool) +$(multi-obj-m): objtool-enabled := $(delay-objtool) +$(multi-obj-m): part-of-module := y $(multi-obj-m): %.o: %.mod FORCE $(call if_changed,link_multi-m) $(call multi_depend, $(multi-obj-m), .o, -objs -y -m) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 0453a1904646..f75138385449 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -225,13 +225,6 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \ $(addprefix -I,$(DTC_INCLUDE)) \ -undef -D__DTS__ -ifneq ($(CONFIG_LTO_CLANG)$(CONFIG_X86_KERNEL_IBT),) -# With CONFIG_LTO_CLANG, .o files in modules might be LLVM bitcode, so we -# need to run LTO to compile them into native code (.lto.o) before further -# processing. -mod-prelink-ext := .prelink -endif - # Useful for describing the dependency of composite objects # Usage: # $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add) diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 7f39599e9fae..35100e981f4a 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -9,7 +9,7 @@ __modfinal: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -# for c_flags and mod-prelink-ext +# for c_flags include $(srctree)/scripts/Makefile.lib # find all modules listed in modules.order @@ -54,9 +54,8 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \ $(cmd); \ printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:) - # Re-generate module BTFs if either module's .ko or vmlinux changed -$(modules): %.ko: %$(mod-prelink-ext).o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE +$(modules): %.ko: %.o %.mod.o scripts/module.lds $(if $(KBUILD_BUILTIN),vmlinux) FORCE +$(call if_changed_except,ld_ko_o,vmlinux) ifdef CONFIG_DEBUG_INFO_BTF_MODULES +$(if $(newer-prereqs),$(call cmd,btf_ko)) diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 8b343480813d..911606496341 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -41,9 +41,6 @@ __modpost: include include/config/auto.conf include $(srctree)/scripts/Kbuild.include -# for mod-prelink-ext -include $(srctree)/scripts/Makefile.lib - MODPOST = scripts/mod/modpost \ $(if $(CONFIG_MODVERSIONS),-m) \ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \ @@ -117,8 +114,6 @@ $(input-symdump): @echo >&2 ' Modules may not have dependencies or modversions.' @echo >&2 ' You may get many unresolved symbol warnings.' -modules := $(sort $(shell cat $(MODORDER))) - # KBUILD_MODPOST_WARN can be set to avoid error out in case of undefined symbols ifneq ($(KBUILD_MODPOST_WARN)$(filter-out $(existing-input-symdump), $(input-symdump)),) MODPOST += -w @@ -127,9 +122,9 @@ endif # Read out modules.order to pass in modpost. # Otherwise, allmodconfig would fail with "Argument list too long". quiet_cmd_modpost = MODPOST $@ - cmd_modpost = sed 's/\.ko$$/$(mod-prelink-ext)\.o/' $< | $(MODPOST) -T - + cmd_modpost = sed 's/ko$$/o/' $< | $(MODPOST) -T - -$(output-symdump): $(MODORDER) $(input-symdump) $(modules:.ko=$(mod-prelink-ext).o) FORCE +$(output-symdump): $(MODORDER) $(input-symdump) FORCE $(call if_changed,modpost) targets += $(output-symdump) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index b70a31b4245a..e74224a6a8e8 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -1903,10 +1903,6 @@ static char *remove_dot(char *s) size_t m = strspn(s + n + 1, "0123456789"); if (m && (s[n + m + 1] == '.' || s[n + m + 1] == 0)) s[n] = 0; - - /* strip trailing .prelink */ - if (strends(s, ".prelink")) - s[strlen(s) - 8] = '\0'; } return s; } @@ -2028,9 +2024,6 @@ static void read_symbols(const char *modname) /* strip trailing .o */ tmp = NOFAIL(strdup(modname)); tmp[strlen(tmp) - 2] = '\0'; - /* strip trailing .prelink */ - if (strends(tmp, ".prelink")) - tmp[strlen(tmp) - 8] = '\0'; mod = new_module(tmp); free(tmp); } -- cgit From 31cb50b5590fe911077b8463ad01144fac8fa4f3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 May 2022 19:01:51 +0900 Subject: kbuild: check static EXPORT_SYMBOL* by script instead of modpost The 'static' specifier and EXPORT_SYMBOL() are an odd combination. Commit 15bfc2348d54 ("modpost: check for static EXPORT_SYMBOL* functions") tried to detect it, but this check has false negatives. Here is the sample code. Makefile: obj-y += foo1.o foo2.o foo1.c: #include static void foo(void) {} EXPORT_SYMBOL(foo); foo2.c: void foo(void) {} foo1.c exports the static symbol 'foo', but modpost cannot catch it because it is fooled by foo2.c, which has a global symbol with the same name. s->is_static is cleared if a global symbol with the same name is found somewhere, but EXPORT_SYMBOL() and the global symbol do not necessarily belong to the same compilation unit. This check should be done per compilation unit, but I do not know how to do it in modpost. modpost runs against vmlinux.o or modules, which merges multiple objects, then forgets their origin. modpost cannot parse individual objects because they may not be ELF but LLVM IR when CONFIG_LTO_CLANG=y. Add a simple bash script to parse the output from ${NM}. This works for CONFIG_LTO_CLANG=y because llvm-nm can dump symbols of LLVM IR files. Revert 15bfc2348d54. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers Tested-by: Nathan Chancellor Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 4 +++ scripts/check-local-export | 65 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/mod/modpost.c | 28 +------------------- 3 files changed, 70 insertions(+), 27 deletions(-) create mode 100755 scripts/check-local-export (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index cc7061258e42..b6ae652a943f 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -249,9 +249,12 @@ cmd_gen_ksymdeps = \ $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd endif +cmd_check_local_export = $(srctree)/scripts/check-local-export $@ + define rule_cc_o_c $(call cmd_and_fixdep,cc_o_c) $(call cmd,gen_ksymdeps) + $(call cmd,check_local_export) $(call cmd,checksrc) $(call cmd,checkdoc) $(call cmd,gen_objtooldep) @@ -262,6 +265,7 @@ endef define rule_as_o_S $(call cmd_and_fixdep,as_o_S) $(call cmd,gen_ksymdeps) + $(call cmd,check_local_export) $(call cmd,gen_objtooldep) $(call cmd,gen_symversions_S) endef diff --git a/scripts/check-local-export b/scripts/check-local-export new file mode 100755 index 000000000000..2c46912be0ef --- /dev/null +++ b/scripts/check-local-export @@ -0,0 +1,65 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-only +# +# Copyright (C) 2022 Masahiro Yamada +# +# Exit with error if a local exported symbol is found. +# EXPORT_SYMBOL should be used for global symbols. + +set -e + +declare -A symbol_types +declare -a export_symbols + +exit_code=0 + +while read value type name +do + # Skip the line if the number of fields is less than 3. + # + # case 1) + # For undefined symbols, the first field (value) is empty. + # The outout looks like this: + # " U _printk" + # It is unneeded to record undefined symbols. + # + # case 2) + # For Clang LTO, llvm-nm outputs a line with type 't' but empty name: + # "---------------- t" + if [[ -z ${name} ]]; then + continue + fi + + # save (name, type) in the associative array + symbol_types[${name}]=${type} + + # append the exported symbol to the array + if [[ ${name} == __ksymtab_* ]]; then + export_symbols+=(${name#__ksymtab_}) + fi + + # If there is no symbol in the object, ${NM} (both GNU nm and llvm-nm) + # shows 'no symbols' diagnostic (but exits with 0). It is harmless and + # hidden by '2>/dev/null'. However, it suppresses real error messages + # as well. Add a hand-crafted error message here. + # + # Use --quiet instead of 2>/dev/null when we upgrade the minimum version + # of binutils to 2.37, llvm to 13.0.0. + # + # Then, the following line will be really simple: + # done < <(${NM} --quiet ${1}) +done < <(${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; false; } ) + +# Catch error in the process substitution +wait $! + +for name in "${export_symbols[@]}" +do + # nm(3) says "If lowercase, the symbol is usually local" + if [[ ${symbol_types[$name]} =~ [a-z] ]]; then + echo "$@: error: local symbol '${name}' was exported" >&2 + exit_code=1 + fi +done + +exit ${exit_code} diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e74224a6a8e8..9269735f85c5 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -212,7 +212,6 @@ struct symbol { unsigned int crc; bool crc_valid; bool weak; - bool is_static; /* true if symbol is not global */ bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */ char name[]; }; @@ -242,7 +241,7 @@ static struct symbol *alloc_symbol(const char *name) memset(s, 0, sizeof(*s)); strcpy(s->name, name); - s->is_static = true; + return s; } @@ -2064,20 +2063,6 @@ static void read_symbols(const char *modname) sym_get_data(&info, sym)); } - // check for static EXPORT_SYMBOL_* functions && global vars - for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { - unsigned char bind = ELF_ST_BIND(sym->st_info); - - if (bind == STB_GLOBAL || bind == STB_WEAK) { - struct symbol *s = - find_symbol(remove_dot(info.strtab + - sym->st_name)); - - if (s) - s->is_static = false; - } - } - check_sec_ref(modname, &info); if (!mod->is_vmlinux) { @@ -2507,7 +2492,6 @@ static void read_dump(const char *fname) mod->from_dump = true; } s = sym_add_exported(symname, mod, gpl_only); - s->is_static = false; sym_set_crc(s, crc); sym_update_namespace(symname, namespace); } @@ -2572,7 +2556,6 @@ int main(int argc, char **argv) char *missing_namespace_deps = NULL; char *dump_write = NULL, *files_source = NULL; int opt; - int n; LIST_HEAD(dump_lists); struct dump_list *dl, *dl2; @@ -2648,15 +2631,6 @@ int main(int argc, char **argv) if (sec_mismatch_count && !sec_mismatch_warn_only) error("Section mismatches detected.\n" "Set CONFIG_SECTION_MISMATCH_WARN_ONLY=y to allow them.\n"); - for (n = 0; n < SYMBOL_HASH_SIZE; n++) { - struct symbol *s; - - for (s = symbolhash[n]; s; s = s->next) { - if (s->is_static) - error("\"%s\" [%s] is a static EXPORT_SYMBOL\n", - s->name, s->module->name); - } - } if (nr_unresolved > MAX_UNRESOLVED_REPORTS) warn("suppressed %u unresolved symbol warnings because there were too many)\n", -- cgit From cd968b97c49214e6557381bddddacbd0e0fb696e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 May 2022 19:01:52 +0900 Subject: kbuild: make built-in.a rule robust against too long argument error Kbuild runs at the top of objtree instead of changing the working directory to subdirectories. I think this design is nice overall but some commands have a scalability issue. The build command of built-in.a is one of them whose length scales with: O(D * N) Here, D is the length of the directory path (i.e. $(obj)/ prefix), N is the number of objects in the Makefile, O() is the big O notation. The deeper directory the Makefile directory is located, the more easily it will hit the too long argument error. We can make it better. Trim the $(obj)/ by Make's builtin function, and restore it by a shell command (sed). With this, the command length scales with: O(D + N) In-tree modules still have some room to the limit (ARG_MAX=2097152), but this is more future-proof for big modules in a deep directory. For example, you can build i915 as builtin (CONFIG_DRM_I915=y) and compare drivers/gpu/drm/i915/.built-in.a.cmd with/without this commit. Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index b6ae652a943f..3c1e20e4a4fc 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -377,9 +377,14 @@ $(subdir-modorder): $(obj)/%/modules.order: $(obj)/% ; # # Rule to compile a set of .o files into one .a file (without symbol table) # +# To make this rule robust against "Argument list too long" error, +# remove $(obj)/ prefix, and restore it by a shell command. quiet_cmd_ar_builtin = AR $@ - cmd_ar_builtin = rm -f $@; $(AR) cDPrST $@ $(real-prereqs) + cmd_ar_builtin = rm -f $@; \ + echo $(patsubst $(obj)/%,%,$(real-prereqs)) | \ + sed -E 's:([^ ]+):$(obj)/\1:g' | \ + xargs $(AR) cDPrST $@ $(obj)/built-in.a: $(real-obj-y) FORCE $(call if_changed,ar_builtin) -- cgit From c6031b1dbbbfec03891bf1baefa2e0803d705601 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 May 2022 19:01:53 +0900 Subject: kbuild: make *.mod rule robust against too long argument error Like built-in.a, the command length of the *.mod rule scales with the depth of the directory times the number of objects in the Makefile. Add $(obj)/ by the shell command (awk) instead of by Make's builtin function. In-tree modules still have some room to the limit (ARG_MAX=2097152), but this is more future-proof for big modules in a deep directory. For example, you can build i915 as a module (CONFIG_DRM_I915=m) and compare drivers/gpu/drm/i915/.i915.mod.cmd with/without this commit. The issue is more critical for external modules because the M= path can be very long as Jeff Johnson reported before [1]. [1] https://lore.kernel.org/linux-kbuild/4c02050c4e95e4cb8cc04282695f8404@codeaurora.org/ Signed-off-by: Masahiro Yamada Reviewed-by: Nicolas Schier Tested-by: Nathan Chancellor Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 3c1e20e4a4fc..a1edbfe4310b 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -275,8 +275,10 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE $(call if_changed_rule,cc_o_c) $(call cmd,force_checksrc) -cmd_mod = echo $(addprefix $(obj)/, $(call real-search, $*.o, .o, -objs -y -m)) | \ - $(AWK) -v RS='( |\n)' '!x[$$0]++' > $@ +# To make this rule robust against "Argument list too long" error, +# ensure to add $(obj)/ prefix by a shell command. +cmd_mod = echo $(call real-search, $*.o, .o, -objs -y -m) | \ + $(AWK) -v RS='( |\n)' '!x[$$0]++ { print("$(obj)/"$$0) }' > $@ $(obj)/%.mod: FORCE $(call if_changed,mod) -- cgit From ebd191b38c5ea177318543a08e544cf2f7df944d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 May 2022 19:01:54 +0900 Subject: kbuild: add cmd_and_savecmd macro Separate out the command execution part of if_changed, as we did for if_changed_dep. This allows us to reuse it in if_changed_rule. define rule_foo $(call cmd_and_savecmd,foo) $(call cmd,bar) endef Signed-off-by: Masahiro Yamada Reviewed-by: Kees Cook Tested-by: Nathan Chancellor Reviewed-by: Nicolas Schier Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Kbuild.include | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 455a0a6ce12d..ece44b735061 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -142,9 +142,11 @@ check-FORCE = $(if $(filter FORCE, $^),,$(warning FORCE prerequisite is missing) if-changed-cond = $(newer-prereqs)$(cmd-check)$(check-FORCE) # Execute command if command has changed or prerequisite(s) are updated. -if_changed = $(if $(if-changed-cond), \ +if_changed = $(if $(if-changed-cond),$(cmd_and_savecmd),@:) + +cmd_and_savecmd = \ $(cmd); \ - printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:) + printf '%s\n' 'cmd_$@ := $(make-cmd)' > $(dot-target).cmd # Execute the command and also postprocess generated .d dependencies file. if_changed_dep = $(if $(if-changed-cond),$(cmd_and_fixdep),@:) -- cgit From f6b66ca4f38b1169313383aec7fa0a8446205ebb Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Fri, 27 May 2022 19:01:55 +0900 Subject: kbuild: rebuild multi-object modules when objtool is updated When CONFIG_LTO_CLANG or CONFIG_X86_KERNEL_IBT is enabled, objtool for multi-object modules is postponed until the objects are linked together. Make sure to re-run objtool and re-link multi-object modules when objtool is updated. Signed-off-by: Masahiro Yamada Reviewed-by: Kees Cook Acked-by: Josh Poimboeuf Tested-by: Nathan Chancellor Reviewed-by: Nicolas Schier Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index a1edbfe4310b..4cb7145071b9 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -413,13 +413,18 @@ $(obj)/modules.order: $(obj-m) FORCE $(obj)/lib.a: $(lib-y) FORCE $(call if_changed,ar) -quiet_cmd_link_multi-m = LD [M] $@ - cmd_link_multi-m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool) +quiet_cmd_ld_multi_m = LD [M] $@ + cmd_ld_multi_m = $(LD) $(ld_flags) -r -o $@ @$(patsubst %.o,%.mod,$@) $(cmd_objtool) + +define rule_ld_multi_m + $(call cmd_and_savecmd,ld_multi_m) + $(call cmd,gen_objtooldep) +endef $(multi-obj-m): objtool-enabled := $(delay-objtool) $(multi-obj-m): part-of-module := y $(multi-obj-m): %.o: %.mod FORCE - $(call if_changed,link_multi-m) + $(call if_changed_rule,ld_multi_m) $(call multi_depend, $(multi-obj-m), .o, -objs -y -m) targets := $(filter-out $(PHONY), $(targets)) -- cgit From a78b6afa9913890e92aede1c17e72dec7e528549 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 29 May 2022 00:47:01 +0900 Subject: kbuild: remove redundant cleanups in scripts/link-vmlinux.sh These are cleaned by the top Makefile. vmlinux.o and .vmlinux.d matches the '*.[aios]' and '.*.d' patterns respectively. Signed-off-by: Masahiro Yamada Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/link-vmlinux.sh | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 68e4be463a76..1c0af7288b79 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -309,8 +309,6 @@ cleanup() rm -f System.map rm -f vmlinux rm -f vmlinux.map - rm -f vmlinux.o - rm -f .vmlinux.d rm -f .vmlinux.objs rm -f .vmlinux.export.c } -- cgit From fae35da4ace3721dfba1b3986a9239fc85cf8c72 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Sat, 28 May 2022 17:31:31 +0200 Subject: docs: move Linux logo into a new `images` folder Having assets in the top-level `Documentation` directory can make it harder to find the documents one needs, especially if we want to add more of them later on. Instead, create a new `images` folder inside it that is used to hold assets such as logos. In addition, update the reference in `scripts/spdxcheck-test.sh`. Link: https://lore.kernel.org/lkml/8735hicoy7.fsf@meer.lwn.net/ Suggested-by: Jonathan Corbet Signed-off-by: Miguel Ojeda Link: https://lore.kernel.org/r/20220528153132.8636-1-ojeda@kernel.org Signed-off-by: Jonathan Corbet --- scripts/spdxcheck-test.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/spdxcheck-test.sh b/scripts/spdxcheck-test.sh index cb76324756bd..9f6d1a74da6e 100644 --- a/scripts/spdxcheck-test.sh +++ b/scripts/spdxcheck-test.sh @@ -1,7 +1,7 @@ #!/bin/sh # run check on a text and a binary file -for FILE in Makefile Documentation/logo.gif; do +for FILE in Makefile Documentation/images/logo.gif; do python3 scripts/spdxcheck.py $FILE python3 scripts/spdxcheck.py - < $FILE done -- cgit From 08145b087e4481458f6075f3af58021a3cf8a940 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Tue, 31 May 2022 18:04:10 +0800 Subject: LoongArch: Add ELF-related definitions Add ELF-related definitions for LoongArch, including: EM_LOONGARCH, KEXEC_ARCH_LOONGARCH, AUDIT_ARCH_LOONGARCH32, AUDIT_ARCH_LOONGARCH64 and NT_LOONGARCH_*. Reviewed-by: WANG Xuerui Reviewed-by: Jiaxun Yang Signed-off-by: Huacai Chen --- scripts/sorttable.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts') diff --git a/scripts/sorttable.c b/scripts/sorttable.c index d00504c5f530..fba40e99f354 100644 --- a/scripts/sorttable.c +++ b/scripts/sorttable.c @@ -60,6 +60,10 @@ #define EM_RISCV 243 #endif +#ifndef EM_LOONGARCH +#define EM_LOONGARCH 258 +#endif + static uint32_t (*r)(const uint32_t *); static uint16_t (*r2)(const uint16_t *); static uint64_t (*r8)(const uint64_t *); @@ -313,6 +317,7 @@ static int do_file(char const *const fname, void *addr) case EM_ARCOMPACT: case EM_ARCV2: case EM_ARM: + case EM_LOONGARCH: case EM_MICROBLAZE: case EM_MIPS: case EM_XTENSA: -- cgit From fa96b57c149061f71a70bd6582d995f6424fbbf4 Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Tue, 31 May 2022 18:04:11 +0800 Subject: LoongArch: Add build infrastructure Add Kbuild, Makefile, Kconfig and link script for LoongArch build infrastructure. Reviewed-by: Guo Ren Reviewed-by: WANG Xuerui Reviewed-by: Jiaxun Yang Signed-off-by: Huacai Chen --- scripts/subarch.include | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/subarch.include b/scripts/subarch.include index 776849a3c500..4bd327d0ae42 100644 --- a/scripts/subarch.include +++ b/scripts/subarch.include @@ -10,4 +10,4 @@ SUBARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \ -e s/s390x/s390/ \ -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \ -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \ - -e s/riscv.*/riscv/) + -e s/riscv.*/riscv/ -e s/loongarch.*/loongarch/) -- cgit From b0d6207bad2cb5a6f2099ac4a6ea4e76864dd596 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 29 May 2022 00:47:02 +0900 Subject: kbuild: clean .tmp_* pattern by make clean Change the "make clean" rule to remove all the .tmp_* files. .tmp_objdiff is the only exception, which should be removed by "make mrproper". Rename the record directory of objdiff, .tmp_objdiff to .objdiff to avoid the removal by "make clean". Signed-off-by: Masahiro Yamada Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/link-vmlinux.sh | 3 --- scripts/objdiff | 6 +++--- 2 files changed, 3 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 1c0af7288b79..3f51b08cc203 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -303,9 +303,6 @@ sorttable() cleanup() { rm -f .btf.* - rm -f .tmp_System.map - rm -f .tmp_initcalls.lds - rm -f .tmp_vmlinux* rm -f System.map rm -f vmlinux rm -f vmlinux.map diff --git a/scripts/objdiff b/scripts/objdiff index 72b0b63c3fe1..0685bc3ce3df 100755 --- a/scripts/objdiff +++ b/scripts/objdiff @@ -20,10 +20,10 @@ # $ ./scripts/objdiff diff COMMIT_A COMMIT_B # $ -# And to clean up (everything is in .tmp_objdiff/*) +# And to clean up (everything is in .objdiff/*) # $ ./scripts/objdiff clean all # -# Note: 'make mrproper' will also remove .tmp_objdiff +# Note: 'make mrproper' will also remove .objdiff SRCTREE=$(cd $(git rev-parse --show-toplevel 2>/dev/null); pwd) @@ -32,7 +32,7 @@ if [ -z "$SRCTREE" ]; then exit 1 fi -TMPD=$SRCTREE/.tmp_objdiff +TMPD=$SRCTREE/.objdiff usage() { echo >&2 "Usage: $0 " -- cgit From 5d45950dfbb1540bba3e3762a3497de8b4a715d3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 29 May 2022 00:47:03 +0900 Subject: kbuild: move vmlinux.o link to scripts/Makefile.vmlinux_o This is a preparation for moving the objtool rule in the next commit. Signed-off-by: Masahiro Yamada Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.vmlinux_o | 61 ++++++++++++++++++++++++++++++++++++++++++++++ scripts/link-vmlinux.sh | 41 +------------------------------ 2 files changed, 62 insertions(+), 40 deletions(-) create mode 100644 scripts/Makefile.vmlinux_o (limited to 'scripts') diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o new file mode 100644 index 000000000000..a9b375ca86d5 --- /dev/null +++ b/scripts/Makefile.vmlinux_o @@ -0,0 +1,61 @@ +# SPDX-License-Identifier: GPL-2.0-only + +PHONY := __default +__default: vmlinux.o + +include include/config/auto.conf +include $(srctree)/scripts/Kbuild.include + +# Generate a linker script to ensure correct ordering of initcalls for Clang LTO +# --------------------------------------------------------------------------- + +quiet_cmd_gen_initcalls_lds = GEN $@ + cmd_gen_initcalls_lds = \ + $(PYTHON3) $(srctree)/scripts/jobserver-exec \ + $(PERL) $(real-prereqs) > $@ + +.tmp_initcalls.lds: $(srctree)/scripts/generate_initcall_order.pl \ + $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) FORCE + $(call if_changed,gen_initcalls_lds) + +targets := .tmp_initcalls.lds + +ifdef CONFIG_LTO_CLANG +initcalls-lds := .tmp_initcalls.lds +endif + +# Link of vmlinux.o used for section mismatch analysis +# --------------------------------------------------------------------------- + +quiet_cmd_ld_vmlinux.o = LD $@ + cmd_ld_vmlinux.o = \ + $(LD) ${KBUILD_LDFLAGS} -r -o $@ \ + $(addprefix -T , $(initcalls-lds)) \ + --whole-archive $(KBUILD_VMLINUX_OBJS) --no-whole-archive \ + --start-group $(KBUILD_VMLINUX_LIBS) --end-group \ + +define rule_ld_vmlinux.o + $(call cmd_and_savecmd,ld_vmlinux.o) +endef + +vmlinux.o: $(initcalls-lds) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) FORCE + $(call if_changed_rule,ld_vmlinux.o) + +targets += vmlinux.o + +# Add FORCE to the prequisites of a target to force it to be always rebuilt. +# --------------------------------------------------------------------------- + +PHONY += FORCE +FORCE: + +# Read all saved command lines and dependencies for the $(targets) we +# may be building above, using $(if_changed{,_dep}). As an +# optimization, we don't need to read them if the target does not +# exist, we will rebuild anyway in that case. + +existing-targets := $(wildcard $(sort $(targets))) + +-include $(foreach f,$(existing-targets),$(dir $(f)).$(notdir $(f)).cmd) + +.PHONY: $(PHONY) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 3f51b08cc203..bf685d4547c1 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -45,45 +45,6 @@ info() printf " %-7s %s\n" "${1}" "${2}" } -# Generate a linker script to ensure correct ordering of initcalls. -gen_initcalls() -{ - info GEN .tmp_initcalls.lds - - ${PYTHON3} ${srctree}/scripts/jobserver-exec \ - ${PERL} ${srctree}/scripts/generate_initcall_order.pl \ - ${KBUILD_VMLINUX_OBJS} ${KBUILD_VMLINUX_LIBS} \ - > .tmp_initcalls.lds -} - -# Link of vmlinux.o used for section mismatch analysis -# ${1} output file -modpost_link() -{ - local objects - local lds="" - - objects="--whole-archive \ - ${KBUILD_VMLINUX_OBJS} \ - --no-whole-archive \ - --start-group \ - ${KBUILD_VMLINUX_LIBS} \ - --end-group" - - if is_enabled CONFIG_LTO_CLANG; then - gen_initcalls - lds="-T .tmp_initcalls.lds" - - # This might take a while, so indicate that we're doing - # an LTO link - info LTO ${1} - else - info LD ${1} - fi - - ${LD} ${KBUILD_LDFLAGS} -r -o ${1} ${lds} ${objects} -} - objtool_link() { local objtoolcmd; @@ -336,7 +297,7 @@ fi; ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1 #link vmlinux.o -modpost_link vmlinux.o +${MAKE} -f "${srctree}/scripts/Makefile.vmlinux_o" objtool_link vmlinux.o # Generate the list of in-tree objects in vmlinux -- cgit From b42d2306502419688190aa6dd4dab4a6def24b3d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sun, 29 May 2022 00:47:04 +0900 Subject: kbuild: factor out the common objtool arguments scripts/Makefile.build and scripts/link-vmlinux.sh have similar setups for the objtool arguments. It was difficult to factor out them because all the vmlinux build rules were written in a shell script. It is somewhat tedious to touch the two files every time a new objtool option is supported. To reduce the code duplication, move the objtool for vmlinux.o into scripts/Makefile.vmlinux_o. Then, move the common macros to Makefile.lib so they are shared between Makefile.build and Makefile.vmlinux_o. Signed-off-by: Masahiro Yamada Tested-by: Sedat Dilek # LLVM-14 (x86-64) --- scripts/Makefile.build | 26 ----------------- scripts/Makefile.lib | 26 +++++++++++++++++ scripts/Makefile.vmlinux_o | 26 +++++++++++++++++ scripts/link-vmlinux.sh | 71 ---------------------------------------------- 4 files changed, 52 insertions(+), 97 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 4cb7145071b9..1f01ac65c0cd 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -210,38 +210,12 @@ cmd_record_mcount = $(if $(findstring $(strip $(CC_FLAGS_FTRACE)),$(_c_flags)), $(sub_cmd_record_mcount)) endif # CONFIG_FTRACE_MCOUNT_USE_RECORDMCOUNT -ifdef CONFIG_OBJTOOL - -objtool := $(objtree)/tools/objtool/objtool - -objtool_args = \ - $(if $(CONFIG_HAVE_JUMP_LABEL_HACK), --hacks=jump_label) \ - $(if $(CONFIG_HAVE_NOINSTR_HACK), --hacks=noinstr) \ - $(if $(CONFIG_X86_KERNEL_IBT), --ibt) \ - $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \ - $(if $(CONFIG_UNWINDER_ORC), --orc) \ - $(if $(CONFIG_RETPOLINE), --retpoline) \ - $(if $(CONFIG_SLS), --sls) \ - $(if $(CONFIG_STACK_VALIDATION), --stackval) \ - $(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \ - --uaccess \ - $(if $(delay-objtool), --link) \ - $(if $(part-of-module), --module) \ - $(if $(CONFIG_GCOV_KERNEL), --no-unreachable) - -cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@) -cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) - -endif # CONFIG_OBJTOOL - # 'OBJECT_FILES_NON_STANDARD := y': skip objtool checking for a directory # 'OBJECT_FILES_NON_STANDARD_foo.o := 'y': skip objtool checking for a file # 'OBJECT_FILES_NON_STANDARD_foo.o := 'n': override directory skip for a file is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetarget).o)$(OBJECT_FILES_NON_STANDARD)n),y) -delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT)) - $(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y)) ifdef CONFIG_TRIM_UNUSED_KSYMS diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index f75138385449..f691fb231ce5 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -225,6 +225,32 @@ dtc_cpp_flags = -Wp,-MMD,$(depfile).pre.tmp -nostdinc \ $(addprefix -I,$(DTC_INCLUDE)) \ -undef -D__DTS__ +ifdef CONFIG_OBJTOOL + +objtool := $(objtree)/tools/objtool/objtool + +objtool_args = \ + $(if $(CONFIG_HAVE_JUMP_LABEL_HACK), --hacks=jump_label) \ + $(if $(CONFIG_HAVE_NOINSTR_HACK), --hacks=noinstr) \ + $(if $(CONFIG_X86_KERNEL_IBT), --ibt) \ + $(if $(CONFIG_FTRACE_MCOUNT_USE_OBJTOOL), --mcount) \ + $(if $(CONFIG_UNWINDER_ORC), --orc) \ + $(if $(CONFIG_RETPOLINE), --retpoline) \ + $(if $(CONFIG_SLS), --sls) \ + $(if $(CONFIG_STACK_VALIDATION), --stackval) \ + $(if $(CONFIG_HAVE_STATIC_CALL_INLINE), --static-call) \ + --uaccess \ + $(if $(delay-objtool), --link) \ + $(if $(part-of-module), --module) \ + $(if $(CONFIG_GCOV_KERNEL), --no-unreachable) + +delay-objtool := $(or $(CONFIG_LTO_CLANG),$(CONFIG_X86_KERNEL_IBT)) + +cmd_objtool = $(if $(objtool-enabled), ; $(objtool) $(objtool_args) $@) +cmd_gen_objtooldep = $(if $(objtool-enabled), { echo ; echo '$@: $$(wildcard $(objtool))' ; } >> $(dot-target).cmd) + +endif # CONFIG_OBJTOOL + # Useful for describing the dependency of composite objects # Usage: # $(call multi_depend, multi_used_targets, suffix_to_remove, suffix_to_add) diff --git a/scripts/Makefile.vmlinux_o b/scripts/Makefile.vmlinux_o index a9b375ca86d5..3c97a1564947 100644 --- a/scripts/Makefile.vmlinux_o +++ b/scripts/Makefile.vmlinux_o @@ -6,6 +6,9 @@ __default: vmlinux.o include include/config/auto.conf include $(srctree)/scripts/Kbuild.include +# for objtool +include $(srctree)/scripts/Makefile.lib + # Generate a linker script to ensure correct ordering of initcalls for Clang LTO # --------------------------------------------------------------------------- @@ -24,6 +27,27 @@ ifdef CONFIG_LTO_CLANG initcalls-lds := .tmp_initcalls.lds endif +# objtool for vmlinux.o +# --------------------------------------------------------------------------- +# +# For LTO and IBT, objtool doesn't run on individual translation units. +# Run everything on vmlinux instead. + +objtool-enabled := $(or $(delay-objtool),$(CONFIG_NOINSTR_VALIDATION)) + +# Reuse objtool_args defined in scripts/Makefile.lib if LTO or IBT is enabled. +# +# Add some more flags as needed. +# --no-unreachable and --link might be added twice, but it is fine. +# +# Expand objtool_args to a simple variable to avoid circular reference. + +objtool_args := \ + $(if $(delay-objtool),$(objtool_args)) \ + $(if $(CONFIG_NOINSTR_VALIDATION), --noinstr) \ + $(if $(CONFIG_GCOV_KERNEL), --no-unreachable) \ + --link + # Link of vmlinux.o used for section mismatch analysis # --------------------------------------------------------------------------- @@ -33,9 +57,11 @@ quiet_cmd_ld_vmlinux.o = LD $@ $(addprefix -T , $(initcalls-lds)) \ --whole-archive $(KBUILD_VMLINUX_OBJS) --no-whole-archive \ --start-group $(KBUILD_VMLINUX_LIBS) --end-group \ + $(cmd_objtool) define rule_ld_vmlinux.o $(call cmd_and_savecmd,ld_vmlinux.o) + $(call cmd,gen_objtooldep) endef vmlinux.o: $(initcalls-lds) $(KBUILD_VMLINUX_OBJS) $(KBUILD_VMLINUX_LIBS) FORCE diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index bf685d4547c1..eecc1863e556 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -45,76 +45,6 @@ info() printf " %-7s %s\n" "${1}" "${2}" } -objtool_link() -{ - local objtoolcmd; - local objtoolopt; - - if ! is_enabled CONFIG_OBJTOOL; then - return; - fi - - if is_enabled CONFIG_LTO_CLANG || is_enabled CONFIG_X86_KERNEL_IBT; then - - # For LTO and IBT, objtool doesn't run on individual - # translation units. Run everything on vmlinux instead. - - if is_enabled CONFIG_HAVE_JUMP_LABEL_HACK; then - objtoolopt="${objtoolopt} --hacks=jump_label" - fi - - if is_enabled CONFIG_HAVE_NOINSTR_HACK; then - objtoolopt="${objtoolopt} --hacks=noinstr" - fi - - if is_enabled CONFIG_X86_KERNEL_IBT; then - objtoolopt="${objtoolopt} --ibt" - fi - - if is_enabled CONFIG_FTRACE_MCOUNT_USE_OBJTOOL; then - objtoolopt="${objtoolopt} --mcount" - fi - - if is_enabled CONFIG_UNWINDER_ORC; then - objtoolopt="${objtoolopt} --orc" - fi - - if is_enabled CONFIG_RETPOLINE; then - objtoolopt="${objtoolopt} --retpoline" - fi - - if is_enabled CONFIG_SLS; then - objtoolopt="${objtoolopt} --sls" - fi - - if is_enabled CONFIG_STACK_VALIDATION; then - objtoolopt="${objtoolopt} --stackval" - fi - - if is_enabled CONFIG_HAVE_STATIC_CALL_INLINE; then - objtoolopt="${objtoolopt} --static-call" - fi - - objtoolopt="${objtoolopt} --uaccess" - fi - - if is_enabled CONFIG_NOINSTR_VALIDATION; then - objtoolopt="${objtoolopt} --noinstr" - fi - - if [ -n "${objtoolopt}" ]; then - - if is_enabled CONFIG_GCOV_KERNEL; then - objtoolopt="${objtoolopt} --no-unreachable" - fi - - objtoolopt="${objtoolopt} --link" - - info OBJTOOL ${1} - tools/objtool/objtool ${objtoolopt} ${1} - fi -} - # Link of vmlinux # ${1} - output file # ${2}, ${3}, ... - optional extra .o files @@ -298,7 +228,6 @@ ${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init need-builtin=1 #link vmlinux.o ${MAKE} -f "${srctree}/scripts/Makefile.vmlinux_o" -objtool_link vmlinux.o # Generate the list of in-tree objects in vmlinux # -- cgit From 8c9ce89c5b63028dd3be43807f10b009cd2c6e51 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 30 May 2022 18:01:38 +0900 Subject: modpost: simplify mod->name allocation mod->name is set to the ELF filename with the suffix ".o" stripped. The current code calls strdup() and free() to manipulate the string, but a simpler approach is to pass new_module() with the name length subtracted by 2. Also, check if the passed filename ends with ".o" before stripping it. The current code blindly chops the suffix: tmp[strlen(tmp) - 2] = '\0' It will cause buffer under-run if strlen(tmp) < 2; Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 9269735f85c5..c1558bacf717 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -172,11 +172,11 @@ static struct module *find_module(const char *modname) return NULL; } -static struct module *new_module(const char *modname) +static struct module *new_module(const char *name, size_t namelen) { struct module *mod; - mod = NOFAIL(malloc(sizeof(*mod) + strlen(modname) + 1)); + mod = NOFAIL(malloc(sizeof(*mod) + namelen + 1)); memset(mod, 0, sizeof(*mod)); INIT_LIST_HEAD(&mod->exported_symbols); @@ -184,8 +184,9 @@ static struct module *new_module(const char *modname) INIT_LIST_HEAD(&mod->missing_namespaces); INIT_LIST_HEAD(&mod->imported_namespaces); - strcpy(mod->name, modname); - mod->is_vmlinux = (strcmp(modname, "vmlinux") == 0); + memcpy(mod->name, name, namelen); + mod->name[namelen] = '\0'; + mod->is_vmlinux = (strcmp(mod->name, "vmlinux") == 0); /* * Set mod->is_gpl_compatible to true by default. If MODULE_LICENSE() @@ -2017,16 +2018,14 @@ static void read_symbols(const char *modname) if (!parse_elf(&info, modname)) return; - { - char *tmp; - - /* strip trailing .o */ - tmp = NOFAIL(strdup(modname)); - tmp[strlen(tmp) - 2] = '\0'; - mod = new_module(tmp); - free(tmp); + if (!strends(modname, ".o")) { + error("%s: filename must be suffixed with .o\n", modname); + return; } + /* strip trailing .o */ + mod = new_module(modname, strlen(modname) - strlen(".o")); + if (!mod->is_vmlinux) { license = get_modinfo(&info, "license"); if (!license) @@ -2488,7 +2487,7 @@ static void read_dump(const char *fname) mod = find_module(modname); if (!mod) { - mod = new_module(modname); + mod = new_module(modname, strlen(modname)); mod->from_dump = true; } s = sym_add_exported(symname, mod, gpl_only); -- cgit From a89227d769845eb9e9ab113f9f83df34d3c91db5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 30 May 2022 18:01:39 +0900 Subject: modpost: use fnmatch() to simplify match() Replace the own implementation for wildcard (glob) matching with a function call to fnmatch(). Also, change the return type to 'bool'. Signed-off-by: Masahiro Yamada --- scripts/mod/modpost.c | 74 +++++++++------------------------------------------ 1 file changed, 13 insertions(+), 61 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index c1558bacf717..29d5a841e215 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -13,6 +13,7 @@ #define _GNU_SOURCE #include +#include #include #include #include @@ -710,29 +711,6 @@ static char *get_modinfo(struct elf_info *info, const char *tag) return get_next_modinfo(info, tag, NULL); } -/** - * Test if string s ends in string sub - * return 0 if match - **/ -static int strrcmp(const char *s, const char *sub) -{ - int slen, sublen; - - if (!s || !sub) - return 1; - - slen = strlen(s); - sublen = strlen(sub); - - if ((slen == 0) || (sublen == 0)) - return 1; - - if (sublen > slen) - return 1; - - return memcmp(s + slen - sublen, sub, sublen); -} - static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) { if (sym) @@ -741,48 +719,22 @@ static const char *sym_name(struct elf_info *elf, Elf_Sym *sym) return "(unknown)"; } -/* The pattern is an array of simple patterns. - * "foo" will match an exact string equal to "foo" - * "*foo" will match a string that ends with "foo" - * "foo*" will match a string that begins with "foo" - * "*foo*" will match a string that contains "foo" +/* + * Check whether the 'string' argument matches one of the 'patterns', + * an array of shell wildcard patterns (glob). + * + * Return true is there is a match. */ -static int match(const char *sym, const char * const pat[]) +static bool match(const char *string, const char *const patterns[]) { - const char *p; - while (*pat) { - const char *endp; - - p = *pat++; - endp = p + strlen(p) - 1; + const char *pattern; - /* "*foo*" */ - if (*p == '*' && *endp == '*') { - char *bare = NOFAIL(strndup(p + 1, strlen(p) - 2)); - char *here = strstr(sym, bare); - - free(bare); - if (here != NULL) - return 1; - } - /* "*foo" */ - else if (*p == '*') { - if (strrcmp(sym, p + 1) == 0) - return 1; - } - /* "foo*" */ - else if (*endp == '*') { - if (strncmp(sym, p, strlen(p) - 1) == 0) - return 1; - } - /* no wildcards */ - else { - if (strcmp(p, sym) == 0) - return 1; - } + while ((pattern = *patterns++)) { + if (!fnmatch(pattern, string, 0)) + return true; } - /* no match */ - return 0; + + return false; } /* sections that we do not want to do full section mismatch check on */ -- cgit From 2bbb486162c4ace673ea423bbd7e7b40f020ad45 Mon Sep 17 00:00:00 2001 From: Isak Ellmer Date: Wed, 1 Jun 2022 15:08:19 +0200 Subject: scripts: kconfig: nconf: make nconfig accept jk keybindings Make nconfig accept jk keybindings for movement in addition to arrow keys. Signed-off-by: Isak Ellmer Signed-off-by: Masahiro Yamada --- scripts/kconfig/nconf.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 7b371bd7fb36..3ba8b1af390f 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -52,8 +52,8 @@ static const char nconf_global_help[] = "\n" "Menu navigation keys\n" "----------------------------------------------------------------------\n" -"Linewise up \n" -"Linewise down \n" +"Linewise up \n" +"Linewise down \n" "Pagewise up \n" "Pagewise down \n" "First entry \n" @@ -1105,9 +1105,11 @@ static void conf(struct menu *menu) break; switch (res) { case KEY_DOWN: + case 'j': menu_driver(curses_menu, REQ_DOWN_ITEM); break; case KEY_UP: + case 'k': menu_driver(curses_menu, REQ_UP_ITEM); break; case KEY_NPAGE: @@ -1287,9 +1289,11 @@ static void conf_choice(struct menu *menu) break; switch (res) { case KEY_DOWN: + case 'j': menu_driver(curses_menu, REQ_DOWN_ITEM); break; case KEY_UP: + case 'k': menu_driver(curses_menu, REQ_UP_ITEM); break; case KEY_NPAGE: -- cgit From 42ce60aa5aa46ae00f71aa806a11510b6db6d1a7 Mon Sep 17 00:00:00 2001 From: Schspa Shi Date: Fri, 3 Jun 2022 17:38:52 +0800 Subject: kbuild: Allow to select bash in a modified environment This fixes the build error when the system has a default bash version which is too old to support associative array variables. The build error log as fellowing: linux/scripts/check-local-export: line 11: declare: -A: invalid option declare: usage: declare [-afFirtx] [-p] [name[=value] ...] Signed-off-by: Schspa Shi Signed-off-by: Masahiro Yamada --- scripts/check-local-export | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/check-local-export b/scripts/check-local-export index 2c46912be0ef..da745e2743b7 100755 --- a/scripts/check-local-export +++ b/scripts/check-local-export @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # SPDX-License-Identifier: GPL-2.0-only # # Copyright (C) 2022 Masahiro Yamada -- cgit From dcea997beed694cbd8705100ca1a6eb0d886de69 Mon Sep 17 00:00:00 2001 From: Josh Poimboeuf Date: Wed, 1 Jun 2022 17:42:22 -0700 Subject: faddr2line: Fix overlapping text section failures, the sequel If a function lives in a section other than .text, but .text also exists in the object, faddr2line may wrongly assume .text. This can result in comically wrong output. For example: $ scripts/faddr2line vmlinux.o enter_from_user_mode+0x1c enter_from_user_mode+0x1c/0x30: find_next_bit at /home/jpoimboe/git/linux/./include/linux/find.h:40 (inlined by) perf_clear_dirty_counters at /home/jpoimboe/git/linux/arch/x86/events/core.c:2504 Fix it by passing the section name to addr2line, unless the object file is vmlinux, in which case the symbol table uses absolute addresses. Fixes: 1d1a0e7c5100 ("scripts/faddr2line: Fix overlapping text section failures") Reported-by: Peter Zijlstra Signed-off-by: Josh Poimboeuf Link: https://lore.kernel.org/r/7d25bc1408bd3a750ac26e60d2f2815a5f4a8363.1654130536.git.jpoimboe@kernel.org --- scripts/faddr2line | 45 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/scripts/faddr2line b/scripts/faddr2line index 0e6268d59883..94ed98dd899f 100755 --- a/scripts/faddr2line +++ b/scripts/faddr2line @@ -95,17 +95,25 @@ __faddr2line() { local print_warnings=$4 local sym_name=${func_addr%+*} - local offset=${func_addr#*+} - offset=${offset%/*} + local func_offset=${func_addr#*+} + func_offset=${func_offset%/*} local user_size= + local file_type + local is_vmlinux=0 [[ $func_addr =~ "/" ]] && user_size=${func_addr#*/} - if [[ -z $sym_name ]] || [[ -z $offset ]] || [[ $sym_name = $func_addr ]]; then + if [[ -z $sym_name ]] || [[ -z $func_offset ]] || [[ $sym_name = $func_addr ]]; then warn "bad func+offset $func_addr" DONE=1 return fi + # vmlinux uses absolute addresses in the section table rather than + # section offsets. + local file_type=$(${READELF} --file-header $objfile | + ${AWK} '$1 == "Type:" { print $2; exit }') + [[ $file_type = "EXEC" ]] && is_vmlinux=1 + # Go through each of the object's symbols which match the func name. # In rare cases there might be duplicates, in which case we print all # matches. @@ -114,9 +122,11 @@ __faddr2line() { local sym_addr=0x${fields[1]} local sym_elf_size=${fields[2]} local sym_sec=${fields[6]} + local sec_size + local sec_name # Get the section size: - local sec_size=$(${READELF} --section-headers --wide $objfile | + sec_size=$(${READELF} --section-headers --wide $objfile | sed 's/\[ /\[/' | ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print "0x" $6; exit }') @@ -126,6 +136,17 @@ __faddr2line() { return fi + # Get the section name: + sec_name=$(${READELF} --section-headers --wide $objfile | + sed 's/\[ /\[/' | + ${AWK} -v sec=$sym_sec '$1 == "[" sec "]" { print $2; exit }') + + if [[ -z $sec_name ]]; then + warn "bad section name: section: $sym_sec" + DONE=1 + return + fi + # Calculate the symbol size. # # Unfortunately we can't use the ELF size, because kallsyms @@ -174,10 +195,10 @@ __faddr2line() { sym_size=0x$(printf %x $sym_size) - # Calculate the section address from user-supplied offset: - local addr=$(($sym_addr + $offset)) + # Calculate the address from user-supplied offset: + local addr=$(($sym_addr + $func_offset)) if [[ -z $addr ]] || [[ $addr = 0 ]]; then - warn "bad address: $sym_addr + $offset" + warn "bad address: $sym_addr + $func_offset" DONE=1 return fi @@ -191,9 +212,9 @@ __faddr2line() { fi # Make sure the provided offset is within the symbol's range: - if [[ $offset -gt $sym_size ]]; then + if [[ $func_offset -gt $sym_size ]]; then [[ $print_warnings = 1 ]] && - echo "skipping $sym_name address at $addr due to size mismatch ($offset > $sym_size)" + echo "skipping $sym_name address at $addr due to size mismatch ($func_offset > $sym_size)" continue fi @@ -202,11 +223,13 @@ __faddr2line() { [[ $FIRST = 0 ]] && echo FIRST=0 - echo "$sym_name+$offset/$sym_size:" + echo "$sym_name+$func_offset/$sym_size:" # Pass section address to addr2line and strip absolute paths # from the output: - local output=$(${ADDR2LINE} -fpie $objfile $addr | sed "s; $dir_prefix\(\./\)*; ;") + local args="--functions --pretty-print --inlines --exe=$objfile" + [[ $is_vmlinux = 0 ]] && args="$args --section=$sec_name" + local output=$(${ADDR2LINE} $args $addr | sed "s; $dir_prefix\(\./\)*; ;") [[ -z $output ]] && continue # Default output (non --list): -- cgit From 7bf179de5b2dfae54a6839eaf7caba44a888ee2e Mon Sep 17 00:00:00 2001 From: Kevin Locke Date: Mon, 6 Jun 2022 20:42:54 -0600 Subject: kbuild: avoid regex RS for POSIX awk In 22f26f21774f8 awk was added to deduplicate *.mod files. The awk invocation passes -v RS='( |\n)' to match a space or newline character as the record separator. Unfortunately, POSIX states[1] > If RS contains more than one character, the results are unspecified. Some implementations (such as the One True Awk[2] used by the BSDs) do not treat RS as a regular expression. When awk does not support regex RS, build failures such as the following are produced (first error using allmodconfig): CC [M] arch/x86/events/intel/uncore.o CC [M] arch/x86/events/intel/uncore_nhmex.o CC [M] arch/x86/events/intel/uncore_snb.o CC [M] arch/x86/events/intel/uncore_snbep.o CC [M] arch/x86/events/intel/uncore_discovery.o LD [M] arch/x86/events/intel/intel-uncore.o ld: cannot find uncore_nhmex.o: No such file or directory ld: cannot find uncore_snb.o: No such file or directory ld: cannot find uncore_snbep.o: No such file or directory ld: cannot find uncore_discovery.o: No such file or directory make[3]: *** [scripts/Makefile.build:422: arch/x86/events/intel/intel-uncore.o] Error 1 make[2]: *** [scripts/Makefile.build:487: arch/x86/events/intel] Error 2 make[1]: *** [scripts/Makefile.build:487: arch/x86/events] Error 2 make: *** [Makefile:1839: arch/x86] Error 2 To avoid this, use printf(1) to produce a newline between each object path, instead of the space produced by echo(1), so that the default RS can be used by awk. [1]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html [2]: https://github.com/onetrueawk/awk Fixes: 22f26f21774f ("kbuild: get rid of duplication in *.mod files") Signed-off-by: Kevin Locke Signed-off-by: Masahiro Yamada --- scripts/Makefile.build | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 1f01ac65c0cd..cac070aee791 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -251,8 +251,8 @@ $(obj)/%.o: $(src)/%.c $(recordmcount_source) FORCE # To make this rule robust against "Argument list too long" error, # ensure to add $(obj)/ prefix by a shell command. -cmd_mod = echo $(call real-search, $*.o, .o, -objs -y -m) | \ - $(AWK) -v RS='( |\n)' '!x[$$0]++ { print("$(obj)/"$$0) }' > $@ +cmd_mod = printf '%s\n' $(call real-search, $*.o, .o, -objs -y -m) | \ + $(AWK) '!x[$$0]++ { print("$(obj)/"$$0) }' > $@ $(obj)/%.mod: FORCE $(call if_changed,mod) -- cgit From 49c3ca34f7dbe5227c0163cba4deb5d29e145fae Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 8 Jun 2022 00:18:40 +0900 Subject: scripts/nsdeps: adjust to the format change of *.mod files Commit 22f26f21774f ("kbuild: get rid of duplication in *.mod files") changed the format of *.mod files to put one object per line, but missed to adjust scripts/nsdeps. Fixes: 22f26f21774f ("kbuild: get rid of duplication in *.mod files") Signed-off-by: Masahiro Yamada --- scripts/nsdeps | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/nsdeps b/scripts/nsdeps index 04c4b96e95ec..f1718cc0d700 100644 --- a/scripts/nsdeps +++ b/scripts/nsdeps @@ -34,9 +34,8 @@ generate_deps() { local mod=${1%.ko:} shift local namespaces="$*" - local mod_source_files="`cat $mod.mod | sed -n 1p \ - | sed -e 's/\.o/\.c/g' \ - | sed "s|[^ ]* *|${src_prefix}&|g"`" + local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod) + for ns in $namespaces; do echo "Adding namespace $ns to module $mod.ko." generate_deps_for_ns $ns "$mod_source_files" -- cgit From 6bfb56e93bcef41859c2d5ab234ffd80b691be35 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 8 Jun 2022 13:18:39 -0700 Subject: cert host tools: Stop complaining about deprecated OpenSSL functions OpenSSL 3.0 deprecated the OpenSSL's ENGINE API. That is as may be, but the kernel build host tools still use it. Disable the warning about deprecated declarations until somebody who cares fixes it. Signed-off-by: Linus Torvalds --- scripts/sign-file.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'scripts') diff --git a/scripts/sign-file.c b/scripts/sign-file.c index fbd34b8e8f57..7434e9ea926e 100644 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -29,6 +29,13 @@ #include #include +/* + * OpenSSL 3.0 deprecates the OpenSSL's ENGINE API. + * + * Remove this if/when that API is no longer used + */ +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /* * Use CMS if we have openssl-1.0.0 or newer available - otherwise we have to * assume that it's not available and its header file is missing and that we -- cgit From da4288b95baa1c7c9aa8a476f58b37eb238745b0 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 8 Jun 2022 10:11:00 +0900 Subject: scripts/check-local-export: avoid 'wait $!' for process substitution Bash 4.4, released in 2016, supports 'wait $!' to check the exit status of a process substitution, but it seems too new. Some people using older bash versions (on CentOS 7, Ubuntu 16.04, etc.) reported an error like this: ./scripts/check-local-export: line 54: wait: pid 17328 is not a child of this shell I used the process substitution to avoid a pipeline, which executes each command in a subshell. If the while-loop is executed in the subshell context, variable changes within are lost after the subshell terminates. Fortunately, Bash 4.2, released in 2011, supports the 'lastpipe' option, which makes the last element of a pipeline run in the current shell process. Switch to the pipeline with 'lastpipe' solution, and also set 'pipefail' to catch errors from ${NM}. Add the bash requirement to Documentation/process/changes.rst. Fixes: 31cb50b5590f ("kbuild: check static EXPORT_SYMBOL* by script instead of modpost") Reported-by: Tetsuo Handa Reported-by: Michael Ellerman Reported-by: Wang Yugui Tested-by: Tetsuo Handa Tested-by: Jon Hunter Acked-by: Nick Desaulniers Tested-by: Sedat Dilek # LLVM-14 (x86-64) Signed-off-by: Masahiro Yamada --- scripts/check-local-export | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) (limited to 'scripts') diff --git a/scripts/check-local-export b/scripts/check-local-export index da745e2743b7..6ccc2f467416 100755 --- a/scripts/check-local-export +++ b/scripts/check-local-export @@ -8,11 +8,31 @@ set -e +# catch errors from ${NM} +set -o pipefail + +# Run the last element of a pipeline in the current shell. +# Without this, the while-loop would be executed in a subshell, and +# the changes made to 'symbol_types' and 'export_symbols' would be lost. +shopt -s lastpipe + declare -A symbol_types declare -a export_symbols exit_code=0 +# 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 really simple: +# ${NM} --quiet ${1} | + +{ ${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; false; } } | while read value type name do # Skip the line if the number of fields is less than 3. @@ -37,21 +57,7 @@ do if [[ ${name} == __ksymtab_* ]]; then export_symbols+=(${name#__ksymtab_}) fi - - # If there is no symbol in the object, ${NM} (both GNU nm and llvm-nm) - # shows 'no symbols' diagnostic (but exits with 0). It is harmless and - # hidden by '2>/dev/null'. However, it suppresses real error messages - # as well. Add a hand-crafted error message here. - # - # Use --quiet instead of 2>/dev/null when we upgrade the minimum version - # of binutils to 2.37, llvm to 13.0.0. - # - # Then, the following line will be really simple: - # done < <(${NM} --quiet ${1}) -done < <(${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; false; } ) - -# Catch error in the process substitution -wait $! +done for name in "${export_symbols[@]}" do -- cgit From 1f7a6cf6b07c74a17343c2559cd5f5018a245961 Mon Sep 17 00:00:00 2001 From: Kuan-Ying Lee Date: Fri, 10 Jun 2022 15:14:57 +0800 Subject: scripts/gdb: change kernel config dumping method MAGIC_START("IKCFG_ST") and MAGIC_END("IKCFG_ED") are moved out from the kernel_config_data variable. Thus, we parse kernel_config_data directly instead of considering offset of MAGIC_START and MAGIC_END. Fixes: 13610aa908dc ("kernel/configs: use .incbin directive to embed config_data.gz") Signed-off-by: Kuan-Ying Lee Signed-off-by: Masahiro Yamada --- scripts/gdb/linux/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/config.py b/scripts/gdb/linux/config.py index 90e1565b1967..8843ab3cbadd 100644 --- a/scripts/gdb/linux/config.py +++ b/scripts/gdb/linux/config.py @@ -24,9 +24,9 @@ class LxConfigDump(gdb.Command): filename = arg try: - py_config_ptr = gdb.parse_and_eval("kernel_config_data + 8") - py_config_size = gdb.parse_and_eval( - "sizeof(kernel_config_data) - 1 - 8 * 2") + py_config_ptr = gdb.parse_and_eval("&kernel_config_data") + py_config_ptr_end = gdb.parse_and_eval("&kernel_config_data_end") + py_config_size = py_config_ptr_end - py_config_ptr except gdb.error as e: raise gdb.GdbError("Can't find config, enable CONFIG_IKCONFIG?") -- cgit From 28438794aba47a27e922857d27b31b74e8559143 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 11 Jun 2022 03:32:30 +0900 Subject: modpost: fix section mismatch check for exported init/exit sections Since commit f02e8a6596b7 ("module: Sort exported symbols"), EXPORT_SYMBOL* is placed in the individual section ___ksymtab(_gpl)+ (3 leading underscores instead of 2). Since then, modpost cannot detect the bad combination of EXPORT_SYMBOL and __init/__exit. Fix the .fromsec field. Fixes: f02e8a6596b7 ("module: Sort exported symbols") Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/mod/modpost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 29d5a841e215..620dc8c4c814 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -980,7 +980,7 @@ static const struct sectioncheck sectioncheck[] = { }, /* Do not export init/exit functions or data */ { - .fromsec = { "__ksymtab*", NULL }, + .fromsec = { "___ksymtab*", NULL }, .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, .mismatch = EXPORT_TO_INIT_EXIT, .symbol_white_list = { DEFAULT_SYMBOL_WHITE_LIST, NULL }, -- cgit From ff139766764675b9df12bcbc8928a02149b7ba95 Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Thu, 16 Jun 2022 19:57:59 +0000 Subject: kbuild: Ignore __this_module in gen_autoksyms.sh Module object files can contain an undefined reference to __this_module, which isn't resolved until we link the final .ko. The kernel doesn't export this symbol, so ignore it in gen_autoksyms.sh. Signed-off-by: Sami Tolvanen Tested-by: Steve Muckle Reviewed-by: Nick Desaulniers Tested-by: Ramji Jiyani --- scripts/gen_autoksyms.sh | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh index faacf7062122..653fadbad302 100755 --- a/scripts/gen_autoksyms.sh +++ b/scripts/gen_autoksyms.sh @@ -56,4 +56,7 @@ EOT # 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" -- cgit