diff options
Diffstat (limited to 'scripts')
29 files changed, 756 insertions, 92 deletions
diff --git a/scripts/Kconfig.toolchain b/scripts/Kconfig.toolchain index 2acbd40a38f1..1d68075f0469 100644 --- a/scripts/Kconfig.toolchain +++ b/scripts/Kconfig.toolchain @@ -233,6 +233,9 @@ config CC_OPT_WNO_FORMAT_OVERFLOW config CC_OPT_WNO_STRINGOP_TRUNCATION def_string "$(cc-option-str,-Wno-stringop-truncation)" +config CC_OPT_WNO_CONSTANT_LOGICAL_OPERAND + def_string "$(cc-option-str,-Wno-constant-logical-operand)" + config CC_HAS_COUNTED_BY bool # clang needs to be at least 20.1.0 to avoid potential crashes diff --git a/scripts/Makefile.autofdo b/scripts/Makefile.autofdo index 57a3aba6ffc2..32c18df237f1 100644 --- a/scripts/Makefile.autofdo +++ b/scripts/Makefile.autofdo @@ -13,7 +13,7 @@ endif ifdef CLANG_AUTOFDO_PROFILE CFLAGS_AUTOFDO_CLANG += -fprofile-sample-use=$(CLANG_AUTOFDO_PROFILE) -ffunction-sections CFLAGS_AUTOFDO_CLANG += -fsplit-machine-functions - RUSTFLAGS_AUTOFDO_CLANG += -Zprofile-sample-use=$(CLANG_AUTOFDO_PROFILE) -Zfunction-sections=y + RUSTFLAGS_AUTOFDO_CLANG += $(if $(call rustc-min-version,110000),-Cprofile-sample-use,-Zprofile-sample-use)=$(CLANG_AUTOFDO_PROFILE) -Zfunction-sections=y RUSTFLAGS_AUTOFDO_CLANG += -Cllvm-args=-split-machine-functions endif diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 33d7f92b2491..9bb4dace669b 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -589,7 +589,10 @@ endif # Single targets # --------------------------------------------------------------------------- -single-subdirs := $(foreach d, $(subdir-ym), $(if $(filter $d/%, $(MAKECMDGOALS)), $d)) +# A single target may match nested entries in subdir-ym. Descend through only +# the deepest match so that two recursive makes do not build the same target. +single-subdir = $(lastword $(sort $(foreach d, $(subdir-ym), $(if $(filter $d/%, $(1)), $d)))) +single-subdirs := $(sort $(foreach g, $(MAKECMDGOALS), $(call single-subdir, $g))) single-subdir-goals := $(filter $(addsuffix /%, $(single-subdirs)), $(MAKECMDGOALS)) $(single-subdir-goals): $(single-subdirs) @@ -603,7 +606,8 @@ $(subdir-ym): $(Q)$(MAKE) $(build)=$@ \ need-builtin=$(if $(filter $@/built-in.a, $(subdir-builtin)),1) \ need-modorder=$(if $(filter $@/modules.order, $(subdir-modorder)),1) \ - $(filter $@/%, $(single-subdir-goals)) + $(filter-out $(addsuffix /%, $(filter $@/%, $(single-subdirs))), \ + $(filter $@/%, $(single-subdir-goals))) # Add FORCE to the prerequisites of a target to force it to be always rebuilt. # --------------------------------------------------------------------------- diff --git a/scripts/Makefile.kcsan b/scripts/Makefile.kcsan index 19f693b68a96..01af6fd71006 100644 --- a/scripts/Makefile.kcsan +++ b/scripts/Makefile.kcsan @@ -24,3 +24,16 @@ kcsan-cflags += $(call cc-option,$(call cc-param,tsan-instrument-func-entry-exit endif export CFLAGS_KCSAN := $(kcsan-cflags) + +ifdef CONFIG_HAVE_KCSAN_RUSTC +# The minimum supported rustc's LLVM supports all of these options. +rustc-param = -Cllvm-args=-$(1) +kcsan-rustflags := -Zsanitizer=thread \ + $(call rustc-param,tsan-compound-read-before-write=1) \ + $(call rustc-param,tsan-distinguish-volatile=1) +ifndef CONFIG_KCSAN_WEAK_MEMORY +kcsan-rustflags += $(call rustc-param,tsan-instrument-func-entry-exit=0) +endif +endif + +export RUSTFLAGS_KCSAN := $(kcsan-rustflags) diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 19e96b30a122..1749d16c3363 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -98,6 +98,9 @@ ifeq ($(CONFIG_KCSAN),y) _c_flags += $(if $(patsubst n%,, \ $(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)$(is-kernel-object)), \ $(CFLAGS_KCSAN)) +_rust_flags += $(if $(patsubst n%,, \ + $(KCSAN_SANITIZE_$(target-stem).o)$(KCSAN_SANITIZE)$(is-kernel-object)), \ + $(RUSTFLAGS_KCSAN)) # Some uninstrumented files provide implied barriers required to avoid false # positives: set KCSAN_INSTRUMENT_BARRIERS for barrier instrumentation only. _c_flags += $(if $(patsubst n%,, \ @@ -493,9 +496,9 @@ quiet_cmd_zstd22_with_size = ZSTD22 $@ # the .ascii directive whereas GCC keeps the <space> as-is. define sed-offsets 's:^[[:space:]]*\.ascii[[:space:]]*"\(.*\)".*:\1:; \ - /^->/{s:->#\(.*\):/* \1 */:; \ - s:^->\([^ ]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ - s:->::; p;}' + /^->/{s:->#\(.*\):/* \1 */:p; \ + s:^->\([[:alnum:]_]*\) [\$$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:p; \ + s:^->BLANK()::p;}' endef # Use filechk to avoid rebuilds when a header changes, but the resulting file diff --git a/scripts/Makefile.warn b/scripts/Makefile.warn index 556fa249ca07..03b677bdbb0a 100644 --- a/scripts/Makefile.warn +++ b/scripts/Makefile.warn @@ -167,6 +167,7 @@ endif ifdef CONFIG_CC_IS_GCC KBUILD_CFLAGS += -Wno-maybe-uninitialized +KBUILD_CFLAGS += $(CONFIG_CC_OPT_WNO_CONSTANT_LOGICAL_OPERAND) endif endif diff --git a/scripts/coccinelle/api/devm_kmalloc_objs.cocci b/scripts/coccinelle/api/devm_kmalloc_objs.cocci new file mode 100644 index 000000000000..322f79a2d965 --- /dev/null +++ b/scripts/coccinelle/api/devm_kmalloc_objs.cocci @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use devm_kmalloc_obj family of macros for allocations +/// +// Confidence: High +// Options: --include-headers-for-types --all-includes --include-headers --keep-comments + +virtual patch + +@initialize:python@ +@@ +import sys + +def alloc_array(name): + func = "FAILED_RENAME" + if name == "devm_kmalloc_array": + func = "devm_kmalloc_objs" + elif name == "devm_kvmalloc_array": + func = "devm_kvmalloc_objs" + elif name == "devm_kcalloc": + func = "devm_kzalloc_objs" + elif name == "devm_kvcalloc": + func = "devm_kvzalloc_objs" + else: + print(f"Unknown transform for {name}", file=sys.stderr) + return func + +// This excludes anything that is assigning to or from integral types or +// string literals. Everything else gets the sizeof() extracted for the +// kmalloc_obj() type/var argument. sizeof(void *) is also excluded because +// it will need case-by-case double-checking to make sure the right type is +// being assigned. +@direct depends on patch && !(file in "tools") && !(file in "samples")@ +typedef u8, u16, u32, u64; +typedef __u8, __u16, __u32, __u64; +typedef uint8_t, uint16_t, uint32_t, uint64_t; +typedef uchar, ushort, uint, ulong; +typedef __le16, __le32, __le64; +typedef __be16, __be32, __be64; +typedef wchar_t; +type INTEGRAL = {u8,__u8,uint8_t,char,unsigned char,uchar,wchar_t, + u16,__u16,uint16_t,unsigned short,ushort, + u32,__u32,uint32_t,unsigned int,uint, + u64,__u64,uint64_t,unsigned long,ulong, + __le16,__le32,__le64,__be16,__be32,__be64}; +char [] STRING; +INTEGRAL *BYTES; +INTEGRAL **BYTES_PTRS; +type TYPE; +expression VAR; +expression GFP; +expression COUNT; +expression FLEX; +expression E; +expression DEV; +identifier ALLOC =~ "^devm_kv?[mz]alloc$"; +fresh identifier ALLOC_OBJ = ALLOC ## "_obj"; +fresh identifier ALLOC_FLEX = ALLOC ## "_flex"; +identifier ALLOC_ARRAY = {devm_kmalloc_array,devm_kvmalloc_array,devm_kcalloc,devm_kvcalloc}; +fresh identifier ALLOC_OBJS = script:python(ALLOC_ARRAY) { alloc_array(ALLOC_ARRAY) }; +@@ + +( +- VAR = ALLOC(DEV,(sizeof(*VAR)), GFP) ++ VAR = ALLOC_OBJ(DEV,*VAR, GFP) +| + ALLOC(DEV,(\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP) +| + BYTES = ALLOC(DEV,(sizeof(E)), GFP) +| + BYTES = ALLOC(DEV,(sizeof(TYPE)), GFP) +| + BYTES_PTRS = ALLOC(DEV,(sizeof(E)), GFP) +| + BYTES_PTRS = ALLOC(DEV,(sizeof(TYPE)), GFP) +| + ALLOC(DEV,(sizeof(void *)), GFP) +| +- ALLOC(DEV,(sizeof(E)), GFP) ++ ALLOC_OBJ(DEV, E, GFP) +| +- ALLOC(DEV,(sizeof(TYPE)), GFP) ++ ALLOC_OBJ(DEV,TYPE, GFP) +| + ALLOC_ARRAY(DEV,COUNT, (\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), GFP) +| + BYTES = ALLOC_ARRAY(DEV, COUNT, (sizeof(E)), GFP) +| + BYTES = ALLOC_ARRAY(DEV,COUNT, (sizeof(TYPE)), GFP) +| + BYTES_PTRS = ALLOC_ARRAY(DEV, COUNT, (sizeof(E)), GFP) +| + BYTES_PTRS = ALLOC_ARRAY(DEV, COUNT, (sizeof(TYPE)), GFP) +| + ALLOC_ARRAY(DEV, (\(sizeof(STRING)\|sizeof(INTEGRAL)\|sizeof(INTEGRAL *)\)), COUNT, GFP) +| + BYTES = ALLOC_ARRAY(DEV, (sizeof(E)), COUNT, GFP) +| + BYTES = ALLOC_ARRAY(DEV, (sizeof(TYPE)), COUNT, GFP) +| + BYTES_PTRS = ALLOC_ARRAY(DEV, (sizeof(E)), COUNT, GFP) +| + BYTES_PTRS = ALLOC_ARRAY(DEV, (sizeof(TYPE)), COUNT, GFP) +| + ALLOC_ARRAY(DEV, COUNT, (sizeof(void *)), GFP) +| + ALLOC_ARRAY(DEV, (sizeof(void *)), COUNT, GFP) +| +- ALLOC_ARRAY(DEV, COUNT, (sizeof(E)), GFP) ++ ALLOC_OBJS(DEV, E, COUNT, GFP) +| +- ALLOC_ARRAY(DEV, COUNT, (sizeof(TYPE)), GFP) ++ ALLOC_OBJS(DEV, TYPE, COUNT, GFP) +| +- ALLOC_ARRAY(DEV, (sizeof(E)), COUNT, GFP) ++ ALLOC_OBJS(DEV, E, COUNT, GFP) +| +- ALLOC_ARRAY(DEV, (sizeof(TYPE)), COUNT, GFP) ++ ALLOC_OBJS(DEV, TYPE, COUNT, GFP) +| +- ALLOC(DEV, struct_size(VAR, FLEX, COUNT), GFP) ++ ALLOC_FLEX(DEV, *VAR, FLEX, COUNT, GFP) +| +- ALLOC(DEV, struct_size_t(TYPE, FLEX, COUNT), GFP) ++ ALLOC_FLEX(DEV, TYPE, FLEX, COUNT, GFP) +) + +@drop_gfp_kernel depends on patch && !(file in "tools") && !(file in "samples")@ +identifier ALLOC = {devm_kmalloc_obj,devm_kmalloc_objs,devm_kmalloc_flex, + devm_kzalloc_obj,devm_kzalloc_objs,devm_kzalloc_flex, + devm_kvmalloc_obj,devm_kvmalloc_objs,devm_kvmalloc_flex, + devm_kvzalloc_obj,devm_kvzalloc_objs,devm_kvzalloc_flex}; +@@ + + ALLOC(... +- , GFP_KERNEL + ) diff --git a/scripts/coccinelle/api/kmalloc_objs.cocci b/scripts/coccinelle/api/kmalloc_objs.cocci index 0a98ddf03eca..e47604f7a1a6 100644 --- a/scripts/coccinelle/api/kmalloc_objs.cocci +++ b/scripts/coccinelle/api/kmalloc_objs.cocci @@ -20,6 +20,10 @@ def alloc_array(name): func = "kzalloc_objs" elif name == "kvcalloc": func = "kvzalloc_objs" + elif name == "devm_kmalloc_array": + func = "devm_kmalloc_objs" + elif name == "devm_kcalloc": + func = "devm_kzalloc_objs" else: print(f"Unknown transform for {name}", file=sys.stderr) return func @@ -42,6 +46,15 @@ def alloc_array(name): // Everything else gets the sizeof() extracted for the kmalloc_obj() // type/var argument. // +// The device-managed allocators differ from the plain ones only by taking +// the managing "struct device *" as a leading argument, so rather than +// repeating every pattern for them, the leading arguments are captured in +// an "expression list" metavariable and replayed on the replacement side. +// ARGS is empty for the plain allocators, in which case Coccinelle drops +// the separating comma as well. Note that there is no devm_kvmalloc +// family, and that the devm array helpers only exist as +// (dev, count, size, gfp). +// // The first matching alternative below wins, so the exclusions must come // before the more general conversions. @direct depends on patch && !(file in "tools") && !(file in "samples")@ @@ -81,150 +94,155 @@ expression GFP; expression COUNT; expression FLEX; expression E; -identifier ALLOC =~ "^kv?[mz]alloc$"; +expression list ARGS; +identifier ALLOC = {kmalloc,kzalloc,kvmalloc,kvzalloc, + devm_kmalloc,devm_kzalloc}; fresh identifier ALLOC_OBJ = ALLOC ## "_obj"; fresh identifier ALLOC_FLEX = ALLOC ## "_flex"; -identifier ALLOC_ARRAY = {kmalloc_array,kvmalloc_array,kcalloc,kvcalloc}; +identifier ALLOC_ARRAY = {kmalloc_array,kvmalloc_array,kcalloc,kvcalloc, + devm_kmalloc_array,devm_kcalloc}; fresh identifier ALLOC_OBJS = script:python(ALLOC_ARRAY) { alloc_array(ALLOC_ARRAY) }; @@ ( // Convert a single object sized by its target: p = kmalloc(sizeof(*p), gfp) -- VAR = ALLOC((sizeof(*VAR)), GFP) -+ VAR = ALLOC_OBJ(*VAR, GFP) +- VAR = ALLOC(ARGS, (sizeof(*VAR)), GFP) ++ VAR = ALLOC_OBJ(ARGS, *VAR, GFP) | // Exclude byte buffers and integral pointers: kmalloc(sizeof(u8), gfp), // kmalloc(sizeof("str"), gfp), kmalloc(sizeof(char *), gfp) - ALLOC((\(sizeof(STRING)\|sizeof(BYTE_TYPES)\| + ALLOC(ARGS, (\(sizeof(STRING)\|sizeof(BYTE_TYPES)\| sizeof(BYTE_TYPES *)\|sizeof(MULTIBYTE_TYPES *)\)), GFP) | // Exclude anything assigned to a byte pointer: // u8 *buf = kmalloc(sizeof(*hdr), gfp) - BYTES = ALLOC((\(sizeof(E)\|sizeof(TYPE)\)), GFP) + BYTES = ALLOC(ARGS, (\(sizeof(E)\|sizeof(TYPE)\)), GFP) | // Convert a multi-byte type to a pointer to it: // u32 *p = kmalloc(sizeof(u32), gfp) \(MULTIBYTES\|CONST_MULTIBYTES\) = -- ALLOC((sizeof(MULTIBYTE_TYPES)), GFP) -+ ALLOC_OBJ(MULTIBYTE_TYPES, GFP) +- ALLOC(ARGS, (sizeof(MULTIBYTE_TYPES)), GFP) ++ ALLOC_OBJ(ARGS, MULTIBYTE_TYPES, GFP) | // Same by expression: u32 *p = kmalloc(sizeof(p[0]), gfp) \(MULTIBYTES\|CONST_MULTIBYTES\) = -- ALLOC((sizeof(MULTIBYTE)), GFP) -+ ALLOC_OBJ(MULTIBYTE, GFP) +- ALLOC(ARGS, (sizeof(MULTIBYTE)), GFP) ++ ALLOC_OBJ(ARGS, MULTIBYTE, GFP) | // Exclude other multi-byte sizes, e.g. to pointers to arrays: s16 (*p)[2] = ... - ALLOC((\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), GFP) + ALLOC(ARGS, (\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), GFP) | // Exclude anything else assigned to a multi-byte pointer: // u32 *p = kmalloc(sizeof(*hdr), gfp) - \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC((\(sizeof(E)\|sizeof(TYPE)\)), GFP) + \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC(ARGS, (\(sizeof(E)\|sizeof(TYPE)\)), GFP) | // Exclude void pointers, to be checked by hand: kmalloc(sizeof(void *), gfp) - ALLOC((sizeof(void *)), GFP) + ALLOC(ARGS, (sizeof(void *)), GFP) | // Convert any other expression: p = kmalloc(sizeof(s->item), gfp) -- ALLOC((sizeof(E)), GFP) -+ ALLOC_OBJ(E, GFP) +- ALLOC(ARGS, (sizeof(E)), GFP) ++ ALLOC_OBJ(ARGS, E, GFP) | // Convert any other type: p = kmalloc(sizeof(struct item), gfp) -- ALLOC((sizeof(TYPE)), GFP) -+ ALLOC_OBJ(TYPE, GFP) +- ALLOC(ARGS, (sizeof(TYPE)), GFP) ++ ALLOC_OBJ(ARGS, TYPE, GFP) | // The same, for arrays allocated as (count, size): // Exclude byte buffers and integral pointers: kcalloc(n, sizeof(u8), gfp), // kcalloc(n, sizeof(char *), gfp) - ALLOC_ARRAY(COUNT, (\(sizeof(STRING)\|sizeof(BYTE_TYPES)\| + ALLOC_ARRAY(ARGS, COUNT, (\(sizeof(STRING)\|sizeof(BYTE_TYPES)\| sizeof(BYTE_TYPES *)\|sizeof(MULTIBYTE_TYPES *)\)), GFP) | // Exclude arrays assigned to a byte pointer: // u8 *buf = kcalloc(n, sizeof(*hdr), gfp) - BYTES = ALLOC_ARRAY(COUNT, (\(sizeof(E)\|sizeof(TYPE)\)), GFP) + BYTES = ALLOC_ARRAY(ARGS, COUNT, (\(sizeof(E)\|sizeof(TYPE)\)), GFP) | // Convert a multi-byte array to a pointer to it: // u32 *p = kcalloc(n, sizeof(u32), gfp) \(MULTIBYTES\|CONST_MULTIBYTES\) = -- ALLOC_ARRAY(COUNT, (sizeof(MULTIBYTE_TYPES)), GFP) -+ ALLOC_OBJS(MULTIBYTE_TYPES, COUNT, GFP) +- ALLOC_ARRAY(ARGS, COUNT, (sizeof(MULTIBYTE_TYPES)), GFP) ++ ALLOC_OBJS(ARGS, MULTIBYTE_TYPES, COUNT, GFP) | // Same by expression: u32 *p = kcalloc(n, sizeof(*p), gfp) \(MULTIBYTES\|CONST_MULTIBYTES\) = -- ALLOC_ARRAY(COUNT, (sizeof(MULTIBYTE)), GFP) -+ ALLOC_OBJS(MULTIBYTE, COUNT, GFP) +- ALLOC_ARRAY(ARGS, COUNT, (sizeof(MULTIBYTE)), GFP) ++ ALLOC_OBJS(ARGS, MULTIBYTE, COUNT, GFP) | // Exclude other multi-byte arrays: // s16 (*pairs)[2] = kcalloc(n, sizeof(s16), gfp) - ALLOC_ARRAY(COUNT, (\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), GFP) + ALLOC_ARRAY(ARGS, COUNT, (\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), GFP) | // Exclude other arrays assigned to a multi-byte pointer: // u32 *p = kcalloc(n, sizeof(*hdr), gfp) - \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC_ARRAY(COUNT, (\(sizeof(E)\|sizeof(TYPE)\)), GFP) + \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC_ARRAY(ARGS, COUNT, (\(sizeof(E)\|sizeof(TYPE)\)), GFP) | // Exclude arrays of void pointers: kcalloc(n, sizeof(void *), gfp) - ALLOC_ARRAY(COUNT, (sizeof(void *)), GFP) + ALLOC_ARRAY(ARGS, COUNT, (sizeof(void *)), GFP) | // Convert any other expression: p = kcalloc(n, sizeof(*p), gfp) -- ALLOC_ARRAY(COUNT, (sizeof(E)), GFP) -+ ALLOC_OBJS(E, COUNT, GFP) +- ALLOC_ARRAY(ARGS, COUNT, (sizeof(E)), GFP) ++ ALLOC_OBJS(ARGS, E, COUNT, GFP) | // Convert any other type: p = kcalloc(n, sizeof(struct item), gfp) -- ALLOC_ARRAY(COUNT, (sizeof(TYPE)), GFP) -+ ALLOC_OBJS(TYPE, COUNT, GFP) +- ALLOC_ARRAY(ARGS, COUNT, (sizeof(TYPE)), GFP) ++ ALLOC_OBJS(ARGS, TYPE, COUNT, GFP) | // The same, for arrays allocated as (size, count): // Exclude byte buffers and integral pointers: kcalloc(sizeof(u8), n, gfp), // kcalloc(sizeof(char *), n, gfp) - ALLOC_ARRAY((\(sizeof(STRING)\|sizeof(BYTE_TYPES)\| + ALLOC_ARRAY(ARGS, (\(sizeof(STRING)\|sizeof(BYTE_TYPES)\| sizeof(BYTE_TYPES *)\|sizeof(MULTIBYTE_TYPES *)\)), COUNT, GFP) | // Exclude arrays assigned to a byte pointer: // u8 *buf = kcalloc(sizeof(*hdr), n, gfp) - BYTES = ALLOC_ARRAY((\(sizeof(E)\|sizeof(TYPE)\)), COUNT, GFP) + BYTES = ALLOC_ARRAY(ARGS, (\(sizeof(E)\|sizeof(TYPE)\)), COUNT, GFP) | // Convert a multi-byte array to a pointer to it: // u32 *p = kcalloc(sizeof(u32), n, gfp) \(MULTIBYTES\|CONST_MULTIBYTES\) = -- ALLOC_ARRAY((sizeof(MULTIBYTE_TYPES)), COUNT, GFP) -+ ALLOC_OBJS(MULTIBYTE_TYPES, COUNT, GFP) +- ALLOC_ARRAY(ARGS, (sizeof(MULTIBYTE_TYPES)), COUNT, GFP) ++ ALLOC_OBJS(ARGS, MULTIBYTE_TYPES, COUNT, GFP) | // Same by expression: u32 *p = kcalloc(sizeof(*p), n, gfp) \(MULTIBYTES\|CONST_MULTIBYTES\) = -- ALLOC_ARRAY((sizeof(MULTIBYTE)), COUNT, GFP) -+ ALLOC_OBJS(MULTIBYTE, COUNT, GFP) +- ALLOC_ARRAY(ARGS, (sizeof(MULTIBYTE)), COUNT, GFP) ++ ALLOC_OBJS(ARGS, MULTIBYTE, COUNT, GFP) | // Exclude other multi-byte arrays: // s16 (*pairs)[2] = kcalloc(sizeof(s16), n, gfp) - ALLOC_ARRAY((\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), COUNT, GFP) + ALLOC_ARRAY(ARGS, (\(sizeof(MULTIBYTE_TYPES)\|sizeof(MULTIBYTE)\)), COUNT, GFP) | // Exclude other arrays assigned to a multi-byte pointer: // u32 *p = kcalloc(sizeof(*hdr), n, gfp) - \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC_ARRAY((\(sizeof(E)\|sizeof(TYPE)\)), COUNT, GFP) + \(MULTIBYTES\|CONST_MULTIBYTES\) = ALLOC_ARRAY(ARGS, (\(sizeof(E)\|sizeof(TYPE)\)), COUNT, GFP) | // Exclude arrays of void pointers: kcalloc(sizeof(void *), n, gfp) - ALLOC_ARRAY((sizeof(void *)), COUNT, GFP) + ALLOC_ARRAY(ARGS, (sizeof(void *)), COUNT, GFP) | // Convert any other expression: p = kcalloc(sizeof(*p), n, gfp) -- ALLOC_ARRAY((sizeof(E)), COUNT, GFP) -+ ALLOC_OBJS(E, COUNT, GFP) +- ALLOC_ARRAY(ARGS, (sizeof(E)), COUNT, GFP) ++ ALLOC_OBJS(ARGS, E, COUNT, GFP) | // Convert any other type: p = kcalloc(sizeof(struct item), n, gfp) -- ALLOC_ARRAY((sizeof(TYPE)), COUNT, GFP) -+ ALLOC_OBJS(TYPE, COUNT, GFP) +- ALLOC_ARRAY(ARGS, (sizeof(TYPE)), COUNT, GFP) ++ ALLOC_OBJS(ARGS, TYPE, COUNT, GFP) | // Convert flexible array structures: p = kmalloc(struct_size(p, data, n), gfp) -- ALLOC(struct_size(VAR, FLEX, COUNT), GFP) -+ ALLOC_FLEX(*VAR, FLEX, COUNT, GFP) +- ALLOC(ARGS, struct_size(VAR, FLEX, COUNT), GFP) ++ ALLOC_FLEX(ARGS, *VAR, FLEX, COUNT, GFP) | // Same by type: kmalloc(struct_size_t(struct item, data, n), gfp) -- ALLOC(struct_size_t(TYPE, FLEX, COUNT), GFP) -+ ALLOC_FLEX(TYPE, FLEX, COUNT, GFP) +- ALLOC(ARGS, struct_size_t(TYPE, FLEX, COUNT), GFP) ++ ALLOC_FLEX(ARGS, TYPE, FLEX, COUNT, GFP) ) @drop_gfp_kernel depends on patch && !(file in "tools") && !(file in "samples")@ identifier ALLOC = {kmalloc_obj,kmalloc_objs,kmalloc_flex, kzalloc_obj,kzalloc_objs,kzalloc_flex, kvmalloc_obj,kvmalloc_objs,kvmalloc_flex, - kvzalloc_obj,kvzalloc_objs,kvzalloc_flex}; + kvzalloc_obj,kvzalloc_objs,kvzalloc_flex, + devm_kmalloc_obj,devm_kmalloc_objs,devm_kmalloc_flex, + devm_kzalloc_obj,devm_kzalloc_objs,devm_kzalloc_flex}; @@ ALLOC(... diff --git a/scripts/coccinelle/free/cleanup-free.cocci b/scripts/coccinelle/free/cleanup-free.cocci new file mode 100644 index 000000000000..2aba766b5bbb --- /dev/null +++ b/scripts/coccinelle/free/cleanup-free.cocci @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Find __cleanup(kfree) +/// Using __cleanup(kfree) will pass the stack address of the annotated +/// local variable to kfree, causing an invalid free. +/// I.e., `T v __cleanup(kfree);` --> `kfree(&v);` +/// Such usage is impossible to be correct. +/// +// Confidence: High +// Copyright: (C) 2026 Ella Ma +// Options: --no-includes --include-headers + +virtual report +virtual org + +// Suggesting using __free for the functions with a DEFINE_FREE definition. +// Update this list when new DEFINE_FREE definitions are added. +@free@ +attribute name __cleanup; +symbol kfree, kfree_sensitive, kvfree, kvfree_atomic, free_percpu; +type T; +identifier v, n; +position p; +@@ + +( + T v __cleanup@p( +( + n +& +( + kfree \| kfree_sensitive \| kvfree \| kvfree_atomic \| free_percpu +) +) + ); +| + T v __cleanup@p( +( + n +& +( + kfree \| kfree_sensitive \| kvfree \| kvfree_atomic \| free_percpu +) +) + ) = ...; +) + +@script:python depends on report@ +p << free.p; +n << free.n; +@@ + +msg = f"ERROR: __cleanup({n}) will cause an invalid free: the stack address of the annotated variable will be passed to {n}; declare the variable using __free({n}) to cause the pointee to be freed" +coccilib.report.print_report(p[0], msg) + +@script:python depends on org@ +p << free.p; +n << free.n; +@@ + +msg = f"ERROR: __cleanup({n}) will cause an invalid free: the stack address of the annotated variable will be passed to {n}; declare the variable using __free({n}) to cause the pointee to be freed" +coccilib.org.print_todo(p[0], msg) + + +// Reporting __cleanup usage for the functions without a DEFINE_FREE definition. +// The following list only contains frequently used functions. Supplement it if +// necessary. +@cleanup@ +attribute name __cleanup; +symbol vfree, vfree_atomic, kfree_const; +type T; +identifier v, n; +position p; +@@ + +( + T v __cleanup@p( +( + n +& +( + vfree \| vfree_atomic \| kfree_const +) +) + ); +| + T v __cleanup@p( +( + n +& +( + vfree \| vfree_atomic \| kfree_const +) +) + ) = ...; +) + +@script:python depends on report@ +p << cleanup.p; +n << cleanup.n; +@@ + +msg = f"ERROR: __cleanup({n}) will cause an invalid free: the stack address of the annotated variable will be passed to {n}" +coccilib.report.print_report(p[0], msg) + +@script:python depends on org@ +p << cleanup.p; +n << cleanup.n; +@@ + +msg = f"ERROR: __cleanup({n}) will cause an invalid free: the stack address of the annotated variable will be passed to {n}" +coccilib.org.print_todo(p[0], msg) diff --git a/scripts/coccinelle/misc/array_end.cocci b/scripts/coccinelle/misc/array_end.cocci new file mode 100644 index 000000000000..2f0bbc4ce17d --- /dev/null +++ b/scripts/coccinelle/misc/array_end.cocci @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// Use ARRAY_END instead of an expression derived from ARRAY_SIZE +// +// Confidence: High +// Copyright: 2026, Alejandro Colomar <alx@kernel.org> +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@depends on context disable zero_multiple_format@ +type T; +T[] a; +expression b; +@@ +( +* a + ARRAY_SIZE(a) +| +* &a[0] + ARRAY_SIZE(a) +| +* &a[ARRAY_SIZE(a)] +| +* &a[ARRAY_SIZE(a) - b] +) + +@depends on patch disable zero_multiple_format@ +type T; +T[] a; +expression b; +@@ +( +- (a + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[0] + ARRAY_SIZE(a)) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a)]) ++ ARRAY_END(a) +| +- (&a[ARRAY_SIZE(a) - b]) ++ ARRAY_END(a) - b +) + +@r depends on org || report disable zero_multiple_format@ +type T; +T[] a; +expression b; +position p; +@@ +( + a@p + ARRAY_SIZE(a) +| + &a[0]@p + ARRAY_SIZE(a) +| + &a[ARRAY_SIZE(a)]@p +| + &a[ARRAY_SIZE(a)@p - b] +) + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING should use ARRAY_END") + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING: opportunity for ARRAY_END") diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh index 39d60d477bf3..8b06810d463a 100755 --- a/scripts/decode_stacktrace.sh +++ b/scripts/decode_stacktrace.sh @@ -346,7 +346,7 @@ handle_line() { echo "${spaces[$last]}${symbol}${module:+ ${module}}${info_str:+ ${info_str}}" } -while read line; do +while IFS= read -r line || [[ -n $line ]]; do # Strip unexpected carriage return at end of line line=${line%$'\r'} diff --git a/scripts/generate_rust_target.rs b/scripts/generate_rust_target.rs index 7687b0dd5474..4b02bffa6b46 100644 --- a/scripts/generate_rust_target.rs +++ b/scripts/generate_rust_target.rs @@ -231,7 +231,7 @@ fn main() { } ts.push("features", features); ts.push("llvm-target", "x86_64-linux-gnu"); - ts.push("supported-sanitizers", ["kcfi", "kernel-address"]); + ts.push("supported-sanitizers", ["kcfi", "kernel-address", "thread"]); if cfg.rustc_version_atleast(1, 91, 0) { ts.push("target-pointer-width", 64); } else { diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 8b436c87ba4a..2e736434b924 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -21,7 +21,7 @@ bool conf_errors(void); struct symbol * sym_lookup(const char *name, int flags); struct symbol * sym_find(const char *name); void print_symbol_for_listconfig(struct symbol *sym); -struct symbol ** sym_re_search(const char *pattern); +struct symbol ** sym_re_search(const char *pattern, int *sym_cnt); const char * sym_type_name(enum symbol_type type); void sym_calc_value(struct symbol *sym); bool sym_dep_errors(void); diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index b8b7bba84a65..ebfc5bd09c1c 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -384,8 +384,10 @@ static void show_help(struct menu *menu) static void search_conf(void) { struct symbol **sym_arr; + int sym_cnt = 0; struct gstr res; struct gstr title; + struct gstr res_title; char *dialog_input; int dres, vscroll = 0, hscroll = 0; bool again; @@ -422,7 +424,7 @@ again: stpart.text = str_get(&sttext); list_add_tail(&stpart.entries, &trail); - sym_arr = sym_re_search(dialog_input); + sym_arr = sym_re_search(dialog_input, &sym_cnt); do { LIST_HEAD(head); struct search_data data = { @@ -433,9 +435,14 @@ again: jump_key_char = 0; res = get_relations_str(sym_arr, &head); set_subtitle(); - dres = show_textbox_ext("Search Results", str_get(&res), 0, 0, + + res_title = str_new(); + str_printf(&res_title, "Search Results (%d)", sym_cnt); + dres = show_textbox_ext(str_get(&res_title), str_get(&res), 0, 0, &vscroll, &hscroll, handle_search_keys, &data); + str_free(&res_title); + again = false; if (dres >= '1' && dres <= '9') { assert(data.target != NULL); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index bda3e2650216..1a3ad09a92d2 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -43,7 +43,7 @@ void menu_warn(const struct menu *menu, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - fprintf(stderr, "%s:%d:warning: ", menu->filename, menu->lineno); + fprintf(stderr, "%s:%d: warning: ", menu->filename, menu->lineno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); @@ -53,7 +53,17 @@ static void prop_warn(const struct property *prop, const char *fmt, ...) { va_list ap; va_start(ap, fmt); - fprintf(stderr, "%s:%d:warning: ", prop->filename, prop->lineno); + fprintf(stderr, "%s:%d: warning: ", prop->filename, prop->lineno); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); +} + +static void prop_err(const struct property *prop, const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "%s:%d: error: ", prop->filename, prop->lineno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); @@ -246,18 +256,15 @@ static int menu_validate_number(struct symbol *sym, struct symbol *sym2, if (sym2->type != S_UNKNOWN || !sym_string_valid(sym, sym2->name)) { - fprintf(stderr, "%s:%d: error: '%s' is an invalid value for '%s'\n", - prop->filename, prop->lineno, sym2->name, - sym_type_name(sym->type)); + prop_err(prop, "'%s' is an invalid value for '%s'", + sym2->name, sym_type_name(sym->type)); return 1; } if (!sym_string_check_bounds(sym, sym2->name)) { - fprintf(stderr, - "%s:%d: error: %s constant '%s' is outside the 64-bit %s bounds\n", - prop->filename, prop->lineno, sym_type_name(sym->type), - sym2->name, sym->type == S_INT ? "signed" : "unsigned"); - + prop_err(prop, "%s constant '%s' is outside the 64-bit %s bounds", + sym_type_name(sym->type), sym2->name, + sym->type == S_INT ? "signed" : "unsigned"); return 1; } @@ -267,9 +274,9 @@ static int menu_validate_number(struct symbol *sym, struct symbol *sym2, static int sym_check_prop(struct symbol *sym) { struct property *prop; - struct symbol *sym2; + struct symbol *sym2, *lower, *upper; char *use; - int errors = 0; + int errors = 0, numeric_errors; for (prop = sym->prop; prop; prop = prop->next) { switch (prop->type) { @@ -318,8 +325,22 @@ static int sym_check_prop(struct symbol *sym) if (sym->type != S_INT && sym->type != S_HEX) prop_warn(prop, "range is only allowed " "for int or hex symbols"); - errors += menu_validate_number(sym, prop->expr->left.sym, prop); - errors += menu_validate_number(sym, prop->expr->right.sym, prop); + lower = prop->expr->left.sym; + upper = prop->expr->right.sym; + numeric_errors = menu_validate_number(sym, lower, prop); + numeric_errors += menu_validate_number(sym, upper, prop); + errors += numeric_errors; + if (numeric_errors || lower->type != S_UNKNOWN || upper->type != S_UNKNOWN) + break; + + if ((sym->type == S_INT && + strtoll(lower->name, NULL, 10) > strtoll(upper->name, NULL, 10)) || + (sym->type == S_HEX && + strtoull(lower->name, NULL, 16) > strtoull(upper->name, NULL, 16))) { + prop_err(prop, "range lower limit '%s' is greater than upper limit '%s'", + lower->name, upper->name); + errors++; + } break; default: ; diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c index 521700ed7152..4c9c4ee7c3a7 100644 --- a/scripts/kconfig/nconf.c +++ b/scripts/kconfig/nconf.c @@ -700,8 +700,10 @@ static int do_exit(void) static void search_conf(void) { struct symbol **sym_arr; + int sym_cnt = 0; struct gstr res; struct gstr title; + struct gstr res_title; char *dialog_input; int dres, vscroll = 0, hscroll = 0; bool again; @@ -732,7 +734,7 @@ again: if (strncasecmp(dialog_input_result, CONFIG_, strlen(CONFIG_)) == 0) dialog_input += strlen(CONFIG_); - sym_arr = sym_re_search(dialog_input); + sym_arr = sym_re_search(dialog_input, &sym_cnt); do { LIST_HEAD(head); @@ -742,10 +744,15 @@ again: }; jump_key_char = 0; res = get_relations_str(sym_arr, &head); + + res_title = str_new(); + str_printf(&res_title, "Search Results (%d)", sym_cnt); dres = show_scroll_win_ext(main_window, - "Search Results", str_get(&res), + str_get(&res_title), str_get(&res), &vscroll, &hscroll, handle_search_keys, &data); + str_free(&res_title); + again = false; if (dres >= '1' && dres <= '9') { assert(data.target != NULL); diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c index 2d097bc7ef1a..5900eba0a512 100644 --- a/scripts/kconfig/nconf.gui.c +++ b/scripts/kconfig/nconf.gui.c @@ -523,7 +523,7 @@ int show_scroll_win_ext(WINDOW *main_window, const char *title, char *text, int x, y, lines, columns; int start_x = 0, start_y = 0; int text_lines = 0, text_cols = 0; - int total_cols = 0; + int total_cols = get_line_length(title) + 4; int win_cols = 0; int win_lines = 0; int i = 0; diff --git a/scripts/kconfig/preprocess.c b/scripts/kconfig/preprocess.c index 783abcaa5cc5..db226898c988 100644 --- a/scripts/kconfig/preprocess.c +++ b/scripts/kconfig/preprocess.c @@ -293,27 +293,33 @@ void variable_add(const char *name, const char *value, if (flavor == VAR_APPEND) { flavor = v->flavor; append = true; - } else { - free(v->value); } } else { /* For undefined variables, += assumes the recursive flavor */ if (flavor == VAR_APPEND) flavor = VAR_RECURSIVE; + } + /* + * Expand the value before touching the variable because the + * right-hand side may refer to the variable itself, like + * "X := $(X) foo". + */ + if (flavor == VAR_SIMPLE) + new_value = expand_string(value); + else + new_value = xstrdup(value); + + if (!v) { v = xmalloc(sizeof(*v)); v->name = xstrdup(name); + v->value = NULL; v->exp_count = 0; list_add_tail(&v->node, &variable_list); } v->flavor = flavor; - if (flavor == VAR_SIMPLE) - new_value = expand_string(value); - else - new_value = xstrdup(value); - if (append) { v->value = xrealloc(v->value, strlen(v->value) + strlen(new_value) + 2); @@ -321,6 +327,7 @@ void variable_add(const char *name, const char *value, strcat(v->value, new_value); free(new_value); } else { + free(v->value); v->value = new_value; } } diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index b02ead7a3f98..8f51dc55226d 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1245,7 +1245,7 @@ void ConfigSearchWindow::search(void) list->clear(); info->clear(); - result = sym_re_search(editField->text().toLatin1()); + result = sym_re_search(editField->text().toLatin1(), nullptr); if (!result) return; for (p = result; *p; p++) { diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 4ced4dd6485b..27138252c667 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -1077,7 +1077,7 @@ static int sym_rel_comp(const void *sym1, const void *sym2) return strcmp(s1->sym->name, s2->sym->name); } -struct symbol **sym_re_search(const char *pattern) +struct symbol **sym_re_search(const char *pattern, int *sym_cnt) { struct symbol *sym, **sym_arr = NULL; struct sym_match *sym_match_arr = NULL; @@ -1122,6 +1122,8 @@ struct symbol **sym_re_search(const char *pattern) sym_arr[i] = sym_match_arr[i].sym; sym_arr[cnt] = NULL; } + if (sym_cnt) + *sym_cnt = cnt; sym_re_search_free: /* sym_match_arr can be NULL if no match, but free(NULL) is OK */ free(sym_match_arr); @@ -1184,7 +1186,7 @@ static void sym_check_print_recursive(struct symbol *last_sym) break; if (!stack) { fprintf(stderr, "unexpected recursive dependency error\n"); - return; + goto out; } for (; stack; stack = stack->next) { @@ -1229,6 +1231,7 @@ static void sym_check_print_recursive(struct symbol *last_sym) "subsection \"Kconfig recursive dependency limitations\"\n" "\n"); +out: if (check_top == &cv_stack) dep_stack_remove(); } diff --git a/scripts/kconfig/tests/err_num_reverse_range/Kconfig b/scripts/kconfig/tests/err_num_reverse_range/Kconfig new file mode 100644 index 000000000000..c55091aca274 --- /dev/null +++ b/scripts/kconfig/tests/err_num_reverse_range/Kconfig @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: GPL-2.0 +# Check constant range bounds. + +config INT_ORDERED + int + range -10 10 + +config INT_EQUAL + int + range 5 5 + +config HEX_ORDERED + hex + range 0x7fffffffffffffff 0xffffffffffffffff + +config HEX_EQUAL + hex + range 0xffffffffffffffff 0xffffffffffffffff + +# Skip ranges with symbolic bounds. + +config INT_LOWER + int + +config INT_UPPER + int + +config INT_SYMBOL_LOWER + int + range INT_LOWER 0 + +config INT_SYMBOL_UPPER + int + range 0 INT_UPPER + +config INT_SYMBOL_BOTH + int + range INT_LOWER INT_UPPER + +config HEX_LOWER + hex + +config HEX_UPPER + hex + +config HEX_SYMBOL_LOWER + hex + range HEX_LOWER 0x0 + +config HEX_SYMBOL_UPPER + hex + range 0x0 HEX_UPPER + +config HEX_SYMBOL_BOTH + hex + range HEX_LOWER HEX_UPPER + +# Reject reversed constant bounds. + +config INT_REVERSED + int + range 10 2 + +config INT_REVERSED_NEGATIVE + int + range -1 -10 + +config INT_REVERSED_SIGNED + int + range 1 -1 + +config INT_REVERSED_QUOTED + int + range "8" "2" + +config HEX_REVERSED + hex + range 0x10 0xf + +config HEX_REVERSED_HIGH + hex + range 0xffffffffffffffff 0x8000000000000000 + +config HEX_REVERSED_UNPREFIXED + hex + range f a + +# Check each conditional range independently. + +config RANGE_CONDITION + bool + +config INT_REVERSED_FIRST + int + range 10 2 if RANGE_CONDITION + range -10 10 if !RANGE_CONDITION + +config INT_REVERSED_SECOND + int + range -10 10 if RANGE_CONDITION + range 10 2 if !RANGE_CONDITION + +config HEX_REVERSED_FIRST + hex + range 0x10 0xf if RANGE_CONDITION + range 0x0 0x10 if !RANGE_CONDITION + +config HEX_REVERSED_SECOND + hex + range 0x0 0x10 if RANGE_CONDITION + range 0x10 0xf if !RANGE_CONDITION diff --git a/scripts/kconfig/tests/err_num_reverse_range/__init__.py b/scripts/kconfig/tests/err_num_reverse_range/__init__.py new file mode 100644 index 000000000000..4a7219bbe49e --- /dev/null +++ b/scripts/kconfig/tests/err_num_reverse_range/__init__.py @@ -0,0 +1,8 @@ +# SPDX-License-Identifier: GPL-2.0 +""" +Reject constant range bounds when the lower bound is greater than the upper. +""" + +def test(conf): + assert conf.olddefconfig() == 1 + assert conf.stderr_matches('expected_stderr') diff --git a/scripts/kconfig/tests/err_num_reverse_range/expected_stderr b/scripts/kconfig/tests/err_num_reverse_range/expected_stderr new file mode 100644 index 000000000000..8742f3f46469 --- /dev/null +++ b/scripts/kconfig/tests/err_num_reverse_range/expected_stderr @@ -0,0 +1,11 @@ +Kconfig:62: error: range lower limit '10' is greater than upper limit '2' +Kconfig:66: error: range lower limit '-1' is greater than upper limit '-10' +Kconfig:70: error: range lower limit '1' is greater than upper limit '-1' +Kconfig:74: error: range lower limit '8' is greater than upper limit '2' +Kconfig:78: error: range lower limit '0x10' is greater than upper limit '0xf' +Kconfig:82: error: range lower limit '0xffffffffffffffff' is greater than upper limit '0x8000000000000000' +Kconfig:86: error: range lower limit 'f' is greater than upper limit 'a' +Kconfig:95: error: range lower limit '10' is greater than upper limit '2' +Kconfig:101: error: range lower limit '10' is greater than upper limit '2' +Kconfig:105: error: range lower limit '0x10' is greater than upper limit '0xf' +Kconfig:111: error: range lower limit '0x10' is greater than upper limit '0xf' diff --git a/scripts/kconfig/tests/err_transitional/expected_stderr b/scripts/kconfig/tests/err_transitional/expected_stderr index b52db4f680f4..ba317850c043 100644 --- a/scripts/kconfig/tests/err_transitional/expected_stderr +++ b/scripts/kconfig/tests/err_transitional/expected_stderr @@ -1,4 +1,4 @@ -Kconfig:46:warning: config symbol defined without type +Kconfig:46: warning: config symbol defined without type Kconfig:7: error: transitional symbols can only have help sections Kconfig:14: error: transitional symbols can only have help sections Kconfig:21: error: transitional symbols can only have help sections diff --git a/scripts/kconfig/tests/preprocess/variable/Kconfig b/scripts/kconfig/tests/preprocess/variable/Kconfig index 9ce2f95cbd24..226114e86a28 100644 --- a/scripts/kconfig/tests/preprocess/variable/Kconfig +++ b/scripts/kconfig/tests/preprocess/variable/Kconfig @@ -51,3 +51,8 @@ $(warning,$(greeting,Hello)) # Unreferenced parameters are just ignored. $(warning,$(greeting,Hello,John,ignored,ignored)) + +# Simply expanded variable referring to itself. +X := 1 +X := $(X) 2 +$(warning,X = $(X)) diff --git a/scripts/kconfig/tests/preprocess/variable/expected_stderr b/scripts/kconfig/tests/preprocess/variable/expected_stderr index a4841c3fdff5..7008e3b1771c 100644 --- a/scripts/kconfig/tests/preprocess/variable/expected_stderr +++ b/scripts/kconfig/tests/preprocess/variable/expected_stderr @@ -7,3 +7,4 @@ Kconfig:41: AB = 5 Kconfig:45: Hello, my name is John. Kconfig:50: Hello, my name is . Kconfig:53: Hello, my name is John. +Kconfig:58: X = 1 2 diff --git a/scripts/mod/devicetable-offsets.c b/scripts/mod/devicetable-offsets.c index 92596bfa6aec..875eafeb743d 100644 --- a/scripts/mod/devicetable-offsets.c +++ b/scripts/mod/devicetable-offsets.c @@ -1,8 +1,64 @@ // SPDX-License-Identifier: GPL-2.0 #define COMPILE_OFFSETS -#include <linux/device-id/scmi.h> +#include <linux/cpufeature.h> #include <linux/kbuild.h> -#include <linux/mod_devicetable.h> + +#include <linux/device-id/acpi.h> +#include <linux/device-id/amba.h> +#include <linux/device-id/ap.h> +#include <linux/device-id/arm_smccc.h> +#include <linux/device-id/auxiliary.h> +#include <linux/device-id/bcma.h> +#include <linux/device-id/ccw.h> +#include <linux/device-id/cdx.h> +#include <linux/device-id/coreboot.h> +#include <linux/device-id/css.h> +#include <linux/device-id/dfl.h> +#include <linux/device-id/dmi.h> +#include <linux/device-id/eisa.h> +#include <linux/device-id/fsl_mc.h> +#include <linux/device-id/hda.h> +#include <linux/device-id/hid.h> +#include <linux/device-id/hv_vmbus.h> +#include <linux/device-id/i2c.h> +#include <linux/device-id/i3c.h> +#include <linux/device-id/ieee1394.h> +#include <linux/device-id/input.h> +#include <linux/device-id/ipack.h> +#include <linux/device-id/isapnp.h> +#include <linux/device-id/ishtp.h> +#include <linux/device-id/mcb.h> +#include <linux/device-id/mdio.h> +#include <linux/device-id/mei_cl.h> +#include <linux/device-id/mhi.h> +#include <linux/device-id/mips_cdmm.h> +#include <linux/device-id/of.h> +#include <linux/device-id/parisc.h> +#include <linux/device-id/pci.h> +#include <linux/device-id/pcmcia.h> +#include <linux/device-id/platform.h> +#include <linux/device-id/pnp.h> +#include <linux/device-id/rio.h> +#include <linux/device-id/rpmsg.h> +#include <linux/device-id/scmi.h> +#include <linux/device-id/sdio.h> +#include <linux/device-id/sdw.h> +#include <linux/device-id/serio.h> +#include <linux/device-id/slim.h> +#include <linux/device-id/spi.h> +#include <linux/device-id/ssam.h> +#include <linux/device-id/ssb.h> +#include <linux/device-id/tb.h> +#include <linux/device-id/tee_client.h> +#include <linux/device-id/typec.h> +#include <linux/device-id/ulpi.h> +#include <linux/device-id/usb.h> +#include <linux/device-id/vchiq.h> +#include <linux/device-id/vio.h> +#include <linux/device-id/virtio.h> +#include <linux/device-id/wmi.h> +#include <linux/device-id/x86_cpu.h> +#include <linux/device-id/zorro.h> #define DEVID(devid) DEFINE(SIZE_##devid, sizeof(struct devid)) #define DEVID_FIELD(devid, field) \ diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 61a831c18721..f848b39145d9 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -121,8 +121,63 @@ typedef struct { /* Big exception to the "don't include kernel headers into userspace, which * even potentially has different endianness and word sizes, since * we handle those differences explicitly below */ +#include "../../include/linux/cpufeature.h" +#include "../../include/linux/device-id/acpi.h" +#include "../../include/linux/device-id/amba.h" +#include "../../include/linux/device-id/ap.h" +#include "../../include/linux/device-id/arm_smccc.h" +#include "../../include/linux/device-id/auxiliary.h" +#include "../../include/linux/device-id/bcma.h" +#include "../../include/linux/device-id/ccw.h" +#include "../../include/linux/device-id/cdx.h" +#include "../../include/linux/device-id/coreboot.h" +#include "../../include/linux/device-id/css.h" +#include "../../include/linux/device-id/dfl.h" +#include "../../include/linux/device-id/dmi.h" +#include "../../include/linux/device-id/eisa.h" +#include "../../include/linux/device-id/fsl_mc.h" +#include "../../include/linux/device-id/hda.h" +#include "../../include/linux/device-id/hid.h" +#include "../../include/linux/device-id/hv_vmbus.h" +#include "../../include/linux/device-id/i2c.h" +#include "../../include/linux/device-id/i3c.h" +#include "../../include/linux/device-id/ieee1394.h" +#include "../../include/linux/device-id/input.h" +#include "../../include/linux/device-id/ipack.h" +#include "../../include/linux/device-id/isapnp.h" +#include "../../include/linux/device-id/ishtp.h" +#include "../../include/linux/device-id/mcb.h" +#include "../../include/linux/device-id/mdio.h" +#include "../../include/linux/device-id/mei_cl.h" +#include "../../include/linux/device-id/mhi.h" +#include "../../include/linux/device-id/mips_cdmm.h" +#include "../../include/linux/device-id/of.h" +#include "../../include/linux/device-id/parisc.h" +#include "../../include/linux/device-id/pci.h" +#include "../../include/linux/device-id/pcmcia.h" +#include "../../include/linux/device-id/platform.h" +#include "../../include/linux/device-id/pnp.h" +#include "../../include/linux/device-id/rio.h" +#include "../../include/linux/device-id/rpmsg.h" #include "../../include/linux/device-id/scmi.h" -#include "../../include/linux/mod_devicetable.h" +#include "../../include/linux/device-id/sdio.h" +#include "../../include/linux/device-id/sdw.h" +#include "../../include/linux/device-id/serio.h" +#include "../../include/linux/device-id/slim.h" +#include "../../include/linux/device-id/spi.h" +#include "../../include/linux/device-id/ssam.h" +#include "../../include/linux/device-id/ssb.h" +#include "../../include/linux/device-id/tb.h" +#include "../../include/linux/device-id/tee_client.h" +#include "../../include/linux/device-id/typec.h" +#include "../../include/linux/device-id/ulpi.h" +#include "../../include/linux/device-id/usb.h" +#include "../../include/linux/device-id/vchiq.h" +#include "../../include/linux/device-id/vio.h" +#include "../../include/linux/device-id/virtio.h" +#include "../../include/linux/device-id/wmi.h" +#include "../../include/linux/device-id/x86_cpu.h" +#include "../../include/linux/device-id/zorro.h" struct devtable { const char *device_id; diff --git a/scripts/modules-check.sh b/scripts/modules-check.sh index 4c8da90de78e..3d12dc53b202 100755 --- a/scripts/modules-check.sh +++ b/scripts/modules-check.sh @@ -13,10 +13,19 @@ exit_code=0 # Check uniqueness of module names check_same_name_modules() { - for m in $(sed 's:.*/::' "$1" | sort | uniq -d) + for m in $(sed 's:.*/::; s/-/_/g' "$1" | sort | uniq -d) do echo "error: the following would cause module name conflict:" >&2 - sed -n "/\/$m/s:^\(.*\)\.o\$: \1.ko:p" "$1" >&2 + awk -v name="$m" ' + { + basename = $0 + sub(/^.*\//, "", basename) + gsub(/-/, "_", basename) + if (basename == name) { + sub(/\.o$/, ".ko") + print " " $0 + } + }' "$1" >&2 exit_code=1 done } |
