From 339949be25863ac15e24659c2ab4b01185e1234a Mon Sep 17 00:00:00 2001 From: Stephen Smalley Date: Thu, 6 Aug 2020 14:34:18 -0400 Subject: scripts/selinux,selinux: update mdp to enable policy capabilities Presently mdp does not enable any SELinux policy capabilities in the dummy policy it generates. Thus, policies derived from it will by default lack various features commonly used in modern policies such as open permission, extended socket classes, network peer controls, etc. Split the policy capability definitions out into their own headers so that we can include them into mdp without pulling in other kernel headers and extend mdp generate policycap statements for the policy capabilities known to the kernel. Policy authors may wish to selectively remove some of these from the generated policy. Signed-off-by: Stephen Smalley Signed-off-by: Paul Moore --- scripts/selinux/mdp/mdp.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'scripts') diff --git a/scripts/selinux/mdp/mdp.c b/scripts/selinux/mdp/mdp.c index 6ceb88eb9b59..105c1c31a316 100644 --- a/scripts/selinux/mdp/mdp.c +++ b/scripts/selinux/mdp/mdp.c @@ -35,6 +35,9 @@ struct security_class_mapping { #include "classmap.h" #include "initial_sid_to_string.h" +#include "policycap_names.h" + +#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) int main(int argc, char *argv[]) { @@ -115,6 +118,10 @@ int main(int argc, char *argv[]) } } + /* enable all policy capabilities */ + for (i = 0; i < ARRAY_SIZE(selinux_policycap_names); i++) + fprintf(fout, "policycap %s;\n", selinux_policycap_names[i]); + /* types, roles, and allows */ fprintf(fout, "type base_t;\n"); fprintf(fout, "role base_r;\n"); -- cgit From 4036707c7c61a0fec7774aec44bbb7350153e8c2 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 19 Aug 2020 14:47:09 +0200 Subject: scripts/dtc: dtx_diff - make help text formatting consistent None of the help texts use capitalization, except the one for the -T option. Drop the capitalization for consistency. Split the single long line that doesn't fit in 80 characters. Reviewed-by: Frank Rowand Signed-off-by: Geert Uytterhoeven Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20200819124709.20401-1-geert+renesas@glider.be --- scripts/dtc/dtx_diff | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/dtc/dtx_diff b/scripts/dtc/dtx_diff index 541c432e7d19..d3422ee15e30 100755 --- a/scripts/dtc/dtx_diff +++ b/scripts/dtc/dtx_diff @@ -29,7 +29,8 @@ Usage: -s SRCTREE linux kernel source tree is at path SRCTREE (default is current directory) -S linux kernel source tree is at root of current git repo - -T Annotate output .dts with input source file and line (-T -T for more details) + -T annotate output .dts with input source file and line + (-T -T for more details) -u unsorted, do not sort DTx -- cgit From b8a49399fb7abd4ec402bea1fec5a974053591b6 Mon Sep 17 00:00:00 2001 From: Andrei Ziureaev Date: Thu, 13 Aug 2020 14:26:11 +0100 Subject: dt-bindings: Use json for processed-schema* Change the format of processed-schema* from yaml to json to speed up validation. With json output, using xargs and appending the output won't work since json has explicit list begin and end characters. Instead, we pass the schema files as a list in a temp file. The parsing time for the processed schema goes down from ~2sec to 70ms. Also, 'make dtbs_check' becomes 33% faster. Some error messages are affected by this change. For example, "True was expected" becomes "... is not of type 'boolean'". The order of messages is also changed. Signed-off-by: Andrei Ziureaev Signed-off-by: Rob Herring --- scripts/Makefile.lib | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 3d599716940c..94133708889d 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -328,7 +328,7 @@ $(obj)/%.dtb: $(src)/%.dts $(DTC) FORCE DT_CHECKER ?= dt-validate DT_BINDING_DIR := Documentation/devicetree/bindings # DT_TMP_SCHEMA may be overridden from Documentation/devicetree/bindings/Makefile -DT_TMP_SCHEMA ?= $(objtree)/$(DT_BINDING_DIR)/processed-schema.yaml +DT_TMP_SCHEMA ?= $(objtree)/$(DT_BINDING_DIR)/processed-schema.json quiet_cmd_dtb_check = CHECK $@ cmd_dtb_check = $(DT_CHECKER) -u $(srctree)/$(DT_BINDING_DIR) -p $(DT_TMP_SCHEMA) $@ -- cgit From 4b2bd20c350a66d4f8a7c2da48b115fd4e06d15e Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Wed, 5 Aug 2020 14:27:40 +0530 Subject: scripts: coccicheck: Add chain mode to list of modes This patch adds chain mode to the list of available modes in coccicheck. Signed-off-by: Sumera Priyadarsini Signed-off-by: Julia Lawall --- scripts/coccicheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/coccicheck b/scripts/coccicheck index e04d328210ac..6e37cf36caae 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -99,7 +99,7 @@ fi if [ "$MODE" = "" ] ; then if [ "$ONLINE" = "0" ] ; then echo 'You have not explicitly specified the mode to use. Using default "report" mode.' - echo 'Available modes are the following: patch, report, context, org' + echo 'Available modes are the following: patch, report, context, org, chain' echo 'You can specify the mode with "make coccicheck MODE="' echo 'Note however that some modes are not implemented by some semantic patches.' fi -- cgit From 7a2624e6de03050c9f15af21c216818d5508b5e9 Mon Sep 17 00:00:00 2001 From: Alex Dewar Date: Fri, 21 Aug 2020 00:55:57 +0100 Subject: coccinelle: add patch rule for dma_alloc_coherent Commit dfd32cad146e ("dma-mapping: remove dma_zalloc_coherent()") removed the definition of dma_zalloc_coherent() and also removed the corresponding patch rule for replacing instances of dma_alloc_coherent + memset in zalloc-simple.cocci (though left the report rule). Add a new patch rule to remove unnecessary calls to memset after allocating with dma_alloc_coherent. While we're at it, fix a couple of typos. Fixes: dfd32cad146e ("dma-mapping: remove dma_zalloc_coherent()") Signed-off-by: Alex Dewar Signed-off-by: Julia Lawall --- scripts/coccinelle/api/alloc/zalloc-simple.cocci | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/coccinelle/api/alloc/zalloc-simple.cocci b/scripts/coccinelle/api/alloc/zalloc-simple.cocci index 26cda3f48f01..b3d0c3c230c1 100644 --- a/scripts/coccinelle/api/alloc/zalloc-simple.cocci +++ b/scripts/coccinelle/api/alloc/zalloc-simple.cocci @@ -127,6 +127,16 @@ statement S; if ((x==NULL) || ...) S - memset((T2)x,0,E1); +@depends on patch@ +type T, T2; +expression x; +expression E1,E2,E3,E4; +statement S; +@@ + x = (T)dma_alloc_coherent(E1, E2, E3, E4); + if ((x==NULL) || ...) S +- memset((T2)x, 0, E2); + //---------------------------------------------------------- // For org mode //---------------------------------------------------------- @@ -199,9 +209,9 @@ statement S; position p; @@ - x = (T)dma_alloc_coherent@p(E2,E1,E3,E4); + x = (T)dma_alloc_coherent@p(E1,E2,E3,E4); if ((x==NULL) || ...) S - memset((T2)x,0,E1); + memset((T2)x,0,E2); @script:python depends on org@ p << r2.p; @@ -217,7 +227,7 @@ p << r2.p; x << r2.x; @@ -msg="WARNING: dma_alloc_coherent use in %s already zeroes out memory, so memset is not needed" % (x) +msg="WARNING: dma_alloc_coherent used in %s already zeroes out memory, so memset is not needed" % (x) coccilib.report.print_report(p[0], msg) //----------------------------------------------------------------- -- cgit From a2fc3718bc22e85378085568ecc5765fb28cabce Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 21 Aug 2020 23:11:37 +0300 Subject: coccinelle: api: add kobj_to_dev.cocci script Use kobj_to_dev() instead of container_of(). Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/api/kobj_to_dev.cocci | 45 ++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 scripts/coccinelle/api/kobj_to_dev.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/api/kobj_to_dev.cocci b/scripts/coccinelle/api/kobj_to_dev.cocci new file mode 100644 index 000000000000..cd5d31c6fe76 --- /dev/null +++ b/scripts/coccinelle/api/kobj_to_dev.cocci @@ -0,0 +1,45 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Use kobj_to_dev() instead of container_of() +/// +// Confidence: High +// Copyright: (C) 2020 Denis Efremov ISPRAS +// Options: --no-includes --include-headers +// +// Keywords: kobj_to_dev, container_of +// + +virtual context +virtual report +virtual org +virtual patch + + +@r depends on !patch@ +expression ptr; +symbol kobj; +position p; +@@ + +* container_of(ptr, struct device, kobj)@p + + +@depends on patch@ +expression ptr; +@@ + +- container_of(ptr, struct device, kobj) ++ kobj_to_dev(ptr) + + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING opportunity for kobj_to_dev()") + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING opportunity for kobj_to_dev()") -- cgit From 14e2ac8de0f91f12122a49f09897b0cd05256460 Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Fri, 24 Jul 2020 09:00:01 +0200 Subject: kcsan: Support compounded read-write instrumentation Add support for compounded read-write instrumentation if supported by the compiler. Adds the necessary instrumentation functions, and a new type which is used to generate a more descriptive report. Furthermore, such compounded memory access instrumentation is excluded from the "assume aligned writes up to word size are atomic" rule, because we cannot assume that the compiler emits code that is atomic for compound ops. LLVM/Clang added support for the feature in: https://github.com/llvm/llvm-project/commit/785d41a261d136b64ab6c15c5d35f2adc5ad53e3 The new instrumentation is emitted for sets of memory accesses in the same basic block to the same address with at least one read appearing before a write. These typically result from compound operations such as ++, --, +=, -=, |=, &=, etc. but also equivalent forms such as "var = var + 1". Where the compiler determines that it is equivalent to emit a call to a single __tsan_read_write instead of separate __tsan_read and __tsan_write, we can then benefit from improved performance and better reporting for such access patterns. The new reports now show that the ops are both reads and writes, for example: read-write to 0xffffffff90548a38 of 8 bytes by task 143 on cpu 3: test_kernel_rmw_array+0x45/0xa0 access_thread+0x71/0xb0 kthread+0x21e/0x240 ret_from_fork+0x22/0x30 read-write to 0xffffffff90548a38 of 8 bytes by task 144 on cpu 2: test_kernel_rmw_array+0x45/0xa0 access_thread+0x71/0xb0 kthread+0x21e/0x240 ret_from_fork+0x22/0x30 Acked-by: Peter Zijlstra (Intel) Signed-off-by: Marco Elver Signed-off-by: Paul E. McKenney --- scripts/Makefile.kcsan | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.kcsan b/scripts/Makefile.kcsan index c50f27b3ac56..c37f9518d5d9 100644 --- a/scripts/Makefile.kcsan +++ b/scripts/Makefile.kcsan @@ -11,5 +11,5 @@ endif # of some options does not break KCSAN nor causes false positive reports. CFLAGS_KCSAN := -fsanitize=thread \ $(call cc-option,$(call cc-param,tsan-instrument-func-entry-exit=0) -fno-optimize-sibling-calls) \ - $(call cc-option,$(call cc-param,tsan-instrument-read-before-write=1)) \ + $(call cc-option,$(call cc-param,tsan-compound-read-before-write=1),$(call cc-option,$(call cc-param,tsan-instrument-read-before-write=1))) \ $(call cc-param,tsan-distinguish-volatile=1) -- cgit From 3570a1bcf45e9a7ddf9ba0e8d6d57cc67675cfef Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Fri, 24 Jul 2020 09:00:08 +0200 Subject: locking/atomics: Use read-write instrumentation for atomic RMWs Use instrument_atomic_read_write() for atomic RMW ops. Cc: Will Deacon Cc: Boqun Feng Cc: Arnd Bergmann Cc: Acked-by: Peter Zijlstra (Intel) Signed-off-by: Marco Elver Signed-off-by: Paul E. McKenney --- scripts/atomic/gen-atomic-instrumented.sh | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/atomic/gen-atomic-instrumented.sh b/scripts/atomic/gen-atomic-instrumented.sh index 6afadf73da17..2b7fec7e6abc 100755 --- a/scripts/atomic/gen-atomic-instrumented.sh +++ b/scripts/atomic/gen-atomic-instrumented.sh @@ -5,9 +5,10 @@ ATOMICDIR=$(dirname $0) . ${ATOMICDIR}/atomic-tbl.sh -#gen_param_check(arg) +#gen_param_check(meta, arg) gen_param_check() { + local meta="$1"; shift local arg="$1"; shift local type="${arg%%:*}" local name="$(gen_param_name "${arg}")" @@ -17,17 +18,25 @@ gen_param_check() i) return;; esac - # We don't write to constant parameters - [ ${type#c} != ${type} ] && rw="read" + if [ ${type#c} != ${type} ]; then + # We don't write to constant parameters. + rw="read" + elif [ "${meta}" != "s" ]; then + # An atomic RMW: if this parameter is not a constant, and this atomic is + # not just a 's'tore, this parameter is both read from and written to. + rw="read_write" + fi printf "\tinstrument_atomic_${rw}(${name}, sizeof(*${name}));\n" } -#gen_param_check(arg...) +#gen_params_checks(meta, arg...) gen_params_checks() { + local meta="$1"; shift + while [ "$#" -gt 0 ]; do - gen_param_check "$1" + gen_param_check "$meta" "$1" shift; done } @@ -77,7 +86,7 @@ gen_proto_order_variant() local ret="$(gen_ret_type "${meta}" "${int}")" local params="$(gen_params "${int}" "${atomic}" "$@")" - local checks="$(gen_params_checks "$@")" + local checks="$(gen_params_checks "${meta}" "$@")" local args="$(gen_args "$@")" local retstmt="$(gen_ret_stmt "${meta}")" -- cgit From 6e22ab9da79343532cd3cde39df25e5a5478c692 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Tue, 25 Aug 2020 21:21:20 +0200 Subject: bpf: Add d_path helper Adding d_path helper function that returns full path for given 'struct path' object, which needs to be the kernel BTF 'path' object. The path is returned in buffer provided 'buf' of size 'sz' and is zero terminated. bpf_d_path(&file->f_path, buf, size); The helper calls directly d_path function, so there's only limited set of function it can be called from. Adding just very modest set for the start. Updating also bpf.h tools uapi header and adding 'path' to bpf_helpers_doc.py script. Signed-off-by: Jiri Olsa Signed-off-by: Alexei Starovoitov Acked-by: Andrii Nakryiko Acked-by: KP Singh Link: https://lore.kernel.org/bpf/20200825192124.710397-11-jolsa@kernel.org --- scripts/bpf_helpers_doc.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py index 5bfa448b4704..08388173973f 100755 --- a/scripts/bpf_helpers_doc.py +++ b/scripts/bpf_helpers_doc.py @@ -432,6 +432,7 @@ class PrinterHelpers(Printer): 'struct __sk_buff', 'struct sk_msg_md', 'struct xdp_md', + 'struct path', ] known_types = { '...', @@ -472,6 +473,7 @@ class PrinterHelpers(Printer): 'struct tcp_request_sock', 'struct udp6_sock', 'struct task_struct', + 'struct path', } mapped_types = { 'u8': '__u8', -- cgit From 6eb6d05958f3208b3dd2b5311f1a6e68abdbe5d5 Mon Sep 17 00:00:00 2001 From: Peter Zijlstra Date: Wed, 29 Jul 2020 20:12:32 +0200 Subject: seqlock,tags: Add support for SEQCOUNT_LOCKTYPE() Such that we might easily find seqcount_LOCKTYPE_t and seqcount_LOCKTYPE_init(). Signed-off-by: Peter Zijlstra (Intel) Link: https://lkml.kernel.org/r/20200729161938.GB2678@hirez.programming.kicks-ass.net --- scripts/tags.sh | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index 32d3f53af10b..fc5b53259a16 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -201,6 +201,8 @@ regex_c=( '/\ Date: Fri, 21 Aug 2020 11:43:58 +0900 Subject: kbuild: hide commands to run Kconfig, and show short log for syncconfig Some targets (localyesconfig, localmodconfig, defconfig) hide the command running, but the others do not. Users know which Kconfig flavor they are running, so it is OK to hide the command. Add $(Q) to all commands consistently. If you want to see the full command running, pass V=1 from the command line. syncconfig is the exceptional case, which occurs without explicit command invocation by the user. Display the Kbuild-style log for it. The ugly bare log will go away. [Before] scripts/kconfig/conf --syncconfig Kconfig [After] SYNC include/config/auto.conf Signed-off-by: Masahiro Yamada --- scripts/kconfig/Makefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index 52b59bf9efe4..e46df0a2d4f9 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -20,19 +20,19 @@ endif unexport CONFIG_ xconfig: $(obj)/qconf - $< $(silent) $(Kconfig) + $(Q)$< $(silent) $(Kconfig) gconfig: $(obj)/gconf - $< $(silent) $(Kconfig) + $(Q)$< $(silent) $(Kconfig) menuconfig: $(obj)/mconf - $< $(silent) $(Kconfig) + $(Q)$< $(silent) $(Kconfig) config: $(obj)/conf - $< $(silent) --oldaskconfig $(Kconfig) + $(Q)$< $(silent) --oldaskconfig $(Kconfig) nconfig: $(obj)/nconf - $< $(silent) $(Kconfig) + $(Q)$< $(silent) $(Kconfig) build_menuconfig: $(obj)/mconf @@ -68,12 +68,12 @@ simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \ PHONY += $(simple-targets) $(simple-targets): $(obj)/conf - $< $(silent) --$@ $(Kconfig) + $(Q)$< $(silent) --$@ $(Kconfig) PHONY += savedefconfig defconfig savedefconfig: $(obj)/conf - $< $(silent) --$@=defconfig $(Kconfig) + $(Q)$< $(silent) --$@=defconfig $(Kconfig) defconfig: $(obj)/conf ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/configs/$(KBUILD_DEFCONFIG)),) @@ -111,7 +111,7 @@ tinyconfig: # CHECK: -o cache_dir= working? PHONY += testconfig testconfig: $(obj)/conf - $(PYTHON3) -B -m pytest $(srctree)/$(src)/tests \ + $(Q)$(PYTHON3) -B -m pytest $(srctree)/$(src)/tests \ -o cache_dir=$(abspath $(obj)/tests/.cache) \ $(if $(findstring 1,$(KBUILD_VERBOSE)),--capture=no) clean-files += tests/.cache -- cgit From 8a685db32f2b3495c91efab6e9462c2fd934778f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:09 +0900 Subject: gen_compile_commands: parse only the first line of .*.cmd files After the allmodconfig build, this script takes about 5 sec on my machine. Most of the run-time is consumed for needless regex matching. We know the format of .*.cmd file; the first line is the build command. There is no need to parse the rest. With this optimization, now it runs 4 times faster. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers Tested-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index c458696ef3a7..1bcf33a93cb9 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -125,11 +125,8 @@ def main(): filepath = os.path.join(dirpath, filename) with open(filepath, 'rt') as f: - for line in f: - result = line_matcher.match(line) - if not result: - continue - + result = line_matcher.match(f.readline()) + if result: try: entry = process_line(directory, dirpath, result.group(1), result.group(2)) -- cgit From ea6cedc5b8a4e666da41f1173ea19970fa60683f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:10 +0900 Subject: gen_compile_commands: use choices for --log_levels option Use 'choices' to check if the given parameter is valid. I also simplified the help message because, with 'choices', --help shows the list of valid parameters: --log_level {DEBUG,INFO,WARNING,ERROR,CRITICAL} I started the help message with a lower case, "the level of log ..." in order to be consistent with the -h option: -h, --help show this help message and exit The message "show this help ..." comes from the ArgumentParser library code, and I do not know how to change it. So, I changed our code. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index 1bcf33a93cb9..535248cf2d7e 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -45,24 +45,18 @@ def parse_arguments(): 'compile_commands.json in the search directory)') parser.add_argument('-o', '--output', type=str, help=output_help) - log_level_help = ('The level of log messages to produce (one of ' + - ', '.join(_VALID_LOG_LEVELS) + '; defaults to ' + + log_level_help = ('the level of log messages to produce (defaults to ' + _DEFAULT_LOG_LEVEL + ')') - parser.add_argument( - '--log_level', type=str, default=_DEFAULT_LOG_LEVEL, - help=log_level_help) + parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS, + default=_DEFAULT_LOG_LEVEL, help=log_level_help) args = parser.parse_args() - log_level = args.log_level - if log_level not in _VALID_LOG_LEVELS: - raise ValueError('%s is not a valid log level' % log_level) - directory = args.directory or os.getcwd() output = args.output or os.path.join(directory, _DEFAULT_OUTPUT) directory = os.path.abspath(directory) - return log_level, directory, output + return args.log_level, directory, output def process_line(root_directory, file_directory, command_prefix, relative_path): -- cgit From 6ca4c6d25949117dc5b4845612e290b6d89e70a8 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:11 +0900 Subject: gen_compile_commands: do not support .cmd files under tools/ directory The tools/ directory uses a different build system, and the format of .cmd files is different because the tools builds run in a different work directory. Supporting two formats compilicates the script. The only loss by this change is objtool. Also, rename the confusing variable 'relative_path' because it is not necessarily a relative path. When the output directory is not the direct child of the source tree (e.g. O=foo/bar), it is an absolute path. Rename it to 'file_path'. os.path.join(root_directory, file_path) works whether the file_path is relative or not. If file_path is already absolute, it returns it as-is. I used os.path.abspath() to normalize file paths. If you run this script against the kernel built with O=foo option, the file_path contains '../' patterns. os.path.abspath() fixes up 'foo/bar/../baz' into 'foo/baz', and produces a cleaner commands_database.json. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index 535248cf2d7e..49fff0b0b385 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -59,23 +59,21 @@ def parse_arguments(): return args.log_level, directory, output -def process_line(root_directory, file_directory, command_prefix, relative_path): +def process_line(root_directory, command_prefix, file_path): """Extracts information from a .cmd line and creates an entry from it. Args: root_directory: The directory that was searched for .cmd files. Usually used directly in the "directory" entry in compile_commands.json. - file_directory: The path to the directory the .cmd file was found in. command_prefix: The extracted command line, up to the last element. - relative_path: The .c file from the end of the extracted command. - Usually relative to root_directory, but sometimes relative to - file_directory and sometimes neither. + file_path: The .c file from the end of the extracted command. + Usually relative to root_directory, but sometimes absolute. Returns: An entry to append to compile_commands. Raises: - ValueError: Could not find the extracted file based on relative_path and + ValueError: Could not find the extracted file based on file_path and root_directory or file_directory. """ # The .cmd files are intended to be included directly by Make, so they @@ -84,20 +82,14 @@ def process_line(root_directory, file_directory, command_prefix, relative_path): # by Make, so this code replaces the escaped version with '#'. prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#') - cur_dir = root_directory - expected_path = os.path.join(cur_dir, relative_path) - if not os.path.exists(expected_path): - # Try using file_directory instead. Some of the tools have a different - # style of .cmd file than the kernel. - cur_dir = file_directory - expected_path = os.path.join(cur_dir, relative_path) - if not os.path.exists(expected_path): - raise ValueError('File %s not in %s or %s' % - (relative_path, root_directory, file_directory)) + # Use os.path.abspath() to normalize the path resolving '.' and '..' . + abs_path = os.path.abspath(os.path.join(root_directory, file_path)) + if not os.path.exists(abs_path): + raise ValueError('File %s not found' % abs_path) return { - 'directory': cur_dir, - 'file': relative_path, - 'command': prefix + relative_path, + 'directory': root_directory, + 'file': abs_path, + 'command': prefix + file_path, } @@ -122,7 +114,7 @@ def main(): result = line_matcher.match(f.readline()) if result: try: - entry = process_line(directory, dirpath, + entry = process_line(directory, result.group(1), result.group(2)) compile_commands.append(entry) except ValueError as err: -- cgit From 0a7d376d04a3c84b503f1efecde8f9d9a7430269 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:12 +0900 Subject: gen_compile_commands: reword the help message of -d option I think the help message of the -d option is somewhat misleading. Path to the kernel source directory to search (defaults to the working directory) The part "kernel source directory" is the source of the confusion. Some people misunderstand as if this script did not support separate output directories. Actually, this script also works for out-of-tree builds. You can use the -d option to point to the object output directory, not to the source directory. It should match to the O= option used in the previous kernel build, and then appears in the "directory" field of compile_commands.json. Reword the help message. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index 49fff0b0b385..f37c1dac8db4 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -31,13 +31,13 @@ def parse_arguments(): Returns: log_level: A logging level to filter log output. - directory: The directory to search for .cmd files. + directory: The work directory where the objects were built. output: Where to write the compile-commands JSON file. """ usage = 'Creates a compile_commands.json database from kernel .cmd files' parser = argparse.ArgumentParser(description=usage) - directory_help = ('Path to the kernel source directory to search ' + directory_help = ('specify the output directory used for the kernel build ' '(defaults to the working directory)') parser.add_argument('-d', '--directory', type=str, help=directory_help) -- cgit From 6fca36f1d82ad5bc385187f0aed93bbaefaa2172 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:13 +0900 Subject: gen_compile_commands: make -o option independent of -d option Change the -o option independent of the -d option, which is I think clearer behavior. Some people may like to use -d to specify a separate output directory, but still output the compile_commands.py in the source directory (unless the source tree is read-only) because it is the default location Clang Tools search for the compilation database. Also, move the default parameter to the default= argument of the .add_argument(). Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index f37c1dac8db4..71a0630ae188 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -39,11 +39,13 @@ def parse_arguments(): directory_help = ('specify the output directory used for the kernel build ' '(defaults to the working directory)') - parser.add_argument('-d', '--directory', type=str, help=directory_help) + parser.add_argument('-d', '--directory', type=str, default='.', + help=directory_help) - output_help = ('The location to write compile_commands.json (defaults to ' - 'compile_commands.json in the search directory)') - parser.add_argument('-o', '--output', type=str, help=output_help) + output_help = ('path to the output command database (defaults to ' + + _DEFAULT_OUTPUT + ')') + parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT, + help=output_help) log_level_help = ('the level of log messages to produce (defaults to ' + _DEFAULT_LOG_LEVEL + ')') @@ -52,11 +54,9 @@ def parse_arguments(): args = parser.parse_args() - directory = args.directory or os.getcwd() - output = args.output or os.path.join(directory, _DEFAULT_OUTPUT) - directory = os.path.abspath(directory) - - return args.log_level, directory, output + return (args.log_level, + os.path.abspath(args.directory), + args.output) def process_line(root_directory, command_prefix, file_path): -- cgit From fc2cb22ec61c1a537337cd0eba458863564a0e1f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:14 +0900 Subject: gen_compile_commands: move directory walk to a generator function Currently, this script walks under the specified directory (default to the current directory), then parses all .cmd files found. Split it into a separate helper function because the next commit will add more helpers to pick up .cmd files associated with given file(s). There is no point to build and return a huge list at once. I used a generator so it works in the for-loop with less memory. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 44 ++++++++++++++++++++++++++++++----------- 1 file changed, 32 insertions(+), 12 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index 71a0630ae188..e45f17be8817 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -33,6 +33,7 @@ def parse_arguments(): log_level: A logging level to filter log output. directory: The work directory where the objects were built. output: Where to write the compile-commands JSON file. + paths: The list of directories to handle to find .cmd files. """ usage = 'Creates a compile_commands.json database from kernel .cmd files' parser = argparse.ArgumentParser(description=usage) @@ -56,7 +57,28 @@ def parse_arguments(): return (args.log_level, os.path.abspath(args.directory), - args.output) + args.output, + [args.directory]) + + +def cmdfiles_in_dir(directory): + """Generate the iterator of .cmd files found under the directory. + + Walk under the given directory, and yield every .cmd file found. + + Args: + directory: The directory to search for .cmd files. + + Yields: + The path to a .cmd file. + """ + + filename_matcher = re.compile(_FILENAME_PATTERN) + + for dirpath, _, filenames in os.walk(directory): + for filename in filenames: + if filename_matcher.match(filename): + yield os.path.join(dirpath, filename) def process_line(root_directory, command_prefix, file_path): @@ -95,31 +117,29 @@ def process_line(root_directory, command_prefix, file_path): def main(): """Walks through the directory and finds and parses .cmd files.""" - log_level, directory, output = parse_arguments() + log_level, directory, output, paths = parse_arguments() level = getattr(logging, log_level) logging.basicConfig(format='%(levelname)s: %(message)s', level=level) - filename_matcher = re.compile(_FILENAME_PATTERN) line_matcher = re.compile(_LINE_PATTERN) compile_commands = [] - for dirpath, _, filenames in os.walk(directory): - for filename in filenames: - if not filename_matcher.match(filename): - continue - filepath = os.path.join(dirpath, filename) - with open(filepath, 'rt') as f: + for path in paths: + cmdfiles = cmdfiles_in_dir(path) + + for cmdfile in cmdfiles: + with open(cmdfile, 'rt') as f: result = line_matcher.match(f.readline()) if result: try: - entry = process_line(directory, - result.group(1), result.group(2)) + entry = process_line(directory, result.group(1), + result.group(2)) compile_commands.append(entry) except ValueError as err: logging.info('Could not add line from %s: %s', - filepath, err) + cmdfile, err) with open(output, 'wt') as f: json.dump(compile_commands, f, indent=2, sort_keys=True) -- cgit From ecca4fea1ede446e9ce3afa0b68b07fd1550f4f5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:15 +0900 Subject: gen_compile_commands: support *.o, *.a, modules.order in positional argument This script currently searches the specified directory for .cmd files. One drawback is it may contain stale .cmd files after you rebuild the kernel several times without 'make clean'. This commit supports *.o, *.a, and modules.order as positional parameters. If such files are given, they are parsed to collect associated .cmd files. I added a generator helper for each of them. This feature is useful to get the list of active .cmd files from the last build, and will be used by the next commit to wire up the compile_commands.json rule to the Makefile. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 100 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index e45f17be8817..92ea0a2ee59e 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -12,6 +12,7 @@ import json import logging import os import re +import subprocess _DEFAULT_OUTPUT = 'compile_commands.json' _DEFAULT_LOG_LEVEL = 'WARNING' @@ -32,8 +33,9 @@ def parse_arguments(): Returns: log_level: A logging level to filter log output. directory: The work directory where the objects were built. + ar: Command used for parsing .a archives. output: Where to write the compile-commands JSON file. - paths: The list of directories to handle to find .cmd files. + paths: The list of files/directories to handle to find .cmd files. """ usage = 'Creates a compile_commands.json database from kernel .cmd files' parser = argparse.ArgumentParser(description=usage) @@ -53,12 +55,21 @@ def parse_arguments(): parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS, default=_DEFAULT_LOG_LEVEL, help=log_level_help) + ar_help = 'command used for parsing .a archives' + parser.add_argument('-a', '--ar', type=str, default='llvm-ar', help=ar_help) + + paths_help = ('directories to search or files to parse ' + '(files should be *.o, *.a, or modules.order). ' + 'If nothing is specified, the current directory is searched') + parser.add_argument('paths', type=str, nargs='*', help=paths_help) + args = parser.parse_args() return (args.log_level, os.path.abspath(args.directory), args.output, - [args.directory]) + args.ar, + args.paths if len(args.paths) > 0 else [args.directory]) def cmdfiles_in_dir(directory): @@ -81,6 +92,73 @@ def cmdfiles_in_dir(directory): yield os.path.join(dirpath, filename) +def to_cmdfile(path): + """Return the path of .cmd file used for the given build artifact + + Args: + Path: file path + + Returns: + The path to .cmd file + """ + dir, base = os.path.split(path) + return os.path.join(dir, '.' + base + '.cmd') + + +def cmdfiles_for_o(obj): + """Generate the iterator of .cmd files associated with the object + + Yield the .cmd file used to build the given object + + Args: + obj: The object path + + Yields: + The path to .cmd file + """ + yield to_cmdfile(obj) + + +def cmdfiles_for_a(archive, ar): + """Generate the iterator of .cmd files associated with the archive. + + Parse the given archive, and yield every .cmd file used to build it. + + Args: + archive: The archive to parse + + Yields: + The path to every .cmd file found + """ + for obj in subprocess.check_output([ar, '-t', archive]).decode().split(): + yield to_cmdfile(obj) + + +def cmdfiles_for_modorder(modorder): + """Generate the iterator of .cmd files associated with the modules.order. + + Parse the given modules.order, and yield every .cmd file used to build the + contained modules. + + Args: + modorder: The modules.order file to parse + + Yields: + The path to every .cmd file found + """ + with open(modorder) as f: + for line in f: + ko = line.rstrip() + base, ext = os.path.splitext(ko) + if ext != '.ko': + sys.exit('{}: module path must end with .ko'.format(ko)) + mod = base + '.mod' + # The first line of *.mod lists the objects that compose the module. + with open(mod) as m: + for obj in m.readline().split(): + yield to_cmdfile(obj) + + def process_line(root_directory, command_prefix, file_path): """Extracts information from a .cmd line and creates an entry from it. @@ -117,7 +195,7 @@ def process_line(root_directory, command_prefix, file_path): def main(): """Walks through the directory and finds and parses .cmd files.""" - log_level, directory, output, paths = parse_arguments() + log_level, directory, output, ar, paths = parse_arguments() level = getattr(logging, log_level) logging.basicConfig(format='%(levelname)s: %(message)s', level=level) @@ -127,7 +205,21 @@ def main(): compile_commands = [] for path in paths: - cmdfiles = cmdfiles_in_dir(path) + # If 'path' is a directory, handle all .cmd files under it. + # Otherwise, handle .cmd files associated with the file. + # Most of built-in objects are linked via archives (built-in.a or lib.a) + # but some objects are linked to vmlinux directly. + # Modules are listed in modules.order. + if os.path.isdir(path): + cmdfiles = cmdfiles_in_dir(path) + elif path.endswith('.o'): + cmdfiles = cmdfiles_for_o(path) + elif path.endswith('.a'): + cmdfiles = cmdfiles_for_a(path, ar) + elif path.endswith('modules.order'): + cmdfiles = cmdfiles_for_modorder(path) + else: + sys.exit('{}: unknown file type'.format(path)) for cmdfile in cmdfiles: with open(cmdfile, 'rt') as f: -- cgit From 8b61f748e2a022f9028c612e44b68ad61caec474 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 22 Aug 2020 23:56:17 +0900 Subject: gen_compile_commands: remove the warning about too few .cmd files This warning was useful when users previously needed to manually build the kernel and run this script. Now you can simply do 'make compile_commands.json', which updates all the necessary build artifacts and automatically creates the compilation database. There is no more worry for a mistake like "Oh, I forgot to build the kernel". Now, this warning is rather annoying. You can create compile_commands.json for an external module: $ make M=/path/to/your/external/module compile_commands.json Then, this warning is displayed since there are usually less than 300 files in a single module. Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/gen_compile_commands.py | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'scripts') diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py index 92ea0a2ee59e..19963708bcf8 100755 --- a/scripts/gen_compile_commands.py +++ b/scripts/gen_compile_commands.py @@ -21,11 +21,6 @@ _FILENAME_PATTERN = r'^\..*\.cmd$' _LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$' _VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] -# A kernel build generally has over 2000 entries in its compile_commands.json -# database. If this code finds 300 or fewer, then warn the user that they might -# not have all the .cmd files, and they might need to compile the kernel. -_LOW_COUNT_THRESHOLD = 300 - def parse_arguments(): """Sets up and parses command-line arguments. @@ -236,11 +231,6 @@ def main(): with open(output, 'wt') as f: json.dump(compile_commands, f, indent=2, sort_keys=True) - count = len(compile_commands) - if count < _LOW_COUNT_THRESHOLD: - logging.warning( - 'Found %s entries. Have you compiled the kernel?', count) - if __name__ == '__main__': main() -- cgit From 6ad7cbc01527223f3f92baac9b122f15651cf76b Mon Sep 17 00:00:00 2001 From: Nathan Huckleberry Date: Sat, 22 Aug 2020 23:56:18 +0900 Subject: Makefile: Add clang-tidy and static analyzer support to makefile This patch adds clang-tidy and the clang static-analyzer as make targets. The goal of this patch is to make static analysis tools usable and extendable by any developer or researcher who is familiar with basic c++. The current static analysis tools require intimate knowledge of the internal workings of the static analysis. Clang-tidy and the clang static analyzers expose an easy to use api and allow users unfamiliar with clang to write new checks with relative ease. ===Clang-tidy=== Clang-tidy is an easily extendable 'linter' that runs on the AST. Clang-tidy checks are easy to write and understand. A check consists of two parts, a matcher and a checker. The matcher is created using a domain specific language that acts on the AST (https://clang.llvm.org/docs/LibASTMatchersReference.html). When AST nodes are found by the matcher a callback is made to the checker. The checker can then execute additional checks and issue warnings. Here is an example clang-tidy check to report functions that have calls to local_irq_disable without calls to local_irq_enable and vice-versa. Functions flagged with __attribute((annotation("ignore_irq_balancing"))) are ignored for analysis. (https://reviews.llvm.org/D65828) ===Clang static analyzer=== The clang static analyzer is a more powerful static analysis tool that uses symbolic execution to find bugs. Currently there is a check that looks for potential security bugs from invalid uses of kmalloc and kfree. There are several more general purpose checks that are useful for the kernel. The clang static analyzer is well documented and designed to be extensible. (https://clang-analyzer.llvm.org/checker_dev_manual.html) (https://github.com/haoNoQ/clang-analyzer-guide/releases/download/v0.1/clang-analyzer-guide-v0.1.pdf) The main draw of the clang tools is how accessible they are. The clang documentation is very nice and these tools are built specifically to be easily extendable by any developer. They provide an accessible method of bug-finding and research to people who are not overly familiar with the kernel codebase. Signed-off-by: Nathan Huckleberry Reviewed-by: Nick Desaulniers Tested-by: Nick Desaulniers Tested-by: Lukas Bulwahn Signed-off-by: Masahiro Yamada --- scripts/clang-tools/gen_compile_commands.py | 236 ++++++++++++++++++++++++++++ scripts/clang-tools/run-clang-tools.py | 74 +++++++++ scripts/gen_compile_commands.py | 236 ---------------------------- 3 files changed, 310 insertions(+), 236 deletions(-) create mode 100755 scripts/clang-tools/gen_compile_commands.py create mode 100755 scripts/clang-tools/run-clang-tools.py delete mode 100755 scripts/gen_compile_commands.py (limited to 'scripts') diff --git a/scripts/clang-tools/gen_compile_commands.py b/scripts/clang-tools/gen_compile_commands.py new file mode 100755 index 000000000000..19963708bcf8 --- /dev/null +++ b/scripts/clang-tools/gen_compile_commands.py @@ -0,0 +1,236 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) Google LLC, 2018 +# +# Author: Tom Roeder +# +"""A tool for generating compile_commands.json in the Linux kernel.""" + +import argparse +import json +import logging +import os +import re +import subprocess + +_DEFAULT_OUTPUT = 'compile_commands.json' +_DEFAULT_LOG_LEVEL = 'WARNING' + +_FILENAME_PATTERN = r'^\..*\.cmd$' +_LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$' +_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] + + +def parse_arguments(): + """Sets up and parses command-line arguments. + + Returns: + log_level: A logging level to filter log output. + directory: The work directory where the objects were built. + ar: Command used for parsing .a archives. + output: Where to write the compile-commands JSON file. + paths: The list of files/directories to handle to find .cmd files. + """ + usage = 'Creates a compile_commands.json database from kernel .cmd files' + parser = argparse.ArgumentParser(description=usage) + + directory_help = ('specify the output directory used for the kernel build ' + '(defaults to the working directory)') + parser.add_argument('-d', '--directory', type=str, default='.', + help=directory_help) + + output_help = ('path to the output command database (defaults to ' + + _DEFAULT_OUTPUT + ')') + parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT, + help=output_help) + + log_level_help = ('the level of log messages to produce (defaults to ' + + _DEFAULT_LOG_LEVEL + ')') + parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS, + default=_DEFAULT_LOG_LEVEL, help=log_level_help) + + ar_help = 'command used for parsing .a archives' + parser.add_argument('-a', '--ar', type=str, default='llvm-ar', help=ar_help) + + paths_help = ('directories to search or files to parse ' + '(files should be *.o, *.a, or modules.order). ' + 'If nothing is specified, the current directory is searched') + parser.add_argument('paths', type=str, nargs='*', help=paths_help) + + args = parser.parse_args() + + return (args.log_level, + os.path.abspath(args.directory), + args.output, + args.ar, + args.paths if len(args.paths) > 0 else [args.directory]) + + +def cmdfiles_in_dir(directory): + """Generate the iterator of .cmd files found under the directory. + + Walk under the given directory, and yield every .cmd file found. + + Args: + directory: The directory to search for .cmd files. + + Yields: + The path to a .cmd file. + """ + + filename_matcher = re.compile(_FILENAME_PATTERN) + + for dirpath, _, filenames in os.walk(directory): + for filename in filenames: + if filename_matcher.match(filename): + yield os.path.join(dirpath, filename) + + +def to_cmdfile(path): + """Return the path of .cmd file used for the given build artifact + + Args: + Path: file path + + Returns: + The path to .cmd file + """ + dir, base = os.path.split(path) + return os.path.join(dir, '.' + base + '.cmd') + + +def cmdfiles_for_o(obj): + """Generate the iterator of .cmd files associated with the object + + Yield the .cmd file used to build the given object + + Args: + obj: The object path + + Yields: + The path to .cmd file + """ + yield to_cmdfile(obj) + + +def cmdfiles_for_a(archive, ar): + """Generate the iterator of .cmd files associated with the archive. + + Parse the given archive, and yield every .cmd file used to build it. + + Args: + archive: The archive to parse + + Yields: + The path to every .cmd file found + """ + for obj in subprocess.check_output([ar, '-t', archive]).decode().split(): + yield to_cmdfile(obj) + + +def cmdfiles_for_modorder(modorder): + """Generate the iterator of .cmd files associated with the modules.order. + + Parse the given modules.order, and yield every .cmd file used to build the + contained modules. + + Args: + modorder: The modules.order file to parse + + Yields: + The path to every .cmd file found + """ + with open(modorder) as f: + for line in f: + ko = line.rstrip() + base, ext = os.path.splitext(ko) + if ext != '.ko': + sys.exit('{}: module path must end with .ko'.format(ko)) + mod = base + '.mod' + # The first line of *.mod lists the objects that compose the module. + with open(mod) as m: + for obj in m.readline().split(): + yield to_cmdfile(obj) + + +def process_line(root_directory, command_prefix, file_path): + """Extracts information from a .cmd line and creates an entry from it. + + Args: + root_directory: The directory that was searched for .cmd files. Usually + used directly in the "directory" entry in compile_commands.json. + command_prefix: The extracted command line, up to the last element. + file_path: The .c file from the end of the extracted command. + Usually relative to root_directory, but sometimes absolute. + + Returns: + An entry to append to compile_commands. + + Raises: + ValueError: Could not find the extracted file based on file_path and + root_directory or file_directory. + """ + # The .cmd files are intended to be included directly by Make, so they + # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the + # kernel version). The compile_commands.json file is not interepreted + # by Make, so this code replaces the escaped version with '#'. + prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#') + + # Use os.path.abspath() to normalize the path resolving '.' and '..' . + abs_path = os.path.abspath(os.path.join(root_directory, file_path)) + if not os.path.exists(abs_path): + raise ValueError('File %s not found' % abs_path) + return { + 'directory': root_directory, + 'file': abs_path, + 'command': prefix + file_path, + } + + +def main(): + """Walks through the directory and finds and parses .cmd files.""" + log_level, directory, output, ar, paths = parse_arguments() + + level = getattr(logging, log_level) + logging.basicConfig(format='%(levelname)s: %(message)s', level=level) + + line_matcher = re.compile(_LINE_PATTERN) + + compile_commands = [] + + for path in paths: + # If 'path' is a directory, handle all .cmd files under it. + # Otherwise, handle .cmd files associated with the file. + # Most of built-in objects are linked via archives (built-in.a or lib.a) + # but some objects are linked to vmlinux directly. + # Modules are listed in modules.order. + if os.path.isdir(path): + cmdfiles = cmdfiles_in_dir(path) + elif path.endswith('.o'): + cmdfiles = cmdfiles_for_o(path) + elif path.endswith('.a'): + cmdfiles = cmdfiles_for_a(path, ar) + elif path.endswith('modules.order'): + cmdfiles = cmdfiles_for_modorder(path) + else: + sys.exit('{}: unknown file type'.format(path)) + + for cmdfile in cmdfiles: + with open(cmdfile, 'rt') as f: + result = line_matcher.match(f.readline()) + if result: + try: + entry = process_line(directory, result.group(1), + result.group(2)) + compile_commands.append(entry) + except ValueError as err: + logging.info('Could not add line from %s: %s', + cmdfile, err) + + with open(output, 'wt') as f: + json.dump(compile_commands, f, indent=2, sort_keys=True) + + +if __name__ == '__main__': + main() diff --git a/scripts/clang-tools/run-clang-tools.py b/scripts/clang-tools/run-clang-tools.py new file mode 100755 index 000000000000..fa7655c7cec0 --- /dev/null +++ b/scripts/clang-tools/run-clang-tools.py @@ -0,0 +1,74 @@ +#!/usr/bin/env python +# SPDX-License-Identifier: GPL-2.0 +# +# Copyright (C) Google LLC, 2020 +# +# Author: Nathan Huckleberry +# +"""A helper routine run clang-tidy and the clang static-analyzer on +compile_commands.json. +""" + +import argparse +import json +import multiprocessing +import os +import subprocess +import sys + + +def parse_arguments(): + """Set up and parses command-line arguments. + Returns: + args: Dict of parsed args + Has keys: [path, type] + """ + usage = """Run clang-tidy or the clang static-analyzer on a + compilation database.""" + parser = argparse.ArgumentParser(description=usage) + + type_help = "Type of analysis to be performed" + parser.add_argument("type", + choices=["clang-tidy", "clang-analyzer"], + help=type_help) + path_help = "Path to the compilation database to parse" + parser.add_argument("path", type=str, help=path_help) + + return parser.parse_args() + + +def init(l, a): + global lock + global args + lock = l + args = a + + +def run_analysis(entry): + # Disable all checks, then re-enable the ones we want + checks = "-checks=-*," + if args.type == "clang-tidy": + checks += "linuxkernel-*" + else: + checks += "clang-analyzer-*" + p = subprocess.run(["clang-tidy", "-p", args.path, checks, entry["file"]], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + cwd=entry["directory"]) + with lock: + sys.stderr.buffer.write(p.stdout) + + +def main(): + args = parse_arguments() + + lock = multiprocessing.Lock() + pool = multiprocessing.Pool(initializer=init, initargs=(lock, args)) + # Read JSON data into the datastore variable + with open(args.path, "r") as f: + datastore = json.load(f) + pool.map(run_analysis, datastore) + + +if __name__ == "__main__": + main() diff --git a/scripts/gen_compile_commands.py b/scripts/gen_compile_commands.py deleted file mode 100755 index 19963708bcf8..000000000000 --- a/scripts/gen_compile_commands.py +++ /dev/null @@ -1,236 +0,0 @@ -#!/usr/bin/env python -# SPDX-License-Identifier: GPL-2.0 -# -# Copyright (C) Google LLC, 2018 -# -# Author: Tom Roeder -# -"""A tool for generating compile_commands.json in the Linux kernel.""" - -import argparse -import json -import logging -import os -import re -import subprocess - -_DEFAULT_OUTPUT = 'compile_commands.json' -_DEFAULT_LOG_LEVEL = 'WARNING' - -_FILENAME_PATTERN = r'^\..*\.cmd$' -_LINE_PATTERN = r'^cmd_[^ ]*\.o := (.* )([^ ]*\.c)$' -_VALID_LOG_LEVELS = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] - - -def parse_arguments(): - """Sets up and parses command-line arguments. - - Returns: - log_level: A logging level to filter log output. - directory: The work directory where the objects were built. - ar: Command used for parsing .a archives. - output: Where to write the compile-commands JSON file. - paths: The list of files/directories to handle to find .cmd files. - """ - usage = 'Creates a compile_commands.json database from kernel .cmd files' - parser = argparse.ArgumentParser(description=usage) - - directory_help = ('specify the output directory used for the kernel build ' - '(defaults to the working directory)') - parser.add_argument('-d', '--directory', type=str, default='.', - help=directory_help) - - output_help = ('path to the output command database (defaults to ' + - _DEFAULT_OUTPUT + ')') - parser.add_argument('-o', '--output', type=str, default=_DEFAULT_OUTPUT, - help=output_help) - - log_level_help = ('the level of log messages to produce (defaults to ' + - _DEFAULT_LOG_LEVEL + ')') - parser.add_argument('--log_level', choices=_VALID_LOG_LEVELS, - default=_DEFAULT_LOG_LEVEL, help=log_level_help) - - ar_help = 'command used for parsing .a archives' - parser.add_argument('-a', '--ar', type=str, default='llvm-ar', help=ar_help) - - paths_help = ('directories to search or files to parse ' - '(files should be *.o, *.a, or modules.order). ' - 'If nothing is specified, the current directory is searched') - parser.add_argument('paths', type=str, nargs='*', help=paths_help) - - args = parser.parse_args() - - return (args.log_level, - os.path.abspath(args.directory), - args.output, - args.ar, - args.paths if len(args.paths) > 0 else [args.directory]) - - -def cmdfiles_in_dir(directory): - """Generate the iterator of .cmd files found under the directory. - - Walk under the given directory, and yield every .cmd file found. - - Args: - directory: The directory to search for .cmd files. - - Yields: - The path to a .cmd file. - """ - - filename_matcher = re.compile(_FILENAME_PATTERN) - - for dirpath, _, filenames in os.walk(directory): - for filename in filenames: - if filename_matcher.match(filename): - yield os.path.join(dirpath, filename) - - -def to_cmdfile(path): - """Return the path of .cmd file used for the given build artifact - - Args: - Path: file path - - Returns: - The path to .cmd file - """ - dir, base = os.path.split(path) - return os.path.join(dir, '.' + base + '.cmd') - - -def cmdfiles_for_o(obj): - """Generate the iterator of .cmd files associated with the object - - Yield the .cmd file used to build the given object - - Args: - obj: The object path - - Yields: - The path to .cmd file - """ - yield to_cmdfile(obj) - - -def cmdfiles_for_a(archive, ar): - """Generate the iterator of .cmd files associated with the archive. - - Parse the given archive, and yield every .cmd file used to build it. - - Args: - archive: The archive to parse - - Yields: - The path to every .cmd file found - """ - for obj in subprocess.check_output([ar, '-t', archive]).decode().split(): - yield to_cmdfile(obj) - - -def cmdfiles_for_modorder(modorder): - """Generate the iterator of .cmd files associated with the modules.order. - - Parse the given modules.order, and yield every .cmd file used to build the - contained modules. - - Args: - modorder: The modules.order file to parse - - Yields: - The path to every .cmd file found - """ - with open(modorder) as f: - for line in f: - ko = line.rstrip() - base, ext = os.path.splitext(ko) - if ext != '.ko': - sys.exit('{}: module path must end with .ko'.format(ko)) - mod = base + '.mod' - # The first line of *.mod lists the objects that compose the module. - with open(mod) as m: - for obj in m.readline().split(): - yield to_cmdfile(obj) - - -def process_line(root_directory, command_prefix, file_path): - """Extracts information from a .cmd line and creates an entry from it. - - Args: - root_directory: The directory that was searched for .cmd files. Usually - used directly in the "directory" entry in compile_commands.json. - command_prefix: The extracted command line, up to the last element. - file_path: The .c file from the end of the extracted command. - Usually relative to root_directory, but sometimes absolute. - - Returns: - An entry to append to compile_commands. - - Raises: - ValueError: Could not find the extracted file based on file_path and - root_directory or file_directory. - """ - # The .cmd files are intended to be included directly by Make, so they - # escape the pound sign '#', either as '\#' or '$(pound)' (depending on the - # kernel version). The compile_commands.json file is not interepreted - # by Make, so this code replaces the escaped version with '#'. - prefix = command_prefix.replace('\#', '#').replace('$(pound)', '#') - - # Use os.path.abspath() to normalize the path resolving '.' and '..' . - abs_path = os.path.abspath(os.path.join(root_directory, file_path)) - if not os.path.exists(abs_path): - raise ValueError('File %s not found' % abs_path) - return { - 'directory': root_directory, - 'file': abs_path, - 'command': prefix + file_path, - } - - -def main(): - """Walks through the directory and finds and parses .cmd files.""" - log_level, directory, output, ar, paths = parse_arguments() - - level = getattr(logging, log_level) - logging.basicConfig(format='%(levelname)s: %(message)s', level=level) - - line_matcher = re.compile(_LINE_PATTERN) - - compile_commands = [] - - for path in paths: - # If 'path' is a directory, handle all .cmd files under it. - # Otherwise, handle .cmd files associated with the file. - # Most of built-in objects are linked via archives (built-in.a or lib.a) - # but some objects are linked to vmlinux directly. - # Modules are listed in modules.order. - if os.path.isdir(path): - cmdfiles = cmdfiles_in_dir(path) - elif path.endswith('.o'): - cmdfiles = cmdfiles_for_o(path) - elif path.endswith('.a'): - cmdfiles = cmdfiles_for_a(path, ar) - elif path.endswith('modules.order'): - cmdfiles = cmdfiles_for_modorder(path) - else: - sys.exit('{}: unknown file type'.format(path)) - - for cmdfile in cmdfiles: - with open(cmdfile, 'rt') as f: - result = line_matcher.match(f.readline()) - if result: - try: - entry = process_line(directory, result.group(1), - result.group(2)) - compile_commands.append(entry) - except ValueError as err: - logging.info('Could not add line from %s: %s', - cmdfile, err) - - with open(output, 'wt') as f: - json.dump(compile_commands, f, indent=2, sort_keys=True) - - -if __name__ == '__main__': - main() -- cgit From 4fcadb39c6b298e105d827741e0b7a6b146633e5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 5 Aug 2020 11:14:38 -0700 Subject: spelling.txt: Remove some duplicate entries Found when Colin King fixed a typo for falied/failed and a git grep showed 2 entries in this file. Signed-off-by: Joe Perches Acked-by: Colin Ian King Signed-off-by: Jiri Kosina --- scripts/spelling.txt | 4 ---- 1 file changed, 4 deletions(-) (limited to 'scripts') diff --git a/scripts/spelling.txt b/scripts/spelling.txt index f253681e7e2a..b703e4fd51e8 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -596,7 +596,6 @@ extenstion||extension extracter||extractor faied||failed faield||failed -falied||failed faild||failed failded||failed failer||failure @@ -793,7 +792,6 @@ interrup||interrupt interrups||interrupts interruptted||interrupted interupted||interrupted -interupt||interrupt intial||initial intialisation||initialisation intialised||initialised @@ -968,7 +966,6 @@ occurd||occurred occured||occurred occurence||occurrence occure||occurred -occured||occurred occuring||occurring offser||offset offet||offset @@ -1437,7 +1434,6 @@ udpate||update uesd||used uknown||unknown usccess||success -usupported||unsupported uncommited||uncommitted uncompatible||incompatible unconditionaly||unconditionally -- cgit From 5e0c074e5b4be02d57d1b60abc3391afe7edd088 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Wed, 2 Sep 2020 07:40:59 +0300 Subject: coccinelle: ifnullfree: add vfree(), kvfree*() functions Extend the list of free functions with kvfree(), kvfree_sensitive(), vfree(). Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/free/ifnullfree.cocci | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/coccinelle/free/ifnullfree.cocci b/scripts/coccinelle/free/ifnullfree.cocci index 2045391e36a0..285b92d5c665 100644 --- a/scripts/coccinelle/free/ifnullfree.cocci +++ b/scripts/coccinelle/free/ifnullfree.cocci @@ -20,8 +20,14 @@ expression E; - if (E != NULL) ( kfree(E); +| + kvfree(E); | kfree_sensitive(E); +| + kvfree_sensitive(E, ...); +| + vfree(E); | debugfs_remove(E); | @@ -42,9 +48,10 @@ position p; @@ * if (E != NULL) -* \(kfree@p\|kfree_sensitive@p\|debugfs_remove@p\|debugfs_remove_recursive@p\| +* \(kfree@p\|kvfree@p\|kfree_sensitive@p\|kvfree_sensitive@p\|vfree@p\| +* debugfs_remove@p\|debugfs_remove_recursive@p\| * usb_free_urb@p\|kmem_cache_destroy@p\|mempool_destroy@p\| -* dma_pool_destroy@p\)(E); +* dma_pool_destroy@p\)(E, ...); @script:python depends on org@ p << r.p; -- cgit From 51fae39bd5018e4f6d3e65a1a1a8ad40b5ee3662 Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Tue, 1 Sep 2020 15:48:42 -0700 Subject: scripts/dev-needs: Add script to list device dependencies This script can be useful for: - Figuring out the list of modules you need to pack in initrd - Figuring out the list of drivers you need to modularize for a device to be fully functional without building in any dependencies. - Figuring out which drivers to enable first, when porting drivers between kernels (say, to upstream). - Plotting graphs of system dependencies, etc. Usage: dev-needs.sh [-c|-d|-m|-f] [filter options] This script needs to be run on the target device once it has booted to a shell. The script takes as input a list of one or more device directories under /sys/devices and then lists the probe dependency chain (suppliers and parents) of these devices. It does a breadth first search of the dependency chain, so the last entry in the output is close to the root of the dependency chain. By default it lists the full path to the devices under /sys/devices. It also takes an optional modifier flag as the first parameter to change what information is listed in the output. If the requested information is not available, the device name is printed. -c lists the compatible string of the dependencies -d lists the driver name of the dependencies that have probed -m lists the module name of the dependencies that have a module -f list the firmware node path of the dependencies -g list the dependencies as edges and nodes for graphviz -t list the dependencies as edges for tsort The filter options provide a way to filter out some dependencies: --allow-no-driver By default dependencies that don't have a driver attached are ignored. This is to avoid following device links to "class" devices that are created when the consumer probes (as in, not a probe dependency). If you want to follow these links anyway, use this flag. --exclude-devlinks Don't follow device links when tracking probe dependencies. --exclude-parents Don't follow parent devices when tracking probe dependencies. Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20200901224842.1787825-1-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- scripts/dev-needs.sh | 315 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100755 scripts/dev-needs.sh (limited to 'scripts') diff --git a/scripts/dev-needs.sh b/scripts/dev-needs.sh new file mode 100755 index 000000000000..454cc304fb44 --- /dev/null +++ b/scripts/dev-needs.sh @@ -0,0 +1,315 @@ +#! /bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Copyright (c) 2020, Google LLC. All rights reserved. +# Author: Saravana Kannan + +function help() { + cat << EOF +Usage: $(basename $0) [-c|-d|-m|-f] [filter options] + +This script needs to be run on the target device once it has booted to a +shell. + +The script takes as input a list of one or more device directories under +/sys/devices and then lists the probe dependency chain (suppliers and +parents) of these devices. It does a breadth first search of the dependency +chain, so the last entry in the output is close to the root of the +dependency chain. + +By default it lists the full path to the devices under /sys/devices. + +It also takes an optional modifier flag as the first parameter to change +what information is listed in the output. If the requested information is +not available, the device name is printed. + + -c lists the compatible string of the dependencies + -d lists the driver name of the dependencies that have probed + -m lists the module name of the dependencies that have a module + -f list the firmware node path of the dependencies + -g list the dependencies as edges and nodes for graphviz + -t list the dependencies as edges for tsort + +The filter options provide a way to filter out some dependencies: + --allow-no-driver By default dependencies that don't have a driver + attached are ignored. This is to avoid following + device links to "class" devices that are created + when the consumer probes (as in, not a probe + dependency). If you want to follow these links + anyway, use this flag. + + --exclude-devlinks Don't follow device links when tracking probe + dependencies. + + --exclude-parents Don't follow parent devices when tracking probe + dependencies. + +EOF +} + +function dev_to_detail() { + local i=0 + while [ $i -lt ${#OUT_LIST[@]} ] + do + local C=${OUT_LIST[i]} + local S=${OUT_LIST[i+1]} + local D="'$(detail_chosen $C $S)'" + if [ ! -z "$D" ] + then + # This weirdness is needed to work with toybox when + # using the -t option. + printf '%05u\t%s\n' ${i} "$D" | tr -d \' + fi + i=$((i+2)) + done +} + +function already_seen() { + local i=0 + while [ $i -lt ${#OUT_LIST[@]} ] + do + if [ "$1" = "${OUT_LIST[$i]}" ] + then + # if-statement treats 0 (no-error) as true + return 0 + fi + i=$(($i+2)) + done + + # if-statement treats 1 (error) as false + return 1 +} + +# Return 0 (no-error/true) if parent was added +function add_parent() { + + if [ ${ALLOW_PARENTS} -eq 0 ] + then + return 1 + fi + + local CON=$1 + # $CON could be a symlink path. So, we need to find the real path and + # then go up one level to find the real parent. + local PARENT=$(realpath $CON/..) + + while [ ! -e ${PARENT}/driver ] + do + if [ "$PARENT" = "/sys/devices" ] + then + return 1 + fi + PARENT=$(realpath $PARENT/..) + done + + CONSUMERS+=($PARENT) + OUT_LIST+=(${CON} ${PARENT}) + return 0 +} + +# Return 0 (no-error/true) if one or more suppliers were added +function add_suppliers() { + local CON=$1 + local RET=1 + + if [ ${ALLOW_DEVLINKS} -eq 0 ] + then + return 1 + fi + + SUPPLIER_LINKS=$(ls -1d $CON/supplier:* 2>/dev/null) + for SL in $SUPPLIER_LINKS; + do + SYNC_STATE=$(cat $SL/sync_state_only) + + # sync_state_only links are proxy dependencies. + # They can also have cycles. So, don't follow them. + if [ "$SYNC_STATE" != '0' ] + then + continue + fi + + SUPPLIER=$(realpath $SL/supplier) + + if [ ! -e $SUPPLIER/driver -a ${ALLOW_NO_DRIVER} -eq 0 ] + then + continue + fi + + CONSUMERS+=($SUPPLIER) + OUT_LIST+=(${CON} ${SUPPLIER}) + RET=0 + done + + return $RET +} + +function detail_compat() { + f=$1/of_node/compatible + if [ -e $f ] + then + echo -n $(cat $f) + else + echo -n $1 + fi +} + +function detail_module() { + f=$1/driver/module + if [ -e $f ] + then + echo -n $(basename $(realpath $f)) + else + echo -n $1 + fi +} + +function detail_driver() { + f=$1/driver + if [ -e $f ] + then + echo -n $(basename $(realpath $f)) + else + echo -n $1 + fi +} + +function detail_fwnode() { + f=$1/firmware_node + if [ ! -e $f ] + then + f=$1/of_node + fi + + if [ -e $f ] + then + echo -n $(realpath $f) + else + echo -n $1 + fi +} + +function detail_graphviz() { + if [ "$2" != "ROOT" ] + then + echo -n "\"$(basename $2)\"->\"$(basename $1)\"" + else + echo -n "\"$(basename $1)\"" + fi +} + +function detail_tsort() { + echo -n "\"$2\" \"$1\"" +} + +function detail_device() { echo -n $1; } + +alias detail=detail_device +ALLOW_NO_DRIVER=0 +ALLOW_DEVLINKS=1 +ALLOW_PARENTS=1 + +while [ $# -gt 0 ] +do + ARG=$1 + case $ARG in + --help) + help + exit 0 + ;; + -c) + alias detail=detail_compat + ;; + -m) + alias detail=detail_module + ;; + -d) + alias detail=detail_driver + ;; + -f) + alias detail=detail_fwnode + ;; + -g) + alias detail=detail_graphviz + ;; + -t) + alias detail=detail_tsort + ;; + --allow-no-driver) + ALLOW_NO_DRIVER=1 + ;; + --exclude-devlinks) + ALLOW_DEVLINKS=0 + ;; + --exclude-parents) + ALLOW_PARENTS=0 + ;; + *) + # Stop at the first argument that's not an option. + break + ;; + esac + shift +done + +function detail_chosen() { + detail $1 $2 +} + +if [ $# -eq 0 ] +then + help + exit 1 +fi + +CONSUMERS=($@) +OUT_LIST=() + +# Do a breadth first, non-recursive tracking of suppliers. The parent is also +# considered a "supplier" as a device can't probe without its parent. +i=0 +while [ $i -lt ${#CONSUMERS[@]} ] +do + CONSUMER=$(realpath ${CONSUMERS[$i]}) + i=$(($i+1)) + + if already_seen ${CONSUMER} + then + continue + fi + + # If this is not a device with a driver, we don't care about its + # suppliers. + if [ ! -e ${CONSUMER}/driver -a ${ALLOW_NO_DRIVER} -eq 0 ] + then + continue + fi + + ROOT=1 + + # Add suppliers to CONSUMERS list and output the consumer details. + # + # We don't need to worry about a cycle in the dependency chain causing + # infinite loops. That's because the kernel doesn't allow cycles in + # device links unless it's a sync_state_only device link. And we ignore + # sync_state_only device links inside add_suppliers. + if add_suppliers ${CONSUMER} + then + ROOT=0 + fi + + if add_parent ${CONSUMER} + then + ROOT=0 + fi + + if [ $ROOT -eq 1 ] + then + OUT_LIST+=(${CONSUMER} "ROOT") + fi +done + +# Can NOT combine sort and uniq using sort -suk2 because stable sort in toybox +# isn't really stable. +dev_to_detail | sort -k2 -k1 | uniq -f 1 | sort | cut -f2- + +exit 0 -- cgit From 7c9dc603d55617edcc3190f9a6d7b5cf763feb57 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 1 Sep 2020 12:48:12 +0300 Subject: coccinelle: misc: add uninitialized_var.cocci script uninitialized_var() macro was removed from the sources [1] and other warning-silencing tricks were deprecated [2]. The purpose of this cocci script is to prevent new occurrences of uninitialized_var() open-coded variants. [1] commit 63a0895d960a ("compiler: Remove uninitialized_var() macro") [2] commit 4b19bec97c88 ("docs: deprecated.rst: Add uninitialized_var()") Cc: Kees Cook Cc: Gustavo A. R. Silva Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/misc/uninitialized_var.cocci | 51 +++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 scripts/coccinelle/misc/uninitialized_var.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/misc/uninitialized_var.cocci b/scripts/coccinelle/misc/uninitialized_var.cocci new file mode 100644 index 000000000000..8fa845cefe11 --- /dev/null +++ b/scripts/coccinelle/misc/uninitialized_var.cocci @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Please, don't reintroduce uninitialized_var(). +/// From Documentation/process/deprecated.rst: +/// For any compiler warnings about uninitialized variables, just add +/// an initializer. Using warning-silencing tricks is dangerous as it +/// papers over real bugs (or can in the future), and suppresses unrelated +/// compiler warnings (e.g. "unused variable"). If the compiler thinks it +/// is uninitialized, either simply initialize the variable or make compiler +/// changes. Keep in mind that in most cases, if an initialization is +/// obviously redundant, the compiler's dead-store elimination pass will make +/// sure there are no needless variable writes. +/// +// Confidence: High +// Copyright: (C) 2020 Denis Efremov ISPRAS +// Options: --no-includes --include-headers +// + +virtual context +virtual report +virtual org + +@r@ +identifier var; +type T; +position p; +@@ + +( +* T var =@p var; +| +* T var =@p *(&(var)); +| +* var =@p var +| +* var =@p *(&(var)) +) + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], + "WARNING this kind of initialization is deprecated (https://www.kernel.org/doc/html/latest/process/deprecated.html#uninitialized-var)") + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], + "WARNING this kind of initialization is deprecated (https://www.kernel.org/doc/html/latest/process/deprecated.html#uninitialized-var)") -- cgit From 3e0d075cb0ab3b1fbddc14855985215407f8a48b Mon Sep 17 00:00:00 2001 From: John Ogness Date: Fri, 14 Aug 2020 23:31:24 +0206 Subject: scripts/gdb: add utils.read_ulong() Add a function for reading unsigned long values, which vary in size depending on the architecture. Signed-off-by: John Ogness Reviewed-by: Nick Desaulniers Tested-by: Nick Desaulniers Tested-by: Petr Mladek Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20200814212525.6118-2-john.ogness@linutronix.de --- scripts/gdb/linux/utils.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'scripts') diff --git a/scripts/gdb/linux/utils.py b/scripts/gdb/linux/utils.py index ea94221dbd39..ff7c1799d588 100644 --- a/scripts/gdb/linux/utils.py +++ b/scripts/gdb/linux/utils.py @@ -123,6 +123,13 @@ def read_u64(buffer, offset): return read_u32(buffer, offset + 4) + (read_u32(buffer, offset) << 32) +def read_ulong(buffer, offset): + if get_long_type().sizeof == 8: + return read_u64(buffer, offset) + else: + return read_u32(buffer, offset) + + target_arch = None -- cgit From e60768311af854734ce2bbfc50f24cff67b54a91 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Fri, 14 Aug 2020 23:31:25 +0206 Subject: scripts/gdb: update for lockless printk ringbuffer With the introduction of the lockless printk ringbuffer, the data structure for the kernel log buffer was changed. Update the gdb scripts to be able to parse/print the new log buffer structure. Fixes: 896fbe20b4e2333fb55 ("printk: use the lockless ringbuffer") Signed-off-by: John Ogness Reported-by: Nick Desaulniers Tested-by: Nick Desaulniers Tested-by: Petr Mladek [akpm@linux-foundation.org: A typo fix.] Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20200814212525.6118-3-john.ogness@linutronix.de --- scripts/gdb/linux/dmesg.py | 139 +++++++++++++++++++++++++++++++++------------ 1 file changed, 102 insertions(+), 37 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py index 2fa7bb83885f..6c6022012ea8 100644 --- a/scripts/gdb/linux/dmesg.py +++ b/scripts/gdb/linux/dmesg.py @@ -16,8 +16,13 @@ import sys from linux import utils -printk_log_type = utils.CachedType("struct printk_log") - +printk_info_type = utils.CachedType("struct printk_info") +prb_data_blk_lpos_type = utils.CachedType("struct prb_data_blk_lpos") +prb_desc_type = utils.CachedType("struct prb_desc") +prb_desc_ring_type = utils.CachedType("struct prb_desc_ring") +prb_data_ring_type = utils.CachedType("struct prb_data_ring") +printk_ringbuffer_type = utils.CachedType("struct printk_ringbuffer") +atomic_long_type = utils.CachedType("atomic_long_t") class LxDmesg(gdb.Command): """Print Linux kernel log buffer.""" @@ -26,44 +31,102 @@ class LxDmesg(gdb.Command): super(LxDmesg, self).__init__("lx-dmesg", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): - log_buf_addr = int(str(gdb.parse_and_eval( - "(void *)'printk.c'::log_buf")).split()[0], 16) - log_first_idx = int(gdb.parse_and_eval("'printk.c'::log_first_idx")) - log_next_idx = int(gdb.parse_and_eval("'printk.c'::log_next_idx")) - log_buf_len = int(gdb.parse_and_eval("'printk.c'::log_buf_len")) - inf = gdb.inferiors()[0] - start = log_buf_addr + log_first_idx - if log_first_idx < log_next_idx: - log_buf_2nd_half = -1 - length = log_next_idx - log_first_idx - log_buf = utils.read_memoryview(inf, start, length).tobytes() - else: - log_buf_2nd_half = log_buf_len - log_first_idx - a = utils.read_memoryview(inf, start, log_buf_2nd_half) - b = utils.read_memoryview(inf, log_buf_addr, log_next_idx) - log_buf = a.tobytes() + b.tobytes() - - length_offset = printk_log_type.get_type()['len'].bitpos // 8 - text_len_offset = printk_log_type.get_type()['text_len'].bitpos // 8 - time_stamp_offset = printk_log_type.get_type()['ts_nsec'].bitpos // 8 - text_offset = printk_log_type.get_type().sizeof - - pos = 0 - while pos < log_buf.__len__(): - length = utils.read_u16(log_buf, pos + length_offset) - if length == 0: - if log_buf_2nd_half == -1: - gdb.write("Corrupted log buffer!\n") + + # read in prb structure + prb_addr = int(str(gdb.parse_and_eval("(void *)'printk.c'::prb")).split()[0], 16) + sz = printk_ringbuffer_type.get_type().sizeof + prb = utils.read_memoryview(inf, prb_addr, sz).tobytes() + + # read in descriptor ring structure + off = printk_ringbuffer_type.get_type()['desc_ring'].bitpos // 8 + addr = prb_addr + off + sz = prb_desc_ring_type.get_type().sizeof + desc_ring = utils.read_memoryview(inf, addr, sz).tobytes() + + # read in descriptor array + off = prb_desc_ring_type.get_type()['count_bits'].bitpos // 8 + desc_ring_count = 1 << utils.read_u32(desc_ring, off) + desc_sz = prb_desc_type.get_type().sizeof + off = prb_desc_ring_type.get_type()['descs'].bitpos // 8 + addr = utils.read_ulong(desc_ring, off) + descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes() + + # read in text data ring structure + off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8 + addr = prb_addr + off + sz = prb_data_ring_type.get_type().sizeof + text_data_ring = utils.read_memoryview(inf, addr, sz).tobytes() + + # read in text data + off = prb_data_ring_type.get_type()['size_bits'].bitpos // 8 + text_data_sz = 1 << utils.read_u32(text_data_ring, off) + off = prb_data_ring_type.get_type()['data'].bitpos // 8 + addr = utils.read_ulong(text_data_ring, off) + text_data = utils.read_memoryview(inf, addr, text_data_sz).tobytes() + + counter_off = atomic_long_type.get_type()['counter'].bitpos // 8 + + sv_off = prb_desc_type.get_type()['state_var'].bitpos // 8 + + off = prb_desc_type.get_type()['text_blk_lpos'].bitpos // 8 + begin_off = off + (prb_data_blk_lpos_type.get_type()['begin'].bitpos // 8) + next_off = off + (prb_data_blk_lpos_type.get_type()['next'].bitpos // 8) + + off = prb_desc_type.get_type()['info'].bitpos // 8 + ts_off = off + printk_info_type.get_type()['ts_nsec'].bitpos // 8 + len_off = off + printk_info_type.get_type()['text_len'].bitpos // 8 + + # definitions from kernel/printk/printk_ringbuffer.h + desc_sv_bits = utils.get_long_type().sizeof * 8 + desc_committed_mask = 1 << (desc_sv_bits - 1) + desc_reuse_mask = 1 << (desc_sv_bits - 2) + desc_flags_mask = desc_committed_mask | desc_reuse_mask + desc_id_mask = ~desc_flags_mask + + # read in tail and head descriptor ids + off = prb_desc_ring_type.get_type()['tail_id'].bitpos // 8 + tail_id = utils.read_u64(desc_ring, off + counter_off) + off = prb_desc_ring_type.get_type()['head_id'].bitpos // 8 + head_id = utils.read_u64(desc_ring, off + counter_off) + + did = tail_id + while True: + ind = did % desc_ring_count + desc_off = desc_sz * ind + + # skip non-committed record + state = utils.read_u64(descs, desc_off + sv_off + counter_off) & desc_flags_mask + if state != desc_committed_mask: + if did == head_id: break - pos = log_buf_2nd_half + did = (did + 1) & desc_id_mask continue - text_len = utils.read_u16(log_buf, pos + text_len_offset) - text_start = pos + text_offset - text = log_buf[text_start:text_start + text_len].decode( - encoding='utf8', errors='replace') - time_stamp = utils.read_u64(log_buf, pos + time_stamp_offset) + begin = utils.read_ulong(descs, desc_off + begin_off) % text_data_sz + end = utils.read_ulong(descs, desc_off + next_off) % text_data_sz + + # handle data-less record + if begin & 1 == 1: + text = "" + else: + # handle wrapping data block + if begin > end: + begin = 0 + + # skip over descriptor id + text_start = begin + utils.get_long_type().sizeof + + text_len = utils.read_u16(descs, desc_off + len_off) + + # handle truncated message + if end - text_start < text_len: + text_len = end - text_start + + text = text_data[text_start:text_start + text_len].decode( + encoding='utf8', errors='replace') + + time_stamp = utils.read_u64(descs, desc_off + ts_off) for line in text.splitlines(): msg = u"[{time:12.6f}] {line}\n".format( @@ -75,7 +138,9 @@ class LxDmesg(gdb.Command): msg = msg.encode(encoding='utf8', errors='replace') gdb.write(msg) - pos += length + if did == head_id: + break + did = (did + 1) & desc_id_mask LxDmesg() -- cgit From 5eb6b4b3e21612be735fe0305c27bfe2e7ab3224 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 9 Sep 2020 16:10:33 +0200 Subject: kernel-doc: include line numbers for function prototypes This should solve bad error reports like this one: ./include/linux/iio/iio.h:0: WARNING: Unknown target name: "devm". Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/56eed0ba50cd726236acd12b11b55ce54854c5ea.1599660067.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index d1b445665ad6..3982d47048a7 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1594,6 +1594,8 @@ sub dump_function($$) { my $file = shift; my $noret = 0; + print_lineno($.); + $prototype =~ s/^static +//; $prototype =~ s/^extern +//; $prototype =~ s/^asmlinkage +//; -- cgit From c9a6bef24e6d70a8293d0d84165a634ae5bf3982 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 9 Sep 2020 16:10:43 +0200 Subject: scripts: device_attr_show.cocci: update location of sysfs doc sysfs.txt was converted and renamed to sysfs.rst. Update device_attr_show.cocci script accordingly. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/048ed24b09aefa0051d76396d6250e35e6ba035c.1599660067.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/coccinelle/api/device_attr_show.cocci | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/coccinelle/api/device_attr_show.cocci b/scripts/coccinelle/api/device_attr_show.cocci index d8ec4bb8ac41..a28dc061653a 100644 --- a/scripts/coccinelle/api/device_attr_show.cocci +++ b/scripts/coccinelle/api/device_attr_show.cocci @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /// -/// From Documentation/filesystems/sysfs.txt: +/// From Documentation/filesystems/sysfs.rst: /// show() must not use snprintf() when formatting the value to be /// returned to user space. If you can guarantee that an overflow /// will never happen you can use sprintf() otherwise you must use -- cgit From 6519a5ab1a9ffe5cf8056f688a69960bf126e723 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Tue, 11 Aug 2020 10:49:53 +0300 Subject: coccinelle: api: update kzfree script to kfree_sensitive Commit 453431a54934 ("mm, treewide: rename kzfree() to kfree_sensitive()") renames kzfree to kfree_sensitive and uses memzero_explicit(...) instead of memset(..., 0, ...) internally. Update cocci script to reflect these changes. Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/api/kfree_sensitive.cocci | 98 ++++++++++++++++++++++++++ scripts/coccinelle/api/kzfree.cocci | 101 --------------------------- 2 files changed, 98 insertions(+), 101 deletions(-) create mode 100644 scripts/coccinelle/api/kfree_sensitive.cocci delete mode 100644 scripts/coccinelle/api/kzfree.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/api/kfree_sensitive.cocci b/scripts/coccinelle/api/kfree_sensitive.cocci new file mode 100644 index 000000000000..e4a066a0b77d --- /dev/null +++ b/scripts/coccinelle/api/kfree_sensitive.cocci @@ -0,0 +1,98 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Use kfree_sensitive, kvfree_sensitive rather than memset or +/// memzero_explicit followed by kfree. +/// +// Confidence: High +// Copyright: (C) 2020 Denis Efremov ISPRAS +// Options: --no-includes --include-headers +// +// Keywords: kfree_sensitive, kvfree_sensitive +// + +virtual context +virtual patch +virtual org +virtual report + +@initialize:python@ +@@ +# kmalloc_oob_in_memset uses memset to explicitly trigger out-of-bounds access +filter = frozenset(['kmalloc_oob_in_memset', + 'kfree_sensitive', 'kvfree_sensitive']) + +def relevant(p): + return not (filter & {el.current_element for el in p}) + +@cond@ +position ok; +@@ + +if (...) + \(memset@ok\|memzero_explicit@ok\)(...); + +@r depends on !patch forall@ +expression E; +position p : script:python() { relevant(p) }; +position m != cond.ok; +type T; +@@ + +( +* memset@m((T)E, 0, ...); +| +* memzero_explicit@m((T)E, ...); +) + ... when != E + when strict +* \(kfree\|vfree\|kvfree\)(E)@p; + +@rp_memzero depends on patch@ +expression E, size; +position p : script:python() { relevant(p) }; +position m != cond.ok; +type T; +@@ + +- memzero_explicit@m((T)E, size); + ... when != E + when strict +( +- kfree(E)@p; ++ kfree_sensitive(E); +| +- \(vfree\|kvfree\)(E)@p; ++ kvfree_sensitive(E, size); +) + +@rp_memset depends on patch@ +expression E, size; +position p : script:python() { relevant(p) }; +position m != cond.ok; +type T; +@@ + +- memset@m((T)E, 0, size); + ... when != E + when strict +( +- kfree(E)@p; ++ kfree_sensitive(E); +| +- \(vfree\|kvfree\)(E)@p; ++ kvfree_sensitive(E, size); +) + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], + "WARNING: opportunity for kfree_sensitive/kvfree_sensitive") + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], + "WARNING: opportunity for kfree_sensitive/kvfree_sensitive") diff --git a/scripts/coccinelle/api/kzfree.cocci b/scripts/coccinelle/api/kzfree.cocci deleted file mode 100644 index 33625bd7cec9..000000000000 --- a/scripts/coccinelle/api/kzfree.cocci +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/// -/// Use kzfree, kvfree_sensitive rather than memset or -/// memzero_explicit followed by kfree -/// -// Confidence: High -// Copyright: (C) 2020 Denis Efremov ISPRAS -// Options: --no-includes --include-headers -// -// Keywords: kzfree, kvfree_sensitive -// - -virtual context -virtual patch -virtual org -virtual report - -@initialize:python@ -@@ -# kmalloc_oob_in_memset uses memset to explicitly trigger out-of-bounds access -filter = frozenset(['kmalloc_oob_in_memset', 'kzfree', 'kvfree_sensitive']) - -def relevant(p): - return not (filter & {el.current_element for el in p}) - -@cond@ -position ok; -@@ - -if (...) - \(memset@ok\|memzero_explicit@ok\)(...); - -@r depends on !patch forall@ -expression E; -position p : script:python() { relevant(p) }; -position m != cond.ok; -type T; -@@ - -( -* memset@m((T)E, 0, ...); -| -* memzero_explicit@m((T)E, ...); -) - ... when != E - when strict -* \(kfree\|vfree\|kvfree\)(E)@p; - -@rp_memzero depends on patch@ -expression E, size; -position p : script:python() { relevant(p) }; -position m != cond.ok; -type T; -@@ - -- memzero_explicit@m((T)E, size); - ... when != E - when strict -// TODO: uncomment when kfree_sensitive will be merged. -// Only this case is commented out because developers -// may not like patches like this since kzfree uses memset -// internally (not memzero_explicit). -//( -//- kfree(E)@p; -//+ kfree_sensitive(E); -//| -- \(vfree\|kvfree\)(E)@p; -+ kvfree_sensitive(E, size); -//) - -@rp_memset depends on patch@ -expression E, size; -position p : script:python() { relevant(p) }; -position m != cond.ok; -type T; -@@ - -- memset@m((T)E, 0, size); - ... when != E - when strict -( -- kfree(E)@p; -+ kzfree(E); -| -- \(vfree\|kvfree\)(E)@p; -+ kvfree_sensitive(E, size); -) - -@script:python depends on report@ -p << r.p; -@@ - -coccilib.report.print_report(p[0], - "WARNING: opportunity for kzfree/kvfree_sensitive") - -@script:python depends on org@ -p << r.p; -@@ - -coccilib.org.print_todo(p[0], - "WARNING: opportunity for kzfree/kvfree_sensitive") -- cgit From a19d1358345e040af9164ee7dd0f39ea0a99d565 Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Sun, 13 Sep 2020 17:35:48 +0530 Subject: scripts: coccicheck: Improve error feedback when coccicheck fails Currently, coccicheck fails with only the message "coccicheck failed" and the error code for the failure. To obtain the error logs, one needs to specify a debug file using the DEBUG_FILE option. Modify coccicheck to display error logs when it crashes unless DEBUG_FILE is set, in which case, the error logs are stored in the specified debug file. Signed-off-by: Sumera Priyadarsini Signed-off-by: Julia Lawall --- scripts/coccicheck | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/coccicheck b/scripts/coccicheck index 6e37cf36caae..85136f4fe970 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -126,8 +126,14 @@ run_cmd_parmap() { if [ $VERBOSE -ne 0 ] ; then echo "Running ($NPROC in parallel): $@" fi - echo $@ >>$DEBUG_FILE - $@ 2>>$DEBUG_FILE + if [ "$DEBUG_FILE" != "/dev/null" -a "$DEBUG_FILE" != "" ]; then + echo $@>>$DEBUG_FILE + $@ 2>>$DEBUG_FILE + else + echo $@ + $@ 2>&1 + fi + err=$? if [[ $err -ne 0 ]]; then echo "coccicheck failed" -- cgit From 10dcb06d40411a73e1ae111717e9a987bb760313 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Mon, 14 Sep 2020 14:39:52 +0206 Subject: printk: ringbuffer: change representation of states Rather than deriving the state by evaluating bits within the flags area of the state variable, assign the states explicit values and set those values in the flags area. Introduce macros to make it simple to read and write state values for the state variable. Although the functionality is preserved, the binary representation for the states is changed. Signed-off-by: John Ogness Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20200914123354.832-5-john.ogness@linutronix.de --- scripts/gdb/linux/dmesg.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py index 6c6022012ea8..dd8c0b95063a 100644 --- a/scripts/gdb/linux/dmesg.py +++ b/scripts/gdb/linux/dmesg.py @@ -78,10 +78,10 @@ class LxDmesg(gdb.Command): len_off = off + printk_info_type.get_type()['text_len'].bitpos // 8 # definitions from kernel/printk/printk_ringbuffer.h + desc_committed = 1 desc_sv_bits = utils.get_long_type().sizeof * 8 - desc_committed_mask = 1 << (desc_sv_bits - 1) - desc_reuse_mask = 1 << (desc_sv_bits - 2) - desc_flags_mask = desc_committed_mask | desc_reuse_mask + desc_flags_shift = desc_sv_bits - 2 + desc_flags_mask = 3 << desc_flags_shift desc_id_mask = ~desc_flags_mask # read in tail and head descriptor ids @@ -96,8 +96,9 @@ class LxDmesg(gdb.Command): desc_off = desc_sz * ind # skip non-committed record - state = utils.read_u64(descs, desc_off + sv_off + counter_off) & desc_flags_mask - if state != desc_committed_mask: + state = 3 & (utils.read_u64(descs, desc_off + sv_off + + counter_off) >> desc_flags_shift) + if state != desc_committed: if did == head_id: break did = (did + 1) & desc_id_mask -- cgit From 4cfc7258f876a7feba673ac6d050f525b39cc84c Mon Sep 17 00:00:00 2001 From: John Ogness Date: Mon, 14 Sep 2020 14:39:53 +0206 Subject: printk: ringbuffer: add finalization/extension support Add support for extending the newest data block. For this, introduce a new finalization state (desc_finalized) denoting a committed descriptor that cannot be extended. Until a record is finalized, a writer can reopen that record to append new data. Reopening a record means transitioning from the desc_committed state back to the desc_reserved state. A writer can explicitly finalize a record if there is no intention of extending it. Also, records are automatically finalized when a new record is reserved. This relieves writers of needing to explicitly finalize while also making such records available to readers sooner. (Readers can only traverse finalized records.) Four new memory barrier pairs are introduced. Two of them are insignificant additions (data_realloc:A/desc_read:D and data_realloc:A/data_push_tail:B) because they are alternate path memory barriers that exactly match the purpose, pairing, and context of the two existing memory barrier pairs they provide an alternate path for. The other two new memory barrier pairs are significant additions: desc_reopen_last:A / _prb_commit:B - When reopening a descriptor, ensure the state transitions back to desc_reserved before fully trusting the descriptor data. _prb_commit:B / desc_reserve:D - When committing a descriptor, ensure the state transitions to desc_committed before checking the head ID to see if the descriptor needs to be finalized. Signed-off-by: John Ogness Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/20200914123354.832-6-john.ogness@linutronix.de --- scripts/gdb/linux/dmesg.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py index dd8c0b95063a..bce14de5f610 100644 --- a/scripts/gdb/linux/dmesg.py +++ b/scripts/gdb/linux/dmesg.py @@ -79,6 +79,7 @@ class LxDmesg(gdb.Command): # definitions from kernel/printk/printk_ringbuffer.h desc_committed = 1 + desc_finalized = 2 desc_sv_bits = utils.get_long_type().sizeof * 8 desc_flags_shift = desc_sv_bits - 2 desc_flags_mask = 3 << desc_flags_shift @@ -98,7 +99,7 @@ class LxDmesg(gdb.Command): # skip non-committed record state = 3 & (utils.read_u64(descs, desc_off + sv_off + counter_off) >> desc_flags_shift) - if state != desc_committed: + if state != desc_committed and state != desc_finalized: if did == head_id: break did = (did + 1) & desc_id_mask -- cgit From a070991fe9d1b6d97eb3cf24a2a6ed5f8e7c0169 Mon Sep 17 00:00:00 2001 From: Jonathan Cameron Date: Thu, 10 Sep 2020 19:54:15 +0100 Subject: kernel-doc: add support for ____cacheline_aligned attribute Subroutine dump_struct uses type attributes to check if the struct syntax is valid. Then, it removes all attributes before using it for output. `____cacheline_aligned` is an attribute that is not included in both steps. Add it, since it is used by kernel structs. Based on previous patch to add ____cacheline_aligned_in_smp. Motivated by patches to reorder this attribute to before the variable name. Whilst we could do that in all cases, that would be a massive change and it is more common in the kernel to place this particular attribute after the variable name. A quick grep suggests approximately 400 instances of which 341 have this attribute just before a semicolon and hence after the variable name. Signed-off-by: Jonathan Cameron Cc: Lee Jones Link: https://lore.kernel.org/r/20200910185415.653139-1-jic23@kernel.org Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 3982d47048a7..724528f4b7d6 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1083,7 +1083,7 @@ sub dump_struct($$) { my $x = shift; my $file = shift; - if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { + if ($x =~ /(struct|union)\s+(\w+)\s*\{(.*)\}(\s*(__packed|__aligned|____cacheline_aligned_in_smp|____cacheline_aligned|__attribute__\s*\(\([a-z0-9,_\s\(\)]*\)\)))*/) { my $decl_type = $1; $declaration_name = $2; my $members = $3; @@ -1099,6 +1099,7 @@ sub dump_struct($$) { $members =~ s/\s*__packed\s*/ /gos; $members =~ s/\s*CRYPTO_MINALIGN_ATTR/ /gos; $members =~ s/\s*____cacheline_aligned_in_smp/ /gos; + $members =~ s/\s*____cacheline_aligned/ /gos; # replace DECLARE_BITMAP $members =~ s/__ETHTOOL_DECLARE_LINK_MODE_MASK\s*\(([^\)]+)\)/DECLARE_BITMAP($1, __ETHTOOL_LINK_MODE_MASK_NBITS)/gos; -- cgit From a608b6a646e8816bc0db156baad2e0679fa4d137 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 9 Sep 2020 07:16:37 +0900 Subject: kconfig: qconf: use delete[] instead of delete to free array (again) Commit c9b09a9249e6 ("kconfig: qconf: use delete[] instead of delete to free array") fixed two lines, but there is one more. (cppcheck does not report it for some reason...) This was detected by Clang. "make HOSTCXX=clang++ xconfig" reports the following: scripts/kconfig/qconf.cc:1279:2: warning: 'delete' applied to a pointer that was allocated with 'new[]'; did you mean 'delete[]'? [-Wmismatched-new-delete] delete data; ^ [] scripts/kconfig/qconf.cc:1239:15: note: allocated with 'new[]' here char *data = new char[count + 1]; ^ Fixes: c4f7398bee9c ("kconfig: qconf: make debug links work again") Fixes: c9b09a9249e6 ("kconfig: qconf: use delete[] instead of delete to free array") Signed-off-by: Masahiro Yamada Reviewed-by: Nick Desaulniers --- scripts/kconfig/qconf.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 8638785328a7..c7216b9110fc 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1276,7 +1276,7 @@ void ConfigInfoView::clicked(const QUrl &url) } free(result); - delete data; + delete[] data; } void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event) -- cgit From 19b835a5db93254a46cb90c95ddde6959d7e1e06 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 9 Sep 2020 07:16:38 +0900 Subject: kconfig: qconf: fix incomplete type 'struct gstr' warning "make HOSTCXX=clang++ xconfig" reports the following: HOSTCXX scripts/kconfig/qconf.o In file included from scripts/kconfig/qconf.cc:23: In file included from scripts/kconfig/lkc.h:15: scripts/kconfig/lkc_proto.h:26:13: warning: 'get_relations_str' has C-linkage specified, but returns incomplete type 'struct gstr' which could be incompatible with C [-Wreturn-type-c-linkage] struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); ^ Currently, get_relations_str() is declared before the struct gstr definition. Move all declarations of menu.c functions below. BTW, some are declared in lkc.h and some in lkc_proto.h, but the difference is unclear. I guess some refactoring is needed. Signed-off-by: Masahiro Yamada Acked-by: Boris Kolpackov --- scripts/kconfig/lkc.h | 47 +++++++++++++++++++++++++++++---------------- scripts/kconfig/lkc_proto.h | 14 -------------- 2 files changed, 30 insertions(+), 31 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/lkc.h b/scripts/kconfig/lkc.h index d4ca8297364f..8454649b17bd 100644 --- a/scripts/kconfig/lkc.h +++ b/scripts/kconfig/lkc.h @@ -66,23 +66,6 @@ static inline void xfwrite(const void *str, size_t len, size_t count, FILE *out) fprintf(stderr, "Error in writing or end of file.\n"); } -/* menu.c */ -void _menu_init(void); -void menu_warn(struct menu *menu, const char *fmt, ...); -struct menu *menu_add_menu(void); -void menu_end_menu(void); -void menu_add_entry(struct symbol *sym); -void menu_add_dep(struct expr *dep); -void menu_add_visibility(struct expr *dep); -struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); -void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); -void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); -void menu_add_option_modules(void); -void menu_add_option_defconfig_list(void); -void menu_add_option_allnoconfig_y(void); -void menu_finalize(struct menu *parent); -void menu_set_type(int type); - /* util.c */ struct file *file_lookup(const char *name); void *xmalloc(size_t size); @@ -109,6 +92,36 @@ void str_append(struct gstr *gs, const char *s); void str_printf(struct gstr *gs, const char *fmt, ...); const char *str_get(struct gstr *gs); +/* menu.c */ +void _menu_init(void); +void menu_warn(struct menu *menu, const char *fmt, ...); +struct menu *menu_add_menu(void); +void menu_end_menu(void); +void menu_add_entry(struct symbol *sym); +void menu_add_dep(struct expr *dep); +void menu_add_visibility(struct expr *dep); +struct property *menu_add_prompt(enum prop_type type, char *prompt, struct expr *dep); +void menu_add_expr(enum prop_type type, struct expr *expr, struct expr *dep); +void menu_add_symbol(enum prop_type type, struct symbol *sym, struct expr *dep); +void menu_add_option_modules(void); +void menu_add_option_defconfig_list(void); +void menu_add_option_allnoconfig_y(void); +void menu_finalize(struct menu *parent); +void menu_set_type(int type); + +extern struct menu rootmenu; + +bool menu_is_empty(struct menu *menu); +bool menu_is_visible(struct menu *menu); +bool menu_has_prompt(struct menu *menu); +const char *menu_get_prompt(struct menu *menu); +struct menu *menu_get_root_menu(struct menu *menu); +struct menu *menu_get_parent_menu(struct menu *menu); +bool menu_has_help(struct menu *menu); +const char *menu_get_help(struct menu *menu); +struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); +void menu_get_ext_help(struct menu *menu, struct gstr *help); + /* symbol.c */ void sym_clear_all_valid(void); struct symbol *sym_choice_default(struct symbol *sym); diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index f9ab98238aef..9e81be33c40f 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -12,20 +12,6 @@ bool conf_get_changed(void); void conf_set_changed_callback(void (*fn)(void)); void conf_set_message_callback(void (*fn)(const char *s)); -/* menu.c */ -extern struct menu rootmenu; - -bool menu_is_empty(struct menu *menu); -bool menu_is_visible(struct menu *menu); -bool menu_has_prompt(struct menu *menu); -const char * menu_get_prompt(struct menu *menu); -struct menu * menu_get_root_menu(struct menu *menu); -struct menu * menu_get_parent_menu(struct menu *menu); -bool menu_has_help(struct menu *menu); -const char * menu_get_help(struct menu *menu); -struct gstr get_relations_str(struct symbol **sym_arr, struct list_head *head); -void menu_get_ext_help(struct menu *menu, struct gstr *help); - /* symbol.c */ extern struct symbol * symbol_hash[SYMBOL_HASHSIZE]; -- cgit From a46afd11414758233f23798cc5be51e554d04efe Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Mon, 14 Sep 2020 23:59:48 +0900 Subject: kconfig: qconf: revive help message in the info view Since commit 68fd110b3e7e ("kconfig: qconf: remove redundant help in the info view"), the help message is no longer displayed. I intended to drop duplicated "Symbol:", "Type:", but precious info about help and reverse dependencies was lost too. Revive it now. "defined at" is contained in menu_get_ext_help(), so I made sure to not display it twice. Fixes: 68fd110b3e7e ("kconfig: qconf: remove redundant help in the info view") Reported-by: Maxim Levitsky Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index c7216b9110fc..8ce624a3b54b 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1108,6 +1108,11 @@ void ConfigInfoView::menuInfo(void) if (showDebug()) stream << debug_info(sym); + struct gstr help_gstr = str_new(); + + menu_get_ext_help(_menu, &help_gstr); + stream << print_filter(str_get(&help_gstr)); + str_free(&help_gstr); } else if (_menu->prompt) { stream << ""; stream << print_filter(_menu->prompt->text); @@ -1119,11 +1124,11 @@ void ConfigInfoView::menuInfo(void) expr_print_help, &stream, E_NONE); stream << "

"; } + + stream << "defined at " << _menu->file->name << ":" + << _menu->lineno << "

"; } } - if (showDebug()) - stream << "defined at " << _menu->file->name << ":" - << _menu->lineno << "

"; setText(info); } -- cgit From b76f0ea013125358d1b4ca147a6f9b6883dd2493 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Mon, 21 Sep 2020 18:28:50 +0300 Subject: coccinelle: misc: add excluded_middle.cocci script Check for !A || A && B condition. It's equivalent to !A || B. Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/misc/excluded_middle.cocci | 39 +++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 scripts/coccinelle/misc/excluded_middle.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/misc/excluded_middle.cocci b/scripts/coccinelle/misc/excluded_middle.cocci new file mode 100644 index 000000000000..ab28393e4843 --- /dev/null +++ b/scripts/coccinelle/misc/excluded_middle.cocci @@ -0,0 +1,39 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Condition !A || A && B is equivalent to !A || B. +/// +// Confidence: High +// Copyright: (C) 2020 Denis Efremov ISPRAS +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@r depends on !patch@ +expression A, B; +position p; +@@ + +* !A || (A &&@p B) + +@depends on patch@ +expression A, B; +@@ + + !A || +- (A && B) ++ B + +@script:python depends on report@ +p << r.p; +@@ + +coccilib.report.print_report(p[0], "WARNING !A || A && B is equivalent to !A || B") + +@script:python depends on org@ +p << r.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING !A || A && B is equivalent to !A || B") -- cgit From 74caba7f2a0685575b3ee5330a118f5922485e02 Mon Sep 17 00:00:00 2001 From: John Ogness Date: Mon, 21 Sep 2020 13:24:45 +0206 Subject: printk: move dictionary keys to dev_printk_info Dictionaries are only used for SUBSYSTEM and DEVICE properties. The current implementation stores the property names each time they are used. This requires more space than otherwise necessary. Also, because the dictionary entries are currently considered optional, it cannot be relied upon that they are always available, even if the writer wanted to store them. These issues will increase should new dictionary properties be introduced. Rather than storing the subsystem and device properties in the dict ring, introduce a struct dev_printk_info with separate fields to store only the property values. Embed this struct within the struct printk_info to provide guaranteed availability. Signed-off-by: John Ogness Reviewed-by: Petr Mladek Signed-off-by: Petr Mladek Link: https://lore.kernel.org/r/87mu1jl6ne.fsf@jogness.linutronix.de --- scripts/gdb/linux/dmesg.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/dmesg.py b/scripts/gdb/linux/dmesg.py index bce14de5f610..a92c55bd8de5 100644 --- a/scripts/gdb/linux/dmesg.py +++ b/scripts/gdb/linux/dmesg.py @@ -52,6 +52,12 @@ class LxDmesg(gdb.Command): addr = utils.read_ulong(desc_ring, off) descs = utils.read_memoryview(inf, addr, desc_sz * desc_ring_count).tobytes() + # read in info array + info_sz = printk_info_type.get_type().sizeof + off = prb_desc_ring_type.get_type()['infos'].bitpos // 8 + addr = utils.read_ulong(desc_ring, off) + infos = utils.read_memoryview(inf, addr, info_sz * desc_ring_count).tobytes() + # read in text data ring structure off = printk_ringbuffer_type.get_type()['text_data_ring'].bitpos // 8 addr = prb_addr + off @@ -73,9 +79,8 @@ class LxDmesg(gdb.Command): begin_off = off + (prb_data_blk_lpos_type.get_type()['begin'].bitpos // 8) next_off = off + (prb_data_blk_lpos_type.get_type()['next'].bitpos // 8) - off = prb_desc_type.get_type()['info'].bitpos // 8 - ts_off = off + printk_info_type.get_type()['ts_nsec'].bitpos // 8 - len_off = off + printk_info_type.get_type()['text_len'].bitpos // 8 + ts_off = printk_info_type.get_type()['ts_nsec'].bitpos // 8 + len_off = printk_info_type.get_type()['text_len'].bitpos // 8 # definitions from kernel/printk/printk_ringbuffer.h desc_committed = 1 @@ -95,6 +100,7 @@ class LxDmesg(gdb.Command): while True: ind = did % desc_ring_count desc_off = desc_sz * ind + info_off = info_sz * ind # skip non-committed record state = 3 & (utils.read_u64(descs, desc_off + sv_off + @@ -119,7 +125,7 @@ class LxDmesg(gdb.Command): # skip over descriptor id text_start = begin + utils.get_long_type().sizeof - text_len = utils.read_u16(descs, desc_off + len_off) + text_len = utils.read_u16(infos, info_off + len_off) # handle truncated message if end - text_start < text_len: @@ -128,7 +134,7 @@ class LxDmesg(gdb.Command): text = text_data[text_start:text_start + text_len].decode( encoding='utf8', errors='replace') - time_stamp = utils.read_u64(descs, desc_off + ts_off) + time_stamp = utils.read_u64(infos, info_off + ts_off) for line in text.splitlines(): msg = u"[{time:12.6f}] {line}\n".format( -- cgit From 017dab341ee75c0d3675b9b3d28be28d38e6defc Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Wed, 23 Sep 2020 20:57:34 +0200 Subject: bpf: Check CONFIG_BPF option for resolve_btfids Currently all the resolve_btfids 'users' are under CONFIG_BPF code, so if we have CONFIG_BPF disabled, resolve_btfids will fail, because there's no data to resolve. Disabling resolve_btfids if there's CONFIG_BPF disabled, so we won't fail such builds. Suggested-by: Andrii Nakryiko Signed-off-by: Jiri Olsa Signed-off-by: Alexei Starovoitov Acked-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20200923185735.3048198-1-jolsa@kernel.org --- scripts/link-vmlinux.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index e6e2d9e5ff48..dbde59d343b1 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -341,9 +341,9 @@ fi vmlinux_link vmlinux "${kallsymso}" ${btf_vmlinux_bin_o} # fill in BTF IDs -if [ -n "${CONFIG_DEBUG_INFO_BTF}" ]; then -info BTFIDS vmlinux -${RESOLVE_BTFIDS} vmlinux +if [ -n "${CONFIG_DEBUG_INFO_BTF}" -a -n "${CONFIG_BPF}" ]; then + info BTFIDS vmlinux + ${RESOLVE_BTFIDS} vmlinux fi if [ -n "${CONFIG_BUILDTIME_TABLE_SORT}" ]; then -- cgit From 596b0474d3d9b1242eab713f84d8873f9887d980 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Tue, 8 Sep 2020 13:27:08 +0900 Subject: kbuild: preprocess module linker script There was a request to preprocess the module linker script like we do for the vmlinux one. (https://lkml.org/lkml/2020/8/21/512) The difference between vmlinux.lds and module.lds is that the latter is needed for external module builds, thus must be cleaned up by 'make mrproper' instead of 'make clean'. Also, it must be created by 'make modules_prepare'. You cannot put it in arch/$(SRCARCH)/kernel/, which is cleaned up by 'make clean'. I moved arch/$(SRCARCH)/kernel/module.lds to arch/$(SRCARCH)/include/asm/module.lds.h, which is included from scripts/module.lds.S. scripts/module.lds is fine because 'make clean' keeps all the build artifacts under scripts/. You can add arch-specific sections in . Signed-off-by: Masahiro Yamada Tested-by: Jessica Yu Acked-by: Will Deacon Acked-by: Geert Uytterhoeven Acked-by: Palmer Dabbelt Reviewed-by: Kees Cook Acked-by: Jessica Yu --- scripts/.gitignore | 1 + scripts/Makefile | 3 +++ scripts/Makefile.modfinal | 5 ++--- scripts/module-common.lds | 26 -------------------------- scripts/module.lds.S | 29 +++++++++++++++++++++++++++++ scripts/package/builddeb | 2 +- 6 files changed, 36 insertions(+), 30 deletions(-) delete mode 100644 scripts/module-common.lds create mode 100644 scripts/module.lds.S (limited to 'scripts') diff --git a/scripts/.gitignore b/scripts/.gitignore index 0d1c8e217cd7..a6c11316c969 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -8,3 +8,4 @@ asn1_compiler extract-cert sign-file insert-sys-cert +/module.lds diff --git a/scripts/Makefile b/scripts/Makefile index bc018e4b733e..b5418ec587fb 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -29,6 +29,9 @@ endif # The following programs are only built on demand hostprogs += unifdef +# The module linker script is preprocessed on demand +targets += module.lds + subdir-$(CONFIG_GCC_PLUGINS) += gcc-plugins subdir-$(CONFIG_MODVERSIONS) += genksyms subdir-$(CONFIG_SECURITY_SELINUX) += selinux diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal index 411c1e600e7d..ae01baf96f4e 100644 --- a/scripts/Makefile.modfinal +++ b/scripts/Makefile.modfinal @@ -33,11 +33,10 @@ quiet_cmd_ld_ko_o = LD [M] $@ cmd_ld_ko_o = \ $(LD) -r $(KBUILD_LDFLAGS) \ $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ - $(addprefix -T , $(KBUILD_LDS_MODULE)) \ - -o $@ $(filter %.o, $^); \ + -T scripts/module.lds -o $@ $(filter %.o, $^); \ $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true) -$(modules): %.ko: %.o %.mod.o $(KBUILD_LDS_MODULE) FORCE +$(modules): %.ko: %.o %.mod.o scripts/module.lds FORCE +$(call if_changed,ld_ko_o) targets += $(modules) $(modules:.ko=.mod.o) diff --git a/scripts/module-common.lds b/scripts/module-common.lds deleted file mode 100644 index d61b9e8678e8..000000000000 --- a/scripts/module-common.lds +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Common module linker script, always used when linking a module. - * Archs are free to supply their own linker scripts. ld will - * combine them automatically. - */ -SECTIONS { - /DISCARD/ : { - *(.discard) - *(.discard.*) - } - - __ksymtab 0 : { *(SORT(___ksymtab+*)) } - __ksymtab_gpl 0 : { *(SORT(___ksymtab_gpl+*)) } - __ksymtab_unused 0 : { *(SORT(___ksymtab_unused+*)) } - __ksymtab_unused_gpl 0 : { *(SORT(___ksymtab_unused_gpl+*)) } - __ksymtab_gpl_future 0 : { *(SORT(___ksymtab_gpl_future+*)) } - __kcrctab 0 : { *(SORT(___kcrctab+*)) } - __kcrctab_gpl 0 : { *(SORT(___kcrctab_gpl+*)) } - __kcrctab_unused 0 : { *(SORT(___kcrctab_unused+*)) } - __kcrctab_unused_gpl 0 : { *(SORT(___kcrctab_unused_gpl+*)) } - __kcrctab_gpl_future 0 : { *(SORT(___kcrctab_gpl_future+*)) } - - .init_array 0 : ALIGN(8) { *(SORT(.init_array.*)) *(.init_array) } - - __jump_table 0 : ALIGN(8) { KEEP(*(__jump_table)) } -} diff --git a/scripts/module.lds.S b/scripts/module.lds.S new file mode 100644 index 000000000000..69b9b71a6a47 --- /dev/null +++ b/scripts/module.lds.S @@ -0,0 +1,29 @@ +/* + * Common module linker script, always used when linking a module. + * Archs are free to supply their own linker scripts. ld will + * combine them automatically. + */ +SECTIONS { + /DISCARD/ : { + *(.discard) + *(.discard.*) + } + + __ksymtab 0 : { *(SORT(___ksymtab+*)) } + __ksymtab_gpl 0 : { *(SORT(___ksymtab_gpl+*)) } + __ksymtab_unused 0 : { *(SORT(___ksymtab_unused+*)) } + __ksymtab_unused_gpl 0 : { *(SORT(___ksymtab_unused_gpl+*)) } + __ksymtab_gpl_future 0 : { *(SORT(___ksymtab_gpl_future+*)) } + __kcrctab 0 : { *(SORT(___kcrctab+*)) } + __kcrctab_gpl 0 : { *(SORT(___kcrctab_gpl+*)) } + __kcrctab_unused 0 : { *(SORT(___kcrctab_unused+*)) } + __kcrctab_unused_gpl 0 : { *(SORT(___kcrctab_unused_gpl+*)) } + __kcrctab_gpl_future 0 : { *(SORT(___kcrctab_gpl_future+*)) } + + .init_array 0 : ALIGN(8) { *(SORT(.init_array.*)) *(.init_array) } + + __jump_table 0 : ALIGN(8) { KEEP(*(__jump_table)) } +} + +/* bring in arch-specific sections */ +#include diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 6df3c9f8b2da..44f212e37935 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -55,7 +55,7 @@ deploy_kernel_headers () { cd $srctree find . arch/$SRCARCH -maxdepth 1 -name Makefile\* find include scripts -type f -o -type l - find arch/$SRCARCH -name module.lds -o -name Kbuild.platforms -o -name Platform + find arch/$SRCARCH -name Kbuild.platforms -o -name Platform find $(find arch/$SRCARCH -name include -o -name scripts -type d) -type f ) > debian/hdrsrcfiles -- cgit From 9909b7681222299dcb6f3b0613c30a65498b6c72 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 10 Sep 2020 22:44:28 +0900 Subject: kbuild: remove redundant CONFIG_KASAN check from scripts/Makefile.kasan Since commit e0fe0bbe57b8 ("kbuild: include scripts/Makefile.* only when relevant CONFIG is enabled"), this file is included only when CONFIG_KASAN=y. This ifdef is redundant. Signed-off-by: Masahiro Yamada Acked-by: Marco Elver --- scripts/Makefile.kasan | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index f4beee1b0013..1532f1a41a8f 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -1,8 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -ifdef CONFIG_KASAN CFLAGS_KASAN_NOSANITIZE := -fno-builtin KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET) -endif ifdef CONFIG_KASAN_GENERIC -- cgit From bb2732112bc52bed7b20b9fc59d7246e4e7ce5ed Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Thu, 10 Sep 2020 22:44:29 +0900 Subject: kbuild: move CFLAGS_{KASAN,UBSAN,KCSAN} exports to relevant Makefiles Move CFLAGS_KASAN*, CFLAGS_UBSAN, CFLAGS_KCSAN to Makefile.kasan, Makefile.ubsan, Makefile.kcsan, respectively. This commit also avoids the same -fsanitize=* flags being added to CFLAGS_UBSAN multiple times. Prior to this commit, the ubsan flags were appended by the '+=' operator, without any initialization. Some build targets such as 'make bindeb-pkg' recurses to the top Makefile, and ended up with adding the same flags to CFLAGS_UBSAN twice. Clear CFLAGS_UBSAN with ':=' to make it a simply expanded variable. This is better than a recursively expanded variable, which evaluates $(call cc-option, ...) multiple times before Kbuild starts descending to subdirectories. Signed-off-by: Masahiro Yamada Acked-by: Marco Elver --- scripts/Makefile.kasan | 2 ++ scripts/Makefile.kcsan | 2 +- scripts/Makefile.ubsan | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index 1532f1a41a8f..1e000cc2e7b4 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -47,3 +47,5 @@ CFLAGS_KASAN := -fsanitize=kernel-hwaddress \ $(instrumentation_flags) endif # CONFIG_KASAN_SW_TAGS + +export CFLAGS_KASAN CFLAGS_KASAN_NOSANITIZE diff --git a/scripts/Makefile.kcsan b/scripts/Makefile.kcsan index c50f27b3ac56..cec50d74e0d0 100644 --- a/scripts/Makefile.kcsan +++ b/scripts/Makefile.kcsan @@ -9,7 +9,7 @@ endif # Keep most options here optional, to allow enabling more compilers if absence # of some options does not break KCSAN nor causes false positive reports. -CFLAGS_KCSAN := -fsanitize=thread \ +export CFLAGS_KCSAN := -fsanitize=thread \ $(call cc-option,$(call cc-param,tsan-instrument-func-entry-exit=0) -fno-optimize-sibling-calls) \ $(call cc-option,$(call cc-param,tsan-instrument-read-before-write=1)) \ $(call cc-param,tsan-distinguish-volatile=1) diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index 27348029b2b8..c661484ee01f 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -1,4 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 + +export CFLAGS_UBSAN := + ifdef CONFIG_UBSAN_ALIGNMENT CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) endif -- cgit From 8c30e7e60d4352c4a98c6ba3f90d602d7500c1df Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:07 +0900 Subject: kconfig: qconf: reformat the intro message The introduction message displayed by 'Help -> Introduction' does not look nice due to excessive new lines. Reformat the message. Signed-off-by: Masahiro Yamada Tested-by: Randy Dunlap --- scripts/kconfig/qconf.cc | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 8ce624a3b54b..cf33e436190e 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1836,17 +1836,24 @@ void ConfigMainWindow::closeEvent(QCloseEvent* e) void ConfigMainWindow::showIntro(void) { - static const QString str = "Welcome to the qconf graphical configuration tool.\n\n" - "For each option, a blank box indicates the feature is disabled, a check\n" - "indicates it is enabled, and a dot indicates that it is to be compiled\n" - "as a module. Clicking on the box will cycle through the three states.\n\n" - "If you do not see an option (e.g., a device driver) that you believe\n" - "should be present, try turning on Show All Options under the Options menu.\n" - "Although there is no cross reference yet to help you figure out what other\n" - "options must be enabled to support the option you are interested in, you can\n" - "still view the help of a grayed-out option.\n\n" - "Toggling Show Debug Info under the Options menu will show the dependencies,\n" - "which you can then match by examining other options.\n\n"; + static const QString str = + "Welcome to the qconf graphical configuration tool.\n" + "\n" + "For each option, a blank box indicates the feature is " + "disabled, a check indicates it is enabled, and a dot " + "indicates that it is to be compiled as a module. Clicking on " + "the box will cycle through the three states.\n" + "\n" + "If you do not see an option (e.g., a device driver) that you " + "believe should be present, try turning on Show All Options " + "under the Options menu. Although there is no cross reference " + "yet to help you figure out what other options must be enabled " + "to support the option you are interested in, you can still " + "view the help of a grayed-out option.\n" + "\n" + "Toggling Show Debug Info under the Options menu will show the " + "dependencies, which you can then match by examining other " + "options.\n"; QMessageBox::information(this, "qconf", str); } -- cgit From 1fb752416f3fb64bfe44d94b7dd646799676b523 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:08 +0900 Subject: kconfig: qconf: update the intro message to match to the current code I do not think "Although there is no cross reference yet ..." is valid any longer. The cross reference is supported via hyperlinks enabled by the "show Debug Info" option. Update the message. Signed-off-by: Masahiro Yamada Tested-by: Randy Dunlap --- scripts/kconfig/qconf.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index cf33e436190e..ae47693f80bf 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1846,10 +1846,10 @@ void ConfigMainWindow::showIntro(void) "\n" "If you do not see an option (e.g., a device driver) that you " "believe should be present, try turning on Show All Options " - "under the Options menu. Although there is no cross reference " - "yet to help you figure out what other options must be enabled " - "to support the option you are interested in, you can still " - "view the help of a grayed-out option.\n" + "under the Options menu. Enabling Show Debug Info will help you" + "figure out what other options must be enabled to support the " + "option you are interested in, and hyperlinks will navigate to " + "them.\n" "\n" "Toggling Show Debug Info under the Options menu will show the " "dependencies, which you can then match by examining other " -- cgit From 6a143041532e7df4bd243f4994d46112bd7137ca Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:09 +0900 Subject: kconfig: qconf: remove unused ConfigItem::okRename() Commit 76538660fb08 ("Port xconfig to Qt5 - Remove custom ListView classes.") removed the original implementation, where ConfigItem::okRename() overrode Q3ListViewItem::okRename(). Commit 59e564408f88 ("Port xconfig to Qt5 - Put back some of the old implementation.") restored the empty stub, but it seems useless. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 8 -------- scripts/kconfig/qconf.h | 1 - 2 files changed, 9 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index ae47693f80bf..bf6c9187daf5 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -82,14 +82,6 @@ QIcon ConfigItem::choiceNoIcon; QIcon ConfigItem::menuIcon; QIcon ConfigItem::menubackIcon; -/* - * set the new data - * TODO check the value - */ -void ConfigItem::okRename(int col) -{ -} - /* * update the displayed of a menu entry */ diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index f97376a8123f..d41670f322b3 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -131,7 +131,6 @@ public: } ~ConfigItem(void); void init(void); - void okRename(int col); void updateMenu(void); void testUpdateMenu(bool v); ConfigList* listView() const -- cgit From f9b918fae678eacdeaad821db57a107fba6fe3a1 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:10 +0900 Subject: kconfig: qconf: move ConfigView::updateList(All) to ConfigList class ConfigView::updateList() iterates over all views, and then calls updateList() against for its ConfigList instance. This means there is no point to implement it in the ConfigView class. Move and rename as follows: ConfigView::updateList() -> ConfigList::updateListForAll() ConfigView::updateListAll() -> ConfigList::updateListAllForAll() I used QList to contain all ConfigList instances. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 70 +++++++++++++++++++++++------------------------- scripts/kconfig/qconf.h | 11 ++++---- 2 files changed, 39 insertions(+), 42 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index bf6c9187daf5..7cab996c3617 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -274,7 +274,7 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e) case Qt::Key_Return: case Qt::Key_Enter: sym_set_string_value(item->menu->sym, text().toLatin1()); - parent()->updateList(); + ConfigList::updateListForAll(); break; default: Parent::keyPressEvent(e); @@ -315,9 +315,16 @@ ConfigList::ConfigList(ConfigView* p, const char *name) showColumn(promptColIdx); + allLists.append(this); + reinit(); } +ConfigList::~ConfigList() +{ + allLists.removeOne(this); +} + bool ConfigList::menuSkip(struct menu *menu) { if (optMode == normalOpt && menu_is_visible(menu)) @@ -454,6 +461,28 @@ update: resizeColumnToContents(0); } +void ConfigList::updateListForAll() +{ + QListIterator it(allLists); + + while (it.hasNext()) { + ConfigList *list = it.next(); + + list->updateList(); + } +} + +void ConfigList::updateListAllForAll() +{ + QListIterator it(allLists); + + while (it.hasNext()) { + ConfigList *list = it.next(); + + list->updateList(); + } +} + void ConfigList::setValue(ConfigItem* item, tristate val) { struct symbol* sym; @@ -474,7 +503,7 @@ void ConfigList::setValue(ConfigItem* item, tristate val) return; if (oldval == no && item->menu->list) item->setExpanded(true); - parent()->updateList(); + ConfigList::updateListForAll(); break; } } @@ -508,7 +537,7 @@ void ConfigList::changeValue(ConfigItem* item) item->setExpanded(true); } if (oldexpr != newexpr) - parent()->updateList(); + ConfigList::updateListForAll(); break; case S_INT: case S_HEX: @@ -904,7 +933,7 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) e->accept(); } -ConfigView*ConfigView::viewList; +QList ConfigList::allLists; QAction *ConfigList::showNormalAction; QAction *ConfigList::showAllAction; QAction *ConfigList::showPromptAction; @@ -921,21 +950,6 @@ ConfigView::ConfigView(QWidget* parent, const char *name) lineEdit = new ConfigLineEdit(this); lineEdit->hide(); verticalLayout->addWidget(lineEdit); - - this->nextView = viewList; - viewList = this; -} - -ConfigView::~ConfigView(void) -{ - ConfigView** vp; - - for (vp = &viewList; *vp; vp = &(*vp)->nextView) { - if (*vp == this) { - *vp = nextView; - break; - } - } } void ConfigView::setShowName(bool b) @@ -976,22 +990,6 @@ void ConfigList::setAllOpen(bool open) } } -void ConfigView::updateList() -{ - ConfigView* v; - - for (v = viewList; v; v = v->nextView) - v->list->updateList(); -} - -void ConfigView::updateListAll(void) -{ - ConfigView* v; - - for (v = viewList; v; v = v->nextView) - v->list->updateListAll(); -} - ConfigInfoView::ConfigInfoView(QWidget* parent, const char *name) : Parent(parent), sym(0), _menu(0) { @@ -1605,7 +1603,7 @@ void ConfigMainWindow::loadConfig(void) free(configname); configname = xstrdup(name); - ConfigView::updateListAll(); + ConfigList::updateListAllForAll(); } bool ConfigMainWindow::saveConfig(void) diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index d41670f322b3..818e00617ae3 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -44,6 +44,7 @@ class ConfigList : public QTreeWidget { typedef class QTreeWidget Parent; public: ConfigList(ConfigView* p, const char *name = 0); + ~ConfigList(); void reinit(void); ConfigItem* findConfigItem(struct menu *); ConfigView* parent(void) const @@ -108,6 +109,10 @@ public: QPalette inactivedColorGroup; QMenu* headerPopup; + static QList allLists; + static void updateListForAll(); + static void updateListAllForAll(); + static QAction *showNormalAction, *showAllAction, *showPromptAction; }; @@ -188,9 +193,6 @@ class ConfigView : public QWidget { typedef class QWidget Parent; public: ConfigView(QWidget* parent, const char *name = 0); - ~ConfigView(void); - static void updateList(); - static void updateListAll(void); bool showName(void) const { return list->showName; } bool showRange(void) const { return list->showRange; } @@ -206,9 +208,6 @@ signals: public: ConfigList* list; ConfigLineEdit* lineEdit; - - static ConfigView* viewList; - ConfigView* nextView; }; class ConfigInfoView : public QTextBrowser { -- cgit From 669a1ee46a0e2ccad769ceca70b08ee57772be94 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:11 +0900 Subject: kconfig: qconf: show data column all the time The next commit will allow users to edit "int", "hex", "string" menus in-place from the data column. The data column should be always displayed. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 29 +---------------------------- scripts/kconfig/qconf.h | 5 +---- 2 files changed, 2 insertions(+), 32 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 7cab996c3617..3ba064af905c 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -288,7 +288,7 @@ void ConfigLineEdit::keyPressEvent(QKeyEvent* e) ConfigList::ConfigList(ConfigView* p, const char *name) : Parent(p), updateAll(false), - showName(false), showRange(false), showData(false), mode(singleMode), optMode(normalOpt), + showName(false), showRange(false), mode(singleMode), optMode(normalOpt), rootEntry(0), headerPopup(0) { setObjectName(name); @@ -307,7 +307,6 @@ ConfigList::ConfigList(ConfigView* p, const char *name) configSettings->beginGroup(name); showName = configSettings->value("/showName", false).toBool(); showRange = configSettings->value("/showRange", false).toBool(); - showData = configSettings->value("/showData", false).toBool(); optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt(); configSettings->endGroup(); connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); @@ -338,7 +337,6 @@ bool ConfigList::menuSkip(struct menu *menu) void ConfigList::reinit(void) { - hideColumn(dataColIdx); hideColumn(yesColIdx); hideColumn(modColIdx); hideColumn(noColIdx); @@ -351,8 +349,6 @@ void ConfigList::reinit(void) showColumn(modColIdx); showColumn(yesColIdx); } - if (showData) - showColumn(dataColIdx); updateListAll(); } @@ -375,7 +371,6 @@ void ConfigList::saveSettings(void) configSettings->beginGroup(objectName()); configSettings->setValue("/showName", showName); configSettings->setValue("/showRange", showRange); - configSettings->setValue("/showData", showData); configSettings->setValue("/optionMode", (int)optMode); configSettings->endGroup(); } @@ -918,15 +913,6 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) action, SLOT(setChecked(bool))); action->setChecked(showRange); headerPopup->addAction(action); - - action = new QAction("Show Data", this); - action->setCheckable(true); - connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowData(bool))); - connect(parent(), SIGNAL(showDataChanged(bool)), - action, SLOT(setChecked(bool))); - action->setChecked(showData); - headerPopup->addAction(action); } headerPopup->exec(e->globalPos()); @@ -970,15 +956,6 @@ void ConfigView::setShowRange(bool b) } } -void ConfigView::setShowData(bool b) -{ - if (list->showData != b) { - list->showData = b; - list->reinit(); - emit showDataChanged(b); - } -} - void ConfigList::setAllOpen(bool open) { QTreeWidgetItemIterator it(this); @@ -1475,9 +1452,6 @@ ConfigMainWindow::ConfigMainWindow(void) QAction *showRangeAction = new QAction("Show Range", this); showRangeAction->setCheckable(true); connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); - QAction *showDataAction = new QAction("Show Data", this); - showDataAction->setCheckable(true); - connect(showDataAction, SIGNAL(toggled(bool)), configView, SLOT(setShowData(bool))); QActionGroup *optGroup = new QActionGroup(this); optGroup->setExclusive(true); @@ -1530,7 +1504,6 @@ ConfigMainWindow::ConfigMainWindow(void) menu = menuBar()->addMenu("&Option"); menu->addAction(showNameAction); menu->addAction(showRangeAction); - menu->addAction(showDataAction); menu->addSeparator(); menu->addActions(optGroup->actions()); menu->addSeparator(); diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index 818e00617ae3..d01a6c620dbb 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -101,7 +101,7 @@ public: bool updateAll; - bool showName, showRange, showData; + bool showName, showRange; enum listMode mode; enum optionMode optMode; struct menu *rootEntry; @@ -196,15 +196,12 @@ public: bool showName(void) const { return list->showName; } bool showRange(void) const { return list->showRange; } - bool showData(void) const { return list->showData; } public slots: void setShowName(bool); void setShowRange(bool); - void setShowData(bool); signals: void showNameChanged(bool); void showRangeChanged(bool); - void showDataChanged(bool); public: ConfigList* list; ConfigLineEdit* lineEdit; -- cgit From 37162a68bf517b6f870d63bbbcc65a81f99bd968 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:12 +0900 Subject: kconfig: qconf: allow to edit "int", "hex", "string" menus in-place Previously, when you double-clicked the "int", "hex", or "string" menus, a line-edit gadget showed up to allow you to input the value, which looked clumsy. Also, it was buggy; the editor opened even if the config option was not editable. For example, just try to double-click CC_VERSION_TEXT, which has no prompt. This commit sub-classes QStyleItemDelegate to allow users to edit "int", "hex", "string" menus in-place. Just double-click (or press the F2 key) in the data column. Then, an editor widget is placed on top of the item view. The two methods are overridden: createEditor - process only when the data column is being accessed and the menu is visible. Otherwise, return nullptr to disallow editing. setModelData - take the new data from the editor, and set it to the addressed symbol. If it was successful, update all the list windows. Otherwise, (the reason for the failure is possibly the input data was out of range), set the old value back to the editor. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 93 +++++++++++++++++++++++++++++++++++++++--------- scripts/kconfig/qconf.h | 15 ++++++++ 2 files changed, 91 insertions(+), 17 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 3ba064af905c..af8d5cc1b24b 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -180,15 +180,7 @@ void ConfigItem::updateMenu(void) case S_INT: case S_HEX: case S_STRING: - const char* data; - - data = sym_get_string_value(sym); - - setText(dataColIdx, data); - if (type == S_STRING) - prompt = QString("%1: %2").arg(prompt).arg(data); - else - prompt = QString("(%2) %1").arg(prompt).arg(data); + setText(dataColIdx, sym_get_string_value(sym)); break; } if (!sym_has_value(sym) && visible) @@ -229,6 +221,17 @@ void ConfigItem::init(void) if (list->mode != fullMode) setExpanded(true); sym_calc_value(menu->sym); + + if (menu->sym) { + enum symbol_type type = menu->sym->type; + + // Allow to edit "int", "hex", and "string" in-place in + // the data column. Unfortunately, you cannot specify + // the flags per column. Set ItemIsEditable for all + // columns here, and check the column in createEditor(). + if (type == S_INT || type == S_HEX || type == S_STRING) + setFlags(flags() | Qt::ItemIsEditable); + } } updateMenu(); } @@ -249,6 +252,61 @@ ConfigItem::~ConfigItem(void) } } +QWidget *ConfigItemDelegate::createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const +{ + ConfigItem *item; + + // Only the data column is editable + if (index.column() != dataColIdx) + return nullptr; + + // You cannot edit invisible menus + item = static_cast(index.internalPointer()); + if (!item || !item->menu || !menu_is_visible(item->menu)) + return nullptr; + + return QStyledItemDelegate::createEditor(parent, option, index); +} + +void ConfigItemDelegate::setModelData(QWidget *editor, + QAbstractItemModel *model, + const QModelIndex &index) const +{ + QLineEdit *lineEdit; + ConfigItem *item; + struct symbol *sym; + bool success; + + lineEdit = qobject_cast(editor); + // If this is not a QLineEdit, use the parent's default. + // (does this happen?) + if (!lineEdit) + goto parent; + + item = static_cast(index.internalPointer()); + if (!item || !item->menu) + goto parent; + + sym = item->menu->sym; + if (!sym) + goto parent; + + success = sym_set_string_value(sym, lineEdit->text().toUtf8().data()); + if (success) { + ConfigList::updateListForAll(); + } else { + QMessageBox::information(editor, "qconf", + "Cannot set the data (maybe due to out of range).\n" + "Setting the old value."); + lineEdit->setText(sym_get_string_value(sym)); + } + +parent: + QStyledItemDelegate::setModelData(editor, model, index); +} + ConfigLineEdit::ConfigLineEdit(ConfigView* parent) : Parent(parent) { @@ -314,6 +372,8 @@ ConfigList::ConfigList(ConfigView* p, const char *name) showColumn(promptColIdx); + setItemDelegate(new ConfigItemDelegate(this)); + allLists.append(this); reinit(); @@ -534,10 +594,7 @@ void ConfigList::changeValue(ConfigItem* item) if (oldexpr != newexpr) ConfigList::updateListForAll(); break; - case S_INT: - case S_HEX: - case S_STRING: - parent()->lineEdit->show(item); + default: break; } } @@ -1802,10 +1859,12 @@ void ConfigMainWindow::showIntro(void) static const QString str = "Welcome to the qconf graphical configuration tool.\n" "\n" - "For each option, a blank box indicates the feature is " - "disabled, a check indicates it is enabled, and a dot " - "indicates that it is to be compiled as a module. Clicking on " - "the box will cycle through the three states.\n" + "For bool and tristate options, a blank box indicates the " + "feature is disabled, a check indicates it is enabled, and a " + "dot indicates that it is to be compiled as a module. Clicking " + "on the box will cycle through the three states. For int, hex, " + "and string options, double-clicking or pressing F2 on the " + "Value cell will allow you to edit the value.\n" "\n" "If you do not see an option (e.g., a device driver) that you " "believe should be present, try turning on Show All Options " diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index d01a6c620dbb..b02acf2464ec 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -172,6 +173,20 @@ public: static QIcon menuIcon, menubackIcon; }; +class ConfigItemDelegate : public QStyledItemDelegate +{ +private: + struct menu *menu; +public: + ConfigItemDelegate(QObject *parent = nullptr) + : QStyledItemDelegate(parent) {} + QWidget *createEditor(QWidget *parent, + const QStyleOptionViewItem &option, + const QModelIndex &index) const override; + void setModelData(QWidget *editor, QAbstractItemModel *model, + const QModelIndex &index) const override; +}; + class ConfigLineEdit : public QLineEdit { Q_OBJECT typedef class QLineEdit Parent; -- cgit From f3eea294e93facc78ffcf3881f88ea02732283a9 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:13 +0900 Subject: kconfig: qconf: remove ConfigLineEdit class Now that "int", "hex", "string" menus are edited in-place, this class is no longer needed. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 39 --------------------------------------- scripts/kconfig/qconf.h | 18 ------------------ 2 files changed, 57 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index af8d5cc1b24b..461681aa5b19 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -307,42 +307,6 @@ parent: QStyledItemDelegate::setModelData(editor, model, index); } -ConfigLineEdit::ConfigLineEdit(ConfigView* parent) - : Parent(parent) -{ - connect(this, SIGNAL(editingFinished()), SLOT(hide())); -} - -void ConfigLineEdit::show(ConfigItem* i) -{ - item = i; - if (sym_get_string_value(item->menu->sym)) - setText(sym_get_string_value(item->menu->sym)); - else - setText(QString()); - Parent::show(); - setFocus(); -} - -void ConfigLineEdit::keyPressEvent(QKeyEvent* e) -{ - switch (e->key()) { - case Qt::Key_Escape: - break; - case Qt::Key_Return: - case Qt::Key_Enter: - sym_set_string_value(item->menu->sym, text().toLatin1()); - ConfigList::updateListForAll(); - break; - default: - Parent::keyPressEvent(e); - return; - } - e->accept(); - parent()->list->setFocus(); - hide(); -} - ConfigList::ConfigList(ConfigView* p, const char *name) : Parent(p), updateAll(false), @@ -990,9 +954,6 @@ ConfigView::ConfigView(QWidget* parent, const char *name) list = new ConfigList(this); verticalLayout->addWidget(list); - lineEdit = new ConfigLineEdit(this); - lineEdit->hide(); - verticalLayout->addWidget(lineEdit); } void ConfigView::setShowName(bool b) diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index b02acf2464ec..a3ee91565d49 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -20,7 +20,6 @@ class ConfigView; class ConfigList; class ConfigItem; -class ConfigLineEdit; class ConfigMainWindow; class ConfigSettings : public QSettings { @@ -187,22 +186,6 @@ public: const QModelIndex &index) const override; }; -class ConfigLineEdit : public QLineEdit { - Q_OBJECT - typedef class QLineEdit Parent; -public: - ConfigLineEdit(ConfigView* parent); - ConfigView* parent(void) const - { - return (ConfigView*)Parent::parent(); - } - void show(ConfigItem *i); - void keyPressEvent(QKeyEvent *e); - -public: - ConfigItem *item; -}; - class ConfigView : public QWidget { Q_OBJECT typedef class QWidget Parent; @@ -219,7 +202,6 @@ signals: void showRangeChanged(bool); public: ConfigList* list; - ConfigLineEdit* lineEdit; }; class ConfigInfoView : public QTextBrowser { -- cgit From 7930dd91a01fe9c0ff7664c7f0bdf38fba9047bc Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:14 +0900 Subject: kconfig: qconf: move setShowName/Range() to ConfigList from ConfigView ConfigView::setShowName/Range() only get access to the 'list' member. Move them to the more relevant ConfigList class. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 53 +++++++++++++++++++++++++----------------------- scripts/kconfig/qconf.h | 12 ++++------- 2 files changed, 32 insertions(+), 33 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 461681aa5b19..5f3e5e145a99 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -920,8 +920,8 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) action = new QAction("Show Name", this); action->setCheckable(true); connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowName(bool))); - connect(parent(), SIGNAL(showNameChanged(bool)), + SLOT(setShowName(bool))); + connect(this, SIGNAL(showNameChanged(bool)), action, SLOT(setChecked(bool))); action->setChecked(showName); headerPopup->addAction(action); @@ -929,8 +929,8 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) action = new QAction("Show Range", this); action->setCheckable(true); connect(action, SIGNAL(toggled(bool)), - parent(), SLOT(setShowRange(bool))); - connect(parent(), SIGNAL(showRangeChanged(bool)), + SLOT(setShowRange(bool))); + connect(this, SIGNAL(showRangeChanged(bool)), action, SLOT(setChecked(bool))); action->setChecked(showRange); headerPopup->addAction(action); @@ -940,6 +940,26 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) e->accept(); } +void ConfigList::setShowName(bool on) +{ + if (showName == on) + return; + + showName = on; + reinit(); + emit showNameChanged(on); +} + +void ConfigList::setShowRange(bool on) +{ + if (showRange == on) + return; + + showRange = on; + reinit(); + emit showRangeChanged(on); +} + QList ConfigList::allLists; QAction *ConfigList::showNormalAction; QAction *ConfigList::showAllAction; @@ -956,24 +976,6 @@ ConfigView::ConfigView(QWidget* parent, const char *name) verticalLayout->addWidget(list); } -void ConfigView::setShowName(bool b) -{ - if (list->showName != b) { - list->showName = b; - list->reinit(); - emit showNameChanged(b); - } -} - -void ConfigView::setShowRange(bool b) -{ - if (list->showRange != b) { - list->showRange = b; - list->reinit(); - emit showRangeChanged(b); - } -} - void ConfigList::setAllOpen(bool open) { QTreeWidgetItemIterator it(this); @@ -1465,11 +1467,12 @@ ConfigMainWindow::ConfigMainWindow(void) QAction *showNameAction = new QAction("Show Name", this); showNameAction->setCheckable(true); - connect(showNameAction, SIGNAL(toggled(bool)), configView, SLOT(setShowName(bool))); - showNameAction->setChecked(configView->showName()); + connect(showNameAction, SIGNAL(toggled(bool)), configList, SLOT(setShowName(bool))); + showNameAction->setChecked(configList->showName); + QAction *showRangeAction = new QAction("Show Range", this); showRangeAction->setCheckable(true); - connect(showRangeAction, SIGNAL(toggled(bool)), configView, SLOT(setShowRange(bool))); + connect(showRangeAction, SIGNAL(toggled(bool)), configList, SLOT(setShowRange(bool))); QActionGroup *optGroup = new QActionGroup(this); optGroup->setExclusive(true); diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index a3ee91565d49..843725584bfa 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -76,6 +76,8 @@ public slots: void updateSelection(void); void saveSettings(void); void setOptionMode(QAction *action); + void setShowName(bool on); + void setShowRange(bool on); signals: void menuChanged(struct menu *menu); @@ -83,6 +85,8 @@ signals: void itemSelected(struct menu *menu); void parentSelected(void); void gotFocus(struct menu *); + void showNameChanged(bool on); + void showRangeChanged(bool on); public: void updateListAll(void) @@ -192,14 +196,6 @@ class ConfigView : public QWidget { public: ConfigView(QWidget* parent, const char *name = 0); - bool showName(void) const { return list->showName; } - bool showRange(void) const { return list->showRange; } -public slots: - void setShowName(bool); - void setShowRange(bool); -signals: - void showNameChanged(bool); - void showRangeChanged(bool); public: ConfigList* list; }; -- cgit From 62ed165651cc71cb1b6d39ced74e47c2b26a55a5 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:15 +0900 Subject: kconfig: qconf: remove ConfigView class Now that ConfigView only contains ConfigList, we can remove ConfigView and just use ConfigList. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 43 +++++++++++++++---------------------------- scripts/kconfig/qconf.h | 21 ++------------------- 2 files changed, 17 insertions(+), 47 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 5f3e5e145a99..4ece85ae7dfa 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -307,8 +307,8 @@ parent: QStyledItemDelegate::setModelData(editor, model, index); } -ConfigList::ConfigList(ConfigView* p, const char *name) - : Parent(p), +ConfigList::ConfigList(QWidget *parent, const char *name) + : QTreeWidget(parent), updateAll(false), showName(false), showRange(false), mode(singleMode), optMode(normalOpt), rootEntry(0), headerPopup(0) @@ -965,17 +965,6 @@ QAction *ConfigList::showNormalAction; QAction *ConfigList::showAllAction; QAction *ConfigList::showPromptAction; -ConfigView::ConfigView(QWidget* parent, const char *name) - : Parent(parent) -{ - setObjectName(name); - QVBoxLayout *verticalLayout = new QVBoxLayout(this); - verticalLayout->setContentsMargins(0, 0, 0, 0); - - list = new ConfigList(this); - verticalLayout->addWidget(list); -} - void ConfigList::setAllOpen(bool open) { QTreeWidgetItemIterator it(this); @@ -1302,12 +1291,12 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent) split = new QSplitter(this); split->setOrientation(Qt::Vertical); - list = new ConfigView(split, "search"); - list->list->mode = listMode; + list = new ConfigList(split, "search"); + list->mode = listMode; info = new ConfigInfoView(split, "search"); - connect(list->list, SIGNAL(menuChanged(struct menu *)), + connect(list, SIGNAL(menuChanged(struct menu *)), info, SLOT(setInfo(struct menu *))); - connect(list->list, SIGNAL(menuChanged(struct menu *)), + connect(list, SIGNAL(menuChanged(struct menu *)), parent, SLOT(setMenuLink(struct menu *))); layout1->addWidget(split); @@ -1351,7 +1340,7 @@ void ConfigSearchWindow::search(void) ConfigItem *lastItem = NULL; free(result); - list->list->clear(); + list->clear(); info->clear(); result = sym_re_search(editField->text().toLatin1()); @@ -1359,7 +1348,7 @@ void ConfigSearchWindow::search(void) return; for (p = result; *p; p++) { for_all_prompts((*p), prop) - lastItem = new ConfigItem(list->list, lastItem, prop->menu, + lastItem = new ConfigItem(list, lastItem, prop->menu, menu_is_visible(prop->menu)); } } @@ -1407,23 +1396,21 @@ ConfigMainWindow::ConfigMainWindow(void) split1->setOrientation(Qt::Horizontal); split1->setChildrenCollapsible(false); - menuView = new ConfigView(widget, "menu"); - menuList = menuView->list; + menuList = new ConfigList(widget, "menu"); split2 = new QSplitter(widget); split2->setChildrenCollapsible(false); split2->setOrientation(Qt::Vertical); // create config tree - configView = new ConfigView(widget, "config"); - configList = configView->list; + configList = new ConfigList(widget, "config"); helpText = new ConfigInfoView(widget, "help"); layout->addWidget(split2); split2->addWidget(split1); - split1->addWidget(configView); - split1->addWidget(menuView); + split1->addWidget(configList); + split1->addWidget(menuList); split2->addWidget(helpText); setTabOrder(configList, helpText); @@ -1732,7 +1719,7 @@ void ConfigMainWindow::showSingleView(void) backAction->setEnabled(true); - menuView->hide(); + menuList->hide(); menuList->setRootMenu(0); configList->mode = singleMode; if (configList->rootEntry == &rootmenu) @@ -1763,7 +1750,7 @@ void ConfigMainWindow::showSplitView(void) menuList->mode = symbolMode; menuList->setRootMenu(&rootmenu); menuList->setAllOpen(true); - menuView->show(); + menuList->show(); menuList->setFocus(); } @@ -1778,7 +1765,7 @@ void ConfigMainWindow::showFullView(void) backAction->setEnabled(false); - menuView->hide(); + menuList->hide(); menuList->setRootMenu(0); configList->mode = fullMode; if (configList->rootEntry == &rootmenu) diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index 843725584bfa..1289fdaa7d82 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -17,7 +17,6 @@ #include "expr.h" -class ConfigView; class ConfigList; class ConfigItem; class ConfigMainWindow; @@ -43,14 +42,10 @@ class ConfigList : public QTreeWidget { Q_OBJECT typedef class QTreeWidget Parent; public: - ConfigList(ConfigView* p, const char *name = 0); + ConfigList(QWidget *parent, const char *name = 0); ~ConfigList(); void reinit(void); ConfigItem* findConfigItem(struct menu *); - ConfigView* parent(void) const - { - return (ConfigView*)Parent::parent(); - } void setSelected(QTreeWidgetItem *item, bool enable) { for (int i = 0; i < selectedItems().size(); i++) selectedItems().at(i)->setSelected(false); @@ -190,16 +185,6 @@ public: const QModelIndex &index) const override; }; -class ConfigView : public QWidget { - Q_OBJECT - typedef class QWidget Parent; -public: - ConfigView(QWidget* parent, const char *name = 0); - -public: - ConfigList* list; -}; - class ConfigInfoView : public QTextBrowser { Q_OBJECT typedef class QTextBrowser Parent; @@ -245,7 +230,7 @@ protected: QLineEdit* editField; QPushButton* searchButton; QSplitter* split; - ConfigView* list; + ConfigList *list; ConfigInfoView* info; struct symbol **result; @@ -280,9 +265,7 @@ protected: void closeEvent(QCloseEvent *e); ConfigSearchWindow *searchWindow; - ConfigView *menuView; ConfigList *menuList; - ConfigView *configView; ConfigList *configList; ConfigInfoView *helpText; QAction *backAction; -- cgit From a0fce283386d76f3e77f4f45b7ec6f0084510baa Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:16 +0900 Subject: kconfig: qconf: remove Y, M, N columns There are so many ways to toggle bool / tristate options. I do not know how useful these columns are. Signed-off-by: Masahiro Yamada --- scripts/kconfig/qconf.cc | 59 ++---------------------------------------------- scripts/kconfig/qconf.h | 6 ++--- 2 files changed, 4 insertions(+), 61 deletions(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 4ece85ae7dfa..21871b7f5f8a 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -139,9 +139,6 @@ void ConfigItem::updateMenu(void) if (!sym_is_changeable(sym) && list->optMode == normalOpt) { setIcon(promptColIdx, QIcon()); - setText(noColIdx, QString()); - setText(modColIdx, QString()); - setText(yesColIdx, QString()); break; } expr = sym_get_tristate_value(sym); @@ -151,12 +148,10 @@ void ConfigItem::updateMenu(void) setIcon(promptColIdx, choiceYesIcon); else setIcon(promptColIdx, symbolYesIcon); - setText(yesColIdx, "Y"); ch = 'Y'; break; case mod: setIcon(promptColIdx, symbolModIcon); - setText(modColIdx, "M"); ch = 'M'; break; default: @@ -164,16 +159,9 @@ void ConfigItem::updateMenu(void) setIcon(promptColIdx, choiceNoIcon); else setIcon(promptColIdx, symbolNoIcon); - setText(noColIdx, "N"); ch = 'N'; break; } - if (expr != no) - setText(noColIdx, sym_tristate_within_range(sym, no) ? "_" : 0); - if (expr != mod) - setText(modColIdx, sym_tristate_within_range(sym, mod) ? "_" : 0); - if (expr != yes) - setText(yesColIdx, sym_tristate_within_range(sym, yes) ? "_" : 0); setText(dataColIdx, QChar(ch)); break; @@ -310,7 +298,7 @@ parent: ConfigList::ConfigList(QWidget *parent, const char *name) : QTreeWidget(parent), updateAll(false), - showName(false), showRange(false), mode(singleMode), optMode(normalOpt), + showName(false), mode(singleMode), optMode(normalOpt), rootEntry(0), headerPopup(0) { setObjectName(name); @@ -320,7 +308,7 @@ ConfigList::ConfigList(QWidget *parent, const char *name) setVerticalScrollMode(ScrollPerPixel); setHorizontalScrollMode(ScrollPerPixel); - setHeaderLabels(QStringList() << "Option" << "Name" << "N" << "M" << "Y" << "Value"); + setHeaderLabels(QStringList() << "Option" << "Name" << "Value"); connect(this, SIGNAL(itemSelectionChanged(void)), SLOT(updateSelection(void))); @@ -328,7 +316,6 @@ ConfigList::ConfigList(QWidget *parent, const char *name) if (name) { configSettings->beginGroup(name); showName = configSettings->value("/showName", false).toBool(); - showRange = configSettings->value("/showRange", false).toBool(); optMode = (enum optionMode)configSettings->value("/optionMode", 0).toInt(); configSettings->endGroup(); connect(configApp, SIGNAL(aboutToQuit()), SLOT(saveSettings())); @@ -361,18 +348,10 @@ bool ConfigList::menuSkip(struct menu *menu) void ConfigList::reinit(void) { - hideColumn(yesColIdx); - hideColumn(modColIdx); - hideColumn(noColIdx); hideColumn(nameColIdx); if (showName) showColumn(nameColIdx); - if (showRange) { - showColumn(noColIdx); - showColumn(modColIdx); - showColumn(yesColIdx); - } updateListAll(); } @@ -394,7 +373,6 @@ void ConfigList::saveSettings(void) if (!objectName().isEmpty()) { configSettings->beginGroup(objectName()); configSettings->setValue("/showName", showName); - configSettings->setValue("/showRange", showRange); configSettings->setValue("/optionMode", (int)optMode); configSettings->endGroup(); } @@ -841,15 +819,6 @@ void ConfigList::mouseReleaseEvent(QMouseEvent* e) } } break; - case noColIdx: - setValue(item, no); - break; - case modColIdx: - setValue(item, mod); - break; - case yesColIdx: - setValue(item, yes); - break; case dataColIdx: changeValue(item); break; @@ -925,15 +894,6 @@ void ConfigList::contextMenuEvent(QContextMenuEvent *e) action, SLOT(setChecked(bool))); action->setChecked(showName); headerPopup->addAction(action); - - action = new QAction("Show Range", this); - action->setCheckable(true); - connect(action, SIGNAL(toggled(bool)), - SLOT(setShowRange(bool))); - connect(this, SIGNAL(showRangeChanged(bool)), - action, SLOT(setChecked(bool))); - action->setChecked(showRange); - headerPopup->addAction(action); } headerPopup->exec(e->globalPos()); @@ -950,16 +910,6 @@ void ConfigList::setShowName(bool on) emit showNameChanged(on); } -void ConfigList::setShowRange(bool on) -{ - if (showRange == on) - return; - - showRange = on; - reinit(); - emit showRangeChanged(on); -} - QList ConfigList::allLists; QAction *ConfigList::showNormalAction; QAction *ConfigList::showAllAction; @@ -1457,10 +1407,6 @@ ConfigMainWindow::ConfigMainWindow(void) connect(showNameAction, SIGNAL(toggled(bool)), configList, SLOT(setShowName(bool))); showNameAction->setChecked(configList->showName); - QAction *showRangeAction = new QAction("Show Range", this); - showRangeAction->setCheckable(true); - connect(showRangeAction, SIGNAL(toggled(bool)), configList, SLOT(setShowRange(bool))); - QActionGroup *optGroup = new QActionGroup(this); optGroup->setExclusive(true); connect(optGroup, SIGNAL(triggered(QAction*)), configList, @@ -1511,7 +1457,6 @@ ConfigMainWindow::ConfigMainWindow(void) // create options menu menu = menuBar()->addMenu("&Option"); menu->addAction(showNameAction); - menu->addAction(showRangeAction); menu->addSeparator(); menu->addActions(optGroup->actions()); menu->addSeparator(); diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h index 1289fdaa7d82..78b0a1dfcd53 100644 --- a/scripts/kconfig/qconf.h +++ b/scripts/kconfig/qconf.h @@ -29,7 +29,7 @@ public: }; enum colIdx { - promptColIdx, nameColIdx, noColIdx, modColIdx, yesColIdx, dataColIdx + promptColIdx, nameColIdx, dataColIdx }; enum listMode { singleMode, menuMode, symbolMode, fullMode, listMode @@ -72,7 +72,6 @@ public slots: void saveSettings(void); void setOptionMode(QAction *action); void setShowName(bool on); - void setShowRange(bool on); signals: void menuChanged(struct menu *menu); @@ -81,7 +80,6 @@ signals: void parentSelected(void); void gotFocus(struct menu *); void showNameChanged(bool on); - void showRangeChanged(bool on); public: void updateListAll(void) @@ -100,7 +98,7 @@ public: bool updateAll; - bool showName, showRange; + bool showName; enum listMode mode; enum optionMode optMode; struct menu *rootEntry; -- cgit From f9a825a7f65a1c94858667934c4ed59bc548dd1f Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Sat, 29 Aug 2020 17:14:17 +0900 Subject: kconfig: qconf: create QApplication after option checks 'scripts/kconfig/qconf -h' just calls usage() and exits, with QApplication unused. There is no need to construct QApplication so early. Do it after the parse stage. Signed-off-by: Masahiro Yamada Tested-by: Randy Dunlap --- scripts/kconfig/qconf.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 21871b7f5f8a..f7eb093614f2 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1851,7 +1851,6 @@ int main(int ac, char** av) const char *name; progname = av[0]; - configApp = new QApplication(ac, av); if (ac > 1 && av[1][0] == '-') { switch (av[1][1]) { case 's': @@ -1872,6 +1871,8 @@ int main(int ac, char** av) conf_read(NULL); //zconfdump(stdout); + configApp = new QApplication(ac, av); + configSettings = new ConfigSettings(); configSettings->beginGroup("/kconfig/qconf"); v = new ConfigMainWindow(); -- cgit From 516d980f85415d76ae3d0d2a871eb20243f46c95 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 23 Sep 2020 02:48:56 +0900 Subject: scripts/kallsyms: skip ppc compiler stub *.long_branch.* / *.plt_branch.* PowerPC allmodconfig often fails to build as follows: LD .tmp_vmlinux.kallsyms1 KSYM .tmp_vmlinux.kallsyms1.o LD .tmp_vmlinux.kallsyms2 KSYM .tmp_vmlinux.kallsyms2.o LD .tmp_vmlinux.kallsyms3 KSYM .tmp_vmlinux.kallsyms3.o LD vmlinux SORTTAB vmlinux SYSMAP System.map Inconsistent kallsyms data Try make KALLSYMS_EXTRA_PASS=1 as a workaround make[2]: *** [../Makefile:1162: vmlinux] Error 1 Setting KALLSYMS_EXTRA_PASS=1 does not help. This is caused by the compiler inserting stubs such as *.long_branch.* and *.plt_branch.* $ powerpc-linux-nm -n .tmp_vmlinux.kallsyms2 [ snip ] c00000000210c010 t 00000075.plt_branch.da9:19 c00000000210c020 t 00000075.plt_branch.1677:5 c00000000210c030 t 00000075.long_branch.memmove c00000000210c034 t 00000075.plt_branch.9e0:5 c00000000210c044 t 00000075.plt_branch.free_initrd_mem ... Actually, the problem mentioned in scripts/link-vmlinux.sh comments; "In theory it's possible this results in even more stubs, but unlikely" is happening here, and ends up with another kallsyms step required. scripts/kallsyms.c already ignores various compiler stubs. Let's do similar to make kallsysms for PowerPC always succeed in 2 steps. Reported-by: Guenter Roeck Signed-off-by: Masahiro Yamada Tested-by: Guenter Roeck --- scripts/kallsyms.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 0096cd965332..7ecd2ccba531 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -82,6 +82,7 @@ static char *sym_name(const struct sym_entry *s) static bool is_ignored_symbol(const char *name, char type) { + /* Symbol names that exactly match to the following are ignored.*/ static const char * const ignored_symbols[] = { /* * Symbols which vary between passes. Passes 1 and 2 must have @@ -104,6 +105,7 @@ static bool is_ignored_symbol(const char *name, char type) NULL }; + /* Symbol names that begin with the following are ignored.*/ static const char * const ignored_prefixes[] = { "$", /* local symbols for ARM, MIPS, etc. */ ".LASANPC", /* s390 kasan local symbols */ @@ -113,6 +115,7 @@ static bool is_ignored_symbol(const char *name, char type) NULL }; + /* Symbol names that end with the following are ignored.*/ static const char * const ignored_suffixes[] = { "_from_arm", /* arm */ "_from_thumb", /* arm */ @@ -120,9 +123,15 @@ static bool is_ignored_symbol(const char *name, char type) NULL }; + /* Symbol names that contain the following are ignored.*/ + static const char * const ignored_matches[] = { + ".long_branch.", /* ppc stub */ + ".plt_branch.", /* ppc stub */ + NULL + }; + const char * const *p; - /* Exclude symbols which vary between passes. */ for (p = ignored_symbols; *p; p++) if (!strcmp(name, *p)) return true; @@ -138,6 +147,11 @@ static bool is_ignored_symbol(const char *name, char type) return true; } + for (p = ignored_matches; *p; p++) { + if (strstr(name, *p)) + return true; + } + if (type == 'U' || type == 'u') return true; /* exclude debugging symbols */ -- cgit From 548b8b5168c90c42e88f70fcf041b4ce0b8e7aa8 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Thu, 17 Sep 2020 08:56:11 +0200 Subject: scripts/setlocalversion: make git describe output more reliable When building for an embedded target using Yocto, we're sometimes observing that the version string that gets built into vmlinux (and thus what uname -a reports) differs from the path under /lib/modules/ where modules get installed in the rootfs, but only in the length of the -gabc123def suffix. Hence modprobe always fails. The problem is that Yocto has the concept of "sstate" (shared state), which allows different developers/buildbots/etc. to share build artifacts, based on a hash of all the metadata that went into building that artifact - and that metadata includes all dependencies (e.g. the compiler used etc.). That normally works quite well; usually a clean build (without using any sstate cache) done by one developer ends up being binary identical to a build done on another host. However, one thing that can cause two developers to end up with different builds [and thus make one's vmlinux package incompatible with the other's kernel-dev package], which is not captured by the metadata hashing, is this `git describe`: The output of that can be affected by (1) git version: before 2.11 git defaulted to a minimum of 7, since 2.11 (git.git commit e6c587) the default is dynamic based on the number of objects in the repo (2) hence even if both run the same git version, the output can differ based on how many remotes are being tracked (or just lots of local development branches or plain old garbage) (3) and of course somebody could have a core.abbrev config setting in ~/.gitconfig So in order to avoid `uname -a` output relying on such random details of the build environment which are rather hard to ensure are consistent between developers and buildbots, make sure the abbreviated sha1 always consists of exactly 12 hex characters. That is consistent with the current rule for -stable patches, and is almost always enough to identify the head commit unambigously - in the few cases where it does not, the v5.4.3-00021- prefix would certainly nail it down. Signed-off-by: Rasmus Villemoes Signed-off-by: Masahiro Yamada --- scripts/setlocalversion | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/setlocalversion b/scripts/setlocalversion index 20f2efd57b11..bb709eda96cd 100755 --- a/scripts/setlocalversion +++ b/scripts/setlocalversion @@ -45,7 +45,7 @@ scm_version() # Check for git and a git repo. if test -z "$(git rev-parse --show-cdup 2>/dev/null)" && - head=$(git rev-parse --verify --short HEAD 2>/dev/null); then + head=$(git rev-parse --verify HEAD 2>/dev/null); then # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore # it, because this version is defined in the top level Makefile. @@ -59,11 +59,22 @@ scm_version() fi # If we are past a tagged commit (like # "v2.6.30-rc5-302-g72357d5"), we pretty print it. - if atag="$(git describe 2>/dev/null)"; then - echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' - - # If we don't have a tag at all we print -g{commitish}. + # + # Ensure the abbreviated sha1 has exactly 12 + # hex characters, to make the output + # independent of git version, local + # core.abbrev settings and/or total number of + # objects in the current repository - passing + # --abbrev=12 ensures a minimum of 12, and the + # awk substr() then picks the 'g' and first 12 + # hex chars. + if atag="$(git describe --abbrev=12 2>/dev/null)"; then + echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),substr($(NF),0,13))}' + + # If we don't have a tag at all we print -g{commitish}, + # again using exactly 12 hex chars. else + head="$(echo $head | cut -c1-12)" printf '%s%s' -g $head fi fi -- cgit From e16a7c47d56b4eeee82be662014c145bce2380e5 Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Thu, 24 Sep 2020 16:56:08 +0530 Subject: scripts: coccicheck: Change default value for parallelism By default, coccicheck utilizes all available threads to implement parallelisation. However, when all available threads are used, a decrease in performance is noted. The elapsed time is minimum when at most one thread per core is used. For example, on benchmarking the semantic patch kfree.cocci for usb/serial using hyperfine, the outputs obtained for J=5 and J=2 are 1.32 and 1.90 times faster than those for J=10 and J=9 respectively for two separate runs. For the larger drivers/staging directory, minimium elapsed time is obtained for J=3 which is 1.86 times faster than that for J=12. The optimal J value does not exceed 6 in any of the test runs. The benchmarks are run on a machine with 6 cores, with 2 threads per core, i.e, 12 hyperthreads in all. To improve performance, modify coccicheck to use at most only one thread per core by default. Signed-off-by: Sumera Priyadarsini Signed-off-by: Julia Lawall --- scripts/coccicheck | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'scripts') diff --git a/scripts/coccicheck b/scripts/coccicheck index 85136f4fe970..6789751607f5 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -75,8 +75,13 @@ else OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE" fi + # Use only one thread per core by default if hyperthreading is enabled + THREADS_PER_CORE=$(lscpu | grep "Thread(s) per core: " | tr -cd [:digit:]) if [ -z "$J" ]; then NPROC=$(getconf _NPROCESSORS_ONLN) + if [ $THREADS_PER_CORE -gt 1 -a $NPROC -gt 2 ] ; then + NPROC=$((NPROC/2)) + fi else NPROC="$J" fi -- cgit From c4d0bfb45068d853a478b9067a95969b1886a30f Mon Sep 17 00:00:00 2001 From: Alan Maguire Date: Mon, 28 Sep 2020 12:31:05 +0100 Subject: bpf: Add bpf_snprintf_btf helper A helper is added to support tracing kernel type information in BPF using the BPF Type Format (BTF). Its signature is long bpf_snprintf_btf(char *str, u32 str_size, struct btf_ptr *ptr, u32 btf_ptr_size, u64 flags); struct btf_ptr * specifies - a pointer to the data to be traced - the BTF id of the type of data pointed to - a flags field is provided for future use; these flags are not to be confused with the BTF_F_* flags below that control how the btf_ptr is displayed; the flags member of the struct btf_ptr may be used to disambiguate types in kernel versus module BTF, etc; the main distinction is the flags relate to the type and information needed in identifying it; not how it is displayed. For example a BPF program with a struct sk_buff *skb could do the following: static struct btf_ptr b = { }; b.ptr = skb; b.type_id = __builtin_btf_type_id(struct sk_buff, 1); bpf_snprintf_btf(str, sizeof(str), &b, sizeof(b), 0, 0); Default output looks like this: (struct sk_buff){ .transport_header = (__u16)65535, .mac_header = (__u16)65535, .end = (sk_buff_data_t)192, .head = (unsigned char *)0x000000007524fd8b, .data = (unsigned char *)0x000000007524fd8b, .truesize = (unsigned int)768, .users = (refcount_t){ .refs = (atomic_t){ .counter = (int)1, }, }, } Flags modifying display are as follows: - BTF_F_COMPACT: no formatting around type information - BTF_F_NONAME: no struct/union member names/types - BTF_F_PTR_RAW: show raw (unobfuscated) pointer values; equivalent to %px. - BTF_F_ZERO: show zero-valued struct/union members; they are not displayed by default Signed-off-by: Alan Maguire Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/1601292670-1616-4-git-send-email-alan.maguire@oracle.com --- scripts/bpf_helpers_doc.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py index 08388173973f..7d86fdd190be 100755 --- a/scripts/bpf_helpers_doc.py +++ b/scripts/bpf_helpers_doc.py @@ -433,6 +433,7 @@ class PrinterHelpers(Printer): 'struct sk_msg_md', 'struct xdp_md', 'struct path', + 'struct btf_ptr', ] known_types = { '...', @@ -474,6 +475,7 @@ class PrinterHelpers(Printer): 'struct udp6_sock', 'struct task_struct', 'struct path', + 'struct btf_ptr', } mapped_types = { 'u8': '__u8', -- cgit From efe84d408bf41975db8506d3a1cc02e794e2309c Mon Sep 17 00:00:00 2001 From: Uwe Kleine-König Date: Sat, 19 Sep 2020 16:39:22 +0200 Subject: scripts/dtc: only append to HOST_EXTRACFLAGS instead of overwriting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When building with $ HOST_EXTRACFLAGS=-g make the expectation is that host tools are built with debug informations. This however doesn't happen if the Makefile assigns a new value to the HOST_EXTRACFLAGS instead of appending to it. So use += instead of := for the first assignment. Fixes: e3fd9b5384f3 ("scripts/dtc: consolidate include path options in Makefile") Signed-off-by: Uwe Kleine-König Signed-off-by: Rob Herring --- scripts/dtc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile index a698ece43fff..4852bf44e913 100644 --- a/scripts/dtc/Makefile +++ b/scripts/dtc/Makefile @@ -9,7 +9,7 @@ dtc-objs := dtc.o flattree.o fstree.o data.o livetree.o treesource.o \ dtc-objs += dtc-lexer.lex.o dtc-parser.tab.o # Source files need to get at the userspace version of libfdt_env.h to compile -HOST_EXTRACFLAGS := -I $(srctree)/$(src)/libfdt +HOST_EXTRACFLAGS += -I $(srctree)/$(src)/libfdt ifeq ($(shell pkg-config --exists yaml-0.1 2>/dev/null && echo yes),) ifneq ($(CHECK_DT_BINDING)$(CHECK_DTBS),) -- cgit From 44d8870f21529cfa8f50b503b5d949c6d46e6fc1 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Wed, 30 Sep 2020 19:00:46 +0300 Subject: coccinelle: api: add kvmalloc script Suggest kvmalloc, kvfree instead of opencoded patterns. Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/api/kvmalloc.cocci | 256 ++++++++++++++++++++++++++++++++++ 1 file changed, 256 insertions(+) create mode 100644 scripts/coccinelle/api/kvmalloc.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/api/kvmalloc.cocci b/scripts/coccinelle/api/kvmalloc.cocci new file mode 100644 index 000000000000..c30dab718a49 --- /dev/null +++ b/scripts/coccinelle/api/kvmalloc.cocci @@ -0,0 +1,256 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Find if/else condition with kmalloc/vmalloc calls. +/// Suggest to use kvmalloc instead. Same for kvfree. +/// +// Confidence: High +// Copyright: (C) 2020 Denis Efremov ISPRAS +// Options: --no-includes --include-headers +// + +virtual patch +virtual report +virtual org +virtual context + +@initialize:python@ +@@ +filter = frozenset(['kvfree']) + +def relevant(p): + return not (filter & {el.current_element for el in p}) + +@kvmalloc depends on !patch@ +expression E, E1, size; +identifier flags; +binary operator cmp = {<=, <, ==, >, >=}; +identifier x; +type T; +position p; +@@ + +( +* if (size cmp E1 || ...)@p { + ... +* E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| +* kmalloc_array\|kmalloc_array_node\|kcalloc_node\) +* (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...) + ... + } else { + ... +* E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) + ... + } +| +* E = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| +* kmalloc_array\|kmalloc_array_node\|kcalloc_node\) +* (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...) + ... when != E = E1 + when != size = E1 + when any +* if (E == NULL)@p { + ... +* E = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) + ... + } +| +* T x = \(kmalloc\|kzalloc\|kcalloc\|kmalloc_node\|kzalloc_node\| +* kmalloc_array\|kmalloc_array_node\|kcalloc_node\) +* (..., size, \(flags\|GFP_KERNEL\|\(GFP_KERNEL\|flags\)|__GFP_NOWARN\), ...); + ... when != x = E1 + when != size = E1 + when any +* if (x == NULL)@p { + ... +* x = \(vmalloc\|vzalloc\|vmalloc_node\|vzalloc_node\)(..., size, ...) + ... + } +) + +@kvfree depends on !patch@ +expression E; +position p : script:python() { relevant(p) }; +@@ + +* if (is_vmalloc_addr(E))@p { + ... +* vfree(E) + ... + } else { + ... when != krealloc(E, ...) + when any +* \(kfree\|kzfree\)(E) + ... + } + +@depends on patch@ +expression E, E1, size, node; +binary operator cmp = {<=, <, ==, >, >=}; +identifier flags, x; +type T; +@@ + +( +- if (size cmp E1) +- E = kmalloc(size, flags); +- else +- E = vmalloc(size); ++ E = kvmalloc(size, flags); +| +- if (size cmp E1) +- E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); +- else +- E = vmalloc(size); ++ E = kvmalloc(size, GFP_KERNEL); +| +- E = kmalloc(size, flags | __GFP_NOWARN); +- if (E == NULL) +- E = vmalloc(size); ++ E = kvmalloc(size, flags); +| +- E = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); +- if (E == NULL) +- E = vmalloc(size); ++ E = kvmalloc(size, GFP_KERNEL); +| +- T x = kmalloc(size, flags | __GFP_NOWARN); +- if (x == NULL) +- x = vmalloc(size); ++ T x = kvmalloc(size, flags); +| +- T x = kmalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); +- if (x == NULL) +- x = vmalloc(size); ++ T x = kvmalloc(size, GFP_KERNEL); +| +- if (size cmp E1) +- E = kzalloc(size, flags); +- else +- E = vzalloc(size); ++ E = kvzalloc(size, flags); +| +- if (size cmp E1) +- E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); +- else +- E = vzalloc(size); ++ E = kvzalloc(size, GFP_KERNEL); +| +- E = kzalloc(size, flags | __GFP_NOWARN); +- if (E == NULL) +- E = vzalloc(size); ++ E = kvzalloc(size, flags); +| +- E = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); +- if (E == NULL) +- E = vzalloc(size); ++ E = kvzalloc(size, GFP_KERNEL); +| +- T x = kzalloc(size, flags | __GFP_NOWARN); +- if (x == NULL) +- x = vzalloc(size); ++ T x = kvzalloc(size, flags); +| +- T x = kzalloc(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\)); +- if (x == NULL) +- x = vzalloc(size); ++ T x = kvzalloc(size, GFP_KERNEL); +| +- if (size cmp E1) +- E = kmalloc_node(size, flags, node); +- else +- E = vmalloc_node(size, node); ++ E = kvmalloc_node(size, flags, node); +| +- if (size cmp E1) +- E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); +- else +- E = vmalloc_node(size, node); ++ E = kvmalloc_node(size, GFP_KERNEL, node); +| +- E = kmalloc_node(size, flags | __GFP_NOWARN, node); +- if (E == NULL) +- E = vmalloc_node(size, node); ++ E = kvmalloc_node(size, flags, node); +| +- E = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); +- if (E == NULL) +- E = vmalloc_node(size, node); ++ E = kvmalloc_node(size, GFP_KERNEL, node); +| +- T x = kmalloc_node(size, flags | __GFP_NOWARN, node); +- if (x == NULL) +- x = vmalloc_node(size, node); ++ T x = kvmalloc_node(size, flags, node); +| +- T x = kmalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); +- if (x == NULL) +- x = vmalloc_node(size, node); ++ T x = kvmalloc_node(size, GFP_KERNEL, node); +| +- if (size cmp E1) +- E = kvzalloc_node(size, flags, node); +- else +- E = vzalloc_node(size, node); ++ E = kvzalloc_node(size, flags, node); +| +- if (size cmp E1) +- E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); +- else +- E = vzalloc_node(size, node); ++ E = kvzalloc_node(size, GFP_KERNEL, node); +| +- E = kvzalloc_node(size, flags | __GFP_NOWARN, node); +- if (E == NULL) +- E = vzalloc_node(size, node); ++ E = kvzalloc_node(size, flags, node); +| +- E = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); +- if (E == NULL) +- E = vzalloc_node(size, node); ++ E = kvzalloc_node(size, GFP_KERNEL, node); +| +- T x = kvzalloc_node(size, flags | __GFP_NOWARN, node); +- if (x == NULL) +- x = vzalloc_node(size, node); ++ T x = kvzalloc_node(size, flags, node); +| +- T x = kvzalloc_node(size, \(GFP_KERNEL\|GFP_KERNEL|__GFP_NOWARN\), node); +- if (x == NULL) +- x = vzalloc_node(size, node); ++ T x = kvzalloc_node(size, GFP_KERNEL, node); +) + +@depends on patch@ +expression E; +position p : script:python() { relevant(p) }; +@@ + +- if (is_vmalloc_addr(E))@p +- vfree(E); +- else +- kfree(E); ++ kvfree(E); + +@script: python depends on report@ +p << kvmalloc.p; +@@ + +coccilib.report.print_report(p[0], "WARNING opportunity for kvmalloc") + +@script: python depends on org@ +p << kvmalloc.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING opportunity for kvmalloc") + +@script: python depends on report@ +p << kvfree.p; +@@ + +coccilib.report.print_report(p[0], "WARNING opportunity for kvfree") + +@script: python depends on org@ +p << kvfree.p; +@@ + +coccilib.org.print_todo(p[0], "WARNING opportunity for kvfree") -- cgit From c5c553850899e2662ecf749ac21fff95d17f59a4 Mon Sep 17 00:00:00 2001 From: Lukas Bulwahn Date: Sat, 26 Sep 2020 21:03:54 +0200 Subject: scripts/spdxcheck.py: handle license identifiers in XML comments Commit cc9539e7884c ("media: docs: use the new SPDX header for GFDL-1.1 on *.svg files") adds SPDX-License-Identifiers enclosed in XML comments, i.e., , for svg files. Unfortunately, ./scripts/spdxcheck.py does not handle SPDX-License-Identifiers in XML comments, so it simply fails on checking these files with 'Invalid License ID: --'. Strip the XML comment ending simply by copying how it was done for comments in C. With that, ./scripts/spdxcheck.py handles the svg files properly. Signed-off-by: Lukas Bulwahn Signed-off-by: Greg Kroah-Hartman --- scripts/spdxcheck.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/spdxcheck.py b/scripts/spdxcheck.py index 6374e078a5f2..bc87200f9c7c 100755 --- a/scripts/spdxcheck.py +++ b/scripts/spdxcheck.py @@ -180,6 +180,9 @@ class id_parser(object): # Remove trailing comment closure if line.strip().endswith('*/'): expr = expr.rstrip('*/').strip() + # Remove trailing xml comment closure + if line.strip().endswith('-->'): + expr = expr.rstrip('-->').strip() # Special case for SH magic boot code files if line.startswith('LIST \"'): expr = expr.rstrip('\"').strip() -- cgit From d43ca1386bf21b783d618e3a5f61c3b2e8759df2 Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Fri, 2 Oct 2020 22:21:48 -0700 Subject: scripts/spelling.txt: fix malformed entry One of the entries has three fields "mistake||correction||correction" rather than the expected two fields "mistake||correction". Fix it. Signed-off-by: Eric Biggers Signed-off-by: Andrew Morton Link: https://lkml.kernel.org/r/20200930234359.255295-1-ebiggers@kernel.org Signed-off-by: Linus Torvalds --- scripts/spelling.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/spelling.txt b/scripts/spelling.txt index f253681e7e2a..feb2efaaa5e6 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -589,7 +589,7 @@ explictly||explicitly expresion||expression exprimental||experimental extened||extended -exteneded||extended||extended +exteneded||extended extensability||extensibility extention||extension extenstion||extension -- cgit From 7b36c1398fb63f9c38cc83dc75f143d2e5995062 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Mon, 21 Sep 2020 20:49:20 +0300 Subject: coccinelle: misc: add flexible_array.cocci script One-element and zero-length arrays are deprecated [1]. Kernel code should always use "flexible array members" instead, except for existing uapi definitions. The script warns about one-element and zero-length arrays in structs. [1] commit 68e4cd17e218 ("docs: deprecated.rst: Add zero-length and one-element arrays") Cc: Kees Cook Cc: Gustavo A. R. Silva Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/misc/flexible_array.cocci | 88 ++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 scripts/coccinelle/misc/flexible_array.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/misc/flexible_array.cocci b/scripts/coccinelle/misc/flexible_array.cocci new file mode 100644 index 000000000000..947fbaff82a9 --- /dev/null +++ b/scripts/coccinelle/misc/flexible_array.cocci @@ -0,0 +1,88 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Zero-length and one-element arrays are deprecated, see +/// Documentation/process/deprecated.rst +/// Flexible-array members should be used instead. +/// +// +// Confidence: High +// Copyright: (C) 2020 Denis Efremov ISPRAS. +// Comments: +// Options: --no-includes --include-headers + +virtual context +virtual report +virtual org +virtual patch + +@initialize:python@ +@@ +def relevant(positions): + for p in positions: + if "uapi" in p.file: + return False + return True + +@r depends on !patch@ +identifier name, array; +type T; +position p : script:python() { relevant(p) }; +@@ + +( + struct name { + ... +* T array@p[\(0\|1\)]; + }; +| + struct { + ... +* T array@p[\(0\|1\)]; + }; +| + union name { + ... +* T array@p[\(0\|1\)]; + }; +| + union { + ... +* T array@p[\(0\|1\)]; + }; +) + +@depends on patch@ +identifier name, array; +type T; +position p : script:python() { relevant(p) }; +@@ + +( + struct name { + ... + T array@p[ +- 0 + ]; + }; +| + struct { + ... + T array@p[ +- 0 + ]; + }; +) + +@script: python depends on report@ +p << r.p; +@@ + +msg = "WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)" +coccilib.report.print_report(p[0], msg) + +@script: python depends on org@ +p << r.p; +@@ + +msg = "WARNING use flexible-array member instead (https://www.kernel.org/doc/html/latest/process/deprecated.html#zero-length-and-one-element-arrays)" +coccilib.org.print_todo(p[0], msg) -- cgit From d89d5f855f84ccf3f7e648813b4bb95c780bd7cd Mon Sep 17 00:00:00 2001 From: Paul Bolle Date: Thu, 1 Oct 2020 22:20:28 +0200 Subject: locking/atomics: Check atomic-arch-fallback.h too The sha1sum of include/linux/atomic-arch-fallback.h isn't checked by check-atomics.sh. It's not clear why it's skipped so let's check it too. Signed-off-by: Paul Bolle Signed-off-by: Peter Zijlstra (Intel) Reviewed-by: Mark Rutland Link: https://lkml.kernel.org/r/20201001202028.1048418-1-pebolle@tiscali.nl --- scripts/atomic/check-atomics.sh | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/atomic/check-atomics.sh b/scripts/atomic/check-atomics.sh index 8378c63a1e09..82748d42ecc5 100755 --- a/scripts/atomic/check-atomics.sh +++ b/scripts/atomic/check-atomics.sh @@ -16,6 +16,7 @@ fi cat < Date: Fri, 25 Sep 2020 00:45:46 +0900 Subject: kbuild: split the build log of kallsyms Currently, the build log shows KSYM + object name. Precisely speaking, kallsyms generates a .S file and then the compiler compiles it into a .o file. Split the build log into two. [Before] GEN modules.builtin LD .tmp_vmlinux.kallsyms1 KSYM .tmp_vmlinux.kallsyms1.o LD .tmp_vmlinux.kallsyms2 KSYM .tmp_vmlinux.kallsyms2.o LD vmlinux [After] GEN modules.builtin LD .tmp_vmlinux.kallsyms1 KSYMS .tmp_vmlinux.kallsyms1.S AS .tmp_vmlinux.kallsyms1.o LD .tmp_vmlinux.kallsyms2 KSYMS .tmp_vmlinux.kallsyms2.S AS .tmp_vmlinux.kallsyms2.o LD vmlinux Signed-off-by: Masahiro Yamada --- scripts/link-vmlinux.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index e6e2d9e5ff48..d9bcf36a1583 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -169,10 +169,9 @@ gen_btf() printf '\1' | dd of=${2} conv=notrunc bs=1 seek=16 status=none } -# Create ${2} .o file with all symbols from the ${1} object file +# Create ${2} .S file with all symbols from the ${1} object file kallsyms() { - info KSYM ${2} local kallsymopt; if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then @@ -187,13 +186,8 @@ kallsyms() kallsymopt="${kallsymopt} --base-relative" fi - local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ - ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" - - local afile="`basename ${2} .o`.S" - - ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${afile} - ${CC} ${aflags} -c -o ${2} ${afile} + info KSYMS ${2} + ${NM} -n ${1} | scripts/kallsyms ${kallsymopt} > ${2} } # Perform one step in kallsyms generation, including temporary linking of @@ -203,9 +197,15 @@ kallsyms_step() kallsymso_prev=${kallsymso} kallsyms_vmlinux=.tmp_vmlinux.kallsyms${1} kallsymso=${kallsyms_vmlinux}.o + kallsyms_S=${kallsyms_vmlinux}.S vmlinux_link ${kallsyms_vmlinux} "${kallsymso_prev}" ${btf_vmlinux_bin_o} - kallsyms ${kallsyms_vmlinux} ${kallsymso} + kallsyms ${kallsyms_vmlinux} ${kallsyms_S} + + info AS ${kallsyms_S} + ${CC} ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS} \ + ${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ + -c -o ${kallsymso} ${kallsyms_S} } # Create map file with all symbols from ${1} -- cgit From 51ccdbfbed79bae4b9c2529ec980de4508455a47 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 21 Sep 2020 00:25:50 +0200 Subject: builddeb: Pass -n to gzip for reproducible packages We should not be encoding the timestamp, otherwise we end up generating unreproducible files that cascade into unreproducible packages. Signed-off-by: Guillem Jover Signed-off-by: Masahiro Yamada --- scripts/package/builddeb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 44f212e37935..30e8c6a20171 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -31,7 +31,7 @@ create_package() { mkdir -p "$pdir/usr/share/doc/$pname" cp debian/copyright "$pdir/usr/share/doc/$pname/" cp debian/changelog "$pdir/usr/share/doc/$pname/changelog.Debian" - gzip -9 "$pdir/usr/share/doc/$pname/changelog.Debian" + gzip -n -9 "$pdir/usr/share/doc/$pname/changelog.Debian" sh -c "cd '$pdir'; find . -type f ! -path './DEBIAN/*' -printf '%P\0' \ | xargs -r0 md5sum > DEBIAN/md5sums" -- cgit From 3e8541803624678925a477a03e19e3c155b5fc12 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 21 Sep 2020 00:25:54 +0200 Subject: builddeb: Enable rootless builds This makes it possible to build the Debian packages without requiring (pseudo-)root privileges, when the build drivers support this mode of operation. See-Also: /usr/share/doc/dpkg/rootless-builds.txt.gz Signed-off-by: Guillem Jover Signed-off-by: Masahiro Yamada --- scripts/package/builddeb | 9 +++++++-- scripts/package/mkdebian | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 30e8c6a20171..6474084c32a4 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -26,6 +26,7 @@ if_enabled_echo() { create_package() { local pname="$1" pdir="$2" + local dpkg_deb_opts mkdir -m 755 -p "$pdir/DEBIAN" mkdir -p "$pdir/usr/share/doc/$pname" @@ -36,14 +37,18 @@ create_package() { | xargs -r0 md5sum > DEBIAN/md5sums" # Fix ownership and permissions - chown -R root:root "$pdir" + if [ "$DEB_RULES_REQUIRES_ROOT" = "no" ]; then + dpkg_deb_opts="--root-owner-group" + else + chown -R root:root "$pdir" + fi chmod -R go-w "$pdir" # in case we are in a restrictive umask environment like 0077 chmod -R a+rX "$pdir" # Create the package dpkg-gencontrol -p$pname -P"$pdir" - dpkg-deb ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" .. + dpkg-deb $dpkg_deb_opts ${KDEB_COMPRESS:+-Z$KDEB_COMPRESS} --build "$pdir" .. } deploy_kernel_headers () { diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index 48fbd3d0284a..dbe42500084c 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -174,6 +174,7 @@ Source: $sourcename Section: kernel Priority: optional Maintainer: $maintainer +Rules-Requires-Root: no Build-Depends: bc, rsync, kmod, cpio, bison, flex | flex:native $extra_build_depends Homepage: https://www.kernel.org/ -- cgit From 76c37668768464a6c2d5c49abd36ba0b48a0b131 Mon Sep 17 00:00:00 2001 From: Guillem Jover Date: Mon, 21 Sep 2020 00:25:53 +0200 Subject: builddeb: Add support for all required debian/rules targets These have been required by the Debian policy for a while, even though the tooling can detect and workaround their omission, but are a hard requirement when using rootless builds. [masahiro: The following Debian policy is particularly important for rootless builds: "Both binary-* targets should depend on the build target, or on the appropriate build-arch or build-indep target, so that the package is built if it has not been already." ] Signed-off-by: Guillem Jover Signed-off-by: Masahiro Yamada --- scripts/package/mkdebian | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index dbe42500084c..3a13b834f281 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -218,11 +218,15 @@ cat < debian/rules srctree ?= . -build: +build-indep: +build-arch: \$(MAKE) KERNELRELEASE=${version} ARCH=${ARCH} \ KBUILD_BUILD_VERSION=${revision} -f \$(srctree)/Makefile -binary-arch: +build: build-arch + +binary-indep: +binary-arch: build-arch \$(MAKE) KERNELRELEASE=${version} ARCH=${ARCH} \ KBUILD_BUILD_VERSION=${revision} -f \$(srctree)/Makefile intdeb-pkg -- cgit From 28c185a88607bc361ec7f071b907285e2e75de1b Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 9 Oct 2020 15:54:53 +0300 Subject: coccinelle: api: kfree_sensitive: print memset position Print memset() call position in addition to the kfree() position to ease issues identification. Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/api/kfree_sensitive.cocci | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/coccinelle/api/kfree_sensitive.cocci b/scripts/coccinelle/api/kfree_sensitive.cocci index e4a066a0b77d..8d980ebf3223 100644 --- a/scripts/coccinelle/api/kfree_sensitive.cocci +++ b/scripts/coccinelle/api/kfree_sensitive.cocci @@ -85,14 +85,16 @@ type T; @script:python depends on report@ p << r.p; +m << r.m; @@ -coccilib.report.print_report(p[0], - "WARNING: opportunity for kfree_sensitive/kvfree_sensitive") +msg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)" +coccilib.report.print_report(p[0], msg % (m[0].line)) @script:python depends on org@ p << r.p; +m << r.m; @@ -coccilib.org.print_todo(p[0], - "WARNING: opportunity for kfree_sensitive/kvfree_sensitive") +msg = "WARNING opportunity for kfree_sensitive/kvfree_sensitive (memset at line %s)" +coccilib.org.print_todo(p[0], msg % (m[0].line)) -- cgit From 7dfbea4c468cfbc7e1ceb619fe337e7582eb1d2d Mon Sep 17 00:00:00 2001 From: Jacob Keller Date: Fri, 9 Oct 2020 17:18:44 -0700 Subject: scripts: remove namespace.pl namespace.pl is intended to help locate symbols which are defined but are not used externally. The goal is to avoid bloat of the namespace in the resulting kernel image. The script relies on object data, and only finds unused symbols for the configuration used to generate that object data. This results in a lot of false positive warnings such as symbols only used by a single architecture, or symbols which are used externally only under certain configurations. Running namespace.pl using allyesconfig, allmodconfig, and x86_64_defconfig yields the following results: * allmodconfig * 11122 unique symbol names with no external reference * 1194 symbols listed as multiply defined * 214 symbols it can't resolve * allyesconfig * 10997 unique symbol names with no external reference * 1194 symbols listed as multiply defined * 214 symbols it can't resolve * x86_64_defconfig * 5757 unique symbol names with no external reference * 528 symbols listed as multiply defined * 154 symbols it can't resolve The script also has no way to easily limit the scope of the checks to a given subset of the kernel, such as only checking for symbols defined within a module or subsystem. Discussion on public mailing lists seems to indicate that many view the tool output as suspect or not very useful (see discussions at [1] and [2] for further context). As described by Masahiro Yamada at [2], namespace.pl provides 3 types of checks: listing multiply defined symbols, resolving external symbols, and warnings about symbols with no reference. The first category of issues is easily caught by the linker as any set of multiply defined symbols should fail to link. The second category of issues is also caught by linking, as undefined symbols would cause issues. Even with modules, these types of issues where a module relies on an external symbol are caught by modpost. The remaining category of issues reported is the list of symbols with no external reference, and is the primary motivation of this script. However, it ought to be clear from the above examples that the output is difficult to sort through. Even allyesconfig has ~10000 entries. The current submit-checklist indicates that patches ought to go through namespacecheck and fix any new issues arising. But that itself presents problems. As described at [1], many cases of reports are due to configuration where a function is used externally by some configuration settings. Prominent maintainers appear to dislike changes modify code such that symbols become static based on CONFIG_* flags ([3], and [4]) One possible solution is to adjust the advice and indicate that we only care about the output of namespacecheck on allyesconfig or allmodconfig builds... However, given the discussion at [2], I suspect that few people are actively using this tool. It doesn't have a maintainer in the MAINTAINERS flie, and it produces so many warnings for unused symbols that it is difficult to use effectively. Thus, I propose we simply remove it. [1] https://lore.kernel.org/netdev/20200708164812.384ae8ea@kicinski-fedora-pc1c0hjn.dhcp.thefacebook.com/ [2] https://lore.kernel.org/lkml/20190129204319.15238-1-jacob.e.keller@intel.com/ [3] https://lore.kernel.org/netdev/20190828.154744.2058157956381129672.davem@davemloft.net/ [4] https://lore.kernel.org/netdev/20190827210928.576c5fef@cakuba.netronome.com/ Signed-off-by: Jacob Keller Acked-by: Randy Dunlap Acked-by: Jakub Kicinski Signed-off-by: Masahiro Yamada --- scripts/namespace.pl | 473 --------------------------------------------------- 1 file changed, 473 deletions(-) delete mode 100755 scripts/namespace.pl (limited to 'scripts') diff --git a/scripts/namespace.pl b/scripts/namespace.pl deleted file mode 100755 index 1da7bca201a4..000000000000 --- a/scripts/namespace.pl +++ /dev/null @@ -1,473 +0,0 @@ -#!/usr/bin/env perl -# -# namespace.pl. Mon Aug 30 2004 -# -# Perform a name space analysis on the linux kernel. -# -# Copyright Keith Owens . GPL. -# -# Invoke by changing directory to the top of the kernel object -# tree then namespace.pl, no parameters. -# -# Tuned for 2.1.x kernels with the new module handling, it will -# work with 2.0 kernels as well. -# -# Last change 2.6.9-rc1, adding support for separate source and object -# trees. -# -# The source must be compiled/assembled first, the object files -# are the primary input to this script. Incomplete or missing -# objects will result in a flawed analysis. Compile both vmlinux -# and modules. -# -# Even with complete objects, treat the result of the analysis -# with caution. Some external references are only used by -# certain architectures, others with certain combinations of -# configuration parameters. Ideally the source should include -# something like -# -# #ifndef CONFIG_... -# static -# #endif -# symbol_definition; -# -# so the symbols are defined as static unless a particular -# CONFIG_... requires it to be external. -# -# A symbol that is suffixed with '(export only)' has these properties -# -# * It is global. -# * It is marked EXPORT_SYMBOL or EXPORT_SYMBOL_GPL, either in the same -# source file or a different source file. -# * Given the current .config, nothing uses the symbol. -# -# The symbol is a candidate for conversion to static, plus removal of the -# export. But be careful that a different .config might use the symbol. -# -# -# Name space analysis and cleanup is an iterative process. You cannot -# expect to find all the problems in a single pass. -# -# * Identify possibly unnecessary global declarations, verify that they -# really are unnecessary and change them to static. -# * Compile and fix up gcc warnings about static, removing dead symbols -# as necessary. -# * make clean and rebuild with different configs (especially -# CONFIG_MODULES=n) to see which symbols are being defined when the -# config does not require them. These symbols bloat the kernel object -# for no good reason, which is frustrating for embedded systems. -# * Wrap config sensitive symbols in #ifdef CONFIG_foo, as long as the -# code does not get too ugly. -# * Repeat the name space analysis until you can live with with the -# result. -# - -use warnings; -use strict; -use File::Find; -use File::Spec; - -my $nm = ($ENV{'NM'} || "nm") . " -p"; -my $objdump = ($ENV{'OBJDUMP'} || "objdump") . " -s -j .comment"; -my $srctree = File::Spec->curdir(); -my $objtree = File::Spec->curdir(); -$srctree = File::Spec->rel2abs($ENV{'srctree'}) if (exists($ENV{'srctree'})); -$objtree = File::Spec->rel2abs($ENV{'objtree'}) if (exists($ENV{'objtree'})); - -if ($#ARGV != -1) { - print STDERR "usage: $0 takes no parameters\n"; - die("giving up\n"); -} - -my %nmdata = (); # nm data for each object -my %def = (); # all definitions for each name -my %ksymtab = (); # names that appear in __ksymtab_ -my %ref = (); # $ref{$name} exists if there is a true external reference to $name -my %export = (); # $export{$name} exists if there is an EXPORT_... of $name - -my %nmexception = ( - 'fs/ext3/bitmap' => 1, - 'fs/ext4/bitmap' => 1, - 'arch/x86/lib/thunk_32' => 1, - 'arch/x86/lib/cmpxchg' => 1, - 'arch/x86/vdso/vdso32/note' => 1, - 'lib/irq_regs' => 1, - 'usr/initramfs_data' => 1, - 'drivers/scsi/aic94xx/aic94xx_dump' => 1, - 'drivers/scsi/libsas/sas_dump' => 1, - 'lib/dec_and_lock' => 1, - 'drivers/ide/ide-probe-mini' => 1, - 'usr/initramfs_data' => 1, - 'drivers/acpi/acpia/exdump' => 1, - 'drivers/acpi/acpia/rsdump' => 1, - 'drivers/acpi/acpia/nsdumpdv' => 1, - 'drivers/acpi/acpia/nsdump' => 1, - 'arch/ia64/sn/kernel/sn2/io' => 1, - 'arch/ia64/kernel/gate-data' => 1, - 'security/capability' => 1, - 'fs/ntfs/sysctl' => 1, - 'fs/jfs/jfs_debug' => 1, -); - -my %nameexception = ( - 'mod_use_count_' => 1, - '__initramfs_end' => 1, - '__initramfs_start' => 1, - '_einittext' => 1, - '_sinittext' => 1, - 'kallsyms_names' => 1, - 'kallsyms_num_syms' => 1, - 'kallsyms_addresses'=> 1, - 'kallsyms_offsets' => 1, - 'kallsyms_relative_base'=> 1, - '__this_module' => 1, - '_etext' => 1, - '_edata' => 1, - '_end' => 1, - '__bss_start' => 1, - '_text' => 1, - '_stext' => 1, - '__gp' => 1, - 'ia64_unw_start' => 1, - 'ia64_unw_end' => 1, - '__init_begin' => 1, - '__init_end' => 1, - '__bss_stop' => 1, - '__nosave_begin' => 1, - '__nosave_end' => 1, - 'pg0' => 1, - 'vdso_enabled' => 1, - '__stack_chk_fail' => 1, - 'VDSO32_PRELINK' => 1, - 'VDSO32_vsyscall' => 1, - 'VDSO32_rt_sigreturn'=>1, - 'VDSO32_sigreturn' => 1, -); - - -&find(\&linux_objects, '.'); # find the objects and do_nm on them -&list_multiply_defined(); -&resolve_external_references(); -&list_extra_externals(); - -exit(0); - -sub linux_objects -{ - # Select objects, ignoring objects which are only created by - # merging other objects. Also ignore all of modules, scripts - # and compressed. Most conglomerate objects are handled by do_nm, - # this list only contains the special cases. These include objects - # that are linked from just one other object and objects for which - # there is really no permanent source file. - my $basename = $_; - $_ = $File::Find::name; - s:^\./::; - if (/.*\.o$/ && - ! ( - m:/built-in.a$: - || m:arch/x86/vdso/: - || m:arch/x86/boot/: - || m:arch/ia64/ia32/ia32.o$: - || m:arch/ia64/kernel/gate-syms.o$: - || m:arch/ia64/lib/__divdi3.o$: - || m:arch/ia64/lib/__divsi3.o$: - || m:arch/ia64/lib/__moddi3.o$: - || m:arch/ia64/lib/__modsi3.o$: - || m:arch/ia64/lib/__udivdi3.o$: - || m:arch/ia64/lib/__udivsi3.o$: - || m:arch/ia64/lib/__umoddi3.o$: - || m:arch/ia64/lib/__umodsi3.o$: - || m:arch/ia64/scripts/check_gas_for_hint.o$: - || m:arch/ia64/sn/kernel/xp.o$: - || m:boot/bbootsect.o$: - || m:boot/bsetup.o$: - || m:/bootsect.o$: - || m:/boot/setup.o$: - || m:/compressed/: - || m:drivers/cdrom/driver.o$: - || m:drivers/char/drm/tdfx_drv.o$: - || m:drivers/ide/ide-detect.o$: - || m:drivers/ide/pci/idedriver-pci.o$: - || m:drivers/media/media.o$: - || m:drivers/scsi/sd_mod.o$: - || m:drivers/video/video.o$: - || m:fs/devpts/devpts.o$: - || m:fs/exportfs/exportfs.o$: - || m:fs/hugetlbfs/hugetlbfs.o$: - || m:fs/msdos/msdos.o$: - || m:fs/nls/nls.o$: - || m:fs/ramfs/ramfs.o$: - || m:fs/romfs/romfs.o$: - || m:fs/vfat/vfat.o$: - || m:init/mounts.o$: - || m:^modules/: - || m:net/netlink/netlink.o$: - || m:net/sched/sched.o$: - || m:/piggy.o$: - || m:^scripts/: - || m:sound/.*/snd-: - || m:^.*/\.tmp_: - || m:^\.tmp_: - || m:/vmlinux-obj.o$: - || m:^tools/: - ) - ) { - do_nm($basename, $_); - } - $_ = $basename; # File::Find expects $_ untouched (undocumented) -} - -sub do_nm -{ - my ($basename, $fullname) = @_; - my ($source, $type, $name); - if (! -e $basename) { - printf STDERR "$basename does not exist\n"; - return; - } - if ($fullname !~ /\.o$/) { - printf STDERR "$fullname is not an object file\n"; - return; - } - ($source = $basename) =~ s/\.o$//; - if (-e "$source.c" || -e "$source.S") { - $source = File::Spec->catfile($objtree, $File::Find::dir, $source) - } else { - $source = File::Spec->catfile($srctree, $File::Find::dir, $source) - } - if (! -e "$source.c" && ! -e "$source.S") { - # No obvious source, exclude the object if it is conglomerate - open(my $objdumpdata, "$objdump $basename|") - or die "$objdump $fullname failed $!\n"; - - my $comment; - while (<$objdumpdata>) { - chomp(); - if (/^In archive/) { - # Archives are always conglomerate - $comment = "GCC:GCC:"; - last; - } - next if (! /^[ 0-9a-f]{5,} /); - $comment .= substr($_, 43); - } - close($objdumpdata); - - if (!defined($comment) || $comment !~ /GCC\:.*GCC\:/m) { - printf STDERR "No source file found for $fullname\n"; - } - return; - } - open (my $nmdata, "$nm $basename|") - or die "$nm $fullname failed $!\n"; - - my @nmdata; - while (<$nmdata>) { - chop; - ($type, $name) = (split(/ +/, $_, 3))[1..2]; - # Expected types - # A absolute symbol - # B weak external reference to data that has been resolved - # C global variable, uninitialised - # D global variable, initialised - # G global variable, initialised, small data section - # R global array, initialised - # S global variable, uninitialised, small bss - # T global label/procedure - # U external reference - # W weak external reference to text that has been resolved - # V similar to W, but the value of the weak symbol becomes zero with no error. - # a assembler equate - # b static variable, uninitialised - # d static variable, initialised - # g static variable, initialised, small data section - # r static array, initialised - # s static variable, uninitialised, small bss - # t static label/procedures - # w weak external reference to text that has not been resolved - # v similar to w - # ? undefined type, used a lot by modules - if ($type !~ /^[ABCDGRSTUWVabdgrstwv?]$/) { - printf STDERR "nm output for $fullname contains unknown type '$_'\n"; - } - elsif ($name =~ /\./) { - # name with '.' is local static - } - else { - $type = 'R' if ($type eq '?'); # binutils replaced ? with R at one point - # binutils keeps changing the type for exported symbols, force it to R - $type = 'R' if ($name =~ /^__ksymtab/ || $name =~ /^__kstrtab/); - $name =~ s/_R[a-f0-9]{8}$//; # module versions adds this - if ($type =~ /[ABCDGRSTWV]/ && - $name ne 'init_module' && - $name ne 'cleanup_module' && - $name ne 'Using_Versions' && - $name !~ /^Version_[0-9]+$/ && - $name !~ /^__parm_/ && - $name !~ /^__kstrtab/ && - $name !~ /^__ksymtab/ && - $name !~ /^__kcrctab_/ && - $name !~ /^__exitcall_/ && - $name !~ /^__initcall_/ && - $name !~ /^__kdb_initcall_/ && - $name !~ /^__kdb_exitcall_/ && - $name !~ /^__module_/ && - $name !~ /^__mod_/ && - $name !~ /^__crc_/ && - $name ne '__this_module' && - $name ne 'kernel_version') { - if (!exists($def{$name})) { - $def{$name} = []; - } - push(@{$def{$name}}, $fullname); - } - push(@nmdata, "$type $name"); - if ($name =~ /^__ksymtab_/) { - $name = substr($name, 10); - if (!exists($ksymtab{$name})) { - $ksymtab{$name} = []; - } - push(@{$ksymtab{$name}}, $fullname); - } - } - } - close($nmdata); - - if ($#nmdata < 0) { - printf "No nm data for $fullname\n" - unless $nmexception{$fullname}; - return; - } - $nmdata{$fullname} = \@nmdata; -} - -sub drop_def -{ - my ($object, $name) = @_; - my $nmdata = $nmdata{$object}; - my ($i, $j); - for ($i = 0; $i <= $#{$nmdata}; ++$i) { - if ($name eq (split(' ', $nmdata->[$i], 2))[1]) { - splice(@{$nmdata{$object}}, $i, 1); - my $def = $def{$name}; - for ($j = 0; $j < $#{$def{$name}}; ++$j) { - if ($def{$name}[$j] eq $object) { - splice(@{$def{$name}}, $j, 1); - } - } - last; - } - } -} - -sub list_multiply_defined -{ - foreach my $name (keys(%def)) { - if ($#{$def{$name}} > 0) { - # Special case for cond_syscall - if ($#{$def{$name}} == 1 && - ($name =~ /^sys_/ || $name =~ /^compat_sys_/ || - $name =~ /^sys32_/)) { - if($def{$name}[0] eq "kernel/sys_ni.o" || - $def{$name}[1] eq "kernel/sys_ni.o") { - &drop_def("kernel/sys_ni.o", $name); - next; - } - } - - printf "$name is multiply defined in :-\n"; - foreach my $module (@{$def{$name}}) { - printf "\t$module\n"; - } - } - } -} - -sub resolve_external_references -{ - my ($kstrtab, $ksymtab, $export); - - printf "\n"; - foreach my $object (keys(%nmdata)) { - my $nmdata = $nmdata{$object}; - for (my $i = 0; $i <= $#{$nmdata}; ++$i) { - my ($type, $name) = split(' ', $nmdata->[$i], 2); - if ($type eq "U" || $type eq "w") { - if (exists($def{$name}) || exists($ksymtab{$name})) { - # add the owning object to the nmdata - $nmdata->[$i] = "$type $name $object"; - # only count as a reference if it is not EXPORT_... - $kstrtab = "R __kstrtab_$name"; - $ksymtab = "R __ksymtab_$name"; - $export = 0; - for (my $j = 0; $j <= $#{$nmdata}; ++$j) { - if ($nmdata->[$j] eq $kstrtab || - $nmdata->[$j] eq $ksymtab) { - $export = 1; - last; - } - } - if ($export) { - $export{$name} = ""; - } - else { - $ref{$name} = "" - } - } - elsif ( ! $nameexception{$name} - && $name !~ /^__sched_text_/ - && $name !~ /^__start_/ - && $name !~ /^__end_/ - && $name !~ /^__stop_/ - && $name !~ /^__scheduling_functions_.*_here/ - && $name !~ /^__.*initcall_/ - && $name !~ /^__.*per_cpu_start/ - && $name !~ /^__.*per_cpu_end/ - && $name !~ /^__alt_instructions/ - && $name !~ /^__setup_/ - && $name !~ /^__mod_timer/ - && $name !~ /^__mod_page_state/ - && $name !~ /^init_module/ - && $name !~ /^cleanup_module/ - ) { - printf "Cannot resolve "; - printf "weak " if ($type eq "w"); - printf "reference to $name from $object\n"; - } - } - } - } -} - -sub list_extra_externals -{ - my %noref = (); - - foreach my $name (keys(%def)) { - if (! exists($ref{$name})) { - my @module = @{$def{$name}}; - foreach my $module (@module) { - if (! exists($noref{$module})) { - $noref{$module} = []; - } - push(@{$noref{$module}}, $name); - } - } - } - if (%noref) { - printf "\nExternally defined symbols with no external references\n"; - foreach my $module (sort(keys(%noref))) { - printf " $module\n"; - foreach (sort(@{$noref{$module}})) { - my $export; - if (exists($export{$_})) { - $export = " (export only)"; - } else { - $export = ""; - } - printf " $_$export\n"; - } - } - } -} -- cgit From 2f324dd8ab2e3d8b097f3eac6d380d1adbdbe6e6 Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Sun, 11 Oct 2020 15:58:43 +0530 Subject: scripts: coccicheck: Add quotes to improve portability While fetching the number of threads per core with lscpu, the [:digit:] set is used for translation of digits from 0-9. However, using [:digit:] instead of "[:digit:]" does not seem to work uniformly for some shell types and configurations (such as zsh). Therefore, modify coccicheck to use double quotes around the [:digit:] set for uniformity and better portability. Signed-off-by: Sumera Priyadarsini Signed-off-by: Julia Lawall --- scripts/coccicheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/coccicheck b/scripts/coccicheck index 6789751607f5..d67907b8a38b 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -76,7 +76,7 @@ else fi # Use only one thread per core by default if hyperthreading is enabled - THREADS_PER_CORE=$(lscpu | grep "Thread(s) per core: " | tr -cd [:digit:]) + THREADS_PER_CORE=$(lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]") if [ -z "$J" ]; then NPROC=$(getconf _NPROCESSORS_ONLN) if [ $THREADS_PER_CORE -gt 1 -a $NPROC -gt 2 ] ; then -- cgit From c5864560d935db879cafa21feca0156d91eba842 Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Sun, 11 Oct 2020 15:59:42 +0530 Subject: scripts: coccicheck: Change default condition for parallelism Currently, Coccinelle uses at most one thread per core by default in machines with more than 2 hyperthreads. However, for systems with only 4 hyperthreads, this does not improve performance. Modify coccicheck to use all available threads in machines with upto 4 hyperthreads. Signed-off-by: Sumera Priyadarsini Signed-off-by: Julia Lawall --- scripts/coccicheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/coccicheck b/scripts/coccicheck index d67907b8a38b..209bb0427b43 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -79,7 +79,7 @@ else THREADS_PER_CORE=$(lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]") if [ -z "$J" ]; then NPROC=$(getconf _NPROCESSORS_ONLN) - if [ $THREADS_PER_CORE -gt 1 -a $NPROC -gt 2 ] ; then + if [ $THREADS_PER_CORE -gt 1 -a $NPROC -gt 4 ] ; then NPROC=$((NPROC/2)) fi else -- cgit From 6e9c9686d826564f44c93cdd6f111b1c0a9dc224 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Mon, 12 Oct 2020 09:58:15 -0500 Subject: scripts/dtc: Update to upstream version v1.6.0-31-gcbca977ea121 This adds the following commits from upstream: cbca977ea121 checks: Allow PCI bridge child nodes without an address 73e0f143b73d libfdt: fdt_strerror(): Fix comparison warning 6c2be7d85315 libfdt: fdt_get_string(): Fix sequential write comparison warnings 82525f41d59e libfdt: libfdt_wip: Fix comparison warning fb1f65f15832 libfdt: fdt_create_with_flags(): Fix comparison warning f28aa271000b libfdt: fdt_move(): Fix comparison warnings 3d7c6f44195a libfdt: fdt_add_string_(): Fix comparison warning 10f682788c30 libfdt: fdt_node_offset_by_phandle(): Fix comparison warning 07158f4cf2a2 libfdt: overlay: Fix comparison warning ce9e1f25a7de libfdt: fdt_resize(): Fix comparison warning faa76fc10bc5 libfdt: fdt_splice_(): Fix comparison warning 54dca0985316 libfdt: fdt_get_string(): Fix comparison warnings f8e11e61624e libfdt: fdt_grab_space_(): Fix comparison warning 0c43d4d7bf5a libfdt: fdt_mem_rsv(): Fix comparison warnings 442ea3dd1579 libfdt: fdt_offset_ptr(): Fix comparison warnings ca19c3db2bf6 Makefile: Specify cflags for libyaml 7bb86f1c0956 libfdt: fix fdt_check_node_offset_ w/ VALID_INPUT 3d522abc7571 dtc: Include stdlib.h in util.h 808cdaaf524f dtc: Avoid UB when shifting 3e3138b4a956 libfdt: fix fdt_check_full buffer overrun Signed-off-by: Rob Herring --- scripts/dtc/checks.c | 4 +--- scripts/dtc/dtc-parser.y | 4 ++-- scripts/dtc/libfdt/fdt.c | 31 +++++++++++++++++++++---------- scripts/dtc/libfdt/fdt_overlay.c | 3 ++- scripts/dtc/libfdt/fdt_ro.c | 20 +++++++++++--------- scripts/dtc/libfdt/fdt_rw.c | 2 +- scripts/dtc/libfdt/fdt_strerror.c | 4 ++-- scripts/dtc/libfdt/fdt_sw.c | 27 +++++++++++++++------------ scripts/dtc/libfdt/fdt_wip.c | 2 +- scripts/dtc/util.h | 1 + scripts/dtc/version_gen.h | 2 +- 11 files changed, 58 insertions(+), 42 deletions(-) (limited to 'scripts') diff --git a/scripts/dtc/checks.c b/scripts/dtc/checks.c index b7955dbd71ca..17cb6890d45a 100644 --- a/scripts/dtc/checks.c +++ b/scripts/dtc/checks.c @@ -891,10 +891,8 @@ static void check_pci_device_reg(struct check *c, struct dt_info *dti, struct no return; prop = get_property(node, "reg"); - if (!prop) { - FAIL(c, dti, node, "missing PCI reg property"); + if (!prop) return; - } cells = (cell_t *)prop->val.val; if (cells[1] || cells[2]) diff --git a/scripts/dtc/dtc-parser.y b/scripts/dtc/dtc-parser.y index 40dcf4f149da..a0316a3cc309 100644 --- a/scripts/dtc/dtc-parser.y +++ b/scripts/dtc/dtc-parser.y @@ -476,8 +476,8 @@ integer_rela: ; integer_shift: - integer_shift DT_LSHIFT integer_add { $$ = $1 << $3; } - | integer_shift DT_RSHIFT integer_add { $$ = $1 >> $3; } + integer_shift DT_LSHIFT integer_add { $$ = ($3 < 64) ? ($1 << $3) : 0; } + | integer_shift DT_RSHIFT integer_add { $$ = ($3 < 64) ? ($1 >> $3) : 0; } | integer_add ; diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c index c28fcc115771..6cf2fa03b037 100644 --- a/scripts/dtc/libfdt/fdt.c +++ b/scripts/dtc/libfdt/fdt.c @@ -134,16 +134,20 @@ int fdt_check_header(const void *fdt) const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) { - unsigned absoffset = offset + fdt_off_dt_struct(fdt); + unsigned int uoffset = offset; + unsigned int absoffset = offset + fdt_off_dt_struct(fdt); + + if (offset < 0) + return NULL; if (!can_assume(VALID_INPUT)) - if ((absoffset < offset) + if ((absoffset < uoffset) || ((absoffset + len) < absoffset) || (absoffset + len) > fdt_totalsize(fdt)) return NULL; if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) - if (((offset + len) < offset) + if (((uoffset + len) < uoffset) || ((offset + len) > fdt_size_dt_struct(fdt))) return NULL; @@ -206,10 +210,11 @@ uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) int fdt_check_node_offset_(const void *fdt, int offset) { - if (can_assume(VALID_INPUT)) - return offset; - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE)) + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE) return -FDT_ERR_BADOFFSET; return offset; @@ -217,8 +222,11 @@ int fdt_check_node_offset_(const void *fdt, int offset) int fdt_check_prop_offset_(const void *fdt, int offset) { - if ((offset < 0) || (offset % FDT_TAGSIZE) - || (fdt_next_tag(fdt, offset, &offset) != FDT_PROP)) + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP) return -FDT_ERR_BADOFFSET; return offset; @@ -306,9 +314,12 @@ const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) int fdt_move(const void *fdt, void *buf, int bufsize) { + if (!can_assume(VALID_INPUT) && bufsize < 0) + return -FDT_ERR_NOSPACE; + FDT_RO_PROBE(fdt); - if (fdt_totalsize(fdt) > bufsize) + if (fdt_totalsize(fdt) > (unsigned int)bufsize) return -FDT_ERR_NOSPACE; memmove(buf, fdt, fdt_totalsize(fdt)); diff --git a/scripts/dtc/libfdt/fdt_overlay.c b/scripts/dtc/libfdt/fdt_overlay.c index b310e49a698e..d217e79b6722 100644 --- a/scripts/dtc/libfdt/fdt_overlay.c +++ b/scripts/dtc/libfdt/fdt_overlay.c @@ -241,6 +241,7 @@ static int overlay_update_local_node_references(void *fdto, if (fixup_len % sizeof(uint32_t)) return -FDT_ERR_BADOVERLAY; + fixup_len /= sizeof(uint32_t); tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); if (!tree_val) { @@ -250,7 +251,7 @@ static int overlay_update_local_node_references(void *fdto, return tree_len; } - for (i = 0; i < (fixup_len / sizeof(uint32_t)); i++) { + for (i = 0; i < fixup_len; i++) { fdt32_t adj_val; uint32_t poffset; diff --git a/scripts/dtc/libfdt/fdt_ro.c b/scripts/dtc/libfdt/fdt_ro.c index e03570a56eb5..91cc6fefe374 100644 --- a/scripts/dtc/libfdt/fdt_ro.c +++ b/scripts/dtc/libfdt/fdt_ro.c @@ -53,7 +53,7 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) err = -FDT_ERR_BADOFFSET; absoffset = stroffset + fdt_off_dt_strings(fdt); - if (absoffset >= totalsize) + if (absoffset >= (unsigned)totalsize) goto fail; len = totalsize - absoffset; @@ -61,17 +61,19 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) if (stroffset < 0) goto fail; if (can_assume(LATEST) || fdt_version(fdt) >= 17) { - if (stroffset >= fdt_size_dt_strings(fdt)) + if ((unsigned)stroffset >= fdt_size_dt_strings(fdt)) goto fail; if ((fdt_size_dt_strings(fdt) - stroffset) < len) len = fdt_size_dt_strings(fdt) - stroffset; } } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { - if ((stroffset >= 0) - || (stroffset < -fdt_size_dt_strings(fdt))) + unsigned int sw_stroffset = -stroffset; + + if ((stroffset >= 0) || + (sw_stroffset > fdt_size_dt_strings(fdt))) goto fail; - if ((-stroffset) < len) - len = -stroffset; + if (sw_stroffset < len) + len = sw_stroffset; } else { err = -FDT_ERR_INTERNAL; goto fail; @@ -157,8 +159,8 @@ int fdt_generate_phandle(const void *fdt, uint32_t *phandle) static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) { - int offset = n * sizeof(struct fdt_reserve_entry); - int absoffset = fdt_off_mem_rsvmap(fdt) + offset; + unsigned int offset = n * sizeof(struct fdt_reserve_entry); + unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset; if (!can_assume(VALID_INPUT)) { if (absoffset < fdt_off_mem_rsvmap(fdt)) @@ -680,7 +682,7 @@ int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) { int offset; - if ((phandle == 0) || (phandle == -1)) + if ((phandle == 0) || (phandle == ~0U)) return -FDT_ERR_BADPHANDLE; FDT_RO_PROBE(fdt); diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c index 93e4a2b56348..68887b969a45 100644 --- a/scripts/dtc/libfdt/fdt_rw.c +++ b/scripts/dtc/libfdt/fdt_rw.c @@ -59,7 +59,7 @@ static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) return -FDT_ERR_BADOFFSET; - if ((p < (char *)fdt) || (dsize + newlen < oldlen)) + if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen)) return -FDT_ERR_BADOFFSET; if (dsize - oldlen + newlen > fdt_totalsize(fdt)) return -FDT_ERR_NOSPACE; diff --git a/scripts/dtc/libfdt/fdt_strerror.c b/scripts/dtc/libfdt/fdt_strerror.c index 768db66eada5..b4356931b06d 100644 --- a/scripts/dtc/libfdt/fdt_strerror.c +++ b/scripts/dtc/libfdt/fdt_strerror.c @@ -40,7 +40,7 @@ static struct fdt_errtabent fdt_errtable[] = { FDT_ERRTABENT(FDT_ERR_NOPHANDLES), FDT_ERRTABENT(FDT_ERR_BADFLAGS), }; -#define FDT_ERRTABSIZE (sizeof(fdt_errtable) / sizeof(fdt_errtable[0])) +#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))) const char *fdt_strerror(int errval) { @@ -48,7 +48,7 @@ const char *fdt_strerror(int errval) return ""; else if (errval == 0) return ""; - else if (errval > -FDT_ERRTABSIZE) { + else if (-errval < FDT_ERRTABSIZE) { const char *s = fdt_errtable[-errval].str; if (s) diff --git a/scripts/dtc/libfdt/fdt_sw.c b/scripts/dtc/libfdt/fdt_sw.c index 94ce4bb91a00..68b543c4dfa2 100644 --- a/scripts/dtc/libfdt/fdt_sw.c +++ b/scripts/dtc/libfdt/fdt_sw.c @@ -93,8 +93,8 @@ static inline uint32_t sw_flags(void *fdt) static void *fdt_grab_space_(void *fdt, size_t len) { - int offset = fdt_size_dt_struct(fdt); - int spaceleft; + unsigned int offset = fdt_size_dt_struct(fdt); + unsigned int spaceleft; spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) - fdt_size_dt_strings(fdt); @@ -108,8 +108,8 @@ static void *fdt_grab_space_(void *fdt, size_t len) int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) { - const size_t hdrsize = FDT_ALIGN(sizeof(struct fdt_header), - sizeof(struct fdt_reserve_entry)); + const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); void *fdt = buf; if (bufsize < hdrsize) @@ -152,6 +152,9 @@ int fdt_resize(void *fdt, void *buf, int bufsize) FDT_SW_PROBE(fdt); + if (bufsize < 0) + return -FDT_ERR_NOSPACE; + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); tailsize = fdt_size_dt_strings(fdt); @@ -159,7 +162,7 @@ int fdt_resize(void *fdt, void *buf, int bufsize) headsize + tailsize > fdt_totalsize(fdt)) return -FDT_ERR_INTERNAL; - if ((headsize + tailsize) > bufsize) + if ((headsize + tailsize) > (unsigned)bufsize) return -FDT_ERR_NOSPACE; oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; @@ -247,18 +250,18 @@ int fdt_end_node(void *fdt) static int fdt_add_string_(void *fdt, const char *s) { char *strtab = (char *)fdt + fdt_totalsize(fdt); - int strtabsize = fdt_size_dt_strings(fdt); - int len = strlen(s) + 1; - int struct_top, offset; + unsigned int strtabsize = fdt_size_dt_strings(fdt); + unsigned int len = strlen(s) + 1; + unsigned int struct_top, offset; - offset = -strtabsize - len; + offset = strtabsize + len; struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); - if (fdt_totalsize(fdt) + offset < struct_top) + if (fdt_totalsize(fdt) - offset < struct_top) return 0; /* no more room :( */ - memcpy(strtab + offset, s, len); + memcpy(strtab - offset, s, len); fdt_set_size_dt_strings(fdt, strtabsize + len); - return offset; + return -offset; } /* Must only be used to roll back in case of error */ diff --git a/scripts/dtc/libfdt/fdt_wip.c b/scripts/dtc/libfdt/fdt_wip.c index f64139e0b3dc..c2d7566a67dc 100644 --- a/scripts/dtc/libfdt/fdt_wip.c +++ b/scripts/dtc/libfdt/fdt_wip.c @@ -23,7 +23,7 @@ int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, if (!propval) return proplen; - if (proplen < (len + idx)) + if ((unsigned)proplen < (len + idx)) return -FDT_ERR_NOSPACE; memcpy((char *)propval + idx, val, len); diff --git a/scripts/dtc/util.h b/scripts/dtc/util.h index 5a4172dd0f84..a771b4654c76 100644 --- a/scripts/dtc/util.h +++ b/scripts/dtc/util.h @@ -2,6 +2,7 @@ #ifndef UTIL_H #define UTIL_H +#include #include #include #include diff --git a/scripts/dtc/version_gen.h b/scripts/dtc/version_gen.h index 0714799446f8..054cdd0fdbe8 100644 --- a/scripts/dtc/version_gen.h +++ b/scripts/dtc/version_gen.h @@ -1 +1 @@ -#define DTC_VERSION "DTC 1.6.0-g9d7888cb" +#define DTC_VERSION "DTC 1.6.0-gcbca977e" -- cgit From 2c92406f33433b624522acbc4e78e6c58c397cd5 Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Tue, 13 Oct 2020 16:48:08 -0700 Subject: scripts/spelling.txt: increase error-prone spell checking Increase direcly,ununsed,manger spelling error check Signed-off-by: Wang Qing Signed-off-by: Andrew Morton Cc: Colin Ian King Cc: Wang Qing Cc: Xiong Cc: SeongJae Park Cc: Jonathan Neuschfer Cc: Luca Ceresoli Cc: Joe Perches Link: https://lkml.kernel.org/r/1601085397-27586-1-git-send-email-wangqing@vivo.com Signed-off-by: Linus Torvalds --- scripts/spelling.txt | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/spelling.txt b/scripts/spelling.txt index feb2efaaa5e6..06f4cf4ca717 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -482,6 +482,7 @@ disgest||digest dispalying||displaying diplay||display directon||direction +direcly||directly direectly||directly diregard||disregard disassocation||disassociation @@ -871,6 +872,7 @@ malplace||misplace managable||manageable managment||management mangement||management +manger||manager manoeuvering||maneuvering manufaucturing||manufacturing mappping||mapping @@ -1478,6 +1480,7 @@ unsolicitied||unsolicited unsuccessfull||unsuccessful unsuported||unsupported untill||until +ununsed||unused unuseful||useless unvalid||invalid upate||update -- cgit From 33c5bb375ea4128b6e72b3ee260b74b59c295957 Mon Sep 17 00:00:00 2001 From: Naoki Hayama Date: Tue, 13 Oct 2020 16:48:11 -0700 Subject: scripts/spelling.txt: add "arbitrary" typo Add "abitrary||arbitrary". Signed-off-by: Naoki Hayama Signed-off-by: Andrew Morton Cc: Colin Ian King Cc: Andy Whitcroft Cc: Joe Perches Link: https://lkml.kernel.org/r/6bf6520d-787d-5749-09b5-ff92185f501f@lineo.co.jp Signed-off-by: Linus Torvalds --- scripts/spelling.txt | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/spelling.txt b/scripts/spelling.txt index 06f4cf4ca717..cb46a79665f5 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -9,6 +9,7 @@ # abandonning||abandoning abigious||ambiguous +abitrary||arbitrary abitrate||arbitrate abnornally||abnormally abnrormal||abnormal -- cgit From d72e720a19393eb611a112e4c5c377785dbd645d Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Tue, 13 Oct 2020 16:48:14 -0700 Subject: scripts/decodecode: add the capability to supply the program counter So that comparing with objdump output from vmlinux can ease pinpointing where the trapping instruction actually is. An example is better than a thousand words: $ PC=0xffffffff8329a927 ./scripts/decodecode < ~/tmp/syz/gfs2.splat [ 477.379104][T23917] Code: 48 83 ec 28 48 89 3c 24 48 89 54 24 08 e8 c1 b4 4a fe 48 8d bb 00 01 00 00 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 97 05 00 00 48 8b 9b 00 01 00 00 48 85 db 0f 84 All code ======== ffffffff8329a8fd: 48 83 ec 28 sub $0x28,%rsp ffffffff8329a901: 48 89 3c 24 mov %rdi,(%rsp) ffffffff8329a905: 48 89 54 24 08 mov %rdx,0x8(%rsp) ffffffff8329a90a: e8 c1 b4 4a fe callq 0xffffffff81745dd0 ffffffff8329a90f: 48 8d bb 00 01 00 00 lea 0x100(%rbx),%rdi ffffffff8329a916: 48 b8 00 00 00 00 00 movabs $0xdffffc0000000000,%rax ffffffff8329a91d: fc ff df ffffffff8329a920: 48 89 fa mov %rdi,%rdx ffffffff8329a923: 48 c1 ea 03 shr $0x3,%rdx ffffffff8329a927:* 80 3c 02 00 cmpb $0x0,(%rdx,%rax,1) <-- trapping instruction ffffffff8329a92b: 0f 85 97 05 00 00 jne 0xffffffff8329aec8 ffffffff8329a931: 48 8b 9b 00 01 00 00 mov 0x100(%rbx),%rbx ffffffff8329a938: 48 85 db test %rbx,%rbx ffffffff8329a93b: 0f .byte 0xf ffffffff8329a93c: 84 .byte 0x84 Signed-off-by: Borislav Petkov Signed-off-by: Andrew Morton Cc: Marc Zyngier Cc: Will Deacon Cc: Rabin Vincent Link: https://lkml.kernel.org/r/20200930111416.GF6810@zn.tnic Link: https://lkml.kernel.org/r/20200929113238.GC21110@zn.tnic Signed-off-by: Linus Torvalds --- scripts/decodecode | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/decodecode b/scripts/decodecode index fbdb325cdf4f..31d884e35f2f 100755 --- a/scripts/decodecode +++ b/scripts/decodecode @@ -6,6 +6,7 @@ # options: set env. variable AFLAGS=options to pass options to "as"; # e.g., to decode an i386 oops on an x86_64 system, use: # AFLAGS=--32 decodecode < 386.oops +# PC=hex - the PC (program counter) the oops points to cleanup() { rm -f $T $T.s $T.o $T.oo $T.aa $T.dis @@ -67,15 +68,19 @@ if [ -z "$ARCH" ]; then esac fi +# Params: (tmp_file, pc_sub) disas() { - ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s > /dev/null 2>&1 + t=$1 + pc_sub=$2 + + ${CROSS_COMPILE}as $AFLAGS -o $t.o $t.s > /dev/null 2>&1 if [ "$ARCH" = "arm" ]; then if [ $width -eq 2 ]; then OBJDUMPFLAGS="-M force-thumb" fi - ${CROSS_COMPILE}strip $1.o + ${CROSS_COMPILE}strip $t.o fi if [ "$ARCH" = "arm64" ]; then @@ -83,11 +88,18 @@ disas() { type=inst fi - ${CROSS_COMPILE}strip $1.o + ${CROSS_COMPILE}strip $t.o fi - ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \ - grep -v "/tmp\|Disassembly\|\.text\|^$" > $1.dis 2>&1 + if [ $pc_sub -ne 0 ]; then + if [ $PC ]; then + adj_vma=$(( $PC - $pc_sub )) + OBJDUMPFLAGS="$OBJDUMPFLAGS --adjust-vma=$adj_vma" + fi + fi + + ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $t.o | \ + grep -v "/tmp\|Disassembly\|\.text\|^$" > $t.dis 2>&1 } marker=`expr index "$code" "\<"` @@ -95,14 +107,17 @@ if [ $marker -eq 0 ]; then marker=`expr index "$code" "\("` fi + touch $T.oo if [ $marker -ne 0 ]; then + # 2 opcode bytes and a single space + pc_sub=$(( $marker / 3 )) echo All code >> $T.oo echo ======== >> $T.oo beforemark=`echo "$code"` echo -n " .$type 0x" > $T.s echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s - disas $T + disas $T $pc_sub cat $T.dis >> $T.oo rm -f $T.o $T.s $T.dis @@ -114,7 +129,7 @@ echo =========================================== >> $T.aa code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'` echo -n " .$type 0x" > $T.s echo $code >> $T.s -disas $T +disas $T 0 cat $T.dis >> $T.aa # (lines of whole $T.oo) - (lines of $T.aa, i.e. "Code starting") + 3, -- cgit From bac977cbc0d6731fb8e67c2be0e4acbd959e10b3 Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 14 Oct 2020 03:38:19 +0900 Subject: kbuild: deb-pkg: do not build linux-headers package if CONFIG_MODULES=n MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit 269a535ca931 ("modpost: generate vmlinux.symvers and reuse it for the second modpost"), with CONFIG_MODULES disabled, "make deb-pkg" (or "make bindeb-pkg") fails with: find: ‘Module.symvers’: No such file or directory If CONFIG_MODULES is disabled, it doesn't really make sense to build the linux-headers package. Fixes: 269a535ca931 ("modpost: generate vmlinux.symvers and reuse it for the second modpost") Reported-by: Josh Triplett Signed-off-by: Masahiro Yamada --- scripts/package/builddeb | 6 ++++-- scripts/package/mkdebian | 19 ++++++++++++------- 2 files changed, 16 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/package/builddeb b/scripts/package/builddeb index 6474084c32a4..1b11f8993629 100755 --- a/scripts/package/builddeb +++ b/scripts/package/builddeb @@ -207,8 +207,10 @@ EOF done if [ "$ARCH" != "um" ]; then - deploy_kernel_headers debian/linux-headers - create_package linux-headers-$version debian/linux-headers + if is_enabled CONFIG_MODULES; then + deploy_kernel_headers debian/linux-headers + create_package linux-headers-$version debian/linux-headers + fi deploy_libc_headers debian/linux-libc-dev create_package linux-libc-dev debian/linux-libc-dev diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index 3a13b834f281..273fd6ed790e 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -184,13 +184,6 @@ Description: Linux kernel, version $version This package contains the Linux kernel, modules and corresponding other files, version: $version. -Package: $kernel_headers_packagename -Architecture: $debarch -Description: Linux kernel headers for $version on $debarch - This package provides kernel header files for $version on $debarch - . - This is useful for people who need to build external modules - Package: linux-libc-dev Section: devel Provides: linux-kernel-headers @@ -201,6 +194,18 @@ Description: Linux support headers for userspace development Multi-Arch: same EOF +if is_enabled CONFIG_MODULES; then +cat <> debian/control + +Package: $kernel_headers_packagename +Architecture: $debarch +Description: Linux kernel headers for $version on $debarch + This package provides kernel header files for $version on $debarch + . + This is useful for people who need to build external modules +EOF +fi + if is_enabled CONFIG_DEBUG_INFO; then cat <> debian/control -- cgit From 0fa21cf4489fe11737d56f8056dda1ba0257bd8d Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 14 Oct 2020 03:38:20 +0900 Subject: kbuild: deb-pkg: clean up package name variables Hard-code the names of linux-headers and debug packages in the control file. The kernel package is different for ARCH=um. Change the code for better readability. Signed-off-by: Masahiro Yamada --- scripts/package/mkdebian | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian index 273fd6ed790e..60a2a63a5e90 100755 --- a/scripts/package/mkdebian +++ b/scripts/package/mkdebian @@ -94,16 +94,16 @@ else packageversion=$version-$revision fi sourcename=$KDEB_SOURCENAME -packagename=linux-image-$version -kernel_headers_packagename=linux-headers-$version -dbg_packagename=$packagename-dbg -debarch= -set_debarch if [ "$ARCH" = "um" ] ; then - packagename=user-mode-linux-$version + packagename=user-mode-linux +else + packagename=linux-image fi +debarch= +set_debarch + email=${DEBEMAIL-$EMAIL} # use email string directly if it contains @@ -178,7 +178,7 @@ Rules-Requires-Root: no Build-Depends: bc, rsync, kmod, cpio, bison, flex | flex:native $extra_build_depends Homepage: https://www.kernel.org/ -Package: $packagename +Package: $packagename-$version Architecture: $debarch Description: Linux kernel, version $version This package contains the Linux kernel, modules and corresponding other @@ -197,7 +197,7 @@ EOF if is_enabled CONFIG_MODULES; then cat <> debian/control -Package: $kernel_headers_packagename +Package: linux-headers-$version Architecture: $debarch Description: Linux kernel headers for $version on $debarch This package provides kernel header files for $version on $debarch @@ -209,7 +209,7 @@ fi if is_enabled CONFIG_DEBUG_INFO; then cat <> debian/control -Package: $dbg_packagename +Package: linux-image-$version-dbg Section: debug Architecture: $debarch Description: Linux kernel debugging symbols for $version -- cgit From d38c8cfb057183f619dc8534030bb64b63f78043 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 1 Oct 2020 08:23:52 +0200 Subject: scripts: kernel-doc: add support for typedef enum The PHY kernel-doc markup has gained support for documenting a typedef enum. However, right now the parser was not prepared for it. So, add support for parsing it. Fixes: 4069a572d423 ("net: phy: Document core PHY structures") Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 724528f4b7d6..adc05406c68e 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1265,14 +1265,22 @@ sub show_warnings($$) { sub dump_enum($$) { my $x = shift; my $file = shift; + my $members; + $x =~ s@/\*.*?\*/@@gos; # strip comments. # strip #define macros inside enums $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; - if ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { + if ($x =~ /typedef\s+enum\s*\{(.*)\}\s*(\w*)\s*;/) { + $declaration_name = $2; + $members = $1; + } elsif ($x =~ /enum\s+(\w*)\s*\{(.*)\}/) { $declaration_name = $1; - my $members = $2; + $members = $2; + } + + if ($declaration_name) { my %_members; $members =~ s/\s+$//; @@ -1307,8 +1315,7 @@ sub dump_enum($$) { 'sections' => \%sections, 'purpose' => $declaration_purpose }); - } - else { + } else { print STDERR "${file}:$.: error: Cannot parse enum!\n"; ++$errors; } -- cgit From efa44475b8f5c692be4c5822a659e1a96f16dacb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 24 Sep 2020 15:30:37 +0200 Subject: scripts: kernel-doc: make it more compatible with Sphinx 3.x With Sphinx 3.x, the ".. c:type:" tag was changed to accept either: .. c:type:: typedef-like declaration .. c:type:: name Using it for other types (including functions) don't work anymore. So, there are newer tags for macro, enum, struct, union, and others, which doesn't exist on older versions. Add a check for the Sphinx version and change the produced tags accordingly. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 71 +++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 65 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index adc05406c68e..096317ef2e97 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -271,6 +271,8 @@ if ($#ARGV == -1) { } my $kernelversion; +my $sphinx_major; + my $dohighlight = ""; my $verbose = 0; @@ -465,6 +467,43 @@ while ($ARGV[0] =~ m/^--?(.*)/) { # continue execution near EOF; +# The C domain dialect changed on Sphinx 3. So, we need to check the +# version in order to produce the right tags. +sub findprog($) +{ + foreach(split(/:/, $ENV{PATH})) { + return "$_/$_[0]" if(-x "$_/$_[0]"); + } +} + +sub get_sphinx_version() +{ + my $ver; + my $major = 1; + + my $cmd = "sphinx-build"; + if (!findprog($cmd)) { + my $cmd = "sphinx-build3"; + return $major if (!findprog($cmd)); + } + + open IN, "$cmd --version 2>&1 |"; + while () { + if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { + $major=$1; + last; + } + # Sphinx 1.2.x uses a different format + if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { + $major=$1; + last; + } + } + close IN; + + return $major; +} + # get kernel version from env sub get_kernel_version() { my $version = 'unknown kernel version'; @@ -848,7 +887,11 @@ sub output_function_rst(%) { my $start = ""; if ($args{'typedef'}) { - print ".. c:type:: ". $args{'function'} . "\n\n"; + if ($sphinx_major < 3) { + print ".. c:type:: ". $args{'function'} . "\n\n"; + } else { + print ".. c:function:: ". $args{'function'} . "\n\n"; + } print_lineno($declaration_start_line); print " **Typedef**: "; $lineprefix = ""; @@ -938,9 +981,14 @@ sub output_enum_rst(%) { my ($parameter); my $oldprefix = $lineprefix; my $count; - my $name = "enum " . $args{'enum'}; - print "\n\n.. c:type:: " . $name . "\n\n"; + if ($sphinx_major < 3) { + my $name = "enum " . $args{'enum'}; + print "\n\n.. c:type:: " . $name . "\n\n"; + } else { + my $name = $args{'enum'}; + print "\n\n.. c:enum:: " . $name . "\n\n"; + } print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); @@ -966,8 +1014,13 @@ sub output_typedef_rst(%) { my %args = %{$_[0]}; my ($parameter); my $oldprefix = $lineprefix; - my $name = "typedef " . $args{'typedef'}; + my $name; + if ($sphinx_major < 3) { + $name = "typedef " . $args{'typedef'}; + } else { + $name = $args{'typedef'}; + } print "\n\n.. c:type:: " . $name . "\n\n"; print_lineno($declaration_start_line); $lineprefix = " "; @@ -982,9 +1035,14 @@ sub output_struct_rst(%) { my %args = %{$_[0]}; my ($parameter); my $oldprefix = $lineprefix; - my $name = $args{'type'} . " " . $args{'struct'}; - print "\n\n.. c:type:: " . $name . "\n\n"; + if ($sphinx_major < 3) { + my $name = $args{'type'} . " " . $args{'struct'}; + print "\n\n.. c:type:: " . $name . "\n\n"; + } else { + my $name = $args{'struct'}; + print "\n\n.. c:struct:: " . $name . "\n\n"; + } print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); @@ -2242,6 +2300,7 @@ sub process_file($) { } +$sphinx_major = get_sphinx_version(); $kernelversion = get_kernel_version(); # generate a sequence of code that will splice in highlighting information -- cgit From e3ad05fe6e6ff645aa91e9a555231ff53470daba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 25 Sep 2020 10:05:40 +0200 Subject: scripts: kernel-doc: use a less pedantic markup for funcs on Sphinx 3.x Unfortunately, Sphinx 3.x parser for c functions is too pedantic: https://github.com/sphinx-doc/sphinx/issues/8241 While it could be relaxed with some configurations, there are several corner cases that it would make it hard to maintain, and will require teaching conf.py about several macros. So, let's instead use the :c:macro notation. This will produce an output that it is not as nice as currently, but it should still be acceptable, and will provide cross-references, removing thousands of warnings when building with newer versions of Sphinx. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 096317ef2e97..d9783c98f33b 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -886,19 +886,29 @@ sub output_function_rst(%) { my $oldprefix = $lineprefix; my $start = ""; - if ($args{'typedef'}) { - if ($sphinx_major < 3) { + if ($sphinx_major < 3) { + if ($args{'typedef'}) { print ".. c:type:: ". $args{'function'} . "\n\n"; + print_lineno($declaration_start_line); + print " **Typedef**: "; + $lineprefix = ""; + output_highlight_rst($args{'purpose'}); + $start = "\n\n**Syntax**\n\n ``"; } else { - print ".. c:function:: ". $args{'function'} . "\n\n"; + print ".. c:function:: "; } - print_lineno($declaration_start_line); - print " **Typedef**: "; - $lineprefix = ""; - output_highlight_rst($args{'purpose'}); - $start = "\n\n**Syntax**\n\n ``"; } else { - print ".. c:function:: "; + print ".. c:macro:: ". $args{'function'} . "\n\n"; + + if ($args{'typedef'}) { + print_lineno($declaration_start_line); + print " **Typedef**: "; + $lineprefix = ""; + output_highlight_rst($args{'purpose'}); + $start = "\n\n**Syntax**\n\n ``"; + } else { + print "``"; + } } if ($args{'functiontype'} ne "") { $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; @@ -925,7 +935,11 @@ sub output_function_rst(%) { if ($args{'typedef'}) { print ");``\n\n"; } else { - print ")\n\n"; + if ($sphinx_major < 3) { + print ")\n\n"; + } else { + print ")``\n"; + } print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); -- cgit From dbe8ba00e5adc7573b8a91855f28a383c9728991 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 28 Sep 2020 12:52:34 +0200 Subject: scripts: kernel-doc: fix troubles with line counts There's currently a bug with the way kernel-doc script counts line numbers that can be seen with: $ ./scripts/kernel-doc -rst -enable-lineno include/linux/math64.h >all && ./scripts/kernel-doc -rst -internal -enable-lineno include/linux/math64.h >int && diff -U0 int all --- int 2020-09-28 12:58:08.927486808 +0200 +++ all 2020-09-28 12:58:08.905486845 +0200 @@ -1 +1 @@ -#define LINENO 27 +#define LINENO 26 @@ -3 +3 @@ -#define LINENO 16 +#define LINENO 15 @@ -9 +9 @@ -#define LINENO 17 +#define LINENO 16 ... This is happening with perl version 5.30.3, but I'm not so sure if this is a perl bug, or if this is due to something else. In any case, fixing it is easy. Basically, when "-internal" parameter is used, the process_export_file() function opens the handle "IN". This makes the line number to be incremented, as the handler for the main open is also "IN". Fix the problem by using a different handler for the main open(). While here, add a missing close for it. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index d9783c98f33b..bdd2ebb4ac41 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -2268,7 +2268,7 @@ sub process_file($) { $file = map_filename($orig_file); - if (!open(IN,"<$file")) { + if (!open(IN_FILE,"<$file")) { print STDERR "Error: Cannot open file $file\n"; ++$errors; return; @@ -2277,9 +2277,9 @@ sub process_file($) { $. = 1; $section_counter = 0; - while () { + while () { while (s/\\\s*$//) { - $_ .= ; + $_ .= ; } # Replace tabs by spaces while ($_ =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {}; @@ -2311,6 +2311,7 @@ sub process_file($) { print STDERR "${file}:1: warning: no structured comments found\n"; } } + close IN_FILE; } -- cgit From eab795ddd84ffdb1c67250062d01a81be20bb208 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 29 Sep 2020 14:23:39 +0200 Subject: scripts: kernel-doc: reimplement -nofunction argument Right now, the build system doesn't use -nofunction, as it is pretty much useless, because it doesn't consider the other output modes (extern, internal), working only with all. Also, it is limited to exclude functions. Re-implement it in order to allow excluding any symbols from the document output, no matter what mode is used. The parameter was also renamed to "-nosymbol", as it express better its meaning. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 44 +++++++++++++++++++++----------------------- 1 file changed, 21 insertions(+), 23 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index bdd2ebb4ac41..6a7996c96bbb 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -66,9 +66,8 @@ Output selection (mutually exclusive): -function NAME Only output documentation for the given function(s) or DOC: section title(s). All other functions and DOC: sections are ignored. May be specified multiple times. - -nofunction NAME Do NOT output documentation for the given function(s); - only output documentation for the other functions and - DOC: sections. May be specified multiple times. + -nosymbol NAME Exclude the specified symbols from the output + documentation. May be specified multiple times. Output selection modifiers: -no-doc-sections Do not output DOC: sections. @@ -288,9 +287,8 @@ my $modulename = "Kernel API"; use constant { OUTPUT_ALL => 0, # output all symbols and doc sections OUTPUT_INCLUDE => 1, # output only specified symbols - OUTPUT_EXCLUDE => 2, # output everything except specified symbols - OUTPUT_EXPORTED => 3, # output exported symbols - OUTPUT_INTERNAL => 4, # output non-exported symbols + OUTPUT_EXPORTED => 2, # output exported symbols + OUTPUT_INTERNAL => 3, # output non-exported symbols }; my $output_selection = OUTPUT_ALL; my $show_not_found = 0; # No longer used @@ -315,6 +313,7 @@ my $man_date = ('January', 'February', 'March', 'April', 'May', 'June', # CAVEAT EMPTOR! Some of the others I localised may not want to be, which # could cause "use of undefined value" or other bugs. my ($function, %function_table, %parametertypes, $declaration_purpose); +my %nosymbol_table = (); my $declaration_start_line; my ($type, $declaration_name, $return_type); my ($newsection, $newcontents, $prototype, $brcount, %source_map); @@ -434,10 +433,9 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $output_selection = OUTPUT_INCLUDE; $function = shift @ARGV; $function_table{$function} = 1; - } elsif ($cmd eq "nofunction") { # output all except specific functions - $output_selection = OUTPUT_EXCLUDE; - $function = shift @ARGV; - $function_table{$function} = 1; + } elsif ($cmd eq "nosymbol") { # Exclude specific symbols + my $symbol = shift @ARGV; + $nosymbol_table{$symbol} = 1; } elsif ($cmd eq "export") { # only exported symbols $output_selection = OUTPUT_EXPORTED; %function_table = (); @@ -570,11 +568,11 @@ sub dump_doc_section { return; } + return if (defined($nosymbol_table{$name})); + if (($output_selection == OUTPUT_ALL) || - ($output_selection == OUTPUT_INCLUDE && - defined($function_table{$name})) || - ($output_selection == OUTPUT_EXCLUDE && - !defined($function_table{$name}))) + (($output_selection == OUTPUT_INCLUDE) && + defined($function_table{$name}))) { dump_section($file, $name, $contents); output_blockhead({'sectionlist' => \@sectionlist, @@ -800,6 +798,8 @@ sub output_blockhead_rst(%) { my ($parameter, $section); foreach $section (@{$args{'sectionlist'}}) { + next if (defined($nosymbol_table{$section})); + if ($output_selection != OUTPUT_INCLUDE) { print "**$section**\n\n"; } @@ -1115,12 +1115,14 @@ sub output_declaration { my $name = shift; my $functype = shift; my $func = "output_${functype}_$output_mode"; + + return if (defined($nosymbol_table{$name})); + if (($output_selection == OUTPUT_ALL) || (($output_selection == OUTPUT_INCLUDE || $output_selection == OUTPUT_EXPORTED) && defined($function_table{$name})) || - (($output_selection == OUTPUT_EXCLUDE || - $output_selection == OUTPUT_INTERNAL) && + ($output_selection == OUTPUT_INTERNAL && !($functype eq "function" && defined($function_table{$name})))) { &$func(@_); @@ -1301,6 +1303,8 @@ sub show_warnings($$) { my $functype = shift; my $name = shift; + return 0 if (defined($nosymbol_table{$name})); + return 1 if ($output_selection == OUTPUT_ALL); if ($output_selection == OUTPUT_EXPORTED) { @@ -1324,13 +1328,6 @@ sub show_warnings($$) { return 0; } } - if ($output_selection == OUTPUT_EXCLUDE) { - if (!defined($function_table{$name})) { - return 1; - } else { - return 0; - } - } die("Please add the new output type at show_warnings()"); } @@ -1952,6 +1949,7 @@ sub process_export_file($) { while () { if (/$export_symbol/) { + next if (defined($nosymbol_table{$2})); $function_table{$2} = 1; } } -- cgit From 47bcacfd2b00e3795eac3faf47eb854eb9675a4f Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Sep 2020 09:47:01 +0200 Subject: scripts: kernel-doc: fix typedef identification Some typedef expressions are output as normal functions. As we need to be clearer about the type with Sphinx 3.x, detect such cases. While here, fix a wrongly-indented block. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 64 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 23 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 6a7996c96bbb..33ad3ce66f73 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1748,30 +1748,48 @@ sub dump_function($$) { return; } - my $prms = join " ", @parameterlist; - check_sections($file, $declaration_name, "function", $sectcheck, $prms); - - # 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. - # TODO: always perform the check. - if ($verbose && !$noret) { - check_return_section($file, $declaration_name, $return_type); - } + my $prms = join " ", @parameterlist; + check_sections($file, $declaration_name, "function", $sectcheck, $prms); + + # 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. + # TODO: always perform the check. + if ($verbose && !$noret) { + check_return_section($file, $declaration_name, $return_type); + } - output_declaration($declaration_name, - 'function', - {'function' => $declaration_name, - 'module' => $modulename, - 'functiontype' => $return_type, - 'parameterlist' => \@parameterlist, - 'parameterdescs' => \%parameterdescs, - 'parametertypes' => \%parametertypes, - 'sectionlist' => \@sectionlist, - 'sections' => \%sections, - 'purpose' => $declaration_purpose - }); + # The function parser can be called with a typedef parameter. + # Handle it. + if ($return_type =~ /typedef/) { + output_declaration($declaration_name, + 'function', + {'function' => $declaration_name, + 'typedef' => 1, + 'module' => $modulename, + 'functiontype' => $return_type, + 'parameterlist' => \@parameterlist, + 'parameterdescs' => \%parameterdescs, + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, + 'purpose' => $declaration_purpose + }); + } else { + output_declaration($declaration_name, + 'function', + {'function' => $declaration_name, + 'module' => $modulename, + 'functiontype' => $return_type, + 'parameterlist' => \@parameterlist, + 'parameterdescs' => \%parameterdescs, + 'parametertypes' => \%parametertypes, + 'sectionlist' => \@sectionlist, + 'sections' => \%sections, + 'purpose' => $declaration_purpose + }); + } } sub reset_state { -- cgit From ed8348e23abce79780f3b679c74a48bcdc47c947 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Sep 2020 12:24:43 +0200 Subject: scripts: kernel-doc: don't mangle with parameter list While kernel-doc needs to parse parameters in order to identify its name, it shouldn't be touching the type, as parsing it is very difficult, and errors happen. One current error is when parsing this parameter: const u32 (*tab)[256] Found at ./lib/crc32.c, on this function: u32 __pure crc32_be_generic (u32 crc, unsigned char const *p, size_t len, const u32 (*tab)[256], u32 polynomial); The current logic mangles it, producing this output: const u32 ( *tab That's something that it is not recognizeable. So, instead, let's push the argument as-is, and use it when printing the function prototype and when describing each argument. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 33ad3ce66f73..09e3e78b9723 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -655,10 +655,10 @@ sub output_function_man(%) { $type = $args{'parametertypes'}{$parameter}; if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function - print ".BI \"" . $parenth . $1 . "\" " . $parameter . " \") (" . $2 . ")" . $post . "\"\n"; + print ".BI \"" . $parenth . $1 . "\" " . " \") (" . $2 . ")" . $post . "\"\n"; } else { $type =~ s/([^\*])$/$1 /; - print ".BI \"" . $parenth . $type . "\" " . $parameter . " \"" . $post . "\"\n"; + print ".BI \"" . $parenth . $type . "\" " . " \"" . $post . "\"\n"; } $count++; $parenth = ""; @@ -929,7 +929,7 @@ sub output_function_rst(%) { # pointer-to-function print $1 . $parameter . ") (" . $2 . ")"; } else { - print $type . " " . $parameter; + print $type; } } if ($args{'typedef'}) { @@ -954,7 +954,7 @@ sub output_function_rst(%) { $type = $args{'parametertypes'}{$parameter}; if ($type ne "") { - print "``$type $parameter``\n"; + print "``$type``\n"; } else { print "``$parameter``\n"; } @@ -1479,7 +1479,7 @@ sub create_parameterlist($$$$) { # Treat preprocessor directive as a typeless variable just to fill # corresponding data structures "correctly". Catch it later in # output_* subs. - push_parameter($arg, "", $file); + push_parameter($arg, "", "", $file); } elsif ($arg =~ m/\(.+\)\s*\(/) { # pointer-to-function $arg =~ tr/#/,/; @@ -1488,7 +1488,7 @@ sub create_parameterlist($$$$) { $type = $arg; $type =~ s/([^\(]+\(\*?)\s*$param/$1/; save_struct_actual($param); - push_parameter($param, $type, $file, $declaration_name); + push_parameter($param, $type, $arg, $file, $declaration_name); } elsif ($arg) { $arg =~ s/\s*:\s*/:/g; $arg =~ s/\s*\[/\[/g; @@ -1513,26 +1513,28 @@ sub create_parameterlist($$$$) { foreach $param (@args) { if ($param =~ m/^(\*+)\s*(.*)/) { save_struct_actual($2); - push_parameter($2, "$type $1", $file, $declaration_name); + + push_parameter($2, "$type $1", $arg, $file, $declaration_name); } elsif ($param =~ m/(.*?):(\d+)/) { if ($type ne "") { # skip unnamed bit-fields save_struct_actual($1); - push_parameter($1, "$type:$2", $file, $declaration_name) + push_parameter($1, "$type:$2", $arg, $file, $declaration_name) } } else { save_struct_actual($param); - push_parameter($param, $type, $file, $declaration_name); + push_parameter($param, $type, $arg, $file, $declaration_name); } } } } } -sub push_parameter($$$$) { +sub push_parameter($$$$$) { my $param = shift; my $type = shift; + my $org_arg = shift; my $file = shift; my $declaration_name = shift; @@ -1596,8 +1598,8 @@ sub push_parameter($$$$) { # "[blah" in a parameter string; ###$param =~ s/\s*//g; push @parameterlist, $param; - $type =~ s/\s\s+/ /g; - $parametertypes{$param} = $type; + $org_arg =~ s/\s\s+/ /g; + $parametertypes{$param} = $org_arg; } sub check_sections($$$$$) { -- cgit From 93351d4196802b3ee01074d96df47b73716984ba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 4 Oct 2020 09:44:28 +0200 Subject: scripts: kernel-doc: allow passing desired Sphinx C domain dialect When kernel-doc is called via kerneldoc.py, there's no need to auto-detect the Sphinx version, as the Sphinx module already knows it. So, add an optional parameter to allow changing the Sphinx dialect. As kernel-doc can also be manually called, keep the auto-detection logic if the parameter was not specified. On such case, emit a warning if sphinx-build can't be found at PATH. I ended using a suggestion from Joe for using a more readable regex, instead of using a complex one with a hidden group like: m/^(\d+)\.(\d+)(?:\.?(\d+)?)/ in order to get the optional argument. Thanks-to: Joe Perches Suggested-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 51 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 09e3e78b9723..ed32883c3221 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -56,6 +56,13 @@ Output format selection (mutually exclusive): -rst Output reStructuredText format. -none Do not output documentation, only warnings. +Output format selection modifier (affects only ReST output): + + -sphinx-version Use the ReST C domain dialect compatible with an + specific Sphinx Version. + If not specified, kernel-doc will auto-detect using + the sphinx-build version found on PATH. + Output selection (mutually exclusive): -export Only output documentation for symbols that have been exported using EXPORT_SYMBOL() or EXPORT_SYMBOL_GPL() @@ -270,7 +277,7 @@ if ($#ARGV == -1) { } my $kernelversion; -my $sphinx_major; +my ($sphinx_major, $sphinx_minor, $sphinx_patch); my $dohighlight = ""; @@ -457,6 +464,23 @@ while ($ARGV[0] =~ m/^--?(.*)/) { $enable_lineno = 1; } elsif ($cmd eq 'show-not-found') { $show_not_found = 1; # A no-op but don't fail + } elsif ($cmd eq "sphinx-version") { + my $ver_string = shift @ARGV; + if ($ver_string =~ m/^(\d+)(\.\d+)?(\.\d+)?/) { + $sphinx_major = $1; + if (defined($2)) { + $sphinx_minor = substr($2,1); + } else { + $sphinx_minor = 0; + } + if (defined($3)) { + $sphinx_patch = substr($3,1) + } else { + $sphinx_patch = 0; + } + } else { + die "Sphinx version should either major.minor or major.minor.patch format\n"; + } } else { # Unknown argument usage(); @@ -477,29 +501,37 @@ sub findprog($) sub get_sphinx_version() { my $ver; - my $major = 1; my $cmd = "sphinx-build"; if (!findprog($cmd)) { my $cmd = "sphinx-build3"; - return $major if (!findprog($cmd)); + if (!findprog($cmd)) { + $sphinx_major = 1; + $sphinx_minor = 2; + $sphinx_patch = 0; + printf STDERR "Warning: Sphinx version not found. Using default (Sphinx version %d.%d.%d)\n", + $sphinx_major, $sphinx_minor, $sphinx_patch; + return; + } } open IN, "$cmd --version 2>&1 |"; while () { if (m/^\s*sphinx-build\s+([\d]+)\.([\d\.]+)(\+\/[\da-f]+)?$/) { - $major=$1; + $sphinx_major = $1; + $sphinx_minor = $2; + $sphinx_patch = $3; last; } # Sphinx 1.2.x uses a different format if (m/^\s*Sphinx.*\s+([\d]+)\.([\d\.]+)$/) { - $major=$1; + $sphinx_major = $1; + $sphinx_minor = $2; + $sphinx_patch = $3; last; } } close IN; - - return $major; } # get kernel version from env @@ -2333,7 +2365,10 @@ sub process_file($) { } -$sphinx_major = get_sphinx_version(); +if ($output_mode eq "rst") { + get_sphinx_version() if (!$sphinx_major); +} + $kernelversion = get_kernel_version(); # generate a sequence of code that will splice in highlighting information -- cgit From 5ef09c96d48b41a55121df1b57404f68d7e4e5f1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 9 Oct 2020 10:15:25 +0200 Subject: scripts: kernel-doc: fix line number handling Address several issues related to pointing to the wrong line number: 1) ensure that line numbers will always be initialized When section is the default (Description), the line number is not initializing, producing this: $ ./scripts/kernel-doc --enable-lineno ./drivers/media/v4l2-core/v4l2-mem2mem.c|less **Description** #define LINENO 0 In case of streamoff or release called on any context, 1] If the context is currently running, then abort job will be called 2] If the context is queued, then the context will be removed from the job_queue Which is not right. Ensure that the line number will always be there. After applied, the result now points to the right location: **Description** #define LINENO 410 In case of streamoff or release called on any context, 1] If the context is currently running, then abort job will be called 2] If the context is queued, then the context will be removed from the job_queue 2) The line numbers for function prototypes are always + 1, because it is taken at the line after handling the prototype. Change the logic to point to the next line after the /** */ block; 3) The "DOC:" line number should point to the same line as this markup is found, and not to the next one. Probably part of the issues were due to a but that was causing the line number offset to be incremented by one, if --export were used. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index ed32883c3221..9496abba9538 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1705,7 +1705,7 @@ sub dump_function($$) { my $file = shift; my $noret = 0; - print_lineno($.); + print_lineno($new_start_line); $prototype =~ s/^static +//; $prototype =~ s/^extern +//; @@ -2033,7 +2033,7 @@ sub process_name($$) { if (/$doc_block/o) { $state = STATE_DOCBLOCK; $contents = ""; - $new_start_line = $. + 1; + $new_start_line = $.; if ( $1 eq "" ) { $section = $section_intro; @@ -2116,6 +2116,7 @@ sub process_body($$) { if ($state == STATE_BODY_WITH_BLANK_LINE && /^\s*\*\s?\S/) { dump_section($file, $section, $contents); $section = $section_default; + $new_start_line = $.; $contents = ""; } @@ -2171,6 +2172,7 @@ sub process_body($$) { $prototype = ""; $state = STATE_PROTO; $brcount = 0; + $new_start_line = $. + 1; } elsif (/$doc_content/) { if ($1 eq "") { if ($section eq $section_context) { -- cgit From 6e9e415854c15dbf920481eb1d245988e405bbc0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 30 Sep 2020 09:47:01 +0200 Subject: scripts: kernel-doc: try to use c:function if possible There are a few namespace clashes by using c:macro everywhere: basically, when using it, we can't have something like: .. c:struct:: pwm_capture .. c:macro:: pwm_capture So, we need to use, instead: .. c:function:: int pwm_capture (struct pwm_device * pwm, struct pwm_capture * result, unsigned long timeout) for the function declaration. The kernel-doc change was proposed by Jakob Lykke Andersen here: https://github.com/jakobandersen/linux_docs/commit/6fd2076ec001cca7466857493cd678df4dfe4a65 Although I did a different implementation. Signed-off-by: Mauro Carvalho Chehab --- scripts/kernel-doc | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9496abba9538..c8f6b11d5da1 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -917,6 +917,7 @@ sub output_function_rst(%) { my ($parameter, $section); my $oldprefix = $lineprefix; my $start = ""; + my $is_macro = 0; if ($sphinx_major < 3) { if ($args{'typedef'}) { @@ -926,11 +927,17 @@ sub output_function_rst(%) { $lineprefix = ""; output_highlight_rst($args{'purpose'}); $start = "\n\n**Syntax**\n\n ``"; + $is_macro = 1; } else { print ".. c:function:: "; } } else { - print ".. c:macro:: ". $args{'function'} . "\n\n"; + if ($args{'typedef'} || $args{'functiontype'} eq "") { + $is_macro = 1; + print ".. c:macro:: ". $args{'function'} . "\n\n"; + } else { + print ".. c:function:: "; + } if ($args{'typedef'}) { print_lineno($declaration_start_line); @@ -939,7 +946,7 @@ sub output_function_rst(%) { output_highlight_rst($args{'purpose'}); $start = "\n\n**Syntax**\n\n ``"; } else { - print "``"; + print "``" if ($is_macro); } } if ($args{'functiontype'} ne "") { @@ -964,14 +971,12 @@ sub output_function_rst(%) { print $type; } } - if ($args{'typedef'}) { - print ");``\n\n"; + if ($is_macro) { + print ")``\n\n"; } else { - if ($sphinx_major < 3) { - print ")\n\n"; - } else { - print ")``\n"; - } + print ")\n\n"; + } + if (!$args{'typedef'}) { print_lineno($declaration_start_line); $lineprefix = " "; output_highlight_rst($args{'purpose'}); -- cgit From 82c2d81361ecd142a54e84a9da1e287113314a4f Mon Sep 17 00:00:00 2001 From: Sumera Priyadarsini Date: Thu, 15 Oct 2020 16:21:40 +0530 Subject: coccinelle: iterators: Add for_each_child.cocci script While iterating over child nodes with the for_each functions, if control is transferred from the middle of the loop, as in the case of a break or return or goto, there is no decrement in the reference counter thus ultimately resulting in a memory leak. Add this script to detect potential memory leaks caused by the absence of of_node_put() before break, goto, or, return statements which transfer control outside the loop. Signed-off-by: Sumera Priyadarsini Signed-off-by: Julia Lawall --- scripts/coccinelle/iterators/for_each_child.cocci | 358 ++++++++++++++++++++++ 1 file changed, 358 insertions(+) create mode 100644 scripts/coccinelle/iterators/for_each_child.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/iterators/for_each_child.cocci b/scripts/coccinelle/iterators/for_each_child.cocci new file mode 100644 index 000000000000..bc394615948e --- /dev/null +++ b/scripts/coccinelle/iterators/for_each_child.cocci @@ -0,0 +1,358 @@ +// SPDX-License-Identifier: GPL-2.0-only +// Adds missing of_node_put() before return/break/goto statement within a for_each iterator for child nodes. +//# False positives can be due to function calls within the for_each +//# loop that may encapsulate an of_node_put. +/// +// Confidence: High +// Copyright: (C) 2020 Sumera Priyadarsini +// URL: http://coccinelle.lip6.fr +// Options: --no-includes --include-headers + +virtual patch +virtual context +virtual org +virtual report + +@r@ +local idexpression n; +expression e1,e2; +iterator name for_each_node_by_name, for_each_node_by_type, +for_each_compatible_node, for_each_matching_node, +for_each_matching_node_and_match, for_each_child_of_node, +for_each_available_child_of_node, for_each_node_with_property; +iterator i; +statement S; +expression list [n1] es; +@@ + +( +( +for_each_node_by_name(n,e1) S +| +for_each_node_by_type(n,e1) S +| +for_each_compatible_node(n,e1,e2) S +| +for_each_matching_node(n,e1) S +| +for_each_matching_node_and_match(n,e1,e2) S +| +for_each_child_of_node(e1,n) S +| +for_each_available_child_of_node(e1,n) S +| +for_each_node_with_property(n,e1) S +) +& +i(es,n,...) S +) + +@ruleone depends on patch && !context && !org && !report@ + +local idexpression r.n; +iterator r.i,i1; +expression e; +expression list [r.n1] es; +statement S; +@@ + + i(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + return n; +| + i1(...,n,...) S +| +- return of_node_get(n); ++ return n; +| ++ of_node_put(n); +? return ...; +) + ... when any + } + +@ruletwo depends on patch && !context && !org && !report@ + +local idexpression r.n; +iterator r.i,i1,i2; +expression e,e1; +expression list [r.n1] es; +statement S,S2; +@@ + + i(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| ++ of_node_put(n); +? break; +) + ... when any + } +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@rulethree depends on patch && !context && !org && !report exists@ + +local idexpression r.n; +iterator r.i,i1,i2; +expression e,e1; +identifier l; +expression list [r.n1] es; +statement S,S2; +@@ + + i(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| ++ of_node_put(n); +? goto l; +) + ... when any + } +... when exists +l: ... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +// ---------------------------------------------------------------------------- + +@ruleone_context depends on !patch && (context || org || report) exists@ +statement S; +expression e; +expression list[r.n1] es; +iterator r.i, i1; +local idexpression r.n; +position j0, j1; +@@ + + i@j0(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + return n; +| + i1(...,n,...) S +| + return @j1 ...; +) + ... when any + } + +@ruleone_disj depends on !patch && (context || org || report)@ +expression list[r.n1] es; +iterator r.i; +local idexpression r.n; +position ruleone_context.j0, ruleone_context.j1; +@@ + +* i@j0(es,n,...) { + ... +*return @j1...; + ... when any + } + +@ruletwo_context depends on !patch && (context || org || report) exists@ +statement S, S2; +expression e, e1; +expression list[r.n1] es; +iterator r.i, i1, i2; +local idexpression r.n; +position j0, j2; +@@ + + i@j0(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| + break@j2; +) + ... when any + } +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@ruletwo_disj depends on !patch && (context || org || report)@ +statement S2; +expression e1; +expression list[r.n1] es; +iterator r.i, i2; +local idexpression r.n; +position ruletwo_context.j0, ruletwo_context.j2; +@@ + +* i@j0(es,n,...) { + ... +*break @j2; + ... when any + } +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@rulethree_context depends on !patch && (context || org || report) exists@ +identifier l; +statement S,S2; +expression e, e1; +expression list[r.n1] es; +iterator r.i, i1, i2; +local idexpression r.n; +position j0, j3; +@@ + + i@j0(es,n,...) { + ... +( + of_node_put(n); +| + e = n +| + i1(...,n,...) S +| + goto l@j3; +) + ... when any + } +... when exists +l: +... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +@rulethree_disj depends on !patch && (context || org || report) exists@ +identifier l; +statement S2; +expression e1; +expression list[r.n1] es; +iterator r.i, i2; +local idexpression r.n; +position rulethree_context.j0, rulethree_context.j3; +@@ + +* i@j0(es,n,...) { + ... +*goto l@j3; + ... when any + } +... when exists + l: + ... when != n + when strict + when forall +( + n = e1; +| +?i2(...,n,...) S2 +) + +// ---------------------------------------------------------------------------- + +@script:python ruleone_org depends on org@ +i << r.i; +j0 << ruleone_context.j0; +j1 << ruleone_context. j1; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before return " % (i) +coccilib.org.print_safe_todo(j0[0], msg) +coccilib.org.print_link(j1[0], "") + +@script:python ruletwo_org depends on org@ +i << r.i; +j0 << ruletwo_context.j0; +j2 << ruletwo_context.j2; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before break " % (i) +coccilib.org.print_safe_todo(j0[0], msg) +coccilib.org.print_link(j2[0], "") + +@script:python rulethree_org depends on org@ +i << r.i; +j0 << rulethree_context.j0; +j3 << rulethree_context.j3; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before goto " % (i) +coccilib.org.print_safe_todo(j0[0], msg) +coccilib.org.print_link(j3[0], "") + +// ---------------------------------------------------------------------------- + +@script:python ruleone_report depends on report@ +i << r.i; +j0 << ruleone_context.j0; +j1 << ruleone_context.j1; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before return around line %s." % (i, j1[0].line) +coccilib.report.print_report(j0[0], msg) + +@script:python ruletwo_report depends on report@ +i << r.i; +j0 << ruletwo_context.j0; +j2 << ruletwo_context.j2; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before break around line %s." % (i,j2[0].line) +coccilib.report.print_report(j0[0], msg) + +@script:python rulethree_report depends on report@ +i << r.i; +j0 << rulethree_context.j0; +j3 << rulethree_context.j3; +@@ + +msg = "WARNING: Function \"%s\" should have of_node_put() before goto around lines %s." % (i,j3[0].line) +coccilib.report.print_report(j0[0], msg) -- cgit From cdfe2d22047661c5e0ecf8f28e7e8843ee177aff Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 Oct 2020 20:10:34 -0700 Subject: get_maintainer: add test for file in VCS It's somewhat common for me to ask get_maintainer to tell me who maintains a patch file rather than the files modified by the patch. Emit a warning if using get_maintainer.pl -f Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Link: https://lkml.kernel.org/r/f63229c051567041819f25e76f49d83c6e4c0f71.camel@perches.com Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 3 +++ 1 file changed, 3 insertions(+) (limited to 'scripts') diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 484d2fbf5921..5a36354a38cc 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -541,6 +541,9 @@ foreach my $file (@ARGV) { die "$P: file '${file}' not found\n"; } } + if ($from_filename && (vcs_exists() && !vcs_file_exists($file))) { + warn "$P: file '$file' not found in version control $!\n"; + } if ($from_filename || ($file ne "&STDIN" && vcs_file_exists($file))) { $file =~ s/^\Q${cur_path}\E//; #strip any absolute path $file =~ s/^\Q${lk_path}\E//; #or the path to the lk tree -- cgit From 6343f6b71f83af8ebfc6f9740d1d74f2db88e6b0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 Oct 2020 20:10:37 -0700 Subject: get_maintainer: exclude MAINTAINERS file(s) from --git-fallback MAINTAINERS files generally have no specific maintainer but are updated by individuals for subsystems all over the source tree. Exclude MAINTAINERS file(s) from --git-fallback searches so the unlucky individuals that update the files the most are not shown by default. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Cc: Rob Herring Cc: Mauro Carvalho Chehab Cc: "David S. Miller" Link: https://lkml.kernel.org/r/2bacb0a9c06fbb6d56a43bf930e808c74243c908.camel@perches.com Signed-off-by: Linus Torvalds --- scripts/get_maintainer.pl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index 5a36354a38cc..2075db0c08b8 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -957,8 +957,10 @@ sub get_maintainers { foreach my $file (@files) { if ($email && - ($email_git || ($email_git_fallback && - !$exact_pattern_match_hash{$file}))) { + ($email_git || + ($email_git_fallback && + $file !~ /MAINTAINERS$/ && + !$exact_pattern_match_hash{$file}))) { vcs_file_signoffs($file); } if ($email && $email_git_blame) { -- cgit From 3e89ad8506f39c4739a6c9ca1e1552f506f000c9 Mon Sep 17 00:00:00 2001 From: Jerome Forissier Date: Thu, 15 Oct 2020 20:11:49 -0700 Subject: checkpatch: add --kconfig-prefix Kconfig allows to customize the CONFIG_ prefix via the $CONFIG_ environment variable. Out-of-tree projects may therefore use Kconfig with a different prefix, or they may use a custom configuration tool which does not use the CONFIG_ prefix at all. Such projects may still want to adhere to the Linux kernel coding style and run checkpatch.pl. One example is OP-TEE [1] which does not use Kconfig but does have configuration options prefixed with CFG_. It also mostly follows the kernel coding style and therefore being able to use checkpatch is quite valuable. To make this possible, add the --kconfig-prefix command line option. [1] https://github.com/OP-TEE/optee_os Signed-off-by: Jerome Forissier Signed-off-by: Andrew Morton Acked-by: Joe Perches Link: http://lkml.kernel.org/r/20200818081732.800449-1-jerome@forissier.org Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 504d2e431c60..9998340d69c6 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -65,6 +65,7 @@ my $allow_c99_comments = 1; # Can be overridden by --ignore C99_COMMENT_TOLERANC # git output parsing needs US English output, so first set backtick child process LANGUAGE my $git_command ='export LANGUAGE=en_US.UTF-8; git'; my $tabsize = 8; +my ${CONFIG_} = "CONFIG_"; sub help { my ($exitcode) = @_; @@ -127,6 +128,8 @@ Options: --typedefsfile Read additional types from this file --color[=WHEN] Use colors 'always', 'never', or only when output is a terminal ('auto'). Default is 'auto'. + --kconfig-prefix=WORD use WORD as a prefix for Kconfig symbols (default + ${CONFIG_}) -h, --help, --version display this help and exit When FILE is - read standard input. @@ -235,6 +238,7 @@ GetOptions( 'color=s' => \$color, 'no-color' => \$color, #keep old behaviors of -nocolor 'nocolor' => \$color, #keep old behaviors of -nocolor + 'kconfig-prefix=s' => \${CONFIG_}, 'h|help' => \$help, 'version' => \$help ) or help(1); @@ -6524,16 +6528,16 @@ sub process { } # check for IS_ENABLED() without CONFIG_ ($rawline for comments too) - if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^CONFIG_/) { + if ($rawline =~ /\bIS_ENABLED\s*\(\s*(\w+)\s*\)/ && $1 !~ /^${CONFIG_}/) { WARN("IS_ENABLED_CONFIG", - "IS_ENABLED($1) is normally used as IS_ENABLED(CONFIG_$1)\n" . $herecurr); + "IS_ENABLED($1) is normally used as IS_ENABLED(${CONFIG_}$1)\n" . $herecurr); } # check for #if defined CONFIG_ || defined CONFIG__MODULE - if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(CONFIG_[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) { + if ($line =~ /^\+\s*#\s*if\s+defined(?:\s*\(?\s*|\s+)(${CONFIG_}[A-Z_]+)\s*\)?\s*\|\|\s*defined(?:\s*\(?\s*|\s+)\1_MODULE\s*\)?\s*$/) { my $config = $1; if (WARN("PREFER_IS_ENABLED", - "Prefer IS_ENABLED() to CONFIG_ || CONFIG__MODULE\n" . $herecurr) && + "Prefer IS_ENABLED() to ${CONFIG_} || ${CONFIG_}_MODULE\n" . $herecurr) && $fix) { $fixed[$fixlinenr] = "\+#if IS_ENABLED($config)"; } -- cgit From 310cd06ba2496002481eb7fd3b02c51d115aa115 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 Oct 2020 20:11:52 -0700 Subject: checkpatch: move repeated word test Currently this test only works on .[ch] files. Move the test to check more file types and the commit log. Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Link: http://lkml.kernel.org/r/180b3b5677771c902b2e2f7a2b7090ede65fe004.camel@perches.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 72 +++++++++++++++++++++++++-------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 9998340d69c6..268028e382b5 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2991,6 +2991,42 @@ sub process { } } +# check for repeated words separated by a single space + if ($rawline =~ /^\+/ || $in_commit_log) { + while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) { + + my $first = $1; + my $second = $2; + + if ($first =~ /(?:struct|union|enum)/) { + pos($rawline) += length($first) + length($second) + 1; + next; + } + + next if ($first ne $second); + next if ($first eq 'long'); + + if (WARN("REPEATED_WORD", + "Possible repeated word: '$first'\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\b$first $second\b/$first/; + } + } + + # if it's a repeated word on consecutive lines in a comment block + if ($prevline =~ /$;+\s*$/ && + $prevrawline =~ /($word_pattern)\s*$/) { + my $last_word = $1; + if ($rawline =~ /^\+\s*\*\s*$last_word /) { + if (WARN("REPEATED_WORD", + "Possible repeated word: '$last_word'\n" . $hereprev) && + $fix) { + $fixed[$fixlinenr] =~ s/(\+\s*\*\s*)$last_word /$1/; + } + } + } + } + # ignore non-hunk lines and lines being removed next if (!$hunk_line || $line =~ /^-/); @@ -3314,42 +3350,6 @@ sub process { } } -# check for repeated words separated by a single space - if ($rawline =~ /^\+/) { - while ($rawline =~ /\b($word_pattern) (?=($word_pattern))/g) { - - my $first = $1; - my $second = $2; - - if ($first =~ /(?:struct|union|enum)/) { - pos($rawline) += length($first) + length($second) + 1; - next; - } - - next if ($first ne $second); - next if ($first eq 'long'); - - if (WARN("REPEATED_WORD", - "Possible repeated word: '$first'\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\b$first $second\b/$first/; - } - } - - # if it's a repeated word on consecutive lines in a comment block - if ($prevline =~ /$;+\s*$/ && - $prevrawline =~ /($word_pattern)\s*$/) { - my $last_word = $1; - if ($rawline =~ /^\+\s*\*\s*$last_word /) { - if (WARN("REPEATED_WORD", - "Possible repeated word: '$last_word'\n" . $hereprev) && - $fix) { - $fixed[$fixlinenr] =~ s/(\+\s*\*\s*)$last_word /$1/; - } - } - } - } - # check for space before tabs. if ($rawline =~ /^\+/ && $rawline =~ / \t/) { my $herevet = "$here\n" . cat_vet($rawline) . "\n"; -- cgit From 40873aba2c6b96c6f21265e6508eaa3de145e30a Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 Oct 2020 20:11:56 -0700 Subject: checkpatch: add test for comma use that should be semicolon There are commas used as statement terminations that should typically have used semicolons instead. Only direct assignments or use of a single function or value on a single line are detected by this test. e.g.: foo = bar(), /* typical use is semicolon not comma */ bar = baz(); Add an imperfect test to detect these comma uses. No false positives were found in testing, but many types of false negatives are possible. e.g.: foo = bar() + 1, /* comma use, but not direct assignment */ bar = baz(); Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Link: https://lkml.kernel.org/r/3bf27caf462007dfa75647b040ab3191374a59de.camel@perches.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 268028e382b5..74ccd122fc07 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4940,6 +4940,17 @@ sub process { } } +# check if a statement with a comma should be two statements like: +# foo = bar(), /* comma should be semicolon */ +# bar = baz(); + if (defined($stat) && + $stat =~ /^\+\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*,\s*(?:$Lval\s*$Assignment\s*)?$FuncArg\s*;\s*$/) { + my $cnt = statement_rawlines($stat); + my $herectx = get_stat_here($linenr, $cnt, $here); + WARN("SUSPECT_COMMA_SEMICOLON", + "Possible comma where semicolon could be used\n" . $herectx); + } + # return is not a function if (defined($stat) && $stat =~ /^.\s*return(\s*)\(/s) { my $spacing = $1; -- cgit From ed4761f7804743e73ba2c0c140535a16d07032b6 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Thu, 15 Oct 2020 20:11:59 -0700 Subject: const_structs.checkpatch: add phy_ops All usages of phy_ops in include/linux uses const phy_ops * and all instances of phy_ops in the kernel that are not const already can be made const (patches have been posted for those separately). Suggested-by: Joe Perches Signed-off-by: Rikard Falkeborn Signed-off-by: Andrew Morton Cc: Kishon Vijay Abraham I Cc: Vinod Koul Link: https://lkml.kernel.org/r/20200824214132.9072-1-rikard.falkeborn@gmail.com Signed-off-by: Linus Torvalds --- scripts/const_structs.checkpatch | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch index e9df9cc28a85..cd45cb3c2b04 100644 --- a/scripts/const_structs.checkpatch +++ b/scripts/const_structs.checkpatch @@ -39,6 +39,7 @@ nlmsvc_binding nvkm_device_chip of_device_id pci_raw_ops +phy_ops pipe_buf_operations platform_hibernation_ops platform_suspend_ops -- cgit From 8020b253631286807ca41f176e96e18af14bfb2e Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Thu, 15 Oct 2020 20:12:02 -0700 Subject: checkpatch: warn if trace_printk and friends are called trace_printk is meant as a debugging tool, and should not be compiled into production code without specific debug Kconfig options enabled, or source code changes, as indicated by the warning that shows up on boot if any trace_printk is called: ** NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE NOTICE ** ** ** ** trace_printk() being used. Allocating extra memory. ** ** ** ** This means that this is a DEBUG kernel and it is ** ** unsafe for production use. ** Let's warn developers when they try to submit such a change. Signed-off-by: Nicolas Boichat Signed-off-by: Andrew Morton Cc: Steven Rostedt Cc: Joe Perches Link: https://lkml.kernel.org/r/20200825193600.v2.1.I723c43c155f02f726c97501be77984f1e6bb740a@changeid Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 74ccd122fc07..81c20557d974 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4274,6 +4274,12 @@ sub process { "Prefer dev_$level(... to dev_printk(KERN_$orig, ...\n" . $herecurr); } +# trace_printk should not be used in production code. + if ($line =~ /\b(trace_printk|trace_puts|ftrace_vprintk)\s*\(/) { + WARN("TRACE_PRINTK", + "Do not use $1() in production code (this can be ignored if built only with a debug config option)\n" . $herecurr); + } + # ENOSYS means "bad syscall nr" and nothing else. This will have a small # number of false positives, but assembly files are not checked, so at # least the arch entry code will not trigger this warning. -- cgit From c12093a11462b775a83ed600bf0036c8bef3e841 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Thu, 15 Oct 2020 20:12:05 -0700 Subject: const_structs.checkpatch: add pinctrl_ops and pinmux_ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit All usages of include/linux of these are const pointers, and all instances in the kernel except one, that are not const can be made const (patches have been posted for those separately). Signed-off-by: Rikard Falkeborn Signed-off-by: Andrew Morton Reviewed-by: Linus Walleij Acked-by: Manivannan Sadhasivam Cc: Joe Perches Cc: Andreas Färber Cc: Rikard Falkeborn Link: https://lkml.kernel.org/r/20200830224352.37114-1-rikard.falkeborn@gmail.com Signed-off-by: Linus Torvalds --- scripts/const_structs.checkpatch | 2 ++ 1 file changed, 2 insertions(+) (limited to 'scripts') diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch index cd45cb3c2b04..1aae4f4fdacc 100644 --- a/scripts/const_structs.checkpatch +++ b/scripts/const_structs.checkpatch @@ -40,6 +40,8 @@ nvkm_device_chip of_device_id pci_raw_ops phy_ops +pinctrl_ops +pinmux_ops pipe_buf_operations platform_hibernation_ops platform_suspend_ops -- cgit From 99ca38c2aa7da5ab39e55f13fd425c6101903ccb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 Oct 2020 20:12:09 -0700 Subject: checkpatch: warn on self-assignments The uninitialized_var() macro was removed recently via commit 63a0895d960a ("compiler: Remove uninitialized_var() macro") as it's not a particularly useful warning and its use can "paper over real bugs". Add a checkpatch test to warn on self-assignments as a means to avoid compiler warnings and as a back-door mechanism to reproduce the old uninitialized_var macro behavior. [akpm@linux-foundation.org: coding style fixes] Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Cc: Kees Cook Cc: Gustavo A. R. Silva Cc: Denis Efremov Cc: Julia Lawall Link: https://lkml.kernel.org/r/afc2cffdd315d3e4394af149278df9e8af7f49f4.camel@perches.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 81c20557d974..5fe8762b1fae 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3899,6 +3899,17 @@ sub process { #ignore lines not being added next if ($line =~ /^[^\+]/); +# check for self assignments used to avoid compiler warnings +# e.g.: int foo = foo, *bar = NULL; +# struct foo bar = *(&(bar)); + if ($line =~ /^\+\s*(?:$Declare)?([A-Za-z_][A-Za-z\d_]*)\s*=/) { + my $var = $1; + if ($line =~ /^\+\s*(?:$Declare)?$var\s*=\s*(?:$var|\*\s*\(?\s*&\s*\(?\s*$var\s*\)?\s*\)?)\s*[;,]/) { + WARN("SELF_ASSIGNMENT", + "Do not use self-assignments to avoid compiler warnings\n" . $herecurr); + } + } + # check for dereferences that span multiple lines if ($prevline =~ /^\+.*$Lval\s*(?:\.|->)\s*$/ && $line =~ /^\+\s*(?!\#\s*(?!define\s+|if))\s*$Lval/) { -- cgit From f5f613259f3fea813c3f698a426c78eac61d8601 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 Oct 2020 20:12:12 -0700 Subject: checkpatch: allow not using -f with files that are in git If a file exists in git and checkpatch is used without the -f flag for scanning a file, then checkpatch will scan the file assuming it's a patch and emit: ERROR: Does not appear to be a unified-diff format patch Change the behavior to assume the -f flag if the file exists in git. [joe@perches.com: fix git "fatal" warning if file argument outside kernel tree] Link: https://lkml.kernel.org/r/b6afa04112d450c2fc120a308d706acd60cee294.camel@perches.com Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Reviewed-by: Julia Lawall Cc: Rasmus Villemoes Link: https://lkml.kernel.org/r/45b81a48e1568bd0126a96f5046eb7aaae9b83c9.camel@perches.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 5fe8762b1fae..360ae4b84ee3 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -974,6 +974,16 @@ sub seed_camelcase_includes { } } +sub git_is_single_file { + my ($filename) = @_; + + return 0 if ((which("git") eq "") || !(-e "$gitroot")); + + my $output = `${git_command} ls-files -- $filename 2>/dev/null`; + my $count = $output =~ tr/\n//; + return $count eq 1 && $output =~ m{^${filename}$}; +} + sub git_commit_info { my ($commit, $id, $desc) = @_; @@ -1047,6 +1057,9 @@ my $vname; $allow_c99_comments = !defined $ignore_type{"C99_COMMENT_TOLERANCE"}; for my $filename (@ARGV) { my $FILE; + my $is_git_file = git_is_single_file($filename); + my $oldfile = $file; + $file = 1 if ($is_git_file); if ($git) { open($FILE, '-|', "git format-patch -M --stdout -1 $filename") || die "$P: $filename: git format-patch failed - $!\n"; @@ -1091,6 +1104,7 @@ for my $filename (@ARGV) { @modifierListFile = (); @typeListFile = (); build_types(); + $file = $oldfile if ($is_git_file); } if (!$quiet) { -- cgit From e7f929f3ca9ecadb7d38340345920af49e09eb6a Mon Sep 17 00:00:00 2001 From: Dwaipayan Ray Date: Thu, 15 Oct 2020 20:12:15 -0700 Subject: checkpatch: extend author Signed-off-by check for split From: header Checkpatch did not handle cases where the author From: header was split into multiple lines. The author identity could not be resolved and checkpatch generated a false NO_AUTHOR_SIGN_OFF warning. A typical example is commit e33bcbab16d1 ("tee: add support for session's client UUID generation"). When checkpatch was run on this commit, it displayed: "WARNING:NO_AUTHOR_SIGN_OFF: Missing Signed-off-by: line by nominal patch author ''" This was due to split header lines not being handled properly and the author himself wrote in commit cd2614967d8b ("checkpatch: warn if missing author Signed-off-by"): "Split From: headers are not fully handled: only the first part is compared." Support split From: headers by correctly parsing the header extension lines. RFC 5322, Section-2.2.3 stated that each extended line must start with a WSP character (a space or htab). The solution was therefore to concatenate the lines which start with a WSP to get the correct long header. Suggested-by: Joe Perches Signed-off-by: Dwaipayan Ray Signed-off-by: Andrew Morton Tested-by: Lukas Bulwahn Reviewed-by: Lukas Bulwahn Acked-by: Joe Perches Link: https://lore.kernel.org/linux-kernel-mentees/f5d8124e54a50480b0a9fa638787bc29b6e09854.camel@perches.com/ Link: https://lkml.kernel.org/r/20200921085436.63003-1-dwaipayanray1@gmail.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 360ae4b84ee3..f40a81f24d43 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2679,6 +2679,10 @@ sub process { # Check the patch for a From: if (decode("MIME-Header", $line) =~ /^From:\s*(.*)/) { $author = $1; + my $curline = $linenr; + while(defined($rawlines[$curline]) && ($rawlines[$curline++] =~ /^[ \t]\s*(.*)/)) { + $author .= $1; + } $author = encode("utf8", $author) if ($line =~ /=\?utf-8\?/i); $author =~ s/"//g; $author = reformat_email($author); -- cgit From a0154cdbd3dcf2b1b92f42cb1351a63f3f947e80 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Thu, 15 Oct 2020 20:12:19 -0700 Subject: checkpatch: emit a warning on embedded filenames Embedding the complete filename path inside the file isn't particularly useful as often the path is moved around and becomes incorrect. Emit a warning when the source contains the filename. [akpm@linux-foundation.org: remove stray " di"] Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Link: https://lkml.kernel.org/r/1fd5f9188a14acdca703ca00301ee323de672a8d.camel@perches.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index f40a81f24d43..5424134e201d 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3271,6 +3271,12 @@ sub process { } } +# check for embedded filenames + if ($rawline =~ /^\+.*\Q$realfile\E/) { + WARN("EMBEDDED_FILENAME", + "It's generally not useful to have the filename in the file\n" . $herecurr); + } + # check we are in a valid source file if not then ignore this hunk next if ($realfile !~ /\.(h|c|s|S|sh|dtsi|dts)$/); -- cgit From 2e44e8033a9bc0420f315c32843ab89c0fc7bd0f Mon Sep 17 00:00:00 2001 From: Dwaipayan Ray Date: Thu, 15 Oct 2020 20:12:22 -0700 Subject: checkpatch: fix multi-statement macro checks for while blocks. Checkpatch.pl doesn't have a check for excluding while (...) {...} blocks from MULTISTATEMENT_MACRO_USE_DO_WHILE error. For example, running checkpatch.pl on the file mm/maccess.c in the kernel generates the following error: ERROR: Macros with complex values should be enclosed in parentheses +#define copy_from_kernel_nofault_loop(dst, src, len, type, err_label) \ + while (len >= sizeof(type)) { \ + __get_kernel_nofault(dst, src, type, err_label); \ + dst += sizeof(type); \ + src += sizeof(type); \ + len -= sizeof(type); \ + } The error is misleading for this case. Enclosing it in parentheses doesn't make any sense. Checkpatch already has an exception list for such common macro types. Added a new exception for while (...) {...} style blocks to the same. In addition, the brace flatten logic was modified by changing the substitution characters from "1" to "1u". This was done to ensure that macros in the form "#define foo(bar) while(bar){bar--;}" were also correctly procecssed. Link: https://lore.kernel.org/linux-kernel-mentees/dc985938aa3986702815a0bd68dfca8a03c85447.camel@perches.com/ Suggested-by: Joe Perches Signed-off-by: Dwaipayan Ray Signed-off-by: Andrew Morton Link: https://lkml.kernel.org/r/20201001171903.312021-1-dwaipayanray1@gmail.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 5424134e201d..8a5f0367a2f1 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5351,9 +5351,9 @@ sub process { $dstat =~ s/\s*$//s; # Flatten any parentheses and braces - while ($dstat =~ s/\([^\(\)]*\)/1/ || - $dstat =~ s/\{[^\{\}]*\}/1/ || - $dstat =~ s/.\[[^\[\]]*\]/1/) + while ($dstat =~ s/\([^\(\)]*\)/1u/ || + $dstat =~ s/\{[^\{\}]*\}/1u/ || + $dstat =~ s/.\[[^\[\]]*\]/1u/) { } @@ -5394,6 +5394,7 @@ sub process { $dstat !~ /^\.$Ident\s*=/ && # .foo = $dstat !~ /^(?:\#\s*$Ident|\#\s*$Constant)\s*$/ && # stringification #foo $dstat !~ /^do\s*$Constant\s*while\s*$Constant;?$/ && # do {...} while (...); // do {...} while (...) + $dstat !~ /^while\s*$Constant\s*$Constant\s*$/ && # while (...) {...} $dstat !~ /^for\s*$Constant$/ && # for (...) $dstat !~ /^for\s*$Constant\s+(?:$Ident|-?$Constant)$/ && # for (...) bar() $dstat !~ /^do\s*{/ && # do {... -- cgit From c70735c23bf6cbfc9d7dad5f4ad562f0e40a89fa Mon Sep 17 00:00:00 2001 From: Łukasz Stelmach Date: Thu, 15 Oct 2020 20:12:25 -0700 Subject: checkpatch: fix false positive on empty block comment lines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To avoid false positives in presence of SPDX-License-Identifier in networking files it is required to increase the leeway for empty block comment lines by one line. For example, checking drivers/net/loopback.c which starts with // SPDX-License-Identifier: GPL-2.0-or-later /* * INET An implementation of the TCP/IP protocol suite for the LINUX rsults in an unnecessary warning WARNING: networking block comments don't use an empty /* line, use /* Comment... +/* + * INET An implementation of the TCP/IP protocol suite for the LINUX Signed-off-by: Łukasz Stelmach Signed-off-by: Andrew Morton Acked-by: Joe Perches Cc: Bartłomiej Żolnierkiewicz Cc: Marek Szyprowski Link: https://lkml.kernel.org/r/20201006083509.19934-1-l.stelmach@samsung.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 8a5f0367a2f1..e1ddcafdc176 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3464,7 +3464,7 @@ sub process { if ($realfile =~ m@^(drivers/net/|net/)@ && $prevrawline =~ /^\+[ \t]*\/\*[ \t]*$/ && $rawline =~ /^\+[ \t]*\*/ && - $realline > 2) { + $realline > 3) { # Do not warn about the initial copyright comment block after SPDX-License-Identifier WARN("NETWORKING_BLOCK_COMMENT_STYLE", "networking block comments don't use an empty /* line, use /* Comment...\n" . $hereprev); } -- cgit From 48ca2d8ac8a1d404a0f85eabfe1546304adbd844 Mon Sep 17 00:00:00 2001 From: Dwaipayan Ray Date: Thu, 15 Oct 2020 20:12:28 -0700 Subject: checkpatch: add new warnings to author signoff checks. The author signed-off-by checks are currently very vague. Cases like same name or same address are not handled separately. For example, running checkpatch on commit be6577af0cef ("parisc: Add atomic64_set_release() define to avoid CPU soft lockups"), gives: WARNING: Missing Signed-off-by: line by nominal patch author 'John David Anglin ' The signoff line was: "Signed-off-by: Dave Anglin " Clearly the author has signed off but with a slightly different version of his name. A more appropriate warning would have been to point out at the name mismatch instead. Previously, the values assumed by $authorsignoff were either 0 or 1 to indicate whether a proper sign off by author is present. Extended the checks to handle four new cases. $authorsignoff values now denote the following: 0: Missing sign off by patch author. 1: Sign off present and identical. 2: Addresses and names match, but comments differ. "James Watson(JW) ", "James Watson " 3: Addresses match, but names are different. "James Watson ", "James " 4: Names match, but addresses are different. "James Watson ", "James Watson " 5: Names match, addresses excluding subaddress details (RFC 5233) match. "James Watson ", "James Watson " Also introduced a new message type FROM_SIGN_OFF_MISMATCH for cases 2, 3, 4 and 5. Suggested-by: Joe Perches Signed-off-by: Dwaipayan Ray Signed-off-by: Andrew Morton Acked-by: Joe Perches Link: https://lore.kernel.org/linux-kernel-mentees/c1ca28e77e8e3bfa7aadf3efa8ed70f97a9d369c.camel@perches.com/ Link: https://lkml.kernel.org/r/20201007192029.551744-1-dwaipayanray1@gmail.com Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 93 ++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e1ddcafdc176..4223a9ac7059 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -1181,10 +1181,10 @@ sub parse_email { } } + $comment = trim($comment); $name = trim($name); $name =~ s/^\"|\"$//g; - $name =~ s/(\s*\([^\)]+\))\s*//; - if (defined($1)) { + if ($name =~ s/(\s*\([^\)]+\))\s*//) { $name_comment = trim($1); } $address = trim($address); @@ -1199,10 +1199,12 @@ sub parse_email { } sub format_email { - my ($name, $address) = @_; + my ($name, $name_comment, $address, $comment) = @_; my $formatted_email; + $name_comment = trim($name_comment); + $comment = trim($comment); $name = trim($name); $name =~ s/^\"|\"$//g; $address = trim($address); @@ -1215,9 +1217,9 @@ sub format_email { if ("$name" eq "") { $formatted_email = "$address"; } else { - $formatted_email = "$name <$address>"; + $formatted_email = "$name$name_comment <$address>"; } - + $formatted_email .= "$comment"; return $formatted_email; } @@ -1225,17 +1227,23 @@ sub reformat_email { my ($email) = @_; my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); - return format_email($email_name, $email_address); + return format_email($email_name, $name_comment, $email_address, $comment); } sub same_email_addresses { - my ($email1, $email2) = @_; + my ($email1, $email2, $match_comment) = @_; my ($email1_name, $name1_comment, $email1_address, $comment1) = parse_email($email1); my ($email2_name, $name2_comment, $email2_address, $comment2) = parse_email($email2); + if ($match_comment != 1) { + return $email1_name eq $email2_name && + $email1_address eq $email2_address; + } return $email1_name eq $email2_name && - $email1_address eq $email2_address; + $email1_address eq $email2_address && + $name1_comment eq $name2_comment && + $comment1 eq $comment2; } sub which { @@ -2365,6 +2373,7 @@ sub process { my $signoff = 0; my $author = ''; my $authorsignoff = 0; + my $author_sob = ''; my $is_patch = 0; my $is_binding_patch = -1; my $in_header_lines = $file ? 0 : 1; @@ -2692,9 +2701,37 @@ sub process { if ($line =~ /^\s*signed-off-by:\s*(.*)/i) { $signoff++; $in_commit_log = 0; - if ($author ne '') { - if (same_email_addresses($1, $author)) { + if ($author ne '' && $authorsignoff != 1) { + if (same_email_addresses($1, $author, 1)) { $authorsignoff = 1; + } else { + my $ctx = $1; + my ($email_name, $email_comment, $email_address, $comment1) = parse_email($ctx); + my ($author_name, $author_comment, $author_address, $comment2) = parse_email($author); + + if ($email_address eq $author_address && $email_name eq $author_name) { + $author_sob = $ctx; + $authorsignoff = 2; + } elsif ($email_address eq $author_address) { + $author_sob = $ctx; + $authorsignoff = 3; + } elsif ($email_name eq $author_name) { + $author_sob = $ctx; + $authorsignoff = 4; + + my $address1 = $email_address; + my $address2 = $author_address; + + if ($address1 =~ /(\S+)\+\S+(\@.*)/) { + $address1 = "$1$2"; + } + if ($address2 =~ /(\S+)\+\S+(\@.*)/) { + $address2 = "$1$2"; + } + if ($address1 eq $address2) { + $authorsignoff = 5; + } + } } } } @@ -2751,7 +2788,7 @@ sub process { } my ($email_name, $name_comment, $email_address, $comment) = parse_email($email); - my $suggested_email = format_email(($email_name, $email_address)); + my $suggested_email = format_email(($email_name, $name_comment, $email_address, $comment)); if ($suggested_email eq "") { ERROR("BAD_SIGN_OFF", "Unrecognized email address: '$email'\n" . $herecurr); @@ -2761,9 +2798,9 @@ sub process { $dequoted =~ s/" missing sign off + # 1 -> sign off identical + # 2 -> names and addresses match, comments mismatch + # 3 -> addresses match, names different + # 4 -> names match, addresses different + # 5 -> names match, addresses excluding subaddress details (refer RFC 5233) match + + my $sob_msg = "'From: $author' != 'Signed-off-by: $author_sob'"; + + if ($authorsignoff == 0) { + ERROR("NO_AUTHOR_SIGN_OFF", + "Missing Signed-off-by: line by nominal patch author '$author'\n"); + } elsif ($authorsignoff == 2) { + CHK("FROM_SIGN_OFF_MISMATCH", + "From:/Signed-off-by: email comments mismatch: $sob_msg\n"); + } elsif ($authorsignoff == 3) { + WARN("FROM_SIGN_OFF_MISMATCH", + "From:/Signed-off-by: email name mismatch: $sob_msg\n"); + } elsif ($authorsignoff == 4) { + WARN("FROM_SIGN_OFF_MISMATCH", + "From:/Signed-off-by: email address mismatch: $sob_msg\n"); + } elsif ($authorsignoff == 5) { + WARN("FROM_SIGN_OFF_MISMATCH", + "From:/Signed-off-by: email subaddress mismatch: $sob_msg\n"); + } } } -- cgit From 998ec76b920086d9f6bac8b11719ee81976743b6 Mon Sep 17 00:00:00 2001 From: Ritesh Harjani Date: Thu, 15 Oct 2020 20:13:29 -0700 Subject: scripts/gdb/proc: add struct mount & struct super_block addr in lx-mounts command This is many times found useful while debugging some FS related issue. mount super_block devname pathname fstype options 0xffff888a0bfa4b40 0xffff888a0bfc1000 none / rootfs rw 0 0 0xffff888a033f75c0 0xffff8889fcf65000 /dev/root / ext4 rw,relatime 0 0 0xffff8889fc8ce040 0xffff888a0bb51000 devtmpfs /dev devtmpfs rw,relatime 0 0 Signed-off-by: Ritesh Harjani Signed-off-by: Andrew Morton Reviewed-by: Jan Kiszka Cc: Kieran Bingham Link: http://lkml.kernel.org/r/a3c4177e1597b3e06d66d55e07d72c0c46a03571.1597742951.git.riteshh@linux.ibm.com Signed-off-by: Linus Torvalds --- scripts/gdb/linux/proc.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/proc.py b/scripts/gdb/linux/proc.py index 6a56bba233a9..09cd871925a5 100644 --- a/scripts/gdb/linux/proc.py +++ b/scripts/gdb/linux/proc.py @@ -167,6 +167,9 @@ values of that process namespace""" if not namespace: raise gdb.GdbError("No namespace for current process") + gdb.write("{:^18} {:^15} {:>9} {} {} options\n".format( + "mount", "super_block", "devname", "pathname", "fstype")) + for vfs in lists.list_for_each_entry(namespace['list'], mount_ptr_type, "mnt_list"): devname = vfs['mnt_devname'].string() @@ -190,14 +193,10 @@ values of that process namespace""" m_flags = int(vfs['mnt']['mnt_flags']) rd = "ro" if (s_flags & constants.LX_SB_RDONLY) else "rw" - gdb.write( - "{} {} {} {}{}{} 0 0\n" - .format(devname, - pathname, - fstype, - rd, - info_opts(FS_INFO, s_flags), - info_opts(MNT_INFO, m_flags))) + gdb.write("{} {} {} {} {} {}{}{} 0 0\n".format( + vfs.format_string(), superblock.format_string(), devname, + pathname, fstype, rd, info_opts(FS_INFO, s_flags), + info_opts(MNT_INFO, m_flags))) LxMounts() -- cgit From 4fbe310e44067e5f15c327483031f9564e6b1826 Mon Sep 17 00:00:00 2001 From: Ritesh Harjani Date: Thu, 15 Oct 2020 20:13:32 -0700 Subject: scripts/gdb/tasks: add headers and improve spacing format With the patch. TASK PID COMM 0xffffffff82c2b8c0 0 swapper/0 0xffff888a0ba20040 1 systemd 0xffff888a0ba24040 2 kthreadd 0xffff888a0ba28040 3 rcu_gp w/o 0xffffffff82c2b8c0 0 swapper/0 0xffff888a0ba20040 1 systemd 0xffff888a0ba24040 2 kthreadd 0xffff888a0ba28040 3 rcu_gp Signed-off-by: Ritesh Harjani Signed-off-by: Andrew Morton Reviewed-by: Jan Kiszka Cc: Kieran Bingham Link: http://lkml.kernel.org/r/54c868c79b5fc364a8be7799891934a6fe6d1464.1597742951.git.riteshh@linux.ibm.com Signed-off-by: Linus Torvalds --- scripts/gdb/linux/tasks.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/gdb/linux/tasks.py b/scripts/gdb/linux/tasks.py index 0301dc1e0138..17ec19e9b5bf 100644 --- a/scripts/gdb/linux/tasks.py +++ b/scripts/gdb/linux/tasks.py @@ -73,11 +73,12 @@ class LxPs(gdb.Command): super(LxPs, self).__init__("lx-ps", gdb.COMMAND_DATA) def invoke(self, arg, from_tty): + gdb.write("{:>10} {:>12} {:>7}\n".format("TASK", "PID", "COMM")) for task in task_lists(): - gdb.write("{address} {pid} {comm}\n".format( - address=task, - pid=task["pid"], - comm=task["comm"].string())) + gdb.write("{} {:^5} {}\n".format( + task.format_string().split()[0], + task["pid"].format_string(), + task["comm"].string())) LxPs() -- cgit From 6a6155f664e31c9be43cd690541a9a682ba3dc22 Mon Sep 17 00:00:00 2001 From: George Popescu Date: Thu, 15 Oct 2020 20:13:38 -0700 Subject: ubsan: introduce CONFIG_UBSAN_LOCAL_BOUNDS for Clang When the kernel is compiled with Clang, -fsanitize=bounds expands to -fsanitize=array-bounds and -fsanitize=local-bounds. Enabling -fsanitize=local-bounds with Clang has the unfortunate side-effect of inserting traps; this goes back to its original intent, which was as a hardening and not a debugging feature [1]. The same feature made its way into -fsanitize=bounds, but the traps remained. For that reason, -fsanitize=bounds was split into 'array-bounds' and 'local-bounds' [2]. Since 'local-bounds' doesn't behave like a normal sanitizer, enable it with Clang only if trapping behaviour was requested by CONFIG_UBSAN_TRAP=y. Add the UBSAN_BOUNDS_LOCAL config to Kconfig.ubsan to enable the 'local-bounds' option by default when UBSAN_TRAP is enabled. [1] http://lists.llvm.org/pipermail/llvm-dev/2012-May/049972.html [2] http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20131021/091536.html Suggested-by: Marco Elver Signed-off-by: George Popescu Signed-off-by: Andrew Morton Reviewed-by: David Brazdil Reviewed-by: Marco Elver Cc: Masahiro Yamada Cc: Michal Marek Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Kees Cook Cc: Dmitry Vyukov Cc: Arnd Bergmann Cc: Peter Zijlstra Link: https://lkml.kernel.org/r/20200922074330.2549523-1-georgepope@google.com Signed-off-by: Linus Torvalds --- scripts/Makefile.ubsan | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index 27348029b2b8..4e3fff0745e8 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -4,7 +4,15 @@ ifdef CONFIG_UBSAN_ALIGNMENT endif ifdef CONFIG_UBSAN_BOUNDS - CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds) + ifdef CONFIG_CC_IS_CLANG + CFLAGS_UBSAN += -fsanitize=array-bounds + else + CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds) + endif +endif + +ifdef CONFIG_UBSAN_LOCAL_BOUNDS + CFLAGS_UBSAN += -fsanitize=local-bounds endif ifdef CONFIG_UBSAN_MISC -- cgit From edc05fe5559e9b79e64cfec3b960f6a913b73493 Mon Sep 17 00:00:00 2001 From: Denis Efremov Date: Fri, 16 Oct 2020 11:54:42 +0300 Subject: coccinelle: api: add kfree_mismatch script Check that alloc and free types of functions match each other. Signed-off-by: Denis Efremov Signed-off-by: Julia Lawall --- scripts/coccinelle/api/kfree_mismatch.cocci | 228 ++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 scripts/coccinelle/api/kfree_mismatch.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/api/kfree_mismatch.cocci b/scripts/coccinelle/api/kfree_mismatch.cocci new file mode 100644 index 000000000000..d46a9b3eb7b3 --- /dev/null +++ b/scripts/coccinelle/api/kfree_mismatch.cocci @@ -0,0 +1,228 @@ +// SPDX-License-Identifier: GPL-2.0-only +/// +/// Check that kvmalloc'ed memory is freed by kfree functions, +/// vmalloc'ed by vfree functions and kvmalloc'ed by kvfree +/// functions. +/// +// Confidence: High +// Copyright: (C) 2020 Denis Efremov ISPRAS +// Options: --no-includes --include-headers +// + +virtual patch +virtual report +virtual org +virtual context + +@alloc@ +expression E, E1; +position kok, vok; +@@ + +( + if (...) { + ... + E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\| + kmalloc_node\|kzalloc_node\|kmalloc_array\| + kmalloc_array_node\|kcalloc_node\)(...)@kok + ... + } else { + ... + E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\| + vzalloc_node\|vmalloc_exec\|vmalloc_32\| + vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\| + __vmalloc_node\)(...)@vok + ... + } +| + E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\|kzalloc_node\| + kmalloc_array\|kmalloc_array_node\|kcalloc_node\)(...)@kok + ... when != E = E1 + when any + if (E == NULL) { + ... + E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\| + vzalloc_node\|vmalloc_exec\|vmalloc_32\| + vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\| + __vmalloc_node\)(...)@vok + ... + } +) + +@free@ +expression E; +position fok; +@@ + + E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\| + kvmalloc_array\)(...) + ... + kvfree(E)@fok + +@vfree depends on !patch@ +expression E; +position a != alloc.kok; +position f != free.fok; +@@ + +* E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\| +* kzalloc_node\|kmalloc_array\|kmalloc_array_node\| +* kcalloc_node\)(...)@a + ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... } + when != is_vmalloc_addr(E) + when any +* \(vfree\|vfree_atomic\|kvfree\)(E)@f + +@depends on patch exists@ +expression E; +position a != alloc.kok; +position f != free.fok; +@@ + + E = \(kmalloc\|kzalloc\|krealloc\|kcalloc\|kmalloc_node\| + kzalloc_node\|kmalloc_array\|kmalloc_array_node\| + kcalloc_node\)(...)@a + ... when != if (...) { ... E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\|vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\|__vmalloc_node_range\|__vmalloc_node\)(...); ... } + when != is_vmalloc_addr(E) + when any +- \(vfree\|vfree_atomic\|kvfree\)(E)@f ++ kfree(E) + +@kfree depends on !patch@ +expression E; +position a != alloc.vok; +position f != free.fok; +@@ + +* E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\| +* vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\| +* __vmalloc_node_range\|__vmalloc_node\)(...)@a + ... when != is_vmalloc_addr(E) + when any +* \(kfree\|kfree_sensitive\|kvfree\)(E)@f + +@depends on patch exists@ +expression E; +position a != alloc.vok; +position f != free.fok; +@@ + + E = \(vmalloc\|vzalloc\|vmalloc_user\|vmalloc_node\|vzalloc_node\| + vmalloc_exec\|vmalloc_32\|vmalloc_32_user\|__vmalloc\| + __vmalloc_node_range\|__vmalloc_node\)(...)@a + ... when != is_vmalloc_addr(E) + when any +- \(kfree\|kvfree\)(E)@f ++ vfree(E) + +@kvfree depends on !patch@ +expression E; +position a, f; +@@ + +* E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\| +* kvmalloc_array\)(...)@a + ... when != is_vmalloc_addr(E) + when any +* \(kfree\|kfree_sensitive\|vfree\|vfree_atomic\)(E)@f + +@depends on patch exists@ +expression E; +@@ + + E = \(kvmalloc\|kvzalloc\|kvcalloc\|kvzalloc_node\|kvmalloc_node\| + kvmalloc_array\)(...) + ... when != is_vmalloc_addr(E) + when any +- \(kfree\|vfree\)(E) ++ kvfree(E) + +@kvfree_switch depends on !patch@ +expression alloc.E; +position f; +@@ + + ... when != is_vmalloc_addr(E) + when any +* \(kfree\|kfree_sensitive\|vfree\|vfree_atomic\)(E)@f + +@depends on patch exists@ +expression alloc.E; +position f; +@@ + + ... when != is_vmalloc_addr(E) + when any +( +- \(kfree\|vfree\)(E)@f ++ kvfree(E) +| +- kfree_sensitive(E)@f ++ kvfree_sensitive(E) +) + +@script: python depends on report@ +a << vfree.a; +f << vfree.f; +@@ + +msg = "WARNING kmalloc is used to allocate this memory at line %s" % (a[0].line) +coccilib.report.print_report(f[0], msg) + +@script: python depends on org@ +a << vfree.a; +f << vfree.f; +@@ + +msg = "WARNING kmalloc is used to allocate this memory at line %s" % (a[0].line) +coccilib.org.print_todo(f[0], msg) + +@script: python depends on report@ +a << kfree.a; +f << kfree.f; +@@ + +msg = "WARNING vmalloc is used to allocate this memory at line %s" % (a[0].line) +coccilib.report.print_report(f[0], msg) + +@script: python depends on org@ +a << kfree.a; +f << kfree.f; +@@ + +msg = "WARNING vmalloc is used to allocate this memory at line %s" % (a[0].line) +coccilib.org.print_todo(f[0], msg) + +@script: python depends on report@ +a << kvfree.a; +f << kvfree.f; +@@ + +msg = "WARNING kvmalloc is used to allocate this memory at line %s" % (a[0].line) +coccilib.report.print_report(f[0], msg) + +@script: python depends on org@ +a << kvfree.a; +f << kvfree.f; +@@ + +msg = "WARNING kvmalloc is used to allocate this memory at line %s" % (a[0].line) +coccilib.org.print_todo(f[0], msg) + +@script: python depends on report@ +ka << alloc.kok; +va << alloc.vok; +f << kvfree_switch.f; +@@ + +msg = "WARNING kmalloc (line %s) && vmalloc (line %s) are used to allocate this memory" % (ka[0].line, va[0].line) +coccilib.report.print_report(f[0], msg) + +@script: python depends on org@ +ka << alloc.kok; +va << alloc.vok; +f << kvfree_switch.f; +@@ + +msg = "WARNING kmalloc (line %s) && vmalloc (line %s) are used to allocate this memory" % (ka[0].line, va[0].line) +coccilib.org.print_todo(f[0], msg) -- cgit From 0f6372e522237f39aff63f2e158d629038f26238 Mon Sep 17 00:00:00 2001 From: Sami Tolvanen Date: Mon, 12 Oct 2020 17:31:45 -0700 Subject: treewide: remove DISABLE_LTO This change removes all instances of DISABLE_LTO from Makefiles, as they are currently unused, and the preferred method of disabling LTO is to filter out the flags instead. Note added by Masahiro Yamada: DISABLE_LTO was added as preparation for GCC LTO, but GCC LTO was not pulled into the mainline. (https://lkml.org/lkml/2014/4/8/272) Suggested-by: Kees Cook Signed-off-by: Sami Tolvanen Reviewed-by: Kees Cook Signed-off-by: Masahiro Yamada --- scripts/Makefile.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index a467b9323442..ae647379b579 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -111,7 +111,7 @@ endif # --------------------------------------------------------------------------- quiet_cmd_cc_s_c = CC $(quiet_modtag) $@ - cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) $(DISABLE_LTO) -fverbose-asm -S -o $@ $< + cmd_cc_s_c = $(CC) $(filter-out $(DEBUG_CFLAGS), $(c_flags)) -fverbose-asm -S -o $@ $< $(obj)/%.s: $(src)/%.c FORCE $(call if_changed_dep,cc_s_c) -- cgit From 8402ee182c417a32d5e5a702f2fa2b01e76dc220 Mon Sep 17 00:00:00 2001 From: Rasmus Villemoes Date: Fri, 16 Oct 2020 14:58:46 +0200 Subject: kbuild: remove leftover comment for filechk utility After commit 43fee2b23895 ("kbuild: do not redirect the first prerequisite for filechk"), the rule is no longer automatically passed $< as stdin, so remove the stale comment. Fixes: 43fee2b23895 ("kbuild: do not redirect the first prerequisite for filechk") Signed-off-by: Rasmus Villemoes Signed-off-by: Masahiro Yamada --- scripts/Kbuild.include | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include index 83a1637417e5..08e011175b4c 100644 --- a/scripts/Kbuild.include +++ b/scripts/Kbuild.include @@ -56,8 +56,6 @@ kecho := $($(quiet)kecho) # - If no file exist it is created # - If the content differ the new file is used # - If they are equal no change, and no timestamp update -# - stdin is piped in from the first prerequisite ($<) so one has -# to specify a valid file as first prerequisite (often the kbuild file) define filechk $(Q)set -e; \ mkdir -p $(dir $@); \ -- cgit From 1e66d50ad3a1dbf0169b14d502be59a4b1213149 Mon Sep 17 00:00:00 2001 From: Chris Down Date: Tue, 20 Oct 2020 10:34:59 +0100 Subject: kbuild: Use uname for LINUX_COMPILE_HOST detection `hostname` may not be present on some systems as it's not mandated by POSIX/SUSv4. This isn't just a theoretical problem: on Arch Linux, `hostname` is provided by `inetutils`, which isn't part of the base distribution. ./scripts/mkcompile_h: line 38: hostname: command not found Use `uname -n` instead, which is more likely to be available (and mandated by standards). Signed-off-by: Chris Down Signed-off-by: Masahiro Yamada --- scripts/mkcompile_h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/mkcompile_h b/scripts/mkcompile_h index baf3ab8d9d49..4ae735039daf 100755 --- a/scripts/mkcompile_h +++ b/scripts/mkcompile_h @@ -35,7 +35,7 @@ else LINUX_COMPILE_BY=$KBUILD_BUILD_USER fi if test -z "$KBUILD_BUILD_HOST"; then - LINUX_COMPILE_HOST=`hostname` + LINUX_COMPILE_HOST=`uname -n` else LINUX_COMPILE_HOST=$KBUILD_BUILD_HOST fi -- cgit From ba452c9e996d8a4c347b32805f91abb70de5de7e Mon Sep 17 00:00:00 2001 From: Toke Høiland-Jørgensen Date: Tue, 20 Oct 2020 23:25:56 +0200 Subject: bpf: Fix bpf_redirect_neigh helper api to support supplying nexthop MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on the discussion in [0], update the bpf_redirect_neigh() helper to accept an optional parameter specifying the nexthop information. This makes it possible to combine bpf_fib_lookup() and bpf_redirect_neigh() without incurring a duplicate FIB lookup - since the FIB lookup helper will return the nexthop information even if no neighbour is present, this can simply be passed on to bpf_redirect_neigh() if bpf_fib_lookup() returns BPF_FIB_LKUP_RET_NO_NEIGH. Thus fix & extend it before helper API is frozen. [0] https://lore.kernel.org/bpf/393e17fc-d187-3a8d-2f0d-a627c7c63fca@iogearbox.net/ Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Daniel Borkmann Reviewed-by: David Ahern Link: https://lore.kernel.org/bpf/160322915615.32199.1187570224032024535.stgit@toke.dk --- scripts/bpf_helpers_doc.py | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/bpf_helpers_doc.py b/scripts/bpf_helpers_doc.py index 7d86fdd190be..6769caae142f 100755 --- a/scripts/bpf_helpers_doc.py +++ b/scripts/bpf_helpers_doc.py @@ -453,6 +453,7 @@ class PrinterHelpers(Printer): 'struct bpf_perf_event_data', 'struct bpf_perf_event_value', 'struct bpf_pidns_info', + 'struct bpf_redir_neigh', 'struct bpf_sk_lookup', 'struct bpf_sock', 'struct bpf_sock_addr', -- cgit From 0f7f635b06483f5204a70417ef6830af68185951 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Sat, 24 Oct 2020 16:59:04 -0700 Subject: checkpatch: enable GIT_DIR environment use to set git repository location If set, use the environment variable GIT_DIR to change the default .git location of the kernel git tree. If GIT_DIR is unset, keep using the current ".git" default. Link: https://lkml.kernel.org/r/c5e23b45562373d632fccb8bc04e563abba4dd1d.camel@perches.com Signed-off-by: Joe Perches Tested-by: Geert Uytterhoeven Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 4223a9ac7059..fab38b493cef 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -43,6 +43,8 @@ my $list_types = 0; my $fix = 0; my $fix_inplace = 0; my $root; +my $gitroot = $ENV{'GIT_DIR'}; +$gitroot = ".git" if !defined($gitroot); my %debug; my %camelcase = (); my %use_type = (); @@ -908,7 +910,7 @@ sub is_maintained_obsolete { sub is_SPDX_License_valid { my ($license) = @_; - return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$root/.git")); + return 1 if (!$tree || which("python") eq "" || !(-e "$root/scripts/spdxcheck.py") || !(-e "$gitroot")); my $root_path = abs_path($root); my $status = `cd "$root_path"; echo "$license" | python scripts/spdxcheck.py -`; @@ -926,7 +928,7 @@ sub seed_camelcase_includes { $camelcase_seeded = 1; - if (-e ".git") { + if (-e "$gitroot") { my $git_last_include_commit = `${git_command} log --no-merges --pretty=format:"%h%n" -1 -- include`; chomp $git_last_include_commit; $camelcase_cache = ".checkpatch-camelcase.git.$git_last_include_commit"; @@ -954,7 +956,7 @@ sub seed_camelcase_includes { return; } - if (-e ".git") { + if (-e "$gitroot") { $files = `${git_command} ls-files "include/*.h"`; @include_files = split('\n', $files); } @@ -987,7 +989,7 @@ sub git_is_single_file { sub git_commit_info { my ($commit, $id, $desc) = @_; - return ($id, $desc) if ((which("git") eq "") || !(-e ".git")); + return ($id, $desc) if ((which("git") eq "") || !(-e "$gitroot")); my $output = `${git_command} log --no-color --format='%H %s' -1 $commit 2>&1`; $output =~ s/^\s*//gm; @@ -1026,7 +1028,7 @@ my $fixlinenr = -1; # If input is git commits, extract all commits from the commit expressions. # For example, HEAD-3 means we need check 'HEAD, HEAD~1, HEAD~2'. -die "$P: No git repository found\n" if ($git && !-e ".git"); +die "$P: No git repository found\n" if ($git && !-e "$gitroot"); if ($git) { my @commits = (); -- cgit From 33def8498fdde180023444b08e12b72a9efed41d Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 21 Oct 2020 19:36:07 -0700 Subject: treewide: Convert macro and uses of __section(foo) to __section("foo") Use a more generic form for __section that requires quotes to avoid complications with clang and gcc differences. Remove the quote operator # from compiler_attributes.h __section macro. Convert all unquoted __section(foo) uses to quoted __section("foo"). Also convert __attribute__((section("foo"))) uses to __section("foo") even if the __attribute__ has multiple list entry forms. Conversion done using the script at: https://lore.kernel.org/lkml/75393e5ddc272dc7403de74d645e6c6e0f4e70eb.camel@perches.com/2-convert_section.pl Signed-off-by: Joe Perches Reviewed-by: Nick Desaulniers Reviewed-by: Miguel Ojeda Signed-off-by: Linus Torvalds --- scripts/mod/modpost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 69341b36f271..f882ce0d9327 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -2254,7 +2254,7 @@ static void add_header(struct buffer *b, struct module *mod) buf_printf(b, "MODULE_INFO(name, KBUILD_MODNAME);\n"); buf_printf(b, "\n"); buf_printf(b, "__visible struct module __this_module\n"); - buf_printf(b, "__section(.gnu.linkonce.this_module) = {\n"); + buf_printf(b, "__section(\".gnu.linkonce.this_module\") = {\n"); buf_printf(b, "\t.name = KBUILD_MODNAME,\n"); if (mod->has_init) buf_printf(b, "\t.init = init_module,\n"); @@ -2308,7 +2308,7 @@ static int add_versions(struct buffer *b, struct module *mod) buf_printf(b, "\n"); buf_printf(b, "static const struct modversion_info ____versions[]\n"); - buf_printf(b, "__used __section(__versions) = {\n"); + buf_printf(b, "__used __section(\"__versions\") = {\n"); for (s = mod->unres; s; s = s->next) { if (!s->module) -- cgit From 6b80975c6308b5dc93b270a2903a314d896974c4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 27 Oct 2020 11:20:36 +0100 Subject: scripts: kernel-doc: fix typedef parsing The include/linux/genalloc.h file defined this typedef: typedef unsigned long (*genpool_algo_t)(unsigned long *map,unsigned long size,unsigned long start,unsigned int nr,void *data, struct gen_pool *pool, unsigned long start_addr); Because it has a type composite of two words (unsigned long), the parser gets the typedef name wrong: .. c:macro:: long **Typedef**: Allocation callback function type definition Fix the regex in order to accept composite types when defining a typedef for a function pointer. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/328e8018041cc44f7a1684e57f8d111230761c4f.1603792384.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index c8f6b11d5da1..c7c9f1e8428d 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1434,13 +1434,14 @@ sub dump_typedef($$) { $x =~ s@/\*.*?\*/@@gos; # strip comments. # Parse function prototypes - if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || - $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { + if ($x =~ /typedef((?:\s+[\w\*]+){1,8})\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ || + $x =~ /typedef((?:\s+[\w\*]+\s+){1,8})\s*\*?(\w\S+)\s*\s*\((.*)\);/) { # Function typedefs $return_type = $1; $declaration_name = $2; my $args = $3; + $return_type =~ s/^\s+//; create_parameterlist($args, ',', $file, $declaration_name); -- cgit From 7efc6c4295f5489e25eaef6d6fb6ceb6a6e238d0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 27 Oct 2020 11:20:37 +0100 Subject: scripts: kernel-doc: split typedef complex regex The typedef regex for function prototypes are very complex. Split them into 3 separate regex and then join them using qr. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/3a4af999a0d62d4ab9dfae1cdefdfcad93383356.1603792384.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index c7c9f1e8428d..cf71897df36d 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1427,17 +1427,21 @@ sub dump_enum($$) { } } +my $typedef_type = qr { ((?:\s+[\w\*]+){1,8})\s* }x; +my $typedef_ident = qr { \*?\s*(\w\S+)\s* }x; +my $typedef_args = qr { \s*\((.*)\); }x; + +my $typedef1 = qr { typedef$typedef_type\($typedef_ident\)$typedef_args }x; +my $typedef2 = qr { typedef$typedef_type$typedef_ident$typedef_args }x; + sub dump_typedef($$) { my $x = shift; my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. - # Parse function prototypes - if ($x =~ /typedef((?:\s+[\w\*]+){1,8})\s*\(\*?\s*(\w\S+)\s*\)\s*\((.*)\);/ || - $x =~ /typedef((?:\s+[\w\*]+\s+){1,8})\s*\*?(\w\S+)\s*\s*\((.*)\);/) { - - # Function typedefs + # Parse function typedef prototypes + if ($x =~ $typedef1 || $x =~ $typedef2) { $return_type = $1; $declaration_name = $2; my $args = $3; -- cgit From 72b97d0b911872ba36a5742b7d790b6b165e11d8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 27 Oct 2020 10:51:05 +0100 Subject: scripts: kernel-doc: use :c:union when needed Sphinx C domain code after 3.2.1 will start complaning if :c:struct would be used for an union type: .../Documentation/gpu/drm-kms-helpers:352: ../drivers/video/hdmi.c:851: WARNING: C 'identifier' cross-reference uses wrong tag: reference name is 'union hdmi_infoframe' but found name is 'struct hdmi_infoframe'. Full reference name is 'union hdmi_infoframe'. Full found name is 'struct hdmi_infoframe'. So, let's address this issue too in advance, in order to avoid future issues. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/6e4ec3eec914df62389a299797a3880ae4490f35.1603791716.git.mchehab+huawei@kernel.org Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index cf71897df36d..f699cf05d409 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1092,7 +1092,11 @@ sub output_struct_rst(%) { print "\n\n.. c:type:: " . $name . "\n\n"; } else { my $name = $args{'struct'}; - print "\n\n.. c:struct:: " . $name . "\n\n"; + if ($args{'type'} eq 'union') { + print "\n\n.. c:union:: " . $name . "\n\n"; + } else { + print "\n\n.. c:struct:: " . $name . "\n\n"; + } } print_lineno($declaration_start_line); $lineprefix = " "; -- cgit From 11ce90a45d380f09213f128b76d68bb525186ad8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:20 +0100 Subject: scripts: get_abi.pl: change script to allow parsing in ReST mode Right now, several ABI files won't parse as ReST, as they contain severe violations to the spec, with makes the script to crash. So, the code has a sanity logic with escapes bad code and cleans tags that can cause Sphinx to crash. Add support for disabling this mode. Right now, as enabling rst-mode causes crash, it is disabled by default. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/34b691e3002e8987c24d851fe37640f95e506a92.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 72 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 47 insertions(+), 25 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index c738cb795514..107672cdacb3 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -12,8 +12,14 @@ my $man; my $debug; my $prefix="Documentation/ABI"; +# +# If true, assumes that the description is formatted with ReST +# +my $description_is_rst = 0; + GetOptions( "debug|d+" => \$debug, + "rst-source!" => \$description_is_rst, "dir=s" => \$prefix, 'help|?' => \$help, man => \$man @@ -137,14 +143,15 @@ sub parse_abi { next; } if ($tag eq "description") { - next if ($content =~ m/^\s*$/); - if ($content =~ m/^(\s*)(.*)/) { - my $new_content = $2; - $space = $new_tag . $sep . $1; - while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} - $space =~ s/./ /g; - $data{$what}->{$tag} .= "$new_content\n"; + # Preserve initial spaces for the first line + $content = ' ' x length($new_tag) . $sep . $content; + $content =~ s,^(\s*):,$1 ,; + if ($content =~ m/^(\s*)(.*)$/) { + $space = $1; + $content = $2; } + while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} + $data{$what}->{$tag} .= $content; } else { $data{$what}->{$tag} = $content; } @@ -160,11 +167,15 @@ sub parse_abi { if ($tag eq "description") { if (!$data{$what}->{description}) { - next if (m/^\s*\n/); + s/^($space)//; if (m/^(\s*)(.*)/) { - $space = $1; - while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} - $data{$what}->{$tag} .= "$2\n"; + my $sp = $1; + while ($sp =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} + my $content = "$sp$2"; + + $content =~ s/^($space)//; + + $data{$what}->{$tag} .= "$content"; } } else { my $content = $_; @@ -274,23 +285,27 @@ sub output_rest { print "Defined on file :ref:`$file <$fileref>`\n\n" if ($type ne "File"); my $desc = $data{$what}->{description}; - $desc =~ s/^\s+//; - - # Remove title markups from the description, as they won't work - $desc =~ s/\n[\-\*\=\^\~]+\n/\n/g; if (!($desc =~ /^\s*$/)) { - if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) { - # put everything inside a code block - $desc =~ s/\n/\n /g; - - print "::\n\n"; - print " $desc\n\n"; + if ($description_is_rst) { + print "$desc\n\n"; } else { - # Escape any special chars from description - $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g; + $desc =~ s/^\s+//; - print "$desc\n\n"; + # Remove title markups from the description, as they won't work + $desc =~ s/\n[\-\*\=\^\~]+\n/\n\n/g; + + if ($desc =~ m/\:\n/ || $desc =~ m/\n[\t ]+/ || $desc =~ m/[\x00-\x08\x0b-\x1f\x7b-\xff]/) { + # put everything inside a code block + $desc =~ s/\n/\n /g; + + print "::\n\n"; + print " $desc\n\n"; + } else { + # Escape any special chars from description + $desc =~s/([\x00-\x08\x0b-\x1f\x21-\x2a\x2d\x2f\x3c-\x40\x5c\x5e-\x60\x7b-\xff])/\\$1/g; + print "$desc\n\n"; + } } } else { print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file}); @@ -382,7 +397,7 @@ abi_book.pl - parse the Linux ABI files and produce a ReST book. =head1 SYNOPSIS -B [--debug] [--man] [--help] [--dir=] [] +B [--debug] [--man] [--help] --[(no-)rst-source] [--dir=] [] Where can be: @@ -405,6 +420,13 @@ B - validate the ABI contents Changes the location of the ABI search. By default, it uses the Documentation/ABI directory. +=item B<--rst-source> and B<--no-rst-source> + +The input file may be using ReST syntax or not. Those two options allow +selecting between a rst-compliant source ABI (--rst-source), or a +plain text that may be violating ReST spec, so it requres some escaping +logic (--no-rst-source). + =item B<--debug> Put the script in verbose mode, useful for debugging. Can be called multiple -- cgit From e9bca8918e3d409f3b575d8db5591e422506c1ea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:21 +0100 Subject: scripts: get_abi.pl: fix parsing on ReST mode When the source ABI file is using ReST notation, the script should handle whitespaces and lines with care, as otherwise the file won't be properly recognized. Address the bugs that are on such part of the script. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/5c22c54fbd0cda797b691d52c568be6d0d1079d8.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 107672cdacb3..0c403af86fd5 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -151,7 +151,8 @@ sub parse_abi { $content = $2; } while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} - $data{$what}->{$tag} .= $content; + + $data{$what}->{$tag} .= "$content\n" if ($content); } else { $data{$what}->{$tag} = $content; } @@ -166,31 +167,28 @@ sub parse_abi { } if ($tag eq "description") { + my $content = $_; + while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} if (!$data{$what}->{description}) { - s/^($space)//; - if (m/^(\s*)(.*)/) { - my $sp = $1; - while ($sp =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} - my $content = "$sp$2"; - - $content =~ s/^($space)//; - - $data{$what}->{$tag} .= "$content"; + # Preserve initial spaces for the first line + if ($content =~ m/^(\s*)(.*)$/) { + $space = $1; + $content = $2; } + + $data{$what}->{$tag} .= "$content\n" if ($content); } else { - my $content = $_; if (m/^\s*\n/) { $data{$what}->{$tag} .= $content; next; } - while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} $space = "" if (!($content =~ s/^($space)//)); - # Compress spaces with tabs - $content =~ s<^ {8}> <\t>; - $content =~ s<^ {1,7}\t> <\t>; - $content =~ s< {1,7}\t> <\t>; +# # Compress spaces with tabs +# $content =~ s<^ {8}> <\t>; +# $content =~ s<^ {1,7}\t> <\t>; +# $content =~ s< {1,7}\t> <\t>; $data{$what}->{$tag} .= $content; } next; -- cgit From 61439c4ada9fd0e4ce73aca81a71344380a3053b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:22 +0100 Subject: scripts: get_abi.pl: Allow optionally record from where a line came from The get_abi.pl reads a lot of files and can join them on a single output file. Store where each "What:" output came from, in order to be able to optionally display it. This is useful for the Sphinx extension, with can now be able to blame what ABI file has issues, and on what line the What: description with problems begin. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/befc387011c5e3c6febd285b7f27610e41c90260.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 0c403af86fd5..6a4d387ebf3b 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -10,6 +10,7 @@ use Fcntl ':mode'; my $help; my $man; my $debug; +my $enable_lineno; my $prefix="Documentation/ABI"; # @@ -19,6 +20,7 @@ my $description_is_rst = 0; GetOptions( "debug|d+" => \$debug, + "enable-lineno" => \$enable_lineno, "rst-source!" => \$description_is_rst, "dir=s" => \$prefix, 'help|?' => \$help, @@ -67,6 +69,7 @@ sub parse_abi { $data{$nametag}->{file} = $name; $data{$nametag}->{filepath} = $file; $data{$nametag}->{is_file} = 1; + $data{$nametag}->{line_no} = 1; my $type = $file; $type =~ s,.*/(.*)/.*,$1,; @@ -126,6 +129,8 @@ sub parse_abi { if ($tag ne "" && $new_tag) { $tag = $new_tag; + $data{$what}->{line_no} = $ln; + if ($new_what) { @{$data{$what}->{label}} = @labels if ($data{$nametag}->{what}); @labels = (); @@ -221,6 +226,12 @@ sub output_rest { my $file = $data{$what}->{file}; my $filepath = $data{$what}->{filepath}; + if ($enable_lineno) { + printf "#define LINENO %s%s#%s\n\n", + $prefix, $data{$what}->{file}, + $data{$what}->{line_no}; + } + my $w = $what; $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g; @@ -369,6 +380,10 @@ sub search_symbols { } } +# Ensure that the prefix will always end with a slash +# While this is not needed for find, it makes the patch nicer +# with --enable-lineno +$prefix =~ s,/?$,/,; # # Parses all ABI files located at $prefix dir @@ -395,7 +410,8 @@ abi_book.pl - parse the Linux ABI files and produce a ReST book. =head1 SYNOPSIS -B [--debug] [--man] [--help] --[(no-)rst-source] [--dir=] [] +B [--debug] [--enable-lineno] [--man] [--help] + [--(no-)rst-source] [--dir=] [] Where can be: @@ -425,6 +441,10 @@ selecting between a rst-compliant source ABI (--rst-source), or a plain text that may be violating ReST spec, so it requres some escaping logic (--no-rst-source). +=item B<--enable-lineno> + +Enable output of #define LINENO lines. + =item B<--debug> Put the script in verbose mode, useful for debugging. Can be called multiple -- cgit From f82a8a74ea81df22b1641ee56cf7195cc2a1bd0b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:23 +0100 Subject: scripts: get_abi.pl: improve its parser to better catch up indentation The original parser for indentation were relying on having just one description for each "what". However, that's not the case: there are a number of ABI symbols that got defined multiple times. Improve the parser for it to better handle descriptions if entries are duplicated. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/eb458bb30be0e5a89192d6057b2e8a7e910dbcb8.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 42 +++++++++++++++++++----------------------- 1 file changed, 19 insertions(+), 23 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 6a4d387ebf3b..bd018eb3815b 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -147,17 +147,19 @@ sub parse_abi { parse_error($file, $ln, "'What:' should come first:", $_); next; } - if ($tag eq "description") { - # Preserve initial spaces for the first line + if ($new_tag eq "description") { + $sep =~ s,:, ,; $content = ' ' x length($new_tag) . $sep . $content; - $content =~ s,^(\s*):,$1 ,; - if ($content =~ m/^(\s*)(.*)$/) { + while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} + if ($content =~ m/^(\s*)(\S.*)$/) { + # Preserve initial spaces for the first line $space = $1; - $content = $2; + $content = "$2\n"; + $data{$what}->{$tag} .= $content; + } else { + undef($space); } - while ($space =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} - $data{$what}->{$tag} .= "$content\n" if ($content); } else { $data{$what}->{$tag} = $content; } @@ -174,28 +176,22 @@ sub parse_abi { if ($tag eq "description") { my $content = $_; while ($content =~ s/\t+/' ' x (length($&) * 8 - length($`) % 8)/e) {} - if (!$data{$what}->{description}) { + if (m/^\s*\n/) { + $data{$what}->{$tag} .= "\n"; + next; + } + + if (!defined($space)) { # Preserve initial spaces for the first line - if ($content =~ m/^(\s*)(.*)$/) { + if ($content =~ m/^(\s*)(\S.*)$/) { $space = $1; - $content = $2; + $content = "$2\n"; } - - $data{$what}->{$tag} .= "$content\n" if ($content); } else { - if (m/^\s*\n/) { - $data{$what}->{$tag} .= $content; - next; - } - $space = "" if (!($content =~ s/^($space)//)); - -# # Compress spaces with tabs -# $content =~ s<^ {8}> <\t>; -# $content =~ s<^ {1,7}\t> <\t>; -# $content =~ s< {1,7}\t> <\t>; - $data{$what}->{$tag} .= $content; } + $data{$what}->{$tag} .= $content; + next; } if (m/^\s*(.*)/) { -- cgit From 234948bf3d27e473ac8043d20dacda146beeb0cb Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:24 +0100 Subject: scripts: get_abi.pl: cleanup ABI cross-reference logic Right now, the cross-references are generated on a single step, when doing ReST output. While this is nice optimization, it prevents auto-creating cross-references for ABI symbols. So, split it into a separate logic. While here, turn on Perl warnings, as it helps to debug problems inside the script. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/dbc97c8c2dfd877921f058134c35b2a8b1f8414b.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 147 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 83 insertions(+), 64 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index bd018eb3815b..d134cc1692ee 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -2,15 +2,16 @@ # SPDX-License-Identifier: GPL-2.0 use strict; +use warnings; use Pod::Usage; use Getopt::Long; use File::Find; use Fcntl ':mode'; -my $help; -my $man; -my $debug; -my $enable_lineno; +my $help = 0; +my $man = 0; +my $debug = 0; +my $enable_lineno = 0; my $prefix="Documentation/ABI"; # @@ -40,6 +41,7 @@ pod2usage(2) if ($cmd eq "search" && !$arg); require Data::Dumper if ($debug); my %data; +my %symbols; # # Displays an error message, printing file name and line @@ -76,12 +78,12 @@ sub parse_abi { my $what; my $new_what; - my $tag; + my $tag = ""; my $ln; my $xrefs; my $space; my @labels; - my $label; + my $label = ""; print STDERR "Opening $file\n" if ($debug > 1); open IN, $file; @@ -110,10 +112,18 @@ sub parse_abi { if ($new_tag =~ m/what/) { $space = ""; + $content =~ s/[,.;]$//; + if ($tag =~ m/what/) { $what .= ", " . $content; } else { - parse_error($file, $ln, "What '$what' doesn't have a description", "") if ($what && !$data{$what}->{description}); + if ($what) { + parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description}); + + foreach my $w(split /, /, $what) { + $symbols{$w} = $what; + }; + } $what = $content; $label = $content; @@ -122,7 +132,7 @@ sub parse_abi { push @labels, [($content, $label)]; $tag = $new_tag; - push @{$data{$nametag}->{xrefs}}, [($content, $label)] if ($data{$nametag}->{what}); + push @{$data{$nametag}->{symbols}}, $content if ($data{$nametag}->{what}); next; } @@ -132,7 +142,7 @@ sub parse_abi { $data{$what}->{line_no} = $ln; if ($new_what) { - @{$data{$what}->{label}} = @labels if ($data{$nametag}->{what}); + @{$data{$what}->{label_list}} = @labels if ($data{$nametag}->{what}); @labels = (); $label = ""; $new_what = 0; @@ -203,36 +213,24 @@ sub parse_abi { # Everything else is error parse_error($file, $ln, "Unexpected line:", $_); } - $data{$nametag}->{description} =~ s/^\n+//; + $data{$nametag}->{description} =~ s/^\n+// if ($data{$nametag}->{description}); + if ($what) { + parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description}); + + foreach my $w(split /, /,$what) { + $symbols{$w} = $what; + }; + } close IN; } -# -# Outputs the book on ReST format -# - -my %labels; - -sub output_rest { - foreach my $what (sort { - ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") || - $a cmp $b - } keys %data) { - my $type = $data{$what}->{type}; - my $file = $data{$what}->{file}; - my $filepath = $data{$what}->{filepath}; - - if ($enable_lineno) { - printf "#define LINENO %s%s#%s\n\n", - $prefix, $data{$what}->{file}, - $data{$what}->{line_no}; - } - - my $w = $what; - $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g; +sub create_labels { + my %labels; + foreach my $what (keys %data) { + next if ($data{$what}->{file} eq "File"); - foreach my $p (@{$data{$what}->{label}}) { + foreach my $p (@{$data{$what}->{label_list}}) { my ($content, $label) = @{$p}; $label = "abi_" . $label . " "; $label =~ tr/A-Z/a-z/; @@ -249,16 +247,39 @@ sub output_rest { } $labels{$label} = 1; - $data{$what}->{label} .= $label; - - printf ".. _%s:\n\n", $label; + $data{$what}->{label} = $label; # only one label is enough last; } + } +} + +# +# Outputs the book on ReST format +# + +sub output_rest { + create_labels(); + + foreach my $what (sort { + ($data{$a}->{type} eq "File") cmp ($data{$b}->{type} eq "File") || + $a cmp $b + } keys %data) { + my $type = $data{$what}->{type}; + my $file = $data{$what}->{file}; + my $filepath = $data{$what}->{filepath}; + + if ($enable_lineno) { + printf "#define LINENO %s%s#%s\n\n", + $prefix, $data{$what}->{file}, + $data{$what}->{line_no}; + } + my $w = $what; + $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g; - $filepath =~ s,.*/(.*/.*),\1,;; + $filepath =~ s,.*/(.*/.*),$1,;; $filepath =~ s,[/\-],_,g;; my $fileref = "abi_file_".$filepath; @@ -269,8 +290,9 @@ sub output_rest { print ".. _$fileref:\n\n"; print "$w\n$bar\n\n"; } else { - my @names = split /\s*,\s*/,$w; + printf ".. _%s:\n\n", $data{$what}->{label}; + my @names = split /, /,$w; my $len = 0; foreach my $name (@names) { @@ -284,12 +306,13 @@ sub output_rest { printf "| %s", $name . " " x ($len - length($name)) . " |\n"; print "+-" . "-" x $len . "-+\n"; } - print "\n"; - } - print "Defined on file :ref:`$file <$fileref>`\n\n" if ($type ne "File"); + print "\nDefined on file :ref:`$file <$fileref>`\n\n"; + } - my $desc = $data{$what}->{description}; + my $desc = ""; + $desc = $data{$what}->{description} if (defined($data{$what}->{description})); + $desc =~ s/\s+$/\n/; if (!($desc =~ /^\s*$/)) { if ($description_is_rst) { @@ -316,18 +339,11 @@ sub output_rest { print "DESCRIPTION MISSING for $what\n\n" if (!$data{$what}->{is_file}); } - if ($data{$what}->{xrefs}) { + if ($data{$what}->{symbols}) { printf "Has the following ABI:\n\n"; - foreach my $p(@{$data{$what}->{xrefs}}) { - my ($content, $label) = @{$p}; - $label = "abi_" . $label . " "; - $label =~ tr/A-Z/a-z/; - - # Convert special chars to "_" - $label =~s/([\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\xff])/_/g; - $label =~ s,_+,_,g; - $label =~ s,_$,,; + foreach my $content(@{$data{$what}->{symbols}}) { + my $label = $data{$symbols{$content}}->{label}; # Escape special chars from content $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g; @@ -355,17 +371,20 @@ sub search_symbols { print "\n$what\n$bar\n\n"; - my $kernelversion = $data{$what}->{kernelversion}; - my $contact = $data{$what}->{contact}; - my $users = $data{$what}->{users}; - my $date = $data{$what}->{date}; - my $desc = $data{$what}->{description}; - $kernelversion =~ s/^\s+//; - $contact =~ s/^\s+//; - $users =~ s/^\s+//; - $users =~ s/\n//g; - $date =~ s/^\s+//; - $desc =~ s/^\s+//; + my $kernelversion = $data{$what}->{kernelversion} if (defined($data{$what}->{kernelversion})); + my $contact = $data{$what}->{contact} if (defined($data{$what}->{contact})); + my $users = $data{$what}->{users} if (defined($data{$what}->{users})); + my $date = $data{$what}->{date} if (defined($data{$what}->{date})); + my $desc = $data{$what}->{description} if (defined($data{$what}->{description})); + + $kernelversion =~ s/^\s+// if ($kernelversion); + $contact =~ s/^\s+// if ($contact); + if ($users) { + $users =~ s/^\s+//; + $users =~ s/\n//g; + } + $date =~ s/^\s+// if ($date); + $desc =~ s/^\s+// if ($desc); printf "Kernel version:\t\t%s\n", $kernelversion if ($kernelversion); printf "Date:\t\t\t%s\n", $date if ($date); -- cgit From c7ba333426bcf4d7330d3a0a768e8048a82e4cc7 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:25 +0100 Subject: scripts: get_abi.pl: detect duplicated ABI definitions The ABI should define only once each What. The current script logic assumes that. However, that's not the case, currently: there are several symbols with a generic definition, and per-driver ones. Better handle such cases, by preserving the cross-references with the files that define them, but also track such cases, producing warnings, as they should be fixed. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/d7a73b8b3aae5b2bff9279996ff9ca4cdfc89196.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 85 +++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 27 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index d134cc1692ee..1d1408fad130 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -114,6 +114,8 @@ sub parse_abi { $space = ""; $content =~ s/[,.;]$//; + push @{$symbols{$content}->{file}}, " $file:" . ($ln - 1); + if ($tag =~ m/what/) { $what .= ", " . $content; } else { @@ -121,7 +123,7 @@ sub parse_abi { parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description}); foreach my $w(split /, /, $what) { - $symbols{$w} = $what; + $symbols{$w}->{xref} = $what; }; } @@ -139,8 +141,6 @@ sub parse_abi { if ($tag ne "" && $new_tag) { $tag = $new_tag; - $data{$what}->{line_no} = $ln; - if ($new_what) { @{$data{$what}->{label_list}} = @labels if ($data{$nametag}->{what}); @labels = (); @@ -148,9 +148,19 @@ sub parse_abi { $new_what = 0; $data{$what}->{type} = $type; - $data{$what}->{file} = $name; - $data{$what}->{filepath} = $file; + if (!defined($data{$what}->{file})) { + $data{$what}->{file} = $name; + $data{$what}->{filepath} = $file; + } else { + if ($name ne $data{$what}->{file}) { + $data{$what}->{file} .= " " . $name; + $data{$what}->{filepath} .= " " . $file; + } + } print STDERR "\twhat: $what\n" if ($debug > 1); + $data{$what}->{line_no} = $ln; + } else { + $data{$what}->{line_no} = $ln if (!defined($data{$what}->{line_no})); } if (!$what) { @@ -218,7 +228,7 @@ sub parse_abi { parse_error($file, $ln, "What '$what' doesn't have a description", "") if (!$data{$what}->{description}); foreach my $w(split /, /,$what) { - $symbols{$w} = $what; + $symbols{$w}->{xref} = $what; }; } close IN; @@ -267,29 +277,20 @@ sub output_rest { $a cmp $b } keys %data) { my $type = $data{$what}->{type}; - my $file = $data{$what}->{file}; - my $filepath = $data{$what}->{filepath}; + + my @file = split / /, $data{$what}->{file}; + my @filepath = split / /, $data{$what}->{filepath}; if ($enable_lineno) { printf "#define LINENO %s%s#%s\n\n", - $prefix, $data{$what}->{file}, + $prefix, $file[0], $data{$what}->{line_no}; } my $w = $what; $w =~ s/([\(\)\_\-\*\=\^\~\\])/\\$1/g; - $filepath =~ s,.*/(.*/.*),$1,;; - $filepath =~ s,[/\-],_,g;; - my $fileref = "abi_file_".$filepath; - - if ($type eq "File") { - my $bar = $w; - $bar =~ s/./-/g; - - print ".. _$fileref:\n\n"; - print "$w\n$bar\n\n"; - } else { + if ($type ne "File") { printf ".. _%s:\n\n", $data{$what}->{label}; my @names = split /, /,$w; @@ -307,7 +308,26 @@ sub output_rest { print "+-" . "-" x $len . "-+\n"; } - print "\nDefined on file :ref:`$file <$fileref>`\n\n"; + print "\n"; + } + + for (my $i = 0; $i < scalar(@filepath); $i++) { + my $path = $filepath[$i]; + my $f = $file[$i]; + + $path =~ s,.*/(.*/.*),$1,;; + $path =~ s,[/\-],_,g;; + my $fileref = "abi_file_".$path; + + if ($type eq "File") { + my $bar = $w; + $bar =~ s/./-/g; + + print ".. _$fileref:\n\n"; + print "$w\n$bar\n\n"; + } else { + print "Defined on file :ref:`$f <$fileref>`\n\n"; + } } my $desc = ""; @@ -343,7 +363,7 @@ sub output_rest { printf "Has the following ABI:\n\n"; foreach my $content(@{$data{$what}->{symbols}}) { - my $label = $data{$symbols{$content}}->{label}; + my $label = $data{$symbols{$content}->{xref}}->{label}; # Escape special chars from content $content =~s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g; @@ -390,7 +410,7 @@ sub search_symbols { printf "Date:\t\t\t%s\n", $date if ($date); printf "Contact:\t\t%s\n", $contact if ($contact); printf "Users:\t\t\t%s\n", $users if ($users); - print "Defined on file:\t$file\n\n"; + print "Defined on file(s):\t$file\n\n"; print "Description:\n\n$desc"; } } @@ -410,12 +430,23 @@ print STDERR Data::Dumper->Dump([\%data], [qw(*data)]) if ($debug); # # Handles the command # -if ($cmd eq "rest") { - output_rest; -} elsif ($cmd eq "search") { +if ($cmd eq "search") { search_symbols; -} +} else { + if ($cmd eq "rest") { + output_rest; + } + + # Warn about duplicated ABI entries + foreach my $what(sort keys %symbols) { + my @files = @{$symbols{$what}->{file}}; + + next if (scalar(@files) == 1); + printf STDERR "Warning: $what is defined %d times: @files\n", + scalar(@files); + } +} __END__ -- cgit From a16ab14eb7a92bfebf71a8a9185c749de86851f4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:26 +0100 Subject: scripts: get_abi.pl: output users in ReST format Right now, the script only outputs Users on search. Print it also in ReST format. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/83def2a692c4c678f21ee6e76b66a54d2be1e796.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 1d1408fad130..e5a5588a8639 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -371,6 +371,14 @@ sub output_rest { print "- :ref:`$content <$label>`\n\n"; } } + + if (defined($data{$what}->{users})) { + my $users = $data{$what}->{users}; + + $users =~ s/\n/\n\t/g; + printf "Users:\n\t%s\n\n", $users if ($users ne ""); + } + } } -- cgit From a4ea67bc65a15dadcda747c7f9d7b0e76e7c842a Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:27 +0100 Subject: scripts: get_abi.pl: prevent duplicated file names The same filename may exist on multiple directories within ABI. Create separate entries at the internal database for each of them. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/ef760f68f54e132c4be52f0027189b4ba31554ec.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index e5a5588a8639..5612f019fae0 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -65,7 +65,10 @@ sub parse_abi { my $name = $file; $name =~ s,.*/,,; - my $nametag = "File $name"; + my $fn = $file; + $fn =~ s,Documentation/ABI/,,; + + my $nametag = "File $fn"; $data{$nametag}->{what} = "File $name"; $data{$nametag}->{type} = "File"; $data{$nametag}->{file} = $name; @@ -320,16 +323,18 @@ sub output_rest { my $fileref = "abi_file_".$path; if ($type eq "File") { - my $bar = $w; - $bar =~ s/./-/g; - print ".. _$fileref:\n\n"; - print "$w\n$bar\n\n"; } else { print "Defined on file :ref:`$f <$fileref>`\n\n"; } } + if ($type eq "File") { + my $bar = $w; + $bar =~ s/./-/g; + print "$w\n$bar\n\n"; + } + my $desc = ""; $desc = $data{$what}->{description} if (defined($data{$what}->{description})); $desc =~ s/\s+$/\n/; -- cgit From c01d62d3fecb27f4c76a0e14b7e5afc15497a74b Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:28 +0100 Subject: scripts: get_abi.pl: use bold font for ABI definitions As we're using tables, let's distinguish the ones used by ABI by using a bold font. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/9ed645c2519169817379c1df5b8cf03828e92520.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 1 + 1 file changed, 1 insertion(+) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 5612f019fae0..12a23f9a2f86 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -300,6 +300,7 @@ sub output_rest { my $len = 0; foreach my $name (@names) { + $name = "**$name**"; $len = length($name) if (length($name) > $len); } -- cgit From 55e5414f2f8e31a8abbd95c43c24b69e83560a20 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:29 +0100 Subject: scripts: get_abi.pl: auto-generate cross references There are several cross-references that can be automatically generated: - References to .rst files inside Documentation/ - References to other ABI files; - References to ABI symbols at /sys/*. Add a logic to automatically parse them and convert into cross references. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/abe756d4f94fb6ffcc3dd3902a766c7c3990ea89.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index 12a23f9a2f86..ff4f9f82ecad 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -3,6 +3,7 @@ use strict; use warnings; +use utf8; use Pod::Usage; use Getopt::Long; use File::Find; @@ -272,6 +273,9 @@ sub create_labels { # Outputs the book on ReST format # +# \b doesn't work well with paths. So, we need to define something else +my $bondary = qr { (?"; + $desc =~ s,\bDocumentation/ABI/$f\b,:ref:`$xref`,g; + } + + @matches = $desc =~ m,$bondary(/sys/[^\s\.\,\;\:\*\s\`\'\(\)]+)$bondary,; + + foreach my $s (@matches) { + if (defined($data{$s}) && defined($data{$s}->{label})) { + my $xref = $s; + + $xref =~ s/([\x00-\x1f\x21-\x2f\x3a-\x40\x7b-\xff])/\\$1/g; + $xref = ":ref:`$xref <" . $data{$s}->{label} . ">`"; + + $desc =~ s,$bondary$s$bondary,$xref,g; + } + } + print "$desc\n\n"; } else { $desc =~ s/^\s+//; -- cgit From 75442fb0ccaacddf1654a5304401a9f556c61004 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:45 +0100 Subject: docs: Kconfig/Makefile: add a check for broken ABI files The files under Documentation/ABI should follow the syntax as defined at Documentation/ABI/README. Allow checking if they're following the syntax by running the ABI parser script on COMPILE_TEST. With that, when there's a problem with a file under Documentation/ABI, it would produce a warning like: Warning: file ./Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats#14: What '/sys/bus/pci/devices//aer_stats/aer_rootport_total_err_cor' doesn't have a description Warning: file ./Documentation/ABI/testing/sysfs-bus-pci-devices-aer_stats#21: What '/sys/bus/pci/devices//aer_stats/aer_rootport_total_err_fatal' doesn't have a description Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/57a38de85cb4b548857207cf1fc1bf1ee08613c9.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index ff4f9f82ecad..f6adf4b38a2b 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -50,7 +50,15 @@ my %symbols; sub parse_error($$$$) { my ($file, $ln, $msg, $data) = @_; - print STDERR "file $file#$ln: $msg at\n\t$data"; + $data =~ s/\s+$/\n/; + + print STDERR "Warning: file $file#$ln:\n\t$msg"; + + if ($data ne "") { + print STDERR ". Line\n\t\t$data"; + } else { + print STDERR "\n"; + } } # @@ -110,7 +118,7 @@ sub parse_abi { # Invalid, but it is a common mistake if ($new_tag eq "where") { - parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", $_); + parse_error($file, $ln, "tag 'Where' is invalid. Should be 'What:' instead", ""); $new_tag = "what"; } @@ -225,7 +233,7 @@ sub parse_abi { } # Everything else is error - parse_error($file, $ln, "Unexpected line:", $_); + parse_error($file, $ln, "Unexpected content", $_); } $data{$nametag}->{description} =~ s/^\n+// if ($data{$nametag}->{description}); if ($what) { -- cgit From 54a19b4d3fe0fa0a31b46cd60951e8177cac25fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:50 +0100 Subject: docs: ABI: cleanup several ABI documents There are some ABI documents that, while they don't generate any warnings, they have issues when parsed by get_abi.pl script on its output result. Address them, in order to provide a clean output. Reviewed-by: Tom Rix # for fpga-manager Reviewed-By: Kajol Jain # for sysfs-bus-event_source-devices-hv_gpci and sysfs-bus-event_source-devices-hv_24x7 Acked-by: Jonathan Cameron #for IIO Acked-by: Oded Gabbay # for Habanalabs Acked-by: Vaibhav Jain # for sysfs-bus-papr-pmem Acked-by: Cezary Rojewski # for catpt Acked-by: Suzuki K Poulose Acked-by: Ilya Dryomov # for rbd Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/5bc78e5b68ed1e9e39135173857cb2e753be868f.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 2 -- 1 file changed, 2 deletions(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index f6adf4b38a2b..d09bb37dd236 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -316,8 +316,6 @@ sub output_rest { $len = length($name) if (length($name) > $len); } - print "What:\n\n"; - print "+-" . "-" x $len . "-+\n"; foreach my $name (@names) { printf "| %s", $name . " " x ($len - length($name)) . " |\n"; -- cgit From 2fcce37a3d2f2f3d7fa36aad2b71cbaca135ffd4 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 30 Oct 2020 08:40:58 +0100 Subject: scripts: get_abi.pl: assume ReST format by default All ABI files are now compatible with ReST format. So, change the script default to assume that the ABI source files are compatible with ReST. Acked-by: Jonathan Corbet Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/4b0af257010570e0e917d82498e42992bec5e173.1604042072.git.mchehab+huawei@kernel.org Signed-off-by: Greg Kroah-Hartman --- scripts/get_abi.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/get_abi.pl b/scripts/get_abi.pl index d09bb37dd236..2cb592f8eba4 100755 --- a/scripts/get_abi.pl +++ b/scripts/get_abi.pl @@ -18,7 +18,7 @@ my $prefix="Documentation/ABI"; # # If true, assumes that the description is formatted with ReST # -my $description_is_rst = 0; +my $description_is_rst = 1; GetOptions( "debug|d+" => \$debug, -- cgit