diff options
Diffstat (limited to 'scripts')
83 files changed, 1217 insertions, 1066 deletions
diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 9f94fc83f086..6413342a03f4 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -82,7 +82,7 @@ ifdef need-builtin targets-for-builtin += $(obj)/built-in.a endif -targets-for-modules := $(foreach x, o mod $(if $(CONFIG_TRIM_UNUSED_KSYMS), usyms), \ +targets-for-modules := $(foreach x, o mod, \ $(patsubst %.o, %.$x, $(filter %.o, $(obj-m)))) ifdef need-modorder @@ -101,7 +101,9 @@ else ifeq ($(KBUILD_CHECKSRC),2) endif ifneq ($(KBUILD_EXTRA_WARN),) - cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $< + cmd_checkdoc = $(srctree)/scripts/kernel-doc -none $(KDOCFLAGS) \ + $(if $(findstring 2, $(KBUILD_EXTRA_WARN)), -Wall) \ + $< endif # Compile C sources (.c) @@ -161,7 +163,7 @@ quiet_cmd_cc_o_c = CC $(quiet_modtag) $@ ifdef CONFIG_MODVERSIONS # When module versioning is enabled the following steps are executed: # o compile a <file>.o from <file>.c -# o if <file>.o doesn't contain a __ksymtab version, i.e. does +# o if <file>.o doesn't contain a __export_symbol_*, i.e. does # not export symbols, it's done. # o otherwise, we calculate symbol versions using the good old # genksyms on the preprocessed source and dump them into the .cmd file. @@ -169,7 +171,7 @@ ifdef CONFIG_MODVERSIONS # be compiled and linked to the kernel and/or modules. gen_symversions = \ - if $(NM) $@ 2>/dev/null | grep -q __ksymtab; then \ + if $(NM) $@ 2>/dev/null | grep -q ' __export_symbol_'; then \ $(call cmd_gensymtypes_$(1),$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \ >> $(dot-target).cmd; \ fi @@ -215,21 +217,12 @@ is-standard-object = $(if $(filter-out y%, $(OBJECT_FILES_NON_STANDARD_$(basetar $(obj)/%.o: objtool-enabled = $(if $(is-standard-object),$(if $(delay-objtool),$(is-single-obj-m),y)) -ifdef CONFIG_TRIM_UNUSED_KSYMS -cmd_gen_ksymdeps = \ - $(CONFIG_SHELL) $(srctree)/scripts/gen_ksymdeps.sh $@ >> $(dot-target).cmd -endif - -cmd_check_local_export = $(srctree)/scripts/check-local-export $@ - ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),) cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi))) endif define rule_cc_o_c $(call cmd_and_fixdep,cc_o_c) - $(call cmd,gen_ksymdeps) - $(call cmd,check_local_export) $(call cmd,checksrc) $(call cmd,checkdoc) $(call cmd,gen_objtooldep) @@ -240,8 +233,6 @@ endef define rule_as_o_S $(call cmd_and_fixdep,as_o_S) - $(call cmd,gen_ksymdeps) - $(call cmd,check_local_export) $(call cmd,gen_objtooldep) $(call cmd,gen_symversions_S) $(call cmd,warn_shared_object) @@ -260,12 +251,6 @@ cmd_mod = printf '%s\n' $(call real-search, $*.o, .o, -objs -y -m) | \ $(obj)/%.mod: FORCE $(call if_changed,mod) -# List module undefined symbols -cmd_undefined_syms = $(NM) $< | sed -n 's/^ *U //p' > $@ - -$(obj)/%.usyms: $(obj)/%.o FORCE - $(call if_changed,undefined_syms) - quiet_cmd_cc_lst_c = MKLST $@ cmd_cc_lst_c = $(CC) $(c_flags) -g -c -o $*.o $< && \ $(CONFIG_SHELL) $(srctree)/scripts/makelst $*.o \ @@ -277,7 +262,7 @@ $(obj)/%.lst: $(src)/%.c FORCE # Compile Rust sources (.rs) # --------------------------------------------------------------------------- -rust_allowed_features := core_ffi_c,explicit_generic_args_with_impl_trait,new_uninit,pin_macro +rust_allowed_features := new_uninit rust_common_cmd = \ RUST_MODFILE=$(modfile) $(RUSTC_OR_CLIPPY) $(rust_flags) \ @@ -340,9 +325,7 @@ $(obj)/%.ll: $(src)/%.rs FORCE cmd_gensymtypes_S = \ { echo "\#include <linux/kernel.h>" ; \ echo "\#include <asm/asm-prototypes.h>" ; \ - $(CPP) $(a_flags) $< | \ - grep "\<___EXPORT_SYMBOL\>" | \ - sed 's/.*___EXPORT_SYMBOL[[:space:]]*\([a-zA-Z0-9_]*\)[[:space:]]*,.*/EXPORT_SYMBOL(\1);/' ; } | \ + $(NM) $@ | sed -n 's/.* __export_symbol_\(.*\)/EXPORT_SYMBOL(\1);/p' ; } | \ $(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms) quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@ diff --git a/scripts/Makefile.clang b/scripts/Makefile.clang index 9076cc939e87..6c23c6af797f 100644 --- a/scripts/Makefile.clang +++ b/scripts/Makefile.clang @@ -4,6 +4,7 @@ CLANG_TARGET_FLAGS_arm := arm-linux-gnueabi CLANG_TARGET_FLAGS_arm64 := aarch64-linux-gnu CLANG_TARGET_FLAGS_hexagon := hexagon-linux-musl +CLANG_TARGET_FLAGS_loongarch := loongarch64-linux-gnusf CLANG_TARGET_FLAGS_m68k := m68k-linux-gnu CLANG_TARGET_FLAGS_mips := mipsel-linux-gnu CLANG_TARGET_FLAGS_powerpc := powerpc64le-linux-gnu @@ -34,6 +35,5 @@ CLANG_FLAGS += -Werror=unknown-warning-option CLANG_FLAGS += -Werror=ignored-optimization-argument CLANG_FLAGS += -Werror=option-ignored CLANG_FLAGS += -Werror=unused-command-line-argument -KBUILD_CFLAGS += $(CLANG_FLAGS) -KBUILD_AFLAGS += $(CLANG_FLAGS) +KBUILD_CPPFLAGS += $(CLANG_FLAGS) export CLANG_FLAGS diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean index 3649900696dd..f2cb4d7ffd96 100644 --- a/scripts/Makefile.clean +++ b/scripts/Makefile.clean @@ -37,8 +37,10 @@ __clean-files := $(wildcard $(addprefix $(obj)/, $(__clean-files))) # ========================================================================== +# To make this rule robust against "Argument list too long" error, +# remove $(obj)/ prefix, and restore it by a shell command. quiet_cmd_clean = CLEAN $(obj) - cmd_clean = rm -rf $(__clean-files) + cmd_clean = printf '$(obj)/%s ' $(patsubst $(obj)/%,%,$(__clean-files)) | xargs rm -rf __clean: $(subdir-ymn) ifneq ($(strip $(__clean-files)),) diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler index 7aa1fbc4aafe..8fcb427405a6 100644 --- a/scripts/Makefile.compiler +++ b/scripts/Makefile.compiler @@ -32,13 +32,13 @@ try-run = $(shell set -e; \ # Usage: aflags-y += $(call as-option,-Wa$(comma)-isa=foo,) as-option = $(call try-run,\ - $(CC) -Werror $(KBUILD_AFLAGS) $(1) -c -x assembler-with-cpp /dev/null -o "$$TMP",$(1),$(2)) + $(CC) -Werror $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(1) -c -x assembler-with-cpp /dev/null -o "$$TMP",$(1),$(2)) # as-instr # Usage: aflags-y += $(call as-instr,instr,option1,option2) as-instr = $(call try-run,\ - printf "%b\n" "$(1)" | $(CC) -Werror $(KBUILD_AFLAGS) -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3)) + printf "%b\n" "$(1)" | $(CC) -Werror $(CLANG_FLAGS) $(KBUILD_AFLAGS) -c -x assembler-with-cpp -o "$$TMP" -,$(2),$(3)) # __cc-option # Usage: MY_CFLAGS += $(call __cc-option,$(CC),$(MY_CFLAGS),-march=winchip-c6,-march=i586) @@ -72,7 +72,3 @@ clang-min-version = $(call test-ge, $(CONFIG_CLANG_VERSION), $1) # ld-option # Usage: KBUILD_LDFLAGS += $(call ld-option, -X, -Y) ld-option = $(call try-run, $(LD) $(KBUILD_LDFLAGS) $(1) -v,$(1),$(2),$(3)) - -# ld-ifversion -# Usage: $(call ld-ifversion, -ge, 22252, y) -ld-ifversion = $(shell [ $(CONFIG_LD_VERSION)0 $(1) $(2)0 ] && echo $(3) || echo $(4)) diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst index 2ab936e4179d..4405d5b67578 100644 --- a/scripts/Makefile.dtbinst +++ b/scripts/Makefile.dtbinst @@ -34,6 +34,6 @@ $(dst)/%.dtbo: $(obj)/%.dtbo PHONY += $(subdirs) $(subdirs): - $(Q)$(MAKE) $(dtbinst)=$@ dst=$(patsubst $(obj)/%,$(dst)/%,$@) + $(Q)$(MAKE) $(dtbinst)=$@ dst=$(if $(CONFIG_ARCH_WANT_FLAT_DTB_INSTALL),$(dst),$(patsubst $(obj)/%,$(dst)/%,$@)) .PHONY: $(PHONY) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 100a386fcd71..68d0134bdbf9 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -418,9 +418,6 @@ endif $(obj)/%.dtb: $(src)/%.dts $(DTC) $(DT_TMP_SCHEMA) FORCE $(call if_changed_dep,dtb) -$(obj)/%.dtbo: $(src)/%.dts $(DTC) FORCE - $(call if_changed_dep,dtc) - $(obj)/%.dtbo: $(src)/%.dtso $(DTC) FORCE $(call if_changed_dep,dtc) diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 4703f652c009..fc19f67039bd 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -23,7 +23,7 @@ modname = $(notdir $(@:.mod.o=)) part-of-module = y quiet_cmd_cc_o_c = CC [M] $@ - cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI), $(c_flags)) -c -o $@ $< + cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI) $(CFLAGS_GCOV), $(c_flags)) -c -o $@ $< %.mod.o: %.mod.c FORCE $(call if_changed_dep,cc_o_c) diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 0980c58d8afc..39472e834b63 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -47,6 +47,7 @@ modpost-args = \ $(if $(KBUILD_MODPOST_WARN),-w) \ $(if $(KBUILD_NSDEPS),-d $(MODULES_NSDEPS)) \ $(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \ + $(if $(findstring 1, $(KBUILD_EXTRA_WARN)),-W) \ -o $@ modpost-deps := $(MODPOST) @@ -90,6 +91,13 @@ targets += .vmlinux.objs .vmlinux.objs: vmlinux.a $(KBUILD_VMLINUX_LIBS) FORCE $(call if_changed,vmlinux_objs) +ifdef CONFIG_TRIM_UNUSED_KSYMS +ksym-wl := $(CONFIG_UNUSED_KSYMS_WHITELIST) +ksym-wl := $(if $(filter-out /%, $(ksym-wl)),$(srctree)/)$(ksym-wl) +modpost-args += -t $(addprefix -u , $(ksym-wl)) +modpost-deps += $(ksym-wl) +endif + ifeq ($(wildcard vmlinux.o),) missing-input := vmlinux.o output-symdump := modules-only.symvers diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index 7099c603ff0a..4749865c1b2c 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -2,7 +2,7 @@ # Enable available and selected UBSAN features. ubsan-cflags-$(CONFIG_UBSAN_ALIGNMENT) += -fsanitize=alignment -ubsan-cflags-$(CONFIG_UBSAN_ONLY_BOUNDS) += -fsanitize=bounds +ubsan-cflags-$(CONFIG_UBSAN_BOUNDS_STRICT) += -fsanitize=bounds-strict ubsan-cflags-$(CONFIG_UBSAN_ARRAY_BOUNDS) += -fsanitize=array-bounds ubsan-cflags-$(CONFIG_UBSAN_LOCAL_BOUNDS) += -fsanitize=local-bounds ubsan-cflags-$(CONFIG_UBSAN_SHIFT) += -fsanitize=shift diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux index 10176dec97ea..3cd6ca15f390 100644 --- a/scripts/Makefile.vmlinux +++ b/scripts/Makefile.vmlinux @@ -19,6 +19,7 @@ quiet_cmd_cc_o_c = CC $@ ifdef CONFIG_MODULES KASAN_SANITIZE_.vmlinux.export.o := n +GCOV_PROFILE_.vmlinux.export.o := n targets += .vmlinux.export.o vmlinux: .vmlinux.export.o endif diff --git a/scripts/adjust_autoksyms.sh b/scripts/adjust_autoksyms.sh deleted file mode 100755 index f1b5ac818411..000000000000 --- a/scripts/adjust_autoksyms.sh +++ /dev/null @@ -1,73 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0-only - -# Script to update include/generated/autoksyms.h and dependency files -# -# Copyright: (C) 2016 Linaro Limited -# Created by: Nicolas Pitre, January 2016 -# - -# Update the include/generated/autoksyms.h file. -# -# For each symbol being added or removed, the corresponding dependency -# file's timestamp is updated to force a rebuild of the affected source -# file. All arguments passed to this script are assumed to be a command -# to be exec'd to trigger a rebuild of those files. - -set -e - -cur_ksyms_file="include/generated/autoksyms.h" -new_ksyms_file="include/generated/autoksyms.h.tmpnew" - -info() { - if [ "$quiet" != "silent_" ]; then - printf " %-7s %s\n" "$1" "$2" - fi -} - -info "CHK" "$cur_ksyms_file" - -# Use "make V=1" to debug this script. -case "$KBUILD_VERBOSE" in -*1*) - set -x - ;; -esac - -# Generate a new symbol list file -$CONFIG_SHELL $srctree/scripts/gen_autoksyms.sh --modorder "$new_ksyms_file" - -# Extract changes between old and new list and touch corresponding -# dependency files. -changed=$( -count=0 -sort "$cur_ksyms_file" "$new_ksyms_file" | uniq -u | -sed -n 's/^#define __KSYM_\(.*\) 1/\1/p' | -while read sympath; do - if [ -z "$sympath" ]; then continue; fi - depfile="include/ksym/${sympath}" - mkdir -p "$(dirname "$depfile")" - touch "$depfile" - # Filesystems with coarse time precision may create timestamps - # equal to the one from a file that was very recently built and that - # needs to be rebuild. Let's guard against that by making sure our - # dep files are always newer than the first file we created here. - while [ ! "$depfile" -nt "$new_ksyms_file" ]; do - touch "$depfile" - done - echo $((count += 1)) -done | tail -1 ) -changed=${changed:-0} - -if [ $changed -gt 0 ]; then - # Replace the old list with tne new one - old=$(grep -c "^#define __KSYM_" "$cur_ksyms_file" || true) - new=$(grep -c "^#define __KSYM_" "$new_ksyms_file" || true) - info "KSYMS" "symbols: before=$old, after=$new, changed=$changed" - info "UPD" "$cur_ksyms_file" - mv -f "$new_ksyms_file" "$cur_ksyms_file" - # Then trigger a rebuild of affected source files - exec $@ -else - rm -f "$new_ksyms_file" -fi diff --git a/scripts/atomic/atomic-tbl.sh b/scripts/atomic/atomic-tbl.sh index 81d5c32039dd..608ff39ebd8c 100755 --- a/scripts/atomic/atomic-tbl.sh +++ b/scripts/atomic/atomic-tbl.sh @@ -36,9 +36,16 @@ meta_has_relaxed() meta_in "$1" "BFIR" } -#find_fallback_template(pfx, name, sfx, order) -find_fallback_template() +#meta_is_implicitly_relaxed(meta) +meta_is_implicitly_relaxed() { + meta_in "$1" "vls" +} + +#find_template(tmpltype, pfx, name, sfx, order) +find_template() +{ + local tmpltype="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift @@ -52,8 +59,8 @@ find_fallback_template() # # Start at the most specific, and fall back to the most general. Once # we find a specific fallback, don't bother looking for more. - for base in "${pfx}${name}${sfx}${order}" "${name}"; do - file="${ATOMICDIR}/fallbacks/${base}" + for base in "${pfx}${name}${sfx}${order}" "${pfx}${name}${sfx}" "${name}"; do + file="${ATOMICDIR}/${tmpltype}/${base}" if [ -f "${file}" ]; then printf "${file}" @@ -62,6 +69,18 @@ find_fallback_template() done } +#find_fallback_template(pfx, name, sfx, order) +find_fallback_template() +{ + find_template "fallbacks" "$@" +} + +#find_kerneldoc_template(pfx, name, sfx, order) +find_kerneldoc_template() +{ + find_template "kerneldoc" "$@" +} + #gen_ret_type(meta, int) gen_ret_type() { local meta="$1"; shift @@ -142,6 +161,91 @@ gen_args() done } +#gen_desc_return(meta) +gen_desc_return() +{ + local meta="$1"; shift + + case "${meta}" in + [v]) + printf "Return: Nothing." + ;; + [Ff]) + printf "Return: The original value of @v." + ;; + [R]) + printf "Return: The updated value of @v." + ;; + [l]) + printf "Return: The value of @v." + ;; + esac +} + +#gen_template_kerneldoc(template, class, meta, pfx, name, sfx, order, atomic, int, args...) +gen_template_kerneldoc() +{ + local template="$1"; shift + local class="$1"; shift + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + local atomic="$1"; shift + local int="$1"; shift + + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + + local ret="$(gen_ret_type "${meta}" "${int}")" + local retstmt="$(gen_ret_stmt "${meta}")" + local params="$(gen_params "${int}" "${atomic}" "$@")" + local args="$(gen_args "$@")" + local desc_order="" + local desc_instrumentation="" + local desc_return="" + + if [ ! -z "${order}" ]; then + desc_order="${order##_}" + elif meta_is_implicitly_relaxed "${meta}"; then + desc_order="relaxed" + else + desc_order="full" + fi + + if [ -z "${class}" ]; then + desc_noinstr="Unsafe to use in noinstr code; use raw_${atomicname}() there." + else + desc_noinstr="Safe to use in noinstr code; prefer ${atomicname}() elsewhere." + fi + + desc_return="$(gen_desc_return "${meta}")" + + . ${template} +} + +#gen_kerneldoc(class, meta, pfx, name, sfx, order, atomic, int, args...) +gen_kerneldoc() +{ + local class="$1"; shift + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + + local tmpl="$(find_kerneldoc_template "${pfx}" "${name}" "${sfx}" "${order}")" + if [ -z "${tmpl}" ]; then + printf "/*\n" + printf " * No kerneldoc available for ${class}${atomicname}\n" + printf " */\n" + else + gen_template_kerneldoc "${tmpl}" "${class}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" + fi +} + #gen_proto_order_variants(meta, pfx, name, sfx, ...) gen_proto_order_variants() { diff --git a/scripts/atomic/atomics.tbl b/scripts/atomic/atomics.tbl index 85ca8d9b5c27..903946cbf1b3 100644 --- a/scripts/atomic/atomics.tbl +++ b/scripts/atomic/atomics.tbl @@ -27,7 +27,7 @@ and vF i v andnot vF i v or vF i v xor vF i v -xchg I v i +xchg I v i:new cmpxchg I v i:old i:new try_cmpxchg B v p:old i:new sub_and_test b i v diff --git a/scripts/atomic/fallbacks/acquire b/scripts/atomic/fallbacks/acquire index ef764085c79a..4da0cab3604e 100755 --- a/scripts/atomic/fallbacks/acquire +++ b/scripts/atomic/fallbacks/acquire @@ -1,9 +1,5 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_${pfx}${name}${sfx}_acquire(${params}) -{ ${ret} ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_acquire_fence(); return ret; -} EOF diff --git a/scripts/atomic/fallbacks/add_negative b/scripts/atomic/fallbacks/add_negative index e5980abf5904..1d3d4ab3a9d2 100755 --- a/scripts/atomic/fallbacks/add_negative +++ b/scripts/atomic/fallbacks/add_negative @@ -1,15 +1,3 @@ cat <<EOF -/** - * arch_${atomic}_add_negative${order} - Add and test if negative - * @i: integer value to add - * @v: pointer of type ${atomic}_t - * - * Atomically adds @i to @v and returns true if the result is negative, - * or false when the result is greater than or equal to zero. - */ -static __always_inline bool -arch_${atomic}_add_negative${order}(${int} i, ${atomic}_t *v) -{ - return arch_${atomic}_add_return${order}(i, v) < 0; -} + return raw_${atomic}_add_return${order}(i, v) < 0; EOF diff --git a/scripts/atomic/fallbacks/add_unless b/scripts/atomic/fallbacks/add_unless index 9e5159c2ccfc..95ecb2b7405b 100755 --- a/scripts/atomic/fallbacks/add_unless +++ b/scripts/atomic/fallbacks/add_unless @@ -1,16 +1,3 @@ cat << EOF -/** - * arch_${atomic}_add_unless - add unless the number is already a given value - * @v: pointer of type ${atomic}_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, if @v was not already @u. - * Returns true if the addition was done. - */ -static __always_inline bool -arch_${atomic}_add_unless(${atomic}_t *v, ${int} a, ${int} u) -{ - return arch_${atomic}_fetch_add_unless(v, a, u) != u; -} + return raw_${atomic}_fetch_add_unless(v, a, u) != u; EOF diff --git a/scripts/atomic/fallbacks/andnot b/scripts/atomic/fallbacks/andnot index 5a42f54a3595..66760457e67a 100755 --- a/scripts/atomic/fallbacks/andnot +++ b/scripts/atomic/fallbacks/andnot @@ -1,7 +1,3 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_${pfx}andnot${sfx}${order}(${int} i, ${atomic}_t *v) -{ - ${retstmt}arch_${atomic}_${pfx}and${sfx}${order}(~i, v); -} + ${retstmt}raw_${atomic}_${pfx}and${sfx}${order}(~i, v); EOF diff --git a/scripts/atomic/fallbacks/cmpxchg b/scripts/atomic/fallbacks/cmpxchg new file mode 100644 index 000000000000..1c8507f62e04 --- /dev/null +++ b/scripts/atomic/fallbacks/cmpxchg @@ -0,0 +1,3 @@ +cat <<EOF + return raw_cmpxchg${order}(&v->counter, old, new); +EOF diff --git a/scripts/atomic/fallbacks/dec b/scripts/atomic/fallbacks/dec index 8c144c818e9e..60d286d40300 100755 --- a/scripts/atomic/fallbacks/dec +++ b/scripts/atomic/fallbacks/dec @@ -1,7 +1,3 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_${pfx}dec${sfx}${order}(${atomic}_t *v) -{ - ${retstmt}arch_${atomic}_${pfx}sub${sfx}${order}(1, v); -} + ${retstmt}raw_${atomic}_${pfx}sub${sfx}${order}(1, v); EOF diff --git a/scripts/atomic/fallbacks/dec_and_test b/scripts/atomic/fallbacks/dec_and_test index 8549f359bd0e..3a0278e0ddd7 100755 --- a/scripts/atomic/fallbacks/dec_and_test +++ b/scripts/atomic/fallbacks/dec_and_test @@ -1,15 +1,3 @@ cat <<EOF -/** - * arch_${atomic}_dec_and_test - decrement and test - * @v: pointer of type ${atomic}_t - * - * Atomically decrements @v by 1 and - * returns true if the result is 0, or false for all other - * cases. - */ -static __always_inline bool -arch_${atomic}_dec_and_test(${atomic}_t *v) -{ - return arch_${atomic}_dec_return(v) == 0; -} + return raw_${atomic}_dec_return(v) == 0; EOF diff --git a/scripts/atomic/fallbacks/dec_if_positive b/scripts/atomic/fallbacks/dec_if_positive index 86bdced3428d..f65c11b4b85b 100755 --- a/scripts/atomic/fallbacks/dec_if_positive +++ b/scripts/atomic/fallbacks/dec_if_positive @@ -1,15 +1,11 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_dec_if_positive(${atomic}_t *v) -{ - ${int} dec, c = arch_${atomic}_read(v); + ${int} dec, c = raw_${atomic}_read(v); do { dec = c - 1; if (unlikely(dec < 0)) break; - } while (!arch_${atomic}_try_cmpxchg(v, &c, dec)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, dec)); return dec; -} EOF diff --git a/scripts/atomic/fallbacks/dec_unless_positive b/scripts/atomic/fallbacks/dec_unless_positive index c531d5afecc4..d025361d7b85 100755 --- a/scripts/atomic/fallbacks/dec_unless_positive +++ b/scripts/atomic/fallbacks/dec_unless_positive @@ -1,14 +1,10 @@ cat <<EOF -static __always_inline bool -arch_${atomic}_dec_unless_positive(${atomic}_t *v) -{ - ${int} c = arch_${atomic}_read(v); + ${int} c = raw_${atomic}_read(v); do { if (unlikely(c > 0)) return false; - } while (!arch_${atomic}_try_cmpxchg(v, &c, c - 1)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, c - 1)); return true; -} EOF diff --git a/scripts/atomic/fallbacks/fence b/scripts/atomic/fallbacks/fence index 07757d8e338e..40d5b397658f 100755 --- a/scripts/atomic/fallbacks/fence +++ b/scripts/atomic/fallbacks/fence @@ -1,11 +1,7 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_${pfx}${name}${sfx}(${params}) -{ ${ret} ret; __atomic_pre_full_fence(); ret = arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); __atomic_post_full_fence(); return ret; -} EOF diff --git a/scripts/atomic/fallbacks/fetch_add_unless b/scripts/atomic/fallbacks/fetch_add_unless index 68ce13c8b9da..8db7e9e17fac 100755 --- a/scripts/atomic/fallbacks/fetch_add_unless +++ b/scripts/atomic/fallbacks/fetch_add_unless @@ -1,23 +1,10 @@ cat << EOF -/** - * arch_${atomic}_fetch_add_unless - add unless the number is already a given value - * @v: pointer of type ${atomic}_t - * @a: the amount to add to v... - * @u: ...unless v is equal to u. - * - * Atomically adds @a to @v, so long as @v was not already @u. - * Returns original value of @v - */ -static __always_inline ${int} -arch_${atomic}_fetch_add_unless(${atomic}_t *v, ${int} a, ${int} u) -{ - ${int} c = arch_${atomic}_read(v); + ${int} c = raw_${atomic}_read(v); do { if (unlikely(c == u)) break; - } while (!arch_${atomic}_try_cmpxchg(v, &c, c + a)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, c + a)); return c; -} EOF diff --git a/scripts/atomic/fallbacks/inc b/scripts/atomic/fallbacks/inc index 3c2c3739169e..56c770f5919c 100755 --- a/scripts/atomic/fallbacks/inc +++ b/scripts/atomic/fallbacks/inc @@ -1,7 +1,3 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_${pfx}inc${sfx}${order}(${atomic}_t *v) -{ - ${retstmt}arch_${atomic}_${pfx}add${sfx}${order}(1, v); -} + ${retstmt}raw_${atomic}_${pfx}add${sfx}${order}(1, v); EOF diff --git a/scripts/atomic/fallbacks/inc_and_test b/scripts/atomic/fallbacks/inc_and_test index 0cf23fe1efb8..7d16a10f2257 100755 --- a/scripts/atomic/fallbacks/inc_and_test +++ b/scripts/atomic/fallbacks/inc_and_test @@ -1,15 +1,3 @@ cat <<EOF -/** - * arch_${atomic}_inc_and_test - increment and test - * @v: pointer of type ${atomic}_t - * - * Atomically increments @v by 1 - * and returns true if the result is zero, or false for all - * other cases. - */ -static __always_inline bool -arch_${atomic}_inc_and_test(${atomic}_t *v) -{ - return arch_${atomic}_inc_return(v) == 0; -} + return raw_${atomic}_inc_return(v) == 0; EOF diff --git a/scripts/atomic/fallbacks/inc_not_zero b/scripts/atomic/fallbacks/inc_not_zero index ed8a1f562667..1fcef1e55bc9 100755 --- a/scripts/atomic/fallbacks/inc_not_zero +++ b/scripts/atomic/fallbacks/inc_not_zero @@ -1,14 +1,3 @@ cat <<EOF -/** - * arch_${atomic}_inc_not_zero - increment unless the number is zero - * @v: pointer of type ${atomic}_t - * - * Atomically increments @v by 1, if @v is non-zero. - * Returns true if the increment was done. - */ -static __always_inline bool -arch_${atomic}_inc_not_zero(${atomic}_t *v) -{ - return arch_${atomic}_add_unless(v, 1, 0); -} + return raw_${atomic}_add_unless(v, 1, 0); EOF diff --git a/scripts/atomic/fallbacks/inc_unless_negative b/scripts/atomic/fallbacks/inc_unless_negative index 95d8ce48233f..7b4b09868842 100755 --- a/scripts/atomic/fallbacks/inc_unless_negative +++ b/scripts/atomic/fallbacks/inc_unless_negative @@ -1,14 +1,10 @@ cat <<EOF -static __always_inline bool -arch_${atomic}_inc_unless_negative(${atomic}_t *v) -{ - ${int} c = arch_${atomic}_read(v); + ${int} c = raw_${atomic}_read(v); do { if (unlikely(c < 0)) return false; - } while (!arch_${atomic}_try_cmpxchg(v, &c, c + 1)); + } while (!raw_${atomic}_try_cmpxchg(v, &c, c + 1)); return true; -} EOF diff --git a/scripts/atomic/fallbacks/read_acquire b/scripts/atomic/fallbacks/read_acquire index a0ea1d26e6b2..e319862d2f1a 100755 --- a/scripts/atomic/fallbacks/read_acquire +++ b/scripts/atomic/fallbacks/read_acquire @@ -1,16 +1,12 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_read_acquire(const ${atomic}_t *v) -{ ${int} ret; if (__native_word(${atomic}_t)) { ret = smp_load_acquire(&(v)->counter); } else { - ret = arch_${atomic}_read(v); + ret = raw_${atomic}_read(v); __atomic_acquire_fence(); } return ret; -} EOF diff --git a/scripts/atomic/fallbacks/release b/scripts/atomic/fallbacks/release index b46feb56d69c..1e6daf57b4ba 100755 --- a/scripts/atomic/fallbacks/release +++ b/scripts/atomic/fallbacks/release @@ -1,8 +1,4 @@ cat <<EOF -static __always_inline ${ret} -arch_${atomic}_${pfx}${name}${sfx}_release(${params}) -{ __atomic_release_fence(); ${retstmt}arch_${atomic}_${pfx}${name}${sfx}_relaxed(${args}); -} EOF diff --git a/scripts/atomic/fallbacks/set_release b/scripts/atomic/fallbacks/set_release index 05cdb7f42477..16a374ae6bb1 100755 --- a/scripts/atomic/fallbacks/set_release +++ b/scripts/atomic/fallbacks/set_release @@ -1,12 +1,8 @@ cat <<EOF -static __always_inline void -arch_${atomic}_set_release(${atomic}_t *v, ${int} i) -{ if (__native_word(${atomic}_t)) { smp_store_release(&(v)->counter, i); } else { __atomic_release_fence(); - arch_${atomic}_set(v, i); + raw_${atomic}_set(v, i); } -} EOF diff --git a/scripts/atomic/fallbacks/sub_and_test b/scripts/atomic/fallbacks/sub_and_test index 260f37341c88..d1f746fe0ca4 100755 --- a/scripts/atomic/fallbacks/sub_and_test +++ b/scripts/atomic/fallbacks/sub_and_test @@ -1,16 +1,3 @@ cat <<EOF -/** - * arch_${atomic}_sub_and_test - subtract value from variable and test result - * @i: integer value to subtract - * @v: pointer of type ${atomic}_t - * - * Atomically subtracts @i from @v and returns - * true if the result is zero, or false for all - * other cases. - */ -static __always_inline bool -arch_${atomic}_sub_and_test(${int} i, ${atomic}_t *v) -{ - return arch_${atomic}_sub_return(i, v) == 0; -} + return raw_${atomic}_sub_return(i, v) == 0; EOF diff --git a/scripts/atomic/fallbacks/try_cmpxchg b/scripts/atomic/fallbacks/try_cmpxchg index 890f850ede37..d4da82092baf 100755 --- a/scripts/atomic/fallbacks/try_cmpxchg +++ b/scripts/atomic/fallbacks/try_cmpxchg @@ -1,11 +1,7 @@ cat <<EOF -static __always_inline bool -arch_${atomic}_try_cmpxchg${order}(${atomic}_t *v, ${int} *old, ${int} new) -{ ${int} r, o = *old; - r = arch_${atomic}_cmpxchg${order}(v, o, new); + r = raw_${atomic}_cmpxchg${order}(v, o, new); if (unlikely(r != o)) *old = r; return likely(r == o); -} EOF diff --git a/scripts/atomic/fallbacks/xchg b/scripts/atomic/fallbacks/xchg new file mode 100644 index 000000000000..e4def1e0d092 --- /dev/null +++ b/scripts/atomic/fallbacks/xchg @@ -0,0 +1,3 @@ +cat <<EOF + return raw_xchg${order}(&v->counter, new); +EOF diff --git a/scripts/atomic/gen-atomic-fallback.sh b/scripts/atomic/gen-atomic-fallback.sh index 6e853f0dad8d..c0c8a85d7c81 100755 --- a/scripts/atomic/gen-atomic-fallback.sh +++ b/scripts/atomic/gen-atomic-fallback.sh @@ -17,23 +17,16 @@ gen_template_fallback() local atomic="$1"; shift local int="$1"; shift - local atomicname="arch_${atomic}_${pfx}${name}${sfx}${order}" - local ret="$(gen_ret_type "${meta}" "${int}")" local retstmt="$(gen_ret_stmt "${meta}")" local params="$(gen_params "${int}" "${atomic}" "$@")" local args="$(gen_args "$@")" - if [ ! -z "${template}" ]; then - printf "#ifndef ${atomicname}\n" - . ${template} - printf "#define ${atomicname} ${atomicname}\n" - printf "#endif\n\n" - fi + . ${template} } -#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) -gen_proto_fallback() +#gen_order_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +gen_order_fallback() { local meta="$1"; shift local pfx="$1"; shift @@ -41,87 +34,124 @@ gen_proto_fallback() local sfx="$1"; shift local order="$1"; shift - local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" + local tmpl_order=${order#_} + local tmpl="${ATOMICDIR}/fallbacks/${tmpl_order:-fence}" gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" } -#gen_basic_fallbacks(basename) -gen_basic_fallbacks() -{ - local basename="$1"; shift -cat << EOF -#define ${basename}_acquire ${basename} -#define ${basename}_release ${basename} -#define ${basename}_relaxed ${basename} -EOF -} - -gen_proto_order_variant() +#gen_proto_fallback(meta, pfx, name, sfx, order, atomic, int, args...) +gen_proto_fallback() { local meta="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift local order="$1"; shift - local atomic="$1" - local basename="arch_${atomic}_${pfx}${name}${sfx}" - - printf "#define ${basename}${order} ${basename}${order}\n" + local tmpl="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" + gen_template_fallback "${tmpl}" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "$@" } -#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) -gen_proto_order_variants() +#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, args...) +gen_proto_order_variant() { local meta="$1"; shift local pfx="$1"; shift local name="$1"; shift local sfx="$1"; shift - local atomic="$1" + local order="$1"; shift + local atomic="$1"; shift + local int="$1"; shift - local basename="arch_${atomic}_${pfx}${name}${sfx}" + local atomicname="${atomic}_${pfx}${name}${sfx}${order}" + local basename="${atomic}_${pfx}${name}${sfx}" local template="$(find_fallback_template "${pfx}" "${name}" "${sfx}" "${order}")" - # If we don't have relaxed atomics, then we don't bother with ordering fallbacks - # read_acquire and set_release need to be templated, though - if ! meta_has_relaxed "${meta}"; then - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" + local ret="$(gen_ret_type "${meta}" "${int}")" + local retstmt="$(gen_ret_stmt "${meta}")" + local params="$(gen_params "${int}" "${atomic}" "$@")" + local args="$(gen_args "$@")" - if meta_has_acquire "${meta}"; then - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" - fi + gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + + printf "static __always_inline ${ret}\n" + printf "raw_${atomicname}(${params})\n" + printf "{\n" + + # Where there is no possible fallback, this order variant is mandatory + # and must be provided by arch code. Add a comment to the header to + # make this obvious. + # + # Ideally we'd error on a missing definition, but arch code might + # define this order variant as a C function without a preprocessor + # symbol. + if [ -z ${template} ] && [ -z "${order}" ] && ! meta_has_relaxed "${meta}"; then + printf "\t${retstmt}arch_${atomicname}(${args});\n" + printf "}\n\n" + return + fi - if meta_has_release "${meta}"; then - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" - fi + printf "#if defined(arch_${atomicname})\n" + printf "\t${retstmt}arch_${atomicname}(${args});\n" - return + # Allow FULL/ACQUIRE/RELEASE ops to be defined in terms of RELAXED ops + if [ "${order}" != "_relaxed" ] && meta_has_relaxed "${meta}"; then + printf "#elif defined(arch_${basename}_relaxed)\n" + gen_order_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" fi - printf "#ifndef ${basename}_relaxed\n" + # Allow ACQUIRE/RELEASE/RELAXED ops to be defined in terms of FULL ops + if [ ! -z "${order}" ]; then + printf "#elif defined(arch_${basename})\n" + printf "\t${retstmt}arch_${basename}(${args});\n" + fi + printf "#else\n" if [ ! -z "${template}" ]; then - printf "#ifdef ${basename}\n" + gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + else + printf "#error \"Unable to define raw_${atomicname}\"\n" fi - gen_basic_fallbacks "${basename}" + printf "#endif\n" + printf "}\n\n" +} - if [ ! -z "${template}" ]; then - printf "#endif /* ${basename} */\n\n" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" - gen_proto_fallback "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" + +#gen_proto_order_variants(meta, pfx, name, sfx, atomic, int, args...) +gen_proto_order_variants() +{ + local meta="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local atomic="$1" + + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" + + if meta_has_acquire "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" fi - printf "#else /* ${basename}_relaxed */\n\n" + if meta_has_release "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" + fi - gen_template_fallback "${ATOMICDIR}/fallbacks/acquire" "${meta}" "${pfx}" "${name}" "${sfx}" "_acquire" "$@" - gen_template_fallback "${ATOMICDIR}/fallbacks/release" "${meta}" "${pfx}" "${name}" "${sfx}" "_release" "$@" - gen_template_fallback "${ATOMICDIR}/fallbacks/fence" "${meta}" "${pfx}" "${name}" "${sfx}" "" "$@" + if meta_has_relaxed "${meta}"; then + gen_proto_order_variant "${meta}" "${pfx}" "${name}" "${sfx}" "_relaxed" "$@" + fi +} - printf "#endif /* ${basename}_relaxed */\n\n" +#gen_basic_fallbacks(basename) +gen_basic_fallbacks() +{ + local basename="$1"; shift +cat << EOF +#define raw_${basename}_acquire arch_${basename} +#define raw_${basename}_release arch_${basename} +#define raw_${basename}_relaxed arch_${basename} +EOF } gen_order_fallbacks() @@ -130,36 +160,65 @@ gen_order_fallbacks() cat <<EOF -#ifndef ${xchg}_acquire -#define ${xchg}_acquire(...) \\ - __atomic_op_acquire(${xchg}, __VA_ARGS__) +#define raw_${xchg}_relaxed arch_${xchg}_relaxed + +#ifdef arch_${xchg}_acquire +#define raw_${xchg}_acquire arch_${xchg}_acquire +#else +#define raw_${xchg}_acquire(...) \\ + __atomic_op_acquire(arch_${xchg}, __VA_ARGS__) #endif -#ifndef ${xchg}_release -#define ${xchg}_release(...) \\ - __atomic_op_release(${xchg}, __VA_ARGS__) +#ifdef arch_${xchg}_release +#define raw_${xchg}_release arch_${xchg}_release +#else +#define raw_${xchg}_release(...) \\ + __atomic_op_release(arch_${xchg}, __VA_ARGS__) #endif -#ifndef ${xchg} -#define ${xchg}(...) \\ - __atomic_op_fence(${xchg}, __VA_ARGS__) +#ifdef arch_${xchg} +#define raw_${xchg} arch_${xchg} +#else +#define raw_${xchg}(...) \\ + __atomic_op_fence(arch_${xchg}, __VA_ARGS__) #endif EOF } -gen_xchg_fallbacks() +gen_xchg_order_fallback() { local xchg="$1"; shift - printf "#ifndef ${xchg}_relaxed\n" + local order="$1"; shift + local forder="${order:-_fence}" - gen_basic_fallbacks ${xchg} + printf "#if defined(arch_${xchg}${order})\n" + printf "#define raw_${xchg}${order} arch_${xchg}${order}\n" - printf "#else /* ${xchg}_relaxed */\n" + if [ "${order}" != "_relaxed" ]; then + printf "#elif defined(arch_${xchg}_relaxed)\n" + printf "#define raw_${xchg}${order}(...) \\\\\n" + printf " __atomic_op${forder}(arch_${xchg}, __VA_ARGS__)\n" + fi + + if [ ! -z "${order}" ]; then + printf "#elif defined(arch_${xchg})\n" + printf "#define raw_${xchg}${order} arch_${xchg}\n" + fi - gen_order_fallbacks ${xchg} + printf "#else\n" + printf "extern void raw_${xchg}${order}_not_implemented(void);\n" + printf "#define raw_${xchg}${order}(...) raw_${xchg}${order}_not_implemented()\n" + printf "#endif\n\n" +} + +gen_xchg_fallbacks() +{ + local xchg="$1"; shift - printf "#endif /* ${xchg}_relaxed */\n\n" + for order in "" "_acquire" "_release" "_relaxed"; do + gen_xchg_order_fallback "${xchg}" "${order}" + done } gen_try_cmpxchg_fallback() @@ -168,40 +227,61 @@ gen_try_cmpxchg_fallback() local order="$1"; shift; cat <<EOF -#ifndef arch_try_${cmpxchg}${order} -#define arch_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ +#define raw_try_${cmpxchg}${order}(_ptr, _oldp, _new) \\ ({ \\ typeof(*(_ptr)) *___op = (_oldp), ___o = *___op, ___r; \\ - ___r = arch_${cmpxchg}${order}((_ptr), ___o, (_new)); \\ + ___r = raw_${cmpxchg}${order}((_ptr), ___o, (_new)); \\ if (unlikely(___r != ___o)) \\ *___op = ___r; \\ likely(___r == ___o); \\ }) -#endif /* arch_try_${cmpxchg}${order} */ - EOF } -gen_try_cmpxchg_fallbacks() +gen_try_cmpxchg_order_fallback() { - local cmpxchg="$1"; shift; + local cmpxchg="$1"; shift + local order="$1"; shift + local forder="${order:-_fence}" - printf "#ifndef arch_try_${cmpxchg}_relaxed\n" - printf "#ifdef arch_try_${cmpxchg}\n" + printf "#if defined(arch_try_${cmpxchg}${order})\n" + printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}${order}\n" + + if [ "${order}" != "_relaxed" ]; then + printf "#elif defined(arch_try_${cmpxchg}_relaxed)\n" + printf "#define raw_try_${cmpxchg}${order}(...) \\\\\n" + printf " __atomic_op${forder}(arch_try_${cmpxchg}, __VA_ARGS__)\n" + fi - gen_basic_fallbacks "arch_try_${cmpxchg}" + if [ ! -z "${order}" ]; then + printf "#elif defined(arch_try_${cmpxchg})\n" + printf "#define raw_try_${cmpxchg}${order} arch_try_${cmpxchg}\n" + fi - printf "#endif /* arch_try_${cmpxchg} */\n\n" + printf "#else\n" + gen_try_cmpxchg_fallback "${cmpxchg}" "${order}" + printf "#endif\n\n" +} + +gen_try_cmpxchg_fallbacks() +{ + local cmpxchg="$1"; shift; for order in "" "_acquire" "_release" "_relaxed"; do - gen_try_cmpxchg_fallback "${cmpxchg}" "${order}" + gen_try_cmpxchg_order_fallback "${cmpxchg}" "${order}" done +} - printf "#else /* arch_try_${cmpxchg}_relaxed */\n" - - gen_order_fallbacks "arch_try_${cmpxchg}" +gen_cmpxchg_local_fallbacks() +{ + local cmpxchg="$1"; shift - printf "#endif /* arch_try_${cmpxchg}_relaxed */\n\n" + printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n" + printf "#ifdef arch_try_${cmpxchg}\n" + printf "#define raw_try_${cmpxchg} arch_try_${cmpxchg}\n" + printf "#else\n" + gen_try_cmpxchg_fallback "${cmpxchg}" "" + printf "#endif\n\n" } cat << EOF @@ -217,16 +297,20 @@ cat << EOF EOF -for xchg in "arch_xchg" "arch_cmpxchg" "arch_cmpxchg64"; do +for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128"; do gen_xchg_fallbacks "${xchg}" done -for cmpxchg in "cmpxchg" "cmpxchg64"; do +for cmpxchg in "cmpxchg" "cmpxchg64" "cmpxchg128"; do gen_try_cmpxchg_fallbacks "${cmpxchg}" done -for cmpxchg in "cmpxchg_local" "cmpxchg64_local"; do - gen_try_cmpxchg_fallback "${cmpxchg}" "" +for cmpxchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local"; do + gen_cmpxchg_local_fallbacks "${cmpxchg}" "" +done + +for cmpxchg in "sync_cmpxchg"; do + printf "#define raw_${cmpxchg} arch_${cmpxchg}\n\n" done grep '^[a-z]' "$1" | while read name meta args; do diff --git a/scripts/atomic/gen-atomic-instrumented.sh b/scripts/atomic/gen-atomic-instrumented.sh index d9ffd74f73ca..8f8f8e3b20f9 100755 --- a/scripts/atomic/gen-atomic-instrumented.sh +++ b/scripts/atomic/gen-atomic-instrumented.sh @@ -68,12 +68,14 @@ gen_proto_order_variant() local args="$(gen_args "$@")" local retstmt="$(gen_ret_stmt "${meta}")" + gen_kerneldoc "" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "${atomic}" "${int}" "$@" + cat <<EOF static __always_inline ${ret} ${atomicname}(${params}) { ${checks} - ${retstmt}arch_${atomicname}(${args}); + ${retstmt}raw_${atomicname}(${args}); } EOF @@ -84,7 +86,6 @@ gen_xchg() { local xchg="$1"; shift local order="$1"; shift - local mult="$1"; shift kcsan_barrier="" if [ "${xchg%_local}" = "${xchg}" ]; then @@ -104,9 +105,9 @@ cat <<EOF EOF [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" cat <<EOF - instrument_atomic_read_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ - instrument_read_write(__ai_oldp, ${mult}sizeof(*__ai_oldp)); \\ - arch_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\ + instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ + instrument_read_write(__ai_oldp, sizeof(*__ai_oldp)); \\ + raw_${xchg}${order}(__ai_ptr, __ai_oldp, __VA_ARGS__); \\ }) EOF @@ -119,8 +120,8 @@ cat <<EOF EOF [ -n "$kcsan_barrier" ] && printf "\t${kcsan_barrier}; \\\\\n" cat <<EOF - instrument_atomic_read_write(__ai_ptr, ${mult}sizeof(*__ai_ptr)); \\ - arch_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\ + instrument_atomic_read_write(__ai_ptr, sizeof(*__ai_ptr)); \\ + raw_${xchg}${order}(__ai_ptr, __VA_ARGS__); \\ }) EOF @@ -134,15 +135,10 @@ cat << EOF // DO NOT MODIFY THIS FILE DIRECTLY /* - * This file provides wrappers with KASAN instrumentation for atomic operations. - * To use this functionality an arch's atomic.h file needs to define all - * atomic operations with arch_ prefix (e.g. arch_atomic_read()) and include - * this file at the end. This file provides atomic_read() that forwards to - * arch_atomic_read() for actual atomic operation. - * Note: if an arch atomic operation is implemented by means of other atomic - * operations (e.g. atomic_read()/atomic_cmpxchg() loop), then it needs to use - * arch_ variants (i.e. arch_atomic_read()/arch_atomic_cmpxchg()) to avoid - * double instrumentation. + * This file provoides atomic operations with explicit instrumentation (e.g. + * KASAN, KCSAN), which should be used unless it is necessary to avoid + * instrumentation. Where it is necessary to aovid instrumenation, the + * raw_atomic*() operations should be used. */ #ifndef _LINUX_ATOMIC_INSTRUMENTED_H #define _LINUX_ATOMIC_INSTRUMENTED_H @@ -166,24 +162,18 @@ grep '^[a-z]' "$1" | while read name meta args; do done -for xchg in "xchg" "cmpxchg" "cmpxchg64" "try_cmpxchg" "try_cmpxchg64"; do +for xchg in "xchg" "cmpxchg" "cmpxchg64" "cmpxchg128" "try_cmpxchg" "try_cmpxchg64" "try_cmpxchg128"; do for order in "" "_acquire" "_release" "_relaxed"; do - gen_xchg "${xchg}" "${order}" "" + gen_xchg "${xchg}" "${order}" printf "\n" done done -for xchg in "cmpxchg_local" "cmpxchg64_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" ; do - gen_xchg "${xchg}" "" "" +for xchg in "cmpxchg_local" "cmpxchg64_local" "cmpxchg128_local" "sync_cmpxchg" "try_cmpxchg_local" "try_cmpxchg64_local" "try_cmpxchg128_local"; do + gen_xchg "${xchg}" "" printf "\n" done -gen_xchg "cmpxchg_double" "" "2 * " - -printf "\n\n" - -gen_xchg "cmpxchg_double_local" "" "2 * " - cat <<EOF #endif /* _LINUX_ATOMIC_INSTRUMENTED_H */ diff --git a/scripts/atomic/gen-atomic-long.sh b/scripts/atomic/gen-atomic-long.sh index eda89cea6e1d..9826be3ba986 100755 --- a/scripts/atomic/gen-atomic-long.sh +++ b/scripts/atomic/gen-atomic-long.sh @@ -32,24 +32,34 @@ gen_args_cast() done } -#gen_proto_order_variant(meta, pfx, name, sfx, order, atomic, int, arg...) +#gen_proto_order_variant(meta, pfx, name, sfx, order, arg...) gen_proto_order_variant() { local meta="$1"; shift - local name="$1$2$3$4"; shift; shift; shift; shift - local atomic="$1"; shift - local int="$1"; shift + local pfx="$1"; shift + local name="$1"; shift + local sfx="$1"; shift + local order="$1"; shift + + local atomicname="${pfx}${name}${sfx}${order}" local ret="$(gen_ret_type "${meta}" "long")" local params="$(gen_params "long" "atomic_long" "$@")" - local argscast="$(gen_args_cast "${int}" "${atomic}" "$@")" + local argscast_32="$(gen_args_cast "int" "atomic" "$@")" + local argscast_64="$(gen_args_cast "s64" "atomic64" "$@")" local retstmt="$(gen_ret_stmt "${meta}")" + gen_kerneldoc "raw_" "${meta}" "${pfx}" "${name}" "${sfx}" "${order}" "atomic_long" "long" "$@" + cat <<EOF static __always_inline ${ret} -arch_atomic_long_${name}(${params}) +raw_atomic_long_${atomicname}(${params}) { - ${retstmt}arch_${atomic}_${name}(${argscast}); +#ifdef CONFIG_64BIT + ${retstmt}raw_atomic64_${atomicname}(${argscast_64}); +#else + ${retstmt}raw_atomic_${atomicname}(${argscast_32}); +#endif } EOF @@ -79,24 +89,12 @@ typedef atomic_t atomic_long_t; #define atomic_long_cond_read_relaxed atomic_cond_read_relaxed #endif -#ifdef CONFIG_64BIT - -EOF - -grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic64" "s64" ${args} -done - -cat <<EOF -#else /* CONFIG_64BIT */ - EOF grep '^[a-z]' "$1" | while read name meta args; do - gen_proto "${meta}" "${name}" "atomic" "int" ${args} + gen_proto "${meta}" "${name}" ${args} done cat <<EOF -#endif /* CONFIG_64BIT */ #endif /* _LINUX_ATOMIC_LONG_H */ EOF diff --git a/scripts/atomic/kerneldoc/add b/scripts/atomic/kerneldoc/add new file mode 100644 index 000000000000..991f3dafceea --- /dev/null +++ b/scripts/atomic/kerneldoc/add @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic add with ${desc_order} ordering + * @i: ${int} value to add + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/add_negative b/scripts/atomic/kerneldoc/add_negative new file mode 100644 index 000000000000..f4ca1f05d1d8 --- /dev/null +++ b/scripts/atomic/kerneldoc/add_negative @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic add and test if negative with ${desc_order} ordering + * @i: ${int} value to add + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is negative, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/add_unless b/scripts/atomic/kerneldoc/add_unless new file mode 100644 index 000000000000..f828e5f6750c --- /dev/null +++ b/scripts/atomic/kerneldoc/add_unless @@ -0,0 +1,18 @@ +if [ -z "${pfx}" ]; then + desc_return="Return: @true if @v was updated, @false otherwise." +fi + +cat <<EOF +/** + * ${class}${atomicname}() - atomic add unless value with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @a: ${int} value to add + * @u: ${int} value to compare with + * + * If (@v != @u), atomically updates @v to (@v + @a) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/and b/scripts/atomic/kerneldoc/and new file mode 100644 index 000000000000..a923574351fc --- /dev/null +++ b/scripts/atomic/kerneldoc/and @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise AND with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v & @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/andnot b/scripts/atomic/kerneldoc/andnot new file mode 100644 index 000000000000..64bb509f866b --- /dev/null +++ b/scripts/atomic/kerneldoc/andnot @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise AND NOT with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v & ~@i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/cmpxchg b/scripts/atomic/kerneldoc/cmpxchg new file mode 100644 index 000000000000..3bce328f50cf --- /dev/null +++ b/scripts/atomic/kerneldoc/cmpxchg @@ -0,0 +1,14 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic compare and exchange with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @old: ${int} value to compare with + * @new: ${int} value to assign + * + * If (@v == @old), atomically updates @v to @new with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The original value of @v. + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec b/scripts/atomic/kerneldoc/dec new file mode 100644 index 000000000000..bbeecbc4c20a --- /dev/null +++ b/scripts/atomic/kerneldoc/dec @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec_and_test b/scripts/atomic/kerneldoc/dec_and_test new file mode 100644 index 000000000000..71bbd23ce4bc --- /dev/null +++ b/scripts/atomic/kerneldoc/dec_and_test @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement and test if zero with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is zero, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec_if_positive b/scripts/atomic/kerneldoc/dec_if_positive new file mode 100644 index 000000000000..04f1aed3cf83 --- /dev/null +++ b/scripts/atomic/kerneldoc/dec_if_positive @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement if positive with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v > 0), atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The old value of (@v - 1), regardless of whether @v was updated. + */ +EOF diff --git a/scripts/atomic/kerneldoc/dec_unless_positive b/scripts/atomic/kerneldoc/dec_unless_positive new file mode 100644 index 000000000000..ee73612f0354 --- /dev/null +++ b/scripts/atomic/kerneldoc/dec_unless_positive @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic decrement unless positive with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v <= 0), atomically updates @v to (@v - 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if @v was updated, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc b/scripts/atomic/kerneldoc/inc new file mode 100644 index 000000000000..9f14f1b3d2ef --- /dev/null +++ b/scripts/atomic/kerneldoc/inc @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc_and_test b/scripts/atomic/kerneldoc/inc_and_test new file mode 100644 index 000000000000..971694d59bbd --- /dev/null +++ b/scripts/atomic/kerneldoc/inc_and_test @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment and test if zero with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is zero, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc_not_zero b/scripts/atomic/kerneldoc/inc_not_zero new file mode 100644 index 000000000000..618be08e653e --- /dev/null +++ b/scripts/atomic/kerneldoc/inc_not_zero @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment unless zero with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v != 0), atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if @v was updated, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/inc_unless_negative b/scripts/atomic/kerneldoc/inc_unless_negative new file mode 100644 index 000000000000..597f23d4dc8d --- /dev/null +++ b/scripts/atomic/kerneldoc/inc_unless_negative @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic increment unless negative with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * If (@v >= 0), atomically updates @v to (@v + 1) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if @v was updated, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/or b/scripts/atomic/kerneldoc/or new file mode 100644 index 000000000000..55b33de50416 --- /dev/null +++ b/scripts/atomic/kerneldoc/or @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise OR with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v | @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/read b/scripts/atomic/kerneldoc/read new file mode 100644 index 000000000000..89fe6147c964 --- /dev/null +++ b/scripts/atomic/kerneldoc/read @@ -0,0 +1,12 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic load with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * + * Atomically loads the value of @v with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The value loaded from @v. + */ +EOF diff --git a/scripts/atomic/kerneldoc/set b/scripts/atomic/kerneldoc/set new file mode 100644 index 000000000000..e82cb9ebbc42 --- /dev/null +++ b/scripts/atomic/kerneldoc/set @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic set with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @i: ${int} value to assign + * + * Atomically sets @v to @i with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: Nothing. + */ +EOF diff --git a/scripts/atomic/kerneldoc/sub b/scripts/atomic/kerneldoc/sub new file mode 100644 index 000000000000..3ba642d04407 --- /dev/null +++ b/scripts/atomic/kerneldoc/sub @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic subtract with ${desc_order} ordering + * @i: ${int} value to subtract + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/atomic/kerneldoc/sub_and_test b/scripts/atomic/kerneldoc/sub_and_test new file mode 100644 index 000000000000..d3760f7749d4 --- /dev/null +++ b/scripts/atomic/kerneldoc/sub_and_test @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic subtract and test if zero with ${desc_order} ordering + * @i: ${int} value to add + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v - @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: @true if the resulting value of @v is zero, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/try_cmpxchg b/scripts/atomic/kerneldoc/try_cmpxchg new file mode 100644 index 000000000000..296553206c06 --- /dev/null +++ b/scripts/atomic/kerneldoc/try_cmpxchg @@ -0,0 +1,15 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic compare and exchange with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @old: pointer to ${int} value to compare with + * @new: ${int} value to assign + * + * If (@v == @old), atomically updates @v to @new with ${desc_order} ordering. + * Otherwise, updates @old to the current value of @v. + * + * ${desc_noinstr} + * + * Return: @true if the exchange occured, @false otherwise. + */ +EOF diff --git a/scripts/atomic/kerneldoc/xchg b/scripts/atomic/kerneldoc/xchg new file mode 100644 index 000000000000..75f04c085f25 --- /dev/null +++ b/scripts/atomic/kerneldoc/xchg @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic exchange with ${desc_order} ordering + * @v: pointer to ${atomic}_t + * @new: ${int} value to assign + * + * Atomically updates @v to @new with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * Return: The original value of @v. + */ +EOF diff --git a/scripts/atomic/kerneldoc/xor b/scripts/atomic/kerneldoc/xor new file mode 100644 index 000000000000..8837270f2806 --- /dev/null +++ b/scripts/atomic/kerneldoc/xor @@ -0,0 +1,13 @@ +cat <<EOF +/** + * ${class}${atomicname}() - atomic bitwise XOR with ${desc_order} ordering + * @i: ${int} value + * @v: pointer to ${atomic}_t + * + * Atomically updates @v to (@v ^ @i) with ${desc_order} ordering. + * + * ${desc_noinstr} + * + * ${desc_return} + */ +EOF diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index fa562806c2be..84b6efa849f4 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -246,8 +246,7 @@ static void *read_file(const char *filename) /* Ignore certain dependencies */ static int is_ignored_file(const char *s, int len) { - return str_ends_with(s, len, "include/generated/autoconf.h") || - str_ends_with(s, len, "include/generated/autoksyms.h"); + return str_ends_with(s, len, "include/generated/autoconf.h"); } /* Do not parse these files */ diff --git a/scripts/check-local-export b/scripts/check-local-export deleted file mode 100755 index f90b5a9c67b3..000000000000 --- a/scripts/check-local-export +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0-only -# -# Copyright (C) 2022 Masahiro Yamada <masahiroy@kernel.org> -# Copyright (C) 2022 Owen Rafferty <owen@owenrafferty.com> -# -# Exit with error if a local exported symbol is found. -# EXPORT_SYMBOL should be used for global symbols. - -set -e -pid=$$ - -# If there is no symbol in the object, ${NM} (both GNU nm and llvm-nm) shows -# 'no symbols' diagnostic (but exits with 0). It is harmless and hidden by -# '2>/dev/null'. However, it suppresses real error messages as well. Add a -# hand-crafted error message here. -# -# TODO: -# Use --quiet instead of 2>/dev/null when we upgrade the minimum version of -# binutils to 2.37, llvm to 13.0.0. -# Then, the following line will be simpler: -# { ${NM} --quiet ${1} || kill 0; } | - -{ ${NM} ${1} 2>/dev/null || { echo "${0}: ${NM} failed" >&2; kill $pid; } } | -${AWK} -v "file=${1}" ' -BEGIN { - i = 0 -} - -# Skip the line if the number of fields is less than 3. -# -# case 1) -# For undefined symbols, the first field (value) is empty. -# The outout looks like this: -# " U _printk" -# It is unneeded to record undefined symbols. -# -# case 2) -# For Clang LTO, llvm-nm outputs a line with type t but empty name: -# "---------------- t" -!length($3) { - next -} - -# save (name, type) in the associative array -{ symbol_types[$3]=$2 } - -# append the exported symbol to the array -($3 ~ /^__ksymtab_/) { - export_symbols[i] = $3 - sub(/^__ksymtab_/, "", export_symbols[i]) - i++ -} - -END { - exit_code = 0 - for (j = 0; j < i; ++j) { - name = export_symbols[j] - # nm(3) says "If lowercase, the symbol is usually local" - if (symbol_types[name] ~ /[a-z]/) { - printf "%s: error: local symbol %s was exported\n", - file, name | "cat 1>&2" - exit_code = 1 - } - } - - exit exit_code -}' - -exit $? diff --git a/scripts/check-sysctl-docs b/scripts/check-sysctl-docs index edc9a629d79e..4f163e0bf6a4 100755 --- a/scripts/check-sysctl-docs +++ b/scripts/check-sysctl-docs @@ -146,16 +146,6 @@ curtable && /\.procname[\t ]*=[\t ]*".+"/ { children[curtable][curentry] = child } -/register_sysctl_table\(.*\)/ { - match($0, /register_sysctl_table\(([^)]+)\)/, tables) - if (debug) print "Registering table " tables[1] - if (children[tables[1]][table]) { - for (entry in entries[children[tables[1]][table]]) { - printentry(entry) - } - } -} - END { for (entry in documented) { if (!seen[entry]) { diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index b30114d637c4..880fde13d9b8 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5046,7 +5046,7 @@ sub process { if|for|while|switch|return|case| volatile|__volatile__| __attribute__|format|__extension__| - asm|__asm__)$/x) + asm|__asm__|scoped_guard)$/x) { # cpp #define statements have non-optional spaces, ie # if there is a space between the name and the open @@ -6997,10 +6997,22 @@ sub process { # } # } +# strcpy uses that should likely be strscpy + if ($line =~ /\bstrcpy\s*\(/) { + WARN("STRCPY", + "Prefer strscpy over strcpy - see: https://github.com/KSPP/linux/issues/88\n" . $herecurr); + } + # strlcpy uses that should likely be strscpy if ($line =~ /\bstrlcpy\s*\(/) { WARN("STRLCPY", - "Prefer strscpy over strlcpy - see: https://lore.kernel.org/r/CAHk-=wgfRnXz0W3D37d01q3JFkr_i_uTL=V6A6G1oUZcprmknw\@mail.gmail.com/\n" . $herecurr); + "Prefer strscpy over strlcpy - see: https://github.com/KSPP/linux/issues/89\n" . $herecurr); + } + +# strncpy uses that should likely be strscpy or strscpy_pad + if ($line =~ /\bstrncpy\s*\(/) { + WARN("STRNCPY", + "Prefer strscpy, strscpy_pad, or __nonstring over strncpy - see: https://github.com/KSPP/linux/issues/90\n" . $herecurr); } # typecasts on min/max could be min_t/max_t @@ -7418,6 +7430,16 @@ sub process { } } +# check for array definition/declarations that should use flexible arrays instead + if ($sline =~ /^[\+ ]\s*\}(?:\s*__packed)?\s*;\s*$/ && + $prevline =~ /^\+\s*(?:\}(?:\s*__packed\s*)?|$Type)\s*$Ident\s*\[\s*(0|1)\s*\]\s*;\s*$/) { + if (ERROR("FLEXIBLE_ARRAY", + "Use C99 flexible arrays - see https://docs.kernel.org/process/deprecated.html#zero-length-and-one-element-arrays\n" . $hereprev) && + $1 == '0' && $fix) { + $fixed[$fixlinenr - 1] =~ s/\[\s*0\s*\]/[]/; + } + } + # nested likely/unlikely calls if ($line =~ /\b(?:(?:un)?likely)\s*\(\s*!?\s*(IS_ERR(?:_OR_NULL|_VALUE)?|WARN)/) { WARN("LIKELY_MISUSE", diff --git a/scripts/gdb/linux/constants.py.in b/scripts/gdb/linux/constants.py.in index 471300ba176c..50a92c4e9984 100644 --- a/scripts/gdb/linux/constants.py.in +++ b/scripts/gdb/linux/constants.py.in @@ -48,12 +48,12 @@ if IS_BUILTIN(CONFIG_COMMON_CLK): LX_GDBPARSED(CLK_GET_RATE_NOCACHE) /* linux/fs.h */ -LX_VALUE(SB_RDONLY) -LX_VALUE(SB_SYNCHRONOUS) -LX_VALUE(SB_MANDLOCK) -LX_VALUE(SB_DIRSYNC) -LX_VALUE(SB_NOATIME) -LX_VALUE(SB_NODIRATIME) +LX_GDBPARSED(SB_RDONLY) +LX_GDBPARSED(SB_SYNCHRONOUS) +LX_GDBPARSED(SB_MANDLOCK) +LX_GDBPARSED(SB_DIRSYNC) +LX_GDBPARSED(SB_NOATIME) +LX_GDBPARSED(SB_NODIRATIME) /* linux/htimer.h */ LX_GDBPARSED(hrtimer_resolution) diff --git a/scripts/gen_autoksyms.sh b/scripts/gen_autoksyms.sh deleted file mode 100755 index 12bcfae940ee..000000000000 --- a/scripts/gen_autoksyms.sh +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0-only - -# Create an autoksyms.h header file from the list of all module's needed symbols -# as recorded in *.usyms files and the user-provided symbol whitelist. - -set -e - -# Use "make V=1" to debug this script. -case "$KBUILD_VERBOSE" in -*1*) - set -x - ;; -esac - -read_modorder= - -if [ "$1" = --modorder ]; then - shift - read_modorder=1 -fi - -output_file="$1" - -needed_symbols= - -# Special case for modversions (see modpost.c) -if grep -q "^CONFIG_MODVERSIONS=y$" include/config/auto.conf; then - needed_symbols="$needed_symbols module_layout" -fi - -ksym_wl=$(sed -n 's/^CONFIG_UNUSED_KSYMS_WHITELIST=\(.*\)$/\1/p' include/config/auto.conf) -if [ -n "$ksym_wl" ]; then - [ "${ksym_wl}" != "${ksym_wl#/}" ] || ksym_wl="$abs_srctree/$ksym_wl" - if [ ! -f "$ksym_wl" ] || [ ! -r "$ksym_wl" ]; then - echo "ERROR: '$ksym_wl' whitelist file not found" >&2 - exit 1 - fi -fi - -# Generate a new ksym list file with symbols needed by the current -# set of modules. -cat > "$output_file" << EOT -/* - * Automatically generated file; DO NOT EDIT. - */ - -EOT - -{ - [ -n "${read_modorder}" ] && sed 's/o$/usyms/' modules.order | xargs cat - echo "$needed_symbols" - [ -n "$ksym_wl" ] && cat "$ksym_wl" -} | sed -e 's/ /\n/g' | sed -n -e '/^$/!p' | -# Remove the dot prefix for ppc64; symbol names with a dot (.) hold entry -# point addresses. -sed -e 's/^\.//' | -sort -u | -# Ignore __this_module. It's not an exported symbol, and will be resolved -# when the final .ko's are linked. -grep -v '^__this_module$' | -sed -e 's/\(.*\)/#define __KSYM_\1 1/' >> "$output_file" diff --git a/scripts/gen_ksymdeps.sh b/scripts/gen_ksymdeps.sh deleted file mode 100755 index 8ee533f33659..000000000000 --- a/scripts/gen_ksymdeps.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# SPDX-License-Identifier: GPL-2.0 - -set -e - -# List of exported symbols -# -# If the object has no symbol, $NM warns 'no symbols'. -# Suppress the stderr. -# TODO: -# Use -q instead of 2>/dev/null when we upgrade the minimum version of -# binutils to 2.37, llvm to 13.0.0. -ksyms=$($NM $1 2>/dev/null | sed -n 's/.*__ksym_marker_\(.*\)/\1/p') - -if [ -z "$ksyms" ]; then - exit 0 -fi - -echo -echo "ksymdeps_$1 := \\" - -for s in $ksyms -do - printf ' $(wildcard include/ksym/%s) \\\n' "$s" -done - -echo -echo "$1: \$(ksymdeps_$1)" -echo -echo "\$(ksymdeps_$1):" diff --git a/scripts/gfp-translate b/scripts/gfp-translate index b2ce416d944b..6c9aed17cf56 100755 --- a/scripts/gfp-translate +++ b/scripts/gfp-translate @@ -63,11 +63,11 @@ fi # Extract GFP flags from the kernel source TMPFILE=`mktemp -t gfptranslate-XXXXXX` || exit 1 -grep -q ___GFP $SOURCE/include/linux/gfp.h +grep -q ___GFP $SOURCE/include/linux/gfp_types.h if [ $? -eq 0 ]; then - grep "^#define ___GFP" $SOURCE/include/linux/gfp.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE + grep "^#define ___GFP" $SOURCE/include/linux/gfp_types.h | sed -e 's/u$//' | grep -v GFP_BITS > $TMPFILE else - grep "^#define __GFP" $SOURCE/include/linux/gfp.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE + grep "^#define __GFP" $SOURCE/include/linux/gfp_types.h | sed -e 's/(__force gfp_t)//' | sed -e 's/u)/)/' | grep -v GFP_BITS | sed -e 's/)\//) \//' > $TMPFILE fi # Parse the flags diff --git a/scripts/head-object-list.txt b/scripts/head-object-list.txt index b2a0e21ea8d7..26359968744e 100644 --- a/scripts/head-object-list.txt +++ b/scripts/head-object-list.txt @@ -34,7 +34,7 @@ arch/powerpc/kernel/head_64.o arch/powerpc/kernel/head_8xx.o arch/powerpc/kernel/head_85xx.o arch/powerpc/kernel/head_book3s_32.o -arch/powerpc/kernel/entry_64.o +arch/powerpc/kernel/prom_entry_64.o arch/powerpc/kernel/fpu.o arch/powerpc/kernel/vector.o arch/powerpc/kernel/prom_init.o diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 0d2db41177b2..d387c9381650 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -19,6 +19,7 @@ * */ +#include <errno.h> #include <getopt.h> #include <stdbool.h> #include <stdio.h> @@ -29,24 +30,8 @@ #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) -#define _stringify_1(x) #x -#define _stringify(x) _stringify_1(x) - #define KSYM_NAME_LEN 512 -/* - * A substantially bigger size than the current maximum. - * - * It cannot be defined as an expression because it gets stringified - * for the fscanf() format string. Therefore, a _Static_assert() is - * used instead to maintain the relationship with KSYM_NAME_LEN. - */ -#define KSYM_NAME_LEN_BUFFER 2048 -_Static_assert( - KSYM_NAME_LEN_BUFFER == KSYM_NAME_LEN * 4, - "Please keep KSYM_NAME_LEN_BUFFER in sync with KSYM_NAME_LEN" -); - struct sym_entry { unsigned long long addr; unsigned int len; @@ -136,24 +121,40 @@ static void check_symbol_range(const char *sym, unsigned long long addr, } } -static struct sym_entry *read_symbol(FILE *in) +static struct sym_entry *read_symbol(FILE *in, char **buf, size_t *buf_len) { - char name[KSYM_NAME_LEN_BUFFER+1], type; + char *name, type, *p; unsigned long long addr; - unsigned int len; + size_t len; + ssize_t readlen; struct sym_entry *sym; - int rc; - rc = fscanf(in, "%llx %c %" _stringify(KSYM_NAME_LEN_BUFFER) "s\n", &addr, &type, name); - if (rc != 3) { - if (rc != EOF && fgets(name, ARRAY_SIZE(name), in) == NULL) - fprintf(stderr, "Read error or end of file.\n"); + readlen = getline(buf, buf_len, in); + if (readlen < 0) { + if (errno) { + perror("read_symbol"); + exit(EXIT_FAILURE); + } return NULL; } - if (strlen(name) >= KSYM_NAME_LEN) { + + if ((*buf)[readlen - 1] == '\n') + (*buf)[readlen - 1] = 0; + + addr = strtoull(*buf, &p, 16); + + if (*buf == p || *p++ != ' ' || !isascii((type = *p++)) || *p++ != ' ') { + fprintf(stderr, "line format error\n"); + exit(EXIT_FAILURE); + } + + name = p; + len = strlen(name); + + if (len >= KSYM_NAME_LEN) { fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n" "Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n", - name, strlen(name), KSYM_NAME_LEN); + name, len, KSYM_NAME_LEN); return NULL; } @@ -169,8 +170,7 @@ static struct sym_entry *read_symbol(FILE *in) /* include the type field in the symbol name, so that it gets * compressed together */ - - len = strlen(name) + 1; + len++; sym = malloc(sizeof(*sym) + len + 1); if (!sym) { @@ -257,6 +257,8 @@ static void read_map(const char *in) { FILE *fp; struct sym_entry *sym; + char *buf = NULL; + size_t buflen = 0; fp = fopen(in, "r"); if (!fp) { @@ -265,7 +267,7 @@ static void read_map(const char *in) } while (!feof(fp)) { - sym = read_symbol(fp); + sym = read_symbol(fp, &buf, &buflen); if (!sym) continue; @@ -284,6 +286,7 @@ static void read_map(const char *in) table[table_cnt++] = sym; } + free(buf); fclose(fp); } @@ -806,7 +809,7 @@ static void record_relative_base(void) int main(int argc, char **argv) { while (1) { - static struct option long_options[] = { + static const struct option long_options[] = { {"all-symbols", no_argument, &all_symbols, 1}, {"absolute-percpu", no_argument, &absolute_percpu, 1}, {"base-relative", no_argument, &base_relative, 1}, diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl index 3387ad7508f7..d51cd7ac15d2 100755 --- a/scripts/kconfig/streamline_config.pl +++ b/scripts/kconfig/streamline_config.pl @@ -317,7 +317,7 @@ foreach my $makefile (@makefiles) { $_ = convert_vars($_, %make_vars); # collect objects after obj-$(CONFIG_FOO_BAR) - if (/obj-\$\((CONFIG_[^\)]*)\)\s*[+:]?=\s*(.*)/) { + if (/obj-\$[({](CONFIG_[^})]*)[)}]\s*[+:]?=\s*(.*)/) { $var = $1; $objs = $2; diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 66b554897899..d0116c6939dc 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -23,7 +23,7 @@ kernel-doc - Print formatted kernel documentation to stdout =head1 SYNOPSIS - kernel-doc [-h] [-v] [-Werror] + kernel-doc [-h] [-v] [-Werror] [-Wall] [-Wreturn] [-Wshort-description] [-Wcontents-before-sections] [ -man | -rst [-sphinx-version VERSION] [-enable-lineno] | -none @@ -64,7 +64,7 @@ my $type_constant = '\b``([^\`]+)``\b'; my $type_constant2 = '\%([-_\w]+)'; my $type_func = '(\w+)\(\)'; my $type_param = '\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; -my $type_param_ref = '([\!]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; +my $type_param_ref = '([\!~]?)\@(\w*((\.\w+)|(->\w+))*(\.\.\.)?)'; my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params my $type_fp_param2 = '\@(\w+->\S+)\(\)'; # Special RST handling for structs with func ptr params my $type_env = '(\$\w+)'; @@ -133,6 +133,9 @@ my $dohighlight = ""; my $verbose = 0; my $Werror = 0; +my $Wreturn = 0; +my $Wshort_desc = 0; +my $Wcontents_before_sections = 0; my $output_mode = "rst"; my $output_preformatted = 0; my $no_doc_sections = 0; @@ -187,9 +190,14 @@ if (defined($ENV{'KCFLAGS'})) { } } +# reading this variable is for backwards compat just in case +# someone was calling it with the variable from outside the +# kernel's build system if (defined($ENV{'KDOC_WERROR'})) { $Werror = "$ENV{'KDOC_WERROR'}"; } +# other environment variables are converted to command-line +# arguments in cmd_checkdoc in the build system # Generated docbook code is inserted in a template at a point where # docbook v3.1 requires a non-zero sequence of RefEntry's; see: @@ -318,6 +326,16 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $verbose = 1; } elsif ($cmd eq "Werror") { $Werror = 1; + } elsif ($cmd eq "Wreturn") { + $Wreturn = 1; + } elsif ($cmd eq "Wshort-desc") { + $Wshort_desc = 1; + } elsif ($cmd eq "Wcontents-before-sections") { + $Wcontents_before_sections = 1; + } elsif ($cmd eq "Wall") { + $Wreturn = 1; + $Wshort_desc = 1; + $Wcontents_before_sections = 1; } elsif (($cmd eq "h") || ($cmd eq "help")) { pod2usage(-exitval => 0, -verbose => 2); } elsif ($cmd eq 'no-doc-sections') { @@ -1751,9 +1769,9 @@ sub dump_function($$) { # This check emits a lot of warnings at the moment, because many # functions don't have a 'Return' doc section. So until the number # of warnings goes sufficiently down, the check is only performed in - # verbose mode. + # -Wreturn mode. # TODO: always perform the check. - if ($verbose && !$noret) { + if ($Wreturn && !$noret) { check_return_section($file, $declaration_name, $return_type); } @@ -2057,7 +2075,7 @@ sub process_name($$) { $state = STATE_NORMAL; } - if (($declaration_purpose eq "") && $verbose) { + if (($declaration_purpose eq "") && $Wshort_desc) { emit_warning("${file}:$.", "missing initial short description on line:\n$_"); } @@ -2106,7 +2124,7 @@ sub process_body($$) { } if (($contents ne "") && ($contents ne "\n")) { - if (!$in_doc_sect && $verbose) { + if (!$in_doc_sect && $Wcontents_before_sections) { emit_warning("${file}:$.", "contents before sections\n"); } dump_section($file, $section, $contents); diff --git a/scripts/min-tool-version.sh b/scripts/min-tool-version.sh index 20d483ec6f5f..2ade63149466 100755 --- a/scripts/min-tool-version.sh +++ b/scripts/min-tool-version.sh @@ -17,7 +17,11 @@ binutils) echo 2.25.0 ;; gcc) - echo 5.1.0 + if [ "$ARCH" = parisc64 ]; then + echo 12.0.0 + else + echo 5.1.0 + fi ;; llvm) if [ "$SRCARCH" = s390 ]; then @@ -27,7 +31,7 @@ llvm) fi ;; rustc) - echo 1.62.0 + echo 1.68.2 ;; bindgen) echo 0.56.0 diff --git a/scripts/mksysmap b/scripts/mksysmap index cb3b1fff3eee..9ba1c9da0a40 100755 --- a/scripts/mksysmap +++ b/scripts/mksysmap @@ -32,7 +32,7 @@ ${NM} -n ${1} | sed >${2} -e " # (do not forget a space before each pattern) # local symbols for ARM, MIPS, etc. -/ \$/d +/ \\$/d # local labels, .LBB, .Ltmpxxx, .L__unnamed_xx, .LASANPC, etc. / \.L/d @@ -40,8 +40,12 @@ ${NM} -n ${1} | sed >${2} -e " # arm64 EFI stub namespace / __efistub_/d +# arm64 local symbols in PIE namespace +/ __pi_\\$/d +/ __pi_\.L/d + # arm64 local symbols in non-VHE KVM namespace -/ __kvm_nvhe_\$/d +/ __kvm_nvhe_\\$/d / __kvm_nvhe_\.L/d # arm64 lld @@ -58,6 +62,8 @@ ${NM} -n ${1} | sed >${2} -e " # CFI type identifiers / __kcfi_typeid_/d +/ __kvm_nvhe___kcfi_typeid_/d +/ __pi___kcfi_typeid_/d # CRC from modversions / __crc_/d diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index 62dc988df84d..abe65f8968dd 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -265,6 +265,7 @@ int main(void) DEVID(cdx_device_id); DEVID_FIELD(cdx_device_id, vendor); DEVID_FIELD(cdx_device_id, device); + DEVID_FIELD(cdx_device_id, override_only); return 0; } diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 28da34ba4359..38120f932b0d 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -1458,8 +1458,23 @@ static int do_cdx_entry(const char *filename, void *symval, { DEF_FIELD(symval, cdx_device_id, vendor); DEF_FIELD(symval, cdx_device_id, device); + DEF_FIELD(symval, cdx_device_id, override_only); - sprintf(alias, "cdx:v%08Xd%08Xd", vendor, device); + switch (override_only) { + case 0: + strcpy(alias, "cdx:"); + break; + case CDX_ID_F_VFIO_DRIVER_OVERRIDE: + strcpy(alias, "vfio_cdx:"); + break; + default: + warn("Unknown CDX driver_override alias %08X\n", + override_only); + return 0; + } + + ADD(alias, "v", vendor != CDX_ANY_ID, vendor); + ADD(alias, "d", device != CDX_ANY_ID, device); return 1; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index d4531d09984d..b29b29707f10 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -35,6 +35,9 @@ static bool warn_unresolved; static int sec_mismatch_count; static bool sec_mismatch_warn_only = true; +/* Trim EXPORT_SYMBOLs that are unused by in-tree modules */ +static bool trim_unused_exports; + /* ignore missing files */ static bool ignore_missing_files; /* If set to 1, only warn (instead of error) about missing ns imports */ @@ -42,6 +45,8 @@ static bool allow_missing_ns_imports; static bool error_occurred; +static bool extra_warn; + /* * Cut off the warnings when there are too many. This typically occurs when * vmlinux is missing. ('make modules' without building vmlinux.) @@ -215,7 +220,9 @@ struct symbol { unsigned int crc; bool crc_valid; bool weak; + bool is_func; bool is_gpl_only; /* exported by EXPORT_SYMBOL_GPL */ + bool used; /* there exists a user of this symbol */ char name[]; }; @@ -297,6 +304,13 @@ static bool contains_namespace(struct list_head *head, const char *namespace) { struct namespace_list *list; + /* + * The default namespace is null string "", which is always implicitly + * contained. + */ + if (!namespace[0]) + return true; + list_for_each_entry(list, head, list) { if (!strcmp(list->namespace, namespace)) return true; @@ -352,26 +366,8 @@ static const char *sec_name(const struct elf_info *info, unsigned int secindex) #define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0) -static void sym_update_namespace(const char *symname, const char *namespace) -{ - struct symbol *s = find_symbol(symname); - - /* - * That symbol should have been created earlier and thus this is - * actually an assertion. - */ - if (!s) { - error("Could not update namespace(%s) for symbol %s\n", - namespace, symname); - return; - } - - free(s->namespace); - s->namespace = namespace[0] ? NOFAIL(strdup(namespace)) : NULL; -} - static struct symbol *sym_add_exported(const char *name, struct module *mod, - bool gpl_only) + bool gpl_only, const char *namespace) { struct symbol *s = find_symbol(name); @@ -384,6 +380,7 @@ static struct symbol *sym_add_exported(const char *name, struct module *mod, s = alloc_symbol(name); s->module = mod; s->is_gpl_only = gpl_only; + s->namespace = NOFAIL(strdup(namespace)); list_add_tail(&s->list, &mod->exported_symbols); hash_add_symbol(s); @@ -531,6 +528,8 @@ static int parse_elf(struct elf_info *info, const char *filename) fatal("%s has NOBITS .modinfo\n", filename); info->modinfo = (void *)hdr + sechdrs[i].sh_offset; info->modinfo_len = sechdrs[i].sh_size; + } else if (!strcmp(secname, ".export_symbol")) { + info->export_symbol_secndx = i; } if (sechdrs[i].sh_type == SHT_SYMTAB) { @@ -653,18 +652,6 @@ static void handle_symbol(struct module *mod, struct elf_info *info, ELF_ST_BIND(sym->st_info) == STB_WEAK); break; default: - /* All exported symbols */ - if (strstarts(symname, "__ksymtab_")) { - const char *name, *secname; - - name = symname + strlen("__ksymtab_"); - secname = sec_name(info, get_secindex(info, sym)); - - if (strstarts(secname, "___ksymtab_gpl+")) - sym_add_exported(name, mod, true); - else if (strstarts(secname, "___ksymtab+")) - sym_add_exported(name, mod, false); - } if (strcmp(symname, "init_module") == 0) mod->has_init = true; if (strcmp(symname, "cleanup_module") == 0) @@ -838,34 +825,14 @@ static void check_section(const char *modname, struct elf_info *elf, #define ALL_TEXT_SECTIONS ALL_INIT_TEXT_SECTIONS, ALL_EXIT_TEXT_SECTIONS, \ TEXT_SECTIONS, OTHER_TEXT_SECTIONS -/* init data sections */ -static const char *const init_data_sections[] = - { ALL_INIT_DATA_SECTIONS, NULL }; - -/* all init sections */ -static const char *const init_sections[] = { ALL_INIT_SECTIONS, NULL }; - -/* all text sections */ -static const char *const text_sections[] = { ALL_TEXT_SECTIONS, NULL }; - -/* data section */ -static const char *const data_sections[] = { DATA_SECTIONS, NULL }; - -static const char *const head_sections[] = { ".head.text*", NULL }; -static const char *const linker_symbols[] = - { "__init_begin", "_sinittext", "_einittext", NULL }; -static const char *const optim_symbols[] = { "*.constprop.*", NULL }; - enum mismatch { TEXT_TO_ANY_INIT, DATA_TO_ANY_INIT, - TEXT_TO_ANY_EXIT, - DATA_TO_ANY_EXIT, + TEXTDATA_TO_ANY_EXIT, XXXINIT_TO_SOME_INIT, XXXEXIT_TO_SOME_EXIT, ANY_INIT_TO_ANY_EXIT, ANY_EXIT_TO_ANY_INIT, - EXPORT_TO_INIT_EXIT, EXTABLE_TO_NON_TEXT, }; @@ -881,27 +848,14 @@ enum mismatch { * targeting sections in this array (white-list). Can be empty. * * @mismatch: Type of mismatch. - * - * @handler: Specific handler to call when a match is found. If NULL, - * default_mismatch_handler() will be called. - * */ struct sectioncheck { const char *fromsec[20]; const char *bad_tosec[20]; const char *good_tosec[20]; enum mismatch mismatch; - void (*handler)(const char *modname, struct elf_info *elf, - const struct sectioncheck* const mismatch, - Elf_Rela *r, Elf_Sym *sym, const char *fromsec); - }; -static void extable_mismatch_handler(const char *modname, struct elf_info *elf, - const struct sectioncheck* const mismatch, - Elf_Rela *r, Elf_Sym *sym, - const char *fromsec); - static const struct sectioncheck sectioncheck[] = { /* Do not reference init/exit code/data from * normal code and data @@ -913,23 +867,13 @@ static const struct sectioncheck sectioncheck[] = { }, { .fromsec = { DATA_SECTIONS, NULL }, - .bad_tosec = { ALL_XXXINIT_SECTIONS, NULL }, - .mismatch = DATA_TO_ANY_INIT, -}, -{ - .fromsec = { DATA_SECTIONS, NULL }, - .bad_tosec = { INIT_SECTIONS, NULL }, + .bad_tosec = { ALL_XXXINIT_SECTIONS, INIT_SECTIONS, NULL }, .mismatch = DATA_TO_ANY_INIT, }, { - .fromsec = { TEXT_SECTIONS, NULL }, - .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, - .mismatch = TEXT_TO_ANY_EXIT, -}, -{ - .fromsec = { DATA_SECTIONS, NULL }, + .fromsec = { TEXT_SECTIONS, DATA_SECTIONS, NULL }, .bad_tosec = { ALL_EXIT_SECTIONS, NULL }, - .mismatch = DATA_TO_ANY_EXIT, + .mismatch = TEXTDATA_TO_ANY_EXIT, }, /* Do not reference init code/data from meminit code/data */ { @@ -960,12 +904,6 @@ static const struct sectioncheck sectioncheck[] = { .bad_tosec = { INIT_SECTIONS, NULL }, .mismatch = ANY_INIT_TO_ANY_EXIT, }, -/* Do not export init/exit functions or data */ -{ - .fromsec = { "___ksymtab*", NULL }, - .bad_tosec = { INIT_SECTIONS, EXIT_SECTIONS, NULL }, - .mismatch = EXPORT_TO_INIT_EXIT, -}, { .fromsec = { "__ex_table", NULL }, /* If you're adding any new black-listed sections in here, consider @@ -974,7 +912,6 @@ static const struct sectioncheck sectioncheck[] = { .bad_tosec = { ".altinstr_replacement", NULL }, .good_tosec = {ALL_TEXT_SECTIONS , NULL}, .mismatch = EXTABLE_TO_NON_TEXT, - .handler = extable_mismatch_handler, } }; @@ -1048,28 +985,19 @@ static const struct sectioncheck *section_mismatch( * fromsec = text section * refsymname = *.constprop.* * - * Pattern 6: - * Hide section mismatch warnings for ELF local symbols. The goal - * is to eliminate false positive modpost warnings caused by - * compiler-generated ELF local symbol names such as ".LANCHOR1". - * Autogenerated symbol names bypass modpost's "Pattern 2" - * whitelisting, which relies on pattern-matching against symbol - * names to work. (One situation where gcc can autogenerate ELF - * local symbols is when "-fsection-anchors" is used.) **/ -static int secref_whitelist(const struct sectioncheck *mismatch, - const char *fromsec, const char *fromsym, +static int secref_whitelist(const char *fromsec, const char *fromsym, const char *tosec, const char *tosym) { /* Check for pattern 1 */ - if (match(tosec, init_data_sections) && - match(fromsec, data_sections) && + if (match(tosec, PATTERNS(ALL_INIT_DATA_SECTIONS)) && + match(fromsec, PATTERNS(DATA_SECTIONS)) && strstarts(fromsym, "__param")) return 0; /* Check for pattern 1a */ if (strcmp(tosec, ".init.text") == 0 && - match(fromsec, data_sections) && + match(fromsec, PATTERNS(DATA_SECTIONS)) && strstarts(fromsym, "__param_ops_")) return 0; @@ -1092,22 +1020,18 @@ static int secref_whitelist(const struct sectioncheck *mismatch, return 0; /* Check for pattern 3 */ - if (match(fromsec, head_sections) && - match(tosec, init_sections)) + if (strstarts(fromsec, ".head.text") && + match(tosec, PATTERNS(ALL_INIT_SECTIONS))) return 0; /* Check for pattern 4 */ - if (match(tosym, linker_symbols)) + if (match(tosym, PATTERNS("__init_begin", "_sinittext", "_einittext"))) return 0; /* Check for pattern 5 */ - if (match(fromsec, text_sections) && - match(tosec, init_sections) && - match(fromsym, optim_symbols)) - return 0; - - /* Check for pattern 6 */ - if (strstarts(fromsym, ".L")) + if (match(fromsec, PATTERNS(ALL_TEXT_SECTIONS)) && + match(tosec, PATTERNS(ALL_INIT_SECTIONS)) && + match(fromsym, PATTERNS("*.constprop.*"))) return 0; return 1; @@ -1131,303 +1055,210 @@ static inline int is_valid_name(struct elf_info *elf, Elf_Sym *sym) return !is_mapping_symbol(name); } -/** - * Find symbol based on relocation record info. - * In some cases the symbol supplied is a valid symbol so - * return refsym. If st_name != 0 we assume this is a valid symbol. - * In other cases the symbol needs to be looked up in the symbol table - * based on section and address. - * **/ -static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf64_Sword addr, - Elf_Sym *relsym) +/* Look up the nearest symbol based on the section and the address */ +static Elf_Sym *find_nearest_sym(struct elf_info *elf, Elf_Addr addr, + unsigned int secndx, bool allow_negative, + Elf_Addr min_distance) { Elf_Sym *sym; Elf_Sym *near = NULL; - Elf64_Sword distance = 20; - Elf64_Sword d; - unsigned int relsym_secindex; - - if (relsym->st_name != 0) - return relsym; + Elf_Addr sym_addr, distance; + bool is_arm = (elf->hdr->e_machine == EM_ARM); - relsym_secindex = get_secindex(elf, relsym); for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { - if (get_secindex(elf, sym) != relsym_secindex) - continue; - if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) + if (get_secindex(elf, sym) != secndx) continue; if (!is_valid_name(elf, sym)) continue; - if (sym->st_value == addr) - return sym; - /* Find a symbol nearby - addr are maybe negative */ - d = sym->st_value - addr; - if (d < 0) - d = addr - sym->st_value; - if (d < distance) { - distance = d; - near = sym; - } - } - /* We need a close match */ - if (distance < 20) - return near; - else - return NULL; -} -/* - * Find symbols before or equal addr and after addr - in the section sec. - * If we find two symbols with equal offset prefer one with a valid name. - * The ELF format may have a better way to detect what type of symbol - * it is, but this works for now. - **/ -static Elf_Sym *find_elf_symbol2(struct elf_info *elf, Elf_Addr addr, - const char *sec) -{ - Elf_Sym *sym; - Elf_Sym *near = NULL; - Elf_Addr distance = ~0; + sym_addr = sym->st_value; - for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { - const char *symsec; + /* + * For ARM Thumb instruction, the bit 0 of st_value is set + * if the symbol is STT_FUNC type. Mask it to get the address. + */ + if (is_arm && ELF_ST_TYPE(sym->st_info) == STT_FUNC) + sym_addr &= ~1; - if (is_shndx_special(sym->st_shndx)) - continue; - symsec = sec_name(elf, get_secindex(elf, sym)); - if (strcmp(symsec, sec) != 0) - continue; - if (!is_valid_name(elf, sym)) + if (addr >= sym_addr) + distance = addr - sym_addr; + else if (allow_negative) + distance = sym_addr - addr; + else continue; - if (sym->st_value <= addr && addr - sym->st_value <= distance) { - distance = addr - sym->st_value; + + if (distance <= min_distance) { + min_distance = distance; near = sym; } + + if (min_distance == 0) + break; } return near; } -static int is_function(Elf_Sym *sym) +static Elf_Sym *find_fromsym(struct elf_info *elf, Elf_Addr addr, + unsigned int secndx) { - if (sym) - return ELF_ST_TYPE(sym->st_info) == STT_FUNC; - else - return -1; + return find_nearest_sym(elf, addr, secndx, false, ~0); } -static inline void get_pretty_name(int is_func, const char** name, const char** name_p) +static Elf_Sym *find_tosym(struct elf_info *elf, Elf_Addr addr, Elf_Sym *sym) { - switch (is_func) { - case 0: *name = "variable"; *name_p = ""; break; - case 1: *name = "function"; *name_p = "()"; break; - default: *name = "(unknown reference)"; *name_p = ""; break; - } + /* If the supplied symbol has a valid name, return it */ + if (is_valid_name(elf, sym)) + return sym; + + /* + * Strive to find a better symbol name, but the resulting name may not + * match the symbol referenced in the original code. + */ + return find_nearest_sym(elf, addr, get_secindex(elf, sym), true, 20); } -/* - * Print a warning about a section mismatch. - * Try to find symbols near it so user can find it. - * Check whitelist before warning - it may be a false positive. - */ -static void report_sec_mismatch(const char *modname, - const struct sectioncheck *mismatch, - const char *fromsec, - const char *fromsym, - const char *tosec, const char *tosym) +static bool is_executable_section(struct elf_info *elf, unsigned int secndx) { - sec_mismatch_count++; + if (secndx >= elf->num_sections) + return false; - switch (mismatch->mismatch) { - case TEXT_TO_ANY_INIT: - case DATA_TO_ANY_INIT: - case TEXT_TO_ANY_EXIT: - case DATA_TO_ANY_EXIT: - case XXXINIT_TO_SOME_INIT: - case XXXEXIT_TO_SOME_EXIT: - case ANY_INIT_TO_ANY_EXIT: - case ANY_EXIT_TO_ANY_INIT: - warn("%s: section mismatch in reference: %s (section: %s) -> %s (section: %s)\n", - modname, fromsym, fromsec, tosym, tosec); - break; - case EXPORT_TO_INIT_EXIT: - warn("%s: EXPORT_SYMBOL used for init/exit symbol: %s (section: %s)\n", - modname, tosym, tosec); - break; - case EXTABLE_TO_NON_TEXT: - fatal("There's a special handler for this mismatch type, we should never get here.\n"); - break; - } + return (elf->sechdrs[secndx].sh_flags & SHF_EXECINSTR) != 0; } static void default_mismatch_handler(const char *modname, struct elf_info *elf, const struct sectioncheck* const mismatch, - Elf_Rela *r, Elf_Sym *sym, const char *fromsec) + Elf_Sym *tsym, + unsigned int fsecndx, const char *fromsec, Elf_Addr faddr, + const char *tosec, Elf_Addr taddr) { - const char *tosec; - Elf_Sym *to; Elf_Sym *from; const char *tosym; const char *fromsym; - from = find_elf_symbol2(elf, r->r_offset, fromsec); + from = find_fromsym(elf, faddr, fsecndx); fromsym = sym_name(elf, from); - tosec = sec_name(elf, get_secindex(elf, sym)); - to = find_elf_symbol(elf, r->r_addend, sym); - tosym = sym_name(elf, to); + tsym = find_tosym(elf, taddr, tsym); + tosym = sym_name(elf, tsym); /* check whitelist - we may ignore it */ - if (secref_whitelist(mismatch, - fromsec, fromsym, tosec, tosym)) { - report_sec_mismatch(modname, mismatch, - fromsec, fromsym, tosec, tosym); + if (!secref_whitelist(fromsec, fromsym, tosec, tosym)) + return; + + sec_mismatch_count++; + + warn("%s: section mismatch in reference: %s+0x%x (section: %s) -> %s (section: %s)\n", + modname, fromsym, (unsigned int)(faddr - from->st_value), fromsec, tosym, tosec); + + if (mismatch->mismatch == EXTABLE_TO_NON_TEXT) { + if (match(tosec, mismatch->bad_tosec)) + fatal("The relocation at %s+0x%lx references\n" + "section \"%s\" which is black-listed.\n" + "Something is seriously wrong and should be fixed.\n" + "You might get more information about where this is\n" + "coming from by using scripts/check_extable.sh %s\n", + fromsec, (long)faddr, tosec, modname); + else if (is_executable_section(elf, get_secindex(elf, tsym))) + warn("The relocation at %s+0x%lx references\n" + "section \"%s\" which is not in the list of\n" + "authorized sections. If you're adding a new section\n" + "and/or if this reference is valid, add \"%s\" to the\n" + "list of authorized sections to jump to on fault.\n" + "This can be achieved by adding \"%s\" to\n" + "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n", + fromsec, (long)faddr, tosec, tosec, tosec); + else + error("%s+0x%lx references non-executable section '%s'\n", + fromsec, (long)faddr, tosec); } } -static int is_executable_section(struct elf_info* elf, unsigned int section_index) +static void check_export_symbol(struct module *mod, struct elf_info *elf, + Elf_Addr faddr, const char *secname, + Elf_Sym *sym) { - if (section_index > elf->num_sections) - fatal("section_index is outside elf->num_sections!\n"); + static const char *prefix = "__export_symbol_"; + const char *label_name, *name, *data; + Elf_Sym *label; + struct symbol *s; + bool is_gpl; - return ((elf->sechdrs[section_index].sh_flags & SHF_EXECINSTR) == SHF_EXECINSTR); -} + label = find_fromsym(elf, faddr, elf->export_symbol_secndx); + label_name = sym_name(elf, label); -/* - * We rely on a gross hack in section_rel[a]() calling find_extable_entry_size() - * to know the sizeof(struct exception_table_entry) for the target architecture. - */ -static unsigned int extable_entry_size = 0; -static void find_extable_entry_size(const char* const sec, const Elf_Rela* r) -{ - /* - * If we're currently checking the second relocation within __ex_table, - * that relocation offset tells us the offsetof(struct - * exception_table_entry, fixup) which is equal to sizeof(struct - * exception_table_entry) divided by two. We use that to our advantage - * since there's no portable way to get that size as every architecture - * seems to go with different sized types. Not pretty but better than - * hard-coding the size for every architecture.. - */ - if (!extable_entry_size) - extable_entry_size = r->r_offset * 2; -} + if (!strstarts(label_name, prefix)) { + error("%s: .export_symbol section contains strange symbol '%s'\n", + mod->name, label_name); + return; + } -static inline bool is_extable_fault_address(Elf_Rela *r) -{ - /* - * extable_entry_size is only discovered after we've handled the - * _second_ relocation in __ex_table, so only abort when we're not - * handling the first reloc and extable_entry_size is zero. - */ - if (r->r_offset && extable_entry_size == 0) - fatal("extable_entry size hasn't been discovered!\n"); - - return ((r->r_offset == 0) || - (r->r_offset % extable_entry_size == 0)); -} - -#define is_second_extable_reloc(Start, Cur, Sec) \ - (((Cur) == (Start) + 1) && (strcmp("__ex_table", (Sec)) == 0)) - -static void report_extable_warnings(const char* modname, struct elf_info* elf, - const struct sectioncheck* const mismatch, - Elf_Rela* r, Elf_Sym* sym, - const char* fromsec, const char* tosec) -{ - Elf_Sym* fromsym = find_elf_symbol2(elf, r->r_offset, fromsec); - const char* fromsym_name = sym_name(elf, fromsym); - Elf_Sym* tosym = find_elf_symbol(elf, r->r_addend, sym); - const char* tosym_name = sym_name(elf, tosym); - const char* from_pretty_name; - const char* from_pretty_name_p; - const char* to_pretty_name; - const char* to_pretty_name_p; - - get_pretty_name(is_function(fromsym), - &from_pretty_name, &from_pretty_name_p); - get_pretty_name(is_function(tosym), - &to_pretty_name, &to_pretty_name_p); - - warn("%s(%s+0x%lx): Section mismatch in reference from the %s %s%s to the %s %s:%s%s\n", - modname, fromsec, (long)r->r_offset, from_pretty_name, - fromsym_name, from_pretty_name_p, - to_pretty_name, tosec, tosym_name, to_pretty_name_p); - - if (!match(tosec, mismatch->bad_tosec) && - is_executable_section(elf, get_secindex(elf, sym))) - fprintf(stderr, - "The relocation at %s+0x%lx references\n" - "section \"%s\" which is not in the list of\n" - "authorized sections. If you're adding a new section\n" - "and/or if this reference is valid, add \"%s\" to the\n" - "list of authorized sections to jump to on fault.\n" - "This can be achieved by adding \"%s\" to \n" - "OTHER_TEXT_SECTIONS in scripts/mod/modpost.c.\n", - fromsec, (long)r->r_offset, tosec, tosec, tosec); -} - -static void extable_mismatch_handler(const char* modname, struct elf_info *elf, - const struct sectioncheck* const mismatch, - Elf_Rela* r, Elf_Sym* sym, - const char *fromsec) -{ - const char* tosec = sec_name(elf, get_secindex(elf, sym)); + if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL && + ELF_ST_BIND(sym->st_info) != STB_WEAK) { + error("%s: local symbol '%s' was exported\n", mod->name, + label_name + strlen(prefix)); + return; + } - sec_mismatch_count++; + name = sym_name(elf, sym); + if (strcmp(label_name + strlen(prefix), name)) { + error("%s: .export_symbol section references '%s', but it does not seem to be an export symbol\n", + mod->name, name); + return; + } - report_extable_warnings(modname, elf, mismatch, r, sym, fromsec, tosec); - - if (match(tosec, mismatch->bad_tosec)) - fatal("The relocation at %s+0x%lx references\n" - "section \"%s\" which is black-listed.\n" - "Something is seriously wrong and should be fixed.\n" - "You might get more information about where this is\n" - "coming from by using scripts/check_extable.sh %s\n", - fromsec, (long)r->r_offset, tosec, modname); - else if (!is_executable_section(elf, get_secindex(elf, sym))) { - if (is_extable_fault_address(r)) - fatal("The relocation at %s+0x%lx references\n" - "section \"%s\" which is not executable, IOW\n" - "it is not possible for the kernel to fault\n" - "at that address. Something is seriously wrong\n" - "and should be fixed.\n", - fromsec, (long)r->r_offset, tosec); - else - fatal("The relocation at %s+0x%lx references\n" - "section \"%s\" which is not executable, IOW\n" - "the kernel will fault if it ever tries to\n" - "jump to it. Something is seriously wrong\n" - "and should be fixed.\n", - fromsec, (long)r->r_offset, tosec); + data = sym_get_data(elf, label); /* license */ + if (!strcmp(data, "GPL")) { + is_gpl = true; + } else if (!strcmp(data, "")) { + is_gpl = false; + } else { + error("%s: unknown license '%s' was specified for '%s'\n", + mod->name, data, name); + return; } + + data += strlen(data) + 1; /* namespace */ + s = sym_add_exported(name, mod, is_gpl, data); + + /* + * We need to be aware whether we are exporting a function or + * a data on some architectures. + */ + s->is_func = (ELF_ST_TYPE(sym->st_info) == STT_FUNC); + + if (match(secname, PATTERNS(INIT_SECTIONS))) + warn("%s: %s: EXPORT_SYMBOL used for init symbol. Remove __init or EXPORT_SYMBOL.\n", + mod->name, name); + else if (match(secname, PATTERNS(EXIT_SECTIONS))) + warn("%s: %s: EXPORT_SYMBOL used for exit symbol. Remove __exit or EXPORT_SYMBOL.\n", + mod->name, name); } -static void check_section_mismatch(const char *modname, struct elf_info *elf, - Elf_Rela *r, Elf_Sym *sym, const char *fromsec) +static void check_section_mismatch(struct module *mod, struct elf_info *elf, + Elf_Sym *sym, + unsigned int fsecndx, const char *fromsec, + Elf_Addr faddr, Elf_Addr taddr) { const char *tosec = sec_name(elf, get_secindex(elf, sym)); - const struct sectioncheck *mismatch = section_mismatch(fromsec, tosec); + const struct sectioncheck *mismatch; - if (mismatch) { - if (mismatch->handler) - mismatch->handler(modname, elf, mismatch, - r, sym, fromsec); - else - default_mismatch_handler(modname, elf, mismatch, - r, sym, fromsec); + if (elf->export_symbol_secndx == fsecndx) { + check_export_symbol(mod, elf, faddr, tosec, sym); + return; } -} -static unsigned int *reloc_location(struct elf_info *elf, - Elf_Shdr *sechdr, Elf_Rela *r) -{ - return sym_get_data_by_offset(elf, sechdr->sh_info, r->r_offset); + mismatch = section_mismatch(fromsec, tosec); + if (!mismatch) + return; + + default_mismatch_handler(mod->name, elf, mismatch, sym, + fsecndx, fromsec, faddr, + tosec, taddr); } -static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) +static int addend_386_rel(uint32_t *location, Elf_Rela *r) { unsigned int r_typ = ELF_R_TYPE(r->r_info); - unsigned int *location = reloc_location(elf, sechdr, r); switch (r_typ) { case R_386_32: @@ -1436,6 +1267,8 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) case R_386_PC32: r->r_addend = TO_NATIVE(*location) + 4; break; + default: + r->r_addend = (Elf_Addr)(-1); } return 0; } @@ -1453,45 +1286,131 @@ static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) #ifndef R_ARM_THM_JUMP24 #define R_ARM_THM_JUMP24 30 #endif + +#ifndef R_ARM_MOVW_ABS_NC +#define R_ARM_MOVW_ABS_NC 43 +#endif + +#ifndef R_ARM_MOVT_ABS +#define R_ARM_MOVT_ABS 44 +#endif + +#ifndef R_ARM_THM_MOVW_ABS_NC +#define R_ARM_THM_MOVW_ABS_NC 47 +#endif + +#ifndef R_ARM_THM_MOVT_ABS +#define R_ARM_THM_MOVT_ABS 48 +#endif + #ifndef R_ARM_THM_JUMP19 #define R_ARM_THM_JUMP19 51 #endif -static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) +static int32_t sign_extend32(int32_t value, int index) +{ + uint8_t shift = 31 - index; + + return (int32_t)(value << shift) >> shift; +} + +static int addend_arm_rel(void *loc, Elf_Sym *sym, Elf_Rela *r) { unsigned int r_typ = ELF_R_TYPE(r->r_info); + uint32_t inst, upper, lower, sign, j1, j2; + int32_t offset; switch (r_typ) { case R_ARM_ABS32: - /* From ARM ABI: (S + A) | T */ - r->r_addend = (int)(long) - (elf->symtab_start + ELF_R_SYM(r->r_info)); + case R_ARM_REL32: + inst = TO_NATIVE(*(uint32_t *)loc); + r->r_addend = inst + sym->st_value; + break; + case R_ARM_MOVW_ABS_NC: + case R_ARM_MOVT_ABS: + inst = TO_NATIVE(*(uint32_t *)loc); + offset = sign_extend32(((inst & 0xf0000) >> 4) | (inst & 0xfff), + 15); + r->r_addend = offset + sym->st_value; break; case R_ARM_PC24: case R_ARM_CALL: case R_ARM_JUMP24: + inst = TO_NATIVE(*(uint32_t *)loc); + offset = sign_extend32((inst & 0x00ffffff) << 2, 25); + r->r_addend = offset + sym->st_value + 8; + break; + case R_ARM_THM_MOVW_ABS_NC: + case R_ARM_THM_MOVT_ABS: + upper = TO_NATIVE(*(uint16_t *)loc); + lower = TO_NATIVE(*((uint16_t *)loc + 1)); + offset = sign_extend32(((upper & 0x000f) << 12) | + ((upper & 0x0400) << 1) | + ((lower & 0x7000) >> 4) | + (lower & 0x00ff), + 15); + r->r_addend = offset + sym->st_value; + break; + case R_ARM_THM_JUMP19: + /* + * Encoding T3: + * S = upper[10] + * imm6 = upper[5:0] + * J1 = lower[13] + * J2 = lower[11] + * imm11 = lower[10:0] + * imm32 = SignExtend(S:J2:J1:imm6:imm11:'0') + */ + upper = TO_NATIVE(*(uint16_t *)loc); + lower = TO_NATIVE(*((uint16_t *)loc + 1)); + + sign = (upper >> 10) & 1; + j1 = (lower >> 13) & 1; + j2 = (lower >> 11) & 1; + offset = sign_extend32((sign << 20) | (j2 << 19) | (j1 << 18) | + ((upper & 0x03f) << 12) | + ((lower & 0x07ff) << 1), + 20); + r->r_addend = offset + sym->st_value + 4; + break; case R_ARM_THM_CALL: case R_ARM_THM_JUMP24: - case R_ARM_THM_JUMP19: - /* From ARM ABI: ((S + A) | T) - P */ - r->r_addend = (int)(long)(elf->hdr + - sechdr->sh_offset + - (r->r_offset - sechdr->sh_addr)); + /* + * Encoding T4: + * S = upper[10] + * imm10 = upper[9:0] + * J1 = lower[13] + * J2 = lower[11] + * imm11 = lower[10:0] + * I1 = NOT(J1 XOR S) + * I2 = NOT(J2 XOR S) + * imm32 = SignExtend(S:I1:I2:imm10:imm11:'0') + */ + upper = TO_NATIVE(*(uint16_t *)loc); + lower = TO_NATIVE(*((uint16_t *)loc + 1)); + + sign = (upper >> 10) & 1; + j1 = (lower >> 13) & 1; + j2 = (lower >> 11) & 1; + offset = sign_extend32((sign << 24) | + ((~(j1 ^ sign) & 1) << 23) | + ((~(j2 ^ sign) & 1) << 22) | + ((upper & 0x03ff) << 12) | + ((lower & 0x07ff) << 1), + 24); + r->r_addend = offset + sym->st_value + 4; break; default: - return 1; + r->r_addend = (Elf_Addr)(-1); } return 0; } -static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) +static int addend_mips_rel(uint32_t *location, Elf_Rela *r) { unsigned int r_typ = ELF_R_TYPE(r->r_info); - unsigned int *location = reloc_location(elf, sechdr, r); - unsigned int inst; + uint32_t inst; - if (r_typ == R_MIPS_HI16) - return 1; /* skip this */ inst = TO_NATIVE(*location); switch (r_typ) { case R_MIPS_LO16: @@ -1503,6 +1422,8 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) case R_MIPS_32: r->r_addend = inst; break; + default: + r->r_addend = (Elf_Addr)(-1); } return 0; } @@ -1523,19 +1444,17 @@ static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r) #define R_LARCH_SUB32 55 #endif -static void section_rela(const char *modname, struct elf_info *elf, +static void section_rela(struct module *mod, struct elf_info *elf, Elf_Shdr *sechdr) { - Elf_Sym *sym; Elf_Rela *rela; Elf_Rela r; unsigned int r_sym; - const char *fromsec; - + unsigned int fsecndx = sechdr->sh_info; + const char *fromsec = sec_name(elf, fsecndx); Elf_Rela *start = (void *)elf->hdr + sechdr->sh_offset; Elf_Rela *stop = (void *)start + sechdr->sh_size; - fromsec = sec_name(elf, sechdr->sh_info); /* if from section (name) is know good then skip it */ if (match(fromsec, section_white_list)) return; @@ -1570,34 +1489,31 @@ static void section_rela(const char *modname, struct elf_info *elf, continue; break; } - sym = elf->symtab_start + r_sym; - /* Skip special sections */ - if (is_shndx_special(sym->st_shndx)) - continue; - if (is_second_extable_reloc(start, rela, fromsec)) - find_extable_entry_size(fromsec, &r); - check_section_mismatch(modname, elf, &r, sym, fromsec); + + check_section_mismatch(mod, elf, elf->symtab_start + r_sym, + fsecndx, fromsec, r.r_offset, r.r_addend); } } -static void section_rel(const char *modname, struct elf_info *elf, +static void section_rel(struct module *mod, struct elf_info *elf, Elf_Shdr *sechdr) { - Elf_Sym *sym; Elf_Rel *rel; Elf_Rela r; unsigned int r_sym; - const char *fromsec; - + unsigned int fsecndx = sechdr->sh_info; + const char *fromsec = sec_name(elf, fsecndx); Elf_Rel *start = (void *)elf->hdr + sechdr->sh_offset; Elf_Rel *stop = (void *)start + sechdr->sh_size; - fromsec = sec_name(elf, sechdr->sh_info); /* if from section (name) is know good then skip it */ if (match(fromsec, section_white_list)) return; for (rel = start; rel < stop; rel++) { + Elf_Sym *tsym; + void *loc; + r.r_offset = TO_NATIVE(rel->r_offset); #if KERNEL_ELFCLASS == ELFCLASS64 if (elf->hdr->e_machine == EM_MIPS) { @@ -1615,27 +1531,26 @@ static void section_rel(const char *modname, struct elf_info *elf, r_sym = ELF_R_SYM(r.r_info); #endif r.r_addend = 0; + + loc = sym_get_data_by_offset(elf, fsecndx, r.r_offset); + tsym = elf->symtab_start + r_sym; + switch (elf->hdr->e_machine) { case EM_386: - if (addend_386_rel(elf, sechdr, &r)) - continue; + addend_386_rel(loc, &r); break; case EM_ARM: - if (addend_arm_rel(elf, sechdr, &r)) - continue; + addend_arm_rel(loc, tsym, &r); break; case EM_MIPS: - if (addend_mips_rel(elf, sechdr, &r)) - continue; + addend_mips_rel(loc, &r); break; + default: + fatal("Please add code to calculate addend for this architecture\n"); } - sym = elf->symtab_start + r_sym; - /* Skip special sections */ - if (is_shndx_special(sym->st_shndx)) - continue; - if (is_second_extable_reloc(start, rel, fromsec)) - find_extable_entry_size(fromsec, &r); - check_section_mismatch(modname, elf, &r, sym, fromsec); + + check_section_mismatch(mod, elf, tsym, + fsecndx, fromsec, r.r_offset, r.r_addend); } } @@ -1651,19 +1566,19 @@ static void section_rel(const char *modname, struct elf_info *elf, * to find all references to a section that reference a section that will * be discarded and warns about it. **/ -static void check_sec_ref(const char *modname, struct elf_info *elf) +static void check_sec_ref(struct module *mod, struct elf_info *elf) { int i; Elf_Shdr *sechdrs = elf->sechdrs; /* Walk through all sections */ for (i = 0; i < elf->num_sections; i++) { - check_section(modname, elf, &elf->sechdrs[i]); + check_section(mod->name, elf, &elf->sechdrs[i]); /* We want to process only relocation sections and not .init */ if (sechdrs[i].sh_type == SHT_RELA) - section_rela(modname, elf, &elf->sechdrs[i]); + section_rela(mod, elf, &elf->sechdrs[i]); else if (sechdrs[i].sh_type == SHT_REL) - section_rel(modname, elf, &elf->sechdrs[i]); + section_rel(mod, elf, &elf->sechdrs[i]); } } @@ -1818,6 +1733,8 @@ static void read_symbols(const char *modname) } } + if (extra_warn && !get_modinfo(&info, "description")) + warn("missing MODULE_DESCRIPTION() in %s\n", modname); for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { symname = remove_dot(info.strtab + sym->st_name); @@ -1825,16 +1742,7 @@ static void read_symbols(const char *modname) handle_moddevtable(mod, &info, sym, symname); } - for (sym = info.symtab_start; sym < info.symtab_stop; sym++) { - symname = remove_dot(info.strtab + sym->st_name); - - /* Apply symbol namespaces from __kstrtabns_<symbol> entries. */ - if (strstarts(symname, "__kstrtabns_")) - sym_update_namespace(symname + strlen("__kstrtabns_"), - sym_get_data(&info, sym)); - } - - check_sec_ref(modname, &info); + check_sec_ref(mod, &info); if (!mod->is_vmlinux) { version = get_modinfo(&info, "version"); @@ -1925,6 +1833,7 @@ static void check_exports(struct module *mod) continue; } + exp->used = true; s->module = exp->module; s->crc_valid = exp->crc_valid; s->crc = exp->crc; @@ -1935,8 +1844,7 @@ static void check_exports(struct module *mod) else basename = mod->name; - if (exp->namespace && - !contains_namespace(&mod->imported_namespaces, exp->namespace)) { + if (!contains_namespace(&mod->imported_namespaces, exp->namespace)) { modpost_log(allow_missing_ns_imports ? LOG_WARN : LOG_ERROR, "module %s uses symbol %s from namespace %s, but does not import it.\n", basename, exp->name, exp->namespace); @@ -1949,6 +1857,23 @@ static void check_exports(struct module *mod) } } +static void handle_white_list_exports(const char *white_list) +{ + char *buf, *p, *name; + + buf = read_text_file(white_list); + p = buf; + + while ((name = strsep(&p, "\n"))) { + struct symbol *sym = find_symbol(name); + + if (sym) + sym->used = true; + } + + free(buf); +} + static void check_modname_len(struct module *mod) { const char *mod_name; @@ -1979,6 +1904,11 @@ static void add_header(struct buffer *b, struct module *mod) buf_printf(b, "#include <linux/vermagic.h>\n"); buf_printf(b, "#include <linux/compiler.h>\n"); buf_printf(b, "\n"); + buf_printf(b, "#ifdef CONFIG_UNWINDER_ORC\n"); + buf_printf(b, "#include <asm/orc_header.h>\n"); + buf_printf(b, "ORC_HEADER;\n"); + buf_printf(b, "#endif\n"); + buf_printf(b, "\n"); buf_printf(b, "BUILD_SALT;\n"); buf_printf(b, "BUILD_LTO_INFO;\n"); buf_printf(b, "\n"); @@ -2017,12 +1947,26 @@ static void add_exported_symbols(struct buffer *buf, struct module *mod) { struct symbol *sym; + /* generate struct for exported symbols */ + buf_printf(buf, "\n"); + list_for_each_entry(sym, &mod->exported_symbols, list) { + if (trim_unused_exports && !sym->used) + continue; + + buf_printf(buf, "KSYMTAB_%s(%s, \"%s\", \"%s\");\n", + sym->is_func ? "FUNC" : "DATA", sym->name, + sym->is_gpl_only ? "_gpl" : "", sym->namespace); + } + if (!modversions) return; /* record CRCs for exported symbols */ buf_printf(buf, "\n"); list_for_each_entry(sym, &mod->exported_symbols, list) { + if (trim_unused_exports && !sym->used) + continue; + if (!sym->crc_valid) warn("EXPORT symbol \"%s\" [%s%s] version generation failed, symbol will not be versioned.\n" "Is \"%s\" prototyped in <asm/asm-prototypes.h>?\n", @@ -2186,9 +2130,6 @@ static void write_mod_c_file(struct module *mod) char fname[PATH_MAX]; int ret; - check_modname_len(mod); - check_exports(mod); - add_header(&buf, mod); add_exported_symbols(&buf, mod); add_versions(&buf, mod); @@ -2260,9 +2201,8 @@ static void read_dump(const char *fname) mod = new_module(modname, strlen(modname)); mod->from_dump = true; } - s = sym_add_exported(symname, mod, gpl_only); + s = sym_add_exported(symname, mod, gpl_only, namespace); sym_set_crc(s, crc); - sym_update_namespace(symname, namespace); } free(buf); return; @@ -2281,10 +2221,13 @@ static void write_dump(const char *fname) if (mod->from_dump) continue; list_for_each_entry(sym, &mod->exported_symbols, list) { + if (trim_unused_exports && !sym->used) + continue; + buf_printf(&buf, "0x%08x\t%s\t%s\tEXPORT_SYMBOL%s\t%s\n", sym->crc, sym->name, mod->name, sym->is_gpl_only ? "_GPL" : "", - sym->namespace ?: ""); + sym->namespace); } } write_buf(&buf, fname); @@ -2323,12 +2266,13 @@ int main(int argc, char **argv) { struct module *mod; char *missing_namespace_deps = NULL; + char *unused_exports_white_list = NULL; char *dump_write = NULL, *files_source = NULL; int opt; LIST_HEAD(dump_lists); struct dump_list *dl, *dl2; - while ((opt = getopt(argc, argv, "ei:mnT:o:awENd:")) != -1) { + while ((opt = getopt(argc, argv, "ei:mnT:to:au:WwENd:")) != -1) { switch (opt) { case 'e': external_module = true; @@ -2353,6 +2297,15 @@ int main(int argc, char **argv) case 'T': files_source = optarg; break; + case 't': + trim_unused_exports = true; + break; + case 'u': + unused_exports_white_list = optarg; + break; + case 'W': + extra_warn = true; + break; case 'w': warn_unresolved = true; break; @@ -2383,6 +2336,17 @@ int main(int argc, char **argv) read_symbols_from_files(files_source); list_for_each_entry(mod, &modules, list) { + if (mod->from_dump || mod->is_vmlinux) + continue; + + check_modname_len(mod); + check_exports(mod); + } + + if (unused_exports_white_list) + handle_white_list_exports(unused_exports_white_list); + + list_for_each_entry(mod, &modules, list) { if (mod->from_dump) continue; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 1178f40a73f3..dfdb9484e325 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -137,6 +137,7 @@ struct elf_info { Elf_Shdr *sechdrs; Elf_Sym *symtab_start; Elf_Sym *symtab_stop; + unsigned int export_symbol_secndx; /* .export_symbol section */ char *strtab; char *modinfo; unsigned int modinfo_len; @@ -151,11 +152,6 @@ struct elf_info { Elf32_Word *symtab_shndx_stop; }; -static inline int is_shndx_special(unsigned int i) -{ - return i != SHN_XINDEX && i >= SHN_LORESERVE && i <= SHN_HIRESERVE; -} - /* Accessor for sym->st_shndx, hides ugliness of "64k sections" */ static inline unsigned int get_secindex(const struct elf_info *info, const Elf_Sym *sym) diff --git a/scripts/orc_hash.sh b/scripts/orc_hash.sh new file mode 100644 index 000000000000..466611aa0053 --- /dev/null +++ b/scripts/orc_hash.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (c) Meta Platforms, Inc. and affiliates. + +set -e + +printf '%s' '#define ORC_HASH ' + +awk ' +/^#define ORC_(REG|TYPE)_/ { print } +/^struct orc_entry {$/ { p=1 } +p { print } +/^}/ { p=0 }' | + sha1sum | + cut -d " " -f 1 | + sed 's/\([0-9a-f]\{2\}\)/0x\1,/g' diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 252faaa5561c..032774eb061e 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -62,18 +62,14 @@ install_linux_image () { ${MAKE} -f ${srctree}/Makefile INSTALL_DTBS_PATH="${pdir}/usr/lib/linux-image-${KERNELRELEASE}" dtbs_install fi - if is_enabled CONFIG_MODULES; then - ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install - rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build" - rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source" - if [ "${SRCARCH}" = um ] ; then - mkdir -p "${pdir}/usr/lib/uml/modules" - mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}" - fi - fi + ${MAKE} -f ${srctree}/Makefile INSTALL_MOD_PATH="${pdir}" modules_install + rm -f "${pdir}/lib/modules/${KERNELRELEASE}/build" + rm -f "${pdir}/lib/modules/${KERNELRELEASE}/source" # Install the kernel if [ "${ARCH}" = um ] ; then + mkdir -p "${pdir}/usr/lib/uml/modules" + mv "${pdir}/lib/modules/${KERNELRELEASE}" "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}" mkdir -p "${pdir}/usr/bin" "${pdir}/usr/share/doc/${pname}" cp System.map "${pdir}/usr/lib/uml/modules/${KERNELRELEASE}/System.map" cp ${KCONFIG_CONFIG} "${pdir}/usr/share/doc/${pname}/config" diff --git a/scripts/pahole-flags.sh b/scripts/pahole-flags.sh index 1f1f1d397c39..728d55190d97 100755 --- a/scripts/pahole-flags.sh +++ b/scripts/pahole-flags.sh @@ -23,5 +23,8 @@ if [ "${pahole_ver}" -ge "124" ]; then # see PAHOLE_HAS_LANG_EXCLUDE extra_paholeopt="${extra_paholeopt} --lang_exclude=rust" fi +if [ "${pahole_ver}" -ge "125" ]; then + extra_paholeopt="${extra_paholeopt} --skip_encoding_btf_inconsistent_proto --btf_gen_optimized" +fi echo ${extra_paholeopt} diff --git a/scripts/remove-stale-files b/scripts/remove-stale-files index 7f432900671a..f3659ea0335b 100755 --- a/scripts/remove-stale-files +++ b/scripts/remove-stale-files @@ -33,3 +33,7 @@ rm -f rust/target.json rm -f scripts/bin2c rm -f .scmversion + +rm -rf include/ksym + +find . -name '*.usyms' | xargs rm -f diff --git a/scripts/spelling.txt b/scripts/spelling.txt index f8bd6178d17b..fc7ba95e86a0 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -155,6 +155,7 @@ aquired||acquired aquisition||acquisition arbitary||arbitrary architechture||architecture +archtecture||architecture arguement||argument arguements||arguments arithmatic||arithmetic @@ -279,6 +280,7 @@ cant'||can't canot||cannot cann't||can't cannnot||cannot +capabiity||capability capabilites||capabilities capabilties||capabilities capabilty||capability @@ -426,6 +428,7 @@ cotrol||control cound||could couter||counter coutner||counter +creationg||creating cryptocraphic||cryptographic cummulative||cumulative cunter||counter @@ -492,6 +495,7 @@ destorys||destroys destroied||destroyed detabase||database deteced||detected +detecion||detection detectt||detect detroyed||destroyed develope||develop @@ -513,6 +517,7 @@ diferent||different differrence||difference diffrent||different differenciate||differentiate +diffreential||differential diffrentiate||differentiate difinition||definition digial||digital @@ -617,6 +622,7 @@ evalute||evaluate evalutes||evaluates evalution||evaluation excecutable||executable +excceed||exceed exceded||exceeded exceds||exceeds exceeed||exceed @@ -632,6 +638,7 @@ existant||existent exixt||exist exsits||exists exlcude||exclude +exlcuding||excluding exlcusive||exclusive exlusive||exclusive exmaple||example @@ -726,6 +733,8 @@ generiously||generously genereate||generate genereted||generated genric||generic +gerenal||general +geting||getting globel||global grabing||grabbing grahical||graphical @@ -899,6 +908,7 @@ iteraions||iterations iternations||iterations itertation||iteration itslef||itself +ivalid||invalid jave||java jeffies||jiffies jumpimng||jumping @@ -977,6 +987,7 @@ microprocesspr||microprocessor migrateable||migratable millenium||millennium milliseonds||milliseconds +minimim||minimum minium||minimum minimam||minimum minimun||minimum @@ -1042,6 +1053,7 @@ notifed||notified notity||notify nubmer||number numebr||number +numer||number numner||number nunber||number obtaion||obtain @@ -1061,6 +1073,7 @@ offet||offset offlaod||offload offloded||offloaded offseting||offsetting +oflload||offload omited||omitted omiting||omitting omitt||omit @@ -1105,6 +1118,7 @@ pakage||package paket||packet pallette||palette paln||plan +palne||plane paramameters||parameters paramaters||parameters paramater||parameter @@ -1181,12 +1195,14 @@ previsously||previously primative||primitive princliple||principle priorty||priority +priting||printing privilaged||privileged privilage||privilege priviledge||privilege priviledges||privileges privleges||privileges probaly||probably +probabalistic||probabilistic procceed||proceed proccesors||processors procesed||processed @@ -1460,6 +1476,7 @@ submited||submitted submition||submission succeded||succeeded suceed||succeed +succesfuly||successfully succesfully||successfully succesful||successful successed||succeeded @@ -1503,6 +1520,7 @@ symetric||symmetric synax||syntax synchonized||synchronized sychronization||synchronization +sychronously||synchronously synchronuously||synchronously syncronize||synchronize syncronized||synchronized @@ -1532,6 +1550,7 @@ threee||three threshhold||threshold thresold||threshold throught||through +tansition||transition trackling||tracking troughput||throughput trys||tries @@ -1611,6 +1630,7 @@ unneccessary||unnecessary unnecesary||unnecessary unneedingly||unnecessarily unnsupported||unsupported +unuspported||unsupported unmached||unmatched unprecise||imprecise unpriviledged||unprivileged @@ -1657,6 +1677,7 @@ verfication||verification veriosn||version verisons||versions verison||version +veritical||vertical verson||version vicefersa||vice-versa virtal||virtual @@ -1677,6 +1698,7 @@ whenver||whenever wheter||whether whe||when wierd||weird +wihout||without wiil||will wirte||write withing||within diff --git a/scripts/tags.sh b/scripts/tags.sh index ea31640b2671..a70d43723146 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -32,6 +32,13 @@ else tree=${srctree}/ fi +# gtags(1) refuses to index any file outside of its current working dir. +# If gtags indexing is requested and the build output directory is not +# the kernel source tree, index all files in absolute-path form. +if [[ "$1" == "gtags" && -n "${tree}" ]]; then + tree=$(realpath "$tree")/ +fi + # Detect if ALLSOURCE_ARCHS is set. If not, we assume SRCARCH if [ "${ALLSOURCE_ARCHS}" = "" ]; then ALLSOURCE_ARCHS=${SRCARCH} @@ -98,7 +105,7 @@ all_compiled_sources() { echo include/generated/autoconf.h find $ignore -name "*.cmd" -exec \ - sed -n -E 's/^source_.* (.*)/\1/p; s/^ (\S.*) \\/\1/p' {} \+ | + grep -Poh '(?<=^ )\S+|(?<== )\S+[^\\](?=$)' {} \+ | awk '!a[$0]++' } | xargs realpath -esq $([ -z "$KBUILD_ABS_SRCTREE" ] && echo --relative-to=.) | sort -u @@ -131,7 +138,7 @@ docscope() dogtags() { - all_target_sources | gtags -i -f - + all_target_sources | gtags -i -C "${tree:-.}" -f - "$PWD" } # Basic regular expressions with an optional /kind-spec/ for ctags and |