From 7f2084fa55e6cb61f61b4224d4a8bafaeee55f9f Mon Sep 17 00:00:00 2001 From: Al Viro Date: Fri, 15 Jan 2016 14:01:22 -0500 Subject: [kbuild] handle exports in lib-y objects reliably Collect the symbols exported by anything that goes into lib.a and add an empty object (lib-exports.o) with explicit undefs for each of those to obj-y. That allows to relax the rules regarding the use of exports in lib-* objects - right now an object with export can be in lib-* only if we are guaranteed that there always will be users in built-in parts of the tree, otherwise it needs to be in obj-*. As the result, we have an unholy mix of lib- and obj- in lib/Makefile and (especially) in arch/*/lib/Makefile. Moreover, a change in generic part of the kernel can lead to mysteriously missing exports on some configs. With this change we don't have to worry about that anymore. One side effect is that built-in.o now pulls everything with exports from the corresponding lib.a (if such exists). That's exactly what we want for linking vmlinux and fortunately it's almost the only thing built-in.o is used in. arch/ia64/hp/sim/boot/bootloader is the only exception and it's easy to get rid of now - just turn everything in arch/ia64/lib into lib-* and don't bother with arch/ia64/lib/built-in.o anymore. [AV: stylistic fix from Michal folded in] Acked-by: Michal Marek Signed-off-by: Al Viro --- scripts/Makefile.build | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'scripts') diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 11602e5efb3b..cd9bf22bb027 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -81,6 +81,7 @@ endif ifneq ($(strip $(lib-y) $(lib-m) $(lib-)),) lib-target := $(obj)/lib.a +obj-y += $(obj)/lib-ksyms.o endif ifneq ($(strip $(obj-y) $(obj-m) $(obj-) $(subdir-m) $(lib-target)),) @@ -395,6 +396,25 @@ $(lib-target): $(lib-y) FORCE $(call if_changed,link_l_target) targets += $(lib-target) + +dummy-object = $(obj)/.lib_exports.o +ksyms-lds = $(dot-target).lds +ifdef CONFIG_HAVE_UNDERSCORE_SYMBOL_PREFIX +ref_prefix = EXTERN(_ +else +ref_prefix = EXTERN( +endif + +quiet_cmd_export_list = EXPORTS $@ +cmd_export_list = $(OBJDUMP) -h $< | \ + sed -ne '/___ksymtab/{s/.*+/$(ref_prefix)/;s/ .*/)/;p}' >$(ksyms-lds);\ + rm -f $(dummy-object);\ + $(AR) rcs$(KBUILD_ARFLAGS) $(dummy-object);\ + $(LD) $(ld_flags) -r -o $@ -T $(ksyms-lds) $(dummy-object);\ + rm $(dummy-object) $(ksyms-lds) + +$(obj)/lib-ksyms.o: $(lib-target) FORCE + $(call if_changed,export_list) endif # -- cgit v1.2.3 From 4c73c0882b34d0383ff417e2d66c127f848cfe06 Mon Sep 17 00:00:00 2001 From: Andrew Donnellan Date: Tue, 5 Jul 2016 17:47:37 +1000 Subject: checkkconfigsymbols.py: add --no-color option, don't print color to non-TTY Only print the ANSI colour escape codes if stdout is a TTY. Useful if redirecting output to a file or piping to another script. Also add a new option, --no-color, if the user wants to disable colour output for whatever reason. Signed-off-by: Andrew Donnellan Acked-by: Valentin Rothberg Signed-off-by: Greg Kroah-Hartman --- scripts/checkkconfigsymbols.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'scripts') diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index df643f60bb41..b140fc9018b1 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -82,6 +82,11 @@ def parse_options(): default=False, help="Reset current Git tree even when it's dirty.") + parser.add_option('', '--no-color', dest='color', action='store_false', + default=True, + help="Don't print colored output. Default when not " + "outputting to a terminal.") + (opts, _) = parser.parse_args() if opts.commit and opts.diff: @@ -116,6 +121,9 @@ def main(): """Main function of this module.""" opts = parse_options() + global color + color = opts.color and sys.stdout.isatty() + if opts.sim and not opts.commit and not opts.diff: sims = find_sims(opts.sim, opts.ignore) if sims: @@ -202,14 +210,14 @@ def yel(string): """ Color %string yellow. """ - return "\033[33m%s\033[0m" % string + return "\033[33m%s\033[0m" % string if color else string def red(string): """ Color %string red. """ - return "\033[31m%s\033[0m" % string + return "\033[31m%s\033[0m" % string if color else string def execute(cmd): -- cgit v1.2.3 From aa10a7826646c56eb4553df8fe81b3d23655c91a Mon Sep 17 00:00:00 2001 From: Markus Heiser Date: Mon, 15 Aug 2016 16:08:27 +0200 Subject: doc-rst: Revert "kernel-doc: fix handling of address_space tags" This reverts commit a88b1672d4ddf9895eb53e6980926d5e960dea8e. From the origin comit log:: The RST cpp:function handler is very pedantic: it doesn't allow any macros like __user on it Since the kernel-doc parser does NOT make use of the cpp:domain, there is no need to change the kernel-doc parser eleminating the address_space tags. Signed-off-by: Markus Heiser Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 3 --- 1 file changed, 3 deletions(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 4f2e9049e8fa..ba081c7636a2 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1849,9 +1849,6 @@ sub output_function_rst(%) { $count++; $type = $args{'parametertypes'}{$parameter}; - # RST doesn't like address_space tags at function prototypes - $type =~ s/__(user|kernel|iomem|percpu|pmem|rcu)\s*//; - if ($type =~ m/([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)/) { # pointer-to-function print $1 . $parameter . ") (" . $2; -- cgit v1.2.3 From dee81e9886748594babac67c14b0f720148e255d Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 24 Aug 2016 21:03:05 +0300 Subject: fixdep: faster CONFIG_ search Do you think kernel build is 100% dominated by gcc? You are wrong! One small utility called "fixdep" consistently manages to sneak into profile's first page (unless you have small monitor of course). The choke point is this clever code: for (; m < end; m++) { if (*m == INT_CONF) { p = (char *) m ; goto conf; } if (*m == INT_ONFI) { p = (char *) m-1; goto conf; } if (*m == INT_NFIG) { p = (char *) m-2; goto conf; } if (*m == INT_FIG_) { p = (char *) m-3; goto conf; } 4 branches per 4 characters is not fast. Use strstr(3), so that SSE2 etc can be used. With this patch, fixdep is so deep at the bottom, it is hard to find it. Signed-off-by: Alexey Dobriyan Signed-off-by: Michal Marek --- scripts/basic/fixdep.c | 86 ++++++++++++++++---------------------------------- 1 file changed, 28 insertions(+), 58 deletions(-) (limited to 'scripts') diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index 746ec1ece614..fff818b92acb 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -82,8 +82,7 @@ * to date before even starting the recursive build, so it's too late * at this point anyway. * - * The algorithm to grep for "CONFIG_..." is bit unusual, but should - * be fast ;-) We don't even try to really parse the header files, but + * We don't even try to really parse the header files, but * merely grep, i.e. if CONFIG_FOO is mentioned in a comment, it will * be picked up as well. It's not a problem with respect to * correctness, since that can only give too many dependencies, thus @@ -115,11 +114,6 @@ #include #include -#define INT_CONF ntohl(0x434f4e46) -#define INT_ONFI ntohl(0x4f4e4649) -#define INT_NFIG ntohl(0x4e464947) -#define INT_FIG_ ntohl(0x4649475f) - int insert_extra_deps; char *target; char *depfile; @@ -241,37 +235,22 @@ static void use_config(const char *m, int slen) print_config(m, slen); } -static void parse_config_file(const char *map, size_t len) +static void parse_config_file(const char *p) { - const int *end = (const int *) (map + len); - /* start at +1, so that p can never be < map */ - const int *m = (const int *) map + 1; - const char *p, *q; - - for (; m < end; m++) { - if (*m == INT_CONF) { p = (char *) m ; goto conf; } - if (*m == INT_ONFI) { p = (char *) m-1; goto conf; } - if (*m == INT_NFIG) { p = (char *) m-2; goto conf; } - if (*m == INT_FIG_) { p = (char *) m-3; goto conf; } - continue; - conf: - if (p > map + len - 7) - continue; - if (memcmp(p, "CONFIG_", 7)) - continue; + const char *q, *r; + + while ((p = strstr(p, "CONFIG_"))) { p += 7; - for (q = p; q < map + len; q++) { - if (!(isalnum(*q) || *q == '_')) - goto found; - } - continue; - - found: - if (!memcmp(q - 7, "_MODULE", 7)) - q -= 7; - if (q - p < 0) - continue; - use_config(p, q - p); + q = p; + while (*q && (isalnum(*q) || *q == '_')) + q++; + if (memcmp(q - 7, "_MODULE", 7) == 0) + r = q - 7; + else + r = q; + if (r > p) + use_config(p, r - p); + p = q; } } @@ -291,7 +270,7 @@ static void do_config_file(const char *filename) { struct stat st; int fd; - void *map; + char *map; fd = open(filename, O_RDONLY); if (fd < 0) { @@ -308,18 +287,23 @@ static void do_config_file(const char *filename) close(fd); return; } - map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if ((long) map == -1) { - perror("fixdep: mmap"); + map = malloc(st.st_size + 1); + if (!map) { + perror("fixdep: malloc"); close(fd); return; } + if (read(fd, map, st.st_size) != st.st_size) { + perror("fixdep: read"); + close(fd); + return; + } + map[st.st_size] = '\0'; + close(fd); - parse_config_file(map, st.st_size); - - munmap(map, st.st_size); + parse_config_file(map); - close(fd); + free(map); } /* @@ -446,22 +430,8 @@ static void print_deps(void) close(fd); } -static void traps(void) -{ - static char test[] __attribute__((aligned(sizeof(int)))) = "CONF"; - int *p = (int *)test; - - if (*p != INT_CONF) { - fprintf(stderr, "fixdep: sizeof(int) != 4 or wrong endianness? %#x\n", - *p); - exit(2); - } -} - int main(int argc, char *argv[]) { - traps(); - if (argc == 5 && !strcmp(argv[1], "-e")) { insert_extra_deps = 1; argv++; -- cgit v1.2.3 From 6d232c80158ae5a6fb497e0462d52c57c4459439 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Aug 2016 22:02:57 -0300 Subject: docs-rst: kernel-doc: better output struct members Right now, for a struct, kernel-doc produces the following output: .. c:type:: struct v4l2_prio_state stores the priority states **Definition** :: struct v4l2_prio_state { atomic_t prios[4]; }; **Members** ``atomic_t prios[4]`` array with elements to store the array priorities Putting a member name in verbatim and adding a continuation line causes the LaTeX output to generate something like: item[atomic_t prios\[4\]] array with elements to store the array priorities Everything inside "item" is non-breakable, with may produce lines bigger than the column width. Also, for function members, like: int (* rx_read) (struct v4l2_subdev *sd, u8 *buf, size_t count,ssize_t *num); It puts the name of the member at the end, like: int (*) (struct v4l2_subdev *sd, u8 *buf, size_t count,ssize_t *num) read With is very confusing. The best is to highlight what really matters: the member name. is a secondary information. So, change kernel-doc, for it to produce the output on a different way: **Members** ``prios[4]`` array with elements to store the array priorities Also, as the type is not part of LaTeX "item[]", LaTeX will split it into multiple lines, if needed. So, both LaTeX/PDF and HTML outputs will look good. It should be noticed, however, that the way Sphinx LaTeX output handles things like: Foo bar is different than the HTML output. On HTML, it will produce something like: **Foo** bar While, on LaTeX, it puts both foo and bar at the same line, like: **Foo** bar Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index ba081c7636a2..d225e178aa1b 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -2000,7 +2000,7 @@ sub output_struct_rst(%) { ($args{'parameterdescs'}{$parameter_name} ne $undescribed) || next; $type = $args{'parametertypes'}{$parameter}; print_lineno($parameterdesc_start_lines{$parameter_name}); - print "``$type $parameter``\n"; + print "``" . $parameter . "``\n"; output_highlight_rst($args{'parameterdescs'}{$parameter_name}); print "\n"; } -- cgit v1.2.3 From 4fab91605a6bcd0c303bcbc292a8bffcf27b3a27 Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Thu, 25 Aug 2016 19:53:08 +1000 Subject: kbuild: genksyms fix for typeof handling The tokenizer misses counting an open-parenthesis when parsing a non-trivial typeof beginning with an open-parenthesis. This function in include/linux/ceph/libceph.h static type *lookup_##name(struct rb_root *root, typeof(((type *)0)->keyfld) key) When instantiated in net/ceph/mon_client.c, causes subsequent symbols including an EXPORT_SYMBOL in that file to be lost. Signed-off-by: Nicholas Piggin Signed-off-by: Michal Marek --- scripts/genksyms/lex.l | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/genksyms/lex.l b/scripts/genksyms/lex.l index e583565f2011..5235aa507ba5 100644 --- a/scripts/genksyms/lex.l +++ b/scripts/genksyms/lex.l @@ -289,6 +289,23 @@ repeat: } break; + case ST_TYPEOF_1: + if (token == IDENT) + { + if (is_reserved_word(yytext, yyleng) + || find_symbol(yytext, SYM_TYPEDEF, 1)) + { + yyless(0); + unput('('); + lexstate = ST_NORMAL; + token = TYPEOF_KEYW; + break; + } + _APP("(", 1); + } + lexstate = ST_TYPEOF; + /* FALLTHRU */ + case ST_TYPEOF: switch (token) { @@ -313,24 +330,6 @@ repeat: } break; - case ST_TYPEOF_1: - if (token == IDENT) - { - if (is_reserved_word(yytext, yyleng) - || find_symbol(yytext, SYM_TYPEDEF, 1)) - { - yyless(0); - unput('('); - lexstate = ST_NORMAL; - token = TYPEOF_KEYW; - break; - } - _APP("(", 1); - } - APP; - lexstate = ST_TYPEOF; - goto repeat; - case ST_BRACKET: APP; switch (token) -- cgit v1.2.3 From 5c6f3225d00d06b2ca91c74644a7bfcfe826a935 Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Thu, 25 Aug 2016 20:03:51 +0200 Subject: kbuild: Regenerate genksyms lexer Update the lexer after 4fab91605a6b ("kbuild: genksyms fix for typeof handling"). Signed-off-by: Michal Marek --- scripts/genksyms/lex.lex.c_shipped | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) (limited to 'scripts') diff --git a/scripts/genksyms/lex.lex.c_shipped b/scripts/genksyms/lex.lex.c_shipped index f82740a69b85..985c5541aae4 100644 --- a/scripts/genksyms/lex.lex.c_shipped +++ b/scripts/genksyms/lex.lex.c_shipped @@ -2098,6 +2098,23 @@ repeat: } break; + case ST_TYPEOF_1: + if (token == IDENT) + { + if (is_reserved_word(yytext, yyleng) + || find_symbol(yytext, SYM_TYPEDEF, 1)) + { + yyless(0); + unput('('); + lexstate = ST_NORMAL; + token = TYPEOF_KEYW; + break; + } + _APP("(", 1); + } + lexstate = ST_TYPEOF; + /* FALLTHRU */ + case ST_TYPEOF: switch (token) { @@ -2122,24 +2139,6 @@ repeat: } break; - case ST_TYPEOF_1: - if (token == IDENT) - { - if (is_reserved_word(yytext, yyleng) - || find_symbol(yytext, SYM_TYPEDEF, 1)) - { - yyless(0); - unput('('); - lexstate = ST_NORMAL; - token = TYPEOF_KEYW; - break; - } - _APP("(", 1); - } - APP; - lexstate = ST_TYPEOF; - goto repeat; - case ST_BRACKET: APP; switch (token) -- cgit v1.2.3 From f175ba174ef3cb8c26e828c710e4e3b0f2bbbf55 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Sat, 27 Aug 2016 10:59:07 +0200 Subject: checkkconfigsymbols.py: avoid shell injection Use subprocess and set shell to False to avoid potential shell injections. Reported-by: Bernd Dietzel Signed-off-by: Valentin Rothberg Signed-off-by: Greg Kroah-Hartman --- scripts/checkkconfigsymbols.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'scripts') diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index b140fc9018b1..0cae73b5c925 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -2,7 +2,7 @@ """Find Kconfig symbols that are referenced but not defined.""" -# (c) 2014-2015 Valentin Rothberg +# (c) 2014-2016 Valentin Rothberg # (c) 2014 Stefan Hengelein # # Licensed under the terms of the GNU GPL License version 2 @@ -12,6 +12,7 @@ import difflib import os import re import signal +import subprocess import sys from multiprocessing import Pool, cpu_count from optparse import OptionParser @@ -222,10 +223,11 @@ def red(string): def execute(cmd): """Execute %cmd and return stdout. Exit in case of error.""" - pop = Popen(cmd, stdout=PIPE, stderr=STDOUT, shell=True) - (stdout, _) = pop.communicate() # wait until finished - if pop.returncode != 0: - sys.exit(stdout) + try: + cmdlist = cmd.split(" ") + stdout = subprocess.check_output(cmdlist, stderr=STDOUT, shell=False) + except subprocess.CalledProcessError as fail: + exit("Failed to execute %s\n%s" % (cmd, fail)) return stdout -- cgit v1.2.3 From 7c5227af25a1bee7c577162bd55600dae8023f5a Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Sun, 28 Aug 2016 08:51:28 +0200 Subject: checkkconfigsymbols.py: port to Python 3 Python 2 is slowly dying, so port the script to Python 3. Signed-off-by: Valentin Rothberg Signed-off-by: Greg Kroah-Hartman --- scripts/checkkconfigsymbols.py | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index 0cae73b5c925..2b13d8a5c0f6 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python2 +#!/usr/bin/env python3 """Find Kconfig symbols that are referenced but not defined.""" @@ -128,9 +128,9 @@ def main(): if opts.sim and not opts.commit and not opts.diff: sims = find_sims(opts.sim, opts.ignore) if sims: - print "%s: %s" % (yel("Similar symbols"), ', '.join(sims)) + print("%s: %s" % (yel("Similar symbols"), ', '.join(sims))) else: - print "%s: no similar symbols found" % yel("Similar symbols") + print("%s: no similar symbols found" % yel("Similar symbols")) sys.exit(0) # dictionary of (un)defined symbols @@ -183,28 +183,28 @@ def main(): # now print the output for feature in sorted(undefined): - print red(feature) + print(red(feature)) files = sorted(undefined.get(feature)) - print "%s: %s" % (yel("Referencing files"), ", ".join(files)) + print("%s: %s" % (yel("Referencing files"), ", ".join(files))) sims = find_sims(feature, opts.ignore, defined) sims_out = yel("Similar symbols") if sims: - print "%s: %s" % (sims_out, ', '.join(sims)) + print("%s: %s" % (sims_out, ', '.join(sims))) else: - print "%s: %s" % (sims_out, "no similar symbols found") + print("%s: %s" % (sims_out, "no similar symbols found")) if opts.find: - print "%s:" % yel("Commits changing symbol") + print("%s:" % yel("Commits changing symbol")) commits = find_commits(feature, opts.diff) if commits: for commit in commits: commit = commit.split(" ", 1) - print "\t- %s (\"%s\")" % (yel(commit[0]), commit[1]) + print("\t- %s (\"%s\")" % (yel(commit[0]), commit[1])) else: - print "\t- no commit found" - print # new line + print("\t- no commit found") + print() # new line def yel(string): @@ -225,7 +225,8 @@ def execute(cmd): """Execute %cmd and return stdout. Exit in case of error.""" try: cmdlist = cmd.split(" ") - stdout = subprocess.check_output(cmdlist, stderr=STDOUT, shell=False) + stdout = subprocess.check_output(cmdlist, stderr=subprocess.STDOUT, shell=False) + stdout = stdout.decode(errors='replace') except subprocess.CalledProcessError as fail: exit("Failed to execute %s\n%s" % (cmd, fail)) return stdout @@ -256,7 +257,7 @@ def get_head(): def partition(lst, size): """Partition list @lst into eveni-sized lists of size @size.""" - return [lst[i::size] for i in xrange(size)] + return [lst[i::size] for i in range(size)] def init_worker(): @@ -350,7 +351,7 @@ def check_symbols_helper(pool, ignore): # inverse mapping of referenced_features to dict(feature: [files]) inv_map = dict() - for _file, features in referenced_features.iteritems(): + for _file, features in referenced_features.items(): for feature in features: inv_map[feature] = inv_map.get(feature, set()) inv_map[feature].add(_file) @@ -388,7 +389,7 @@ def parse_source_file(sfile): if not os.path.exists(sfile): return references - with open(sfile, "r") as stream: + with open(sfile, "r", encoding='utf-8', errors='replace') as stream: lines = stream.readlines() for line in lines: @@ -437,7 +438,7 @@ def parse_kconfig_file(kfile): if not os.path.exists(kfile): return defined, references - with open(kfile, "r") as stream: + with open(kfile, "r", encoding='utf-8', errors='replace') as stream: lines = stream.readlines() for i in range(len(lines)): -- cgit v1.2.3 From 14390e31641e6fb482ad75b7f46bc54d798f8b87 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Sun, 28 Aug 2016 08:51:29 +0200 Subject: checkkconfigsymbols: use ArgumentParser Replace the deprecated OptionParser with ArgumentParser, as recommended by pylint. Signed-off-by: Valentin Rothberg Signed-off-by: Greg Kroah-Hartman --- scripts/checkkconfigsymbols.py | 142 ++++++++++++++++++++--------------------- 1 file changed, 69 insertions(+), 73 deletions(-) (limited to 'scripts') diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index 2b13d8a5c0f6..322c5e817b4c 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -8,6 +8,7 @@ # Licensed under the terms of the GNU GPL License version 2 +import argparse import difflib import os import re @@ -15,7 +16,6 @@ import signal import subprocess import sys from multiprocessing import Pool, cpu_count -from optparse import OptionParser from subprocess import Popen, PIPE, STDOUT @@ -43,62 +43,58 @@ REGEX_QUOTES = re.compile("(\"(.*?)\")") def parse_options(): """The user interface of this module.""" - usage = "%prog [options]\n\n" \ - "Run this tool to detect Kconfig symbols that are referenced but " \ - "not defined in\nKconfig. The output of this tool has the " \ - "format \'Undefined symbol\\tFile list\'\n\n" \ - "If no option is specified, %prog will default to check your\n" \ - "current tree. Please note that specifying commits will " \ - "\'git reset --hard\'\nyour current tree! You may save " \ - "uncommitted changes to avoid losing data." - - parser = OptionParser(usage=usage) - - parser.add_option('-c', '--commit', dest='commit', action='store', - default="", - help="Check if the specified commit (hash) introduces " - "undefined Kconfig symbols.") - - parser.add_option('-d', '--diff', dest='diff', action='store', - default="", - help="Diff undefined symbols between two commits. The " - "input format bases on Git log's " - "\'commmit1..commit2\'.") - - parser.add_option('-f', '--find', dest='find', action='store_true', - default=False, - help="Find and show commits that may cause symbols to be " - "missing. Required to run with --diff.") - - parser.add_option('-i', '--ignore', dest='ignore', action='store', - default="", - help="Ignore files matching this pattern. Note that " - "the pattern needs to be a Python regex. To " - "ignore defconfigs, specify -i '.*defconfig'.") - - parser.add_option('-s', '--sim', dest='sim', action='store', default="", - help="Print a list of maximum 10 string-similar symbols.") - - parser.add_option('', '--force', dest='force', action='store_true', - default=False, - help="Reset current Git tree even when it's dirty.") - - parser.add_option('', '--no-color', dest='color', action='store_false', - default=True, - help="Don't print colored output. Default when not " - "outputting to a terminal.") - - (opts, _) = parser.parse_args() - - if opts.commit and opts.diff: + usage = "Run this tool to detect Kconfig symbols that are referenced but " \ + "not defined in Kconfig. If no option is specified, " \ + "checkkconfigsymbols defaults to check your current tree. " \ + "Please note that specifying commits will 'git reset --hard\' " \ + "your current tree! You may save uncommitted changes to avoid " \ + "losing data." + + parser = argparse.ArgumentParser(description=usage) + + parser.add_argument('-c', '--commit', dest='commit', action='store', + default="", + help="check if the specified commit (hash) introduces " + "undefined Kconfig symbols") + + parser.add_argument('-d', '--diff', dest='diff', action='store', + default="", + help="diff undefined symbols between two commits " + "(e.g., -d commmit1..commit2)") + + parser.add_argument('-f', '--find', dest='find', action='store_true', + default=False, + help="find and show commits that may cause symbols to be " + "missing (required to run with --diff)") + + parser.add_argument('-i', '--ignore', dest='ignore', action='store', + default="", + help="ignore files matching this Python regex " + "(e.g., -i '.*defconfig')") + + parser.add_argument('-s', '--sim', dest='sim', action='store', default="", + help="print a list of max. 10 string-similar symbols") + + parser.add_argument('--force', dest='force', action='store_true', + default=False, + help="reset current Git tree even when it's dirty") + + parser.add_argument('--no-color', dest='color', action='store_false', + default=True, + help="don't print colored output (default when not " + "outputting to a terminal)") + + args = parser.parse_args() + + if args.commit and args.diff: sys.exit("Please specify only one option at once.") - if opts.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", opts.diff): + if args.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", args.diff): sys.exit("Please specify valid input in the following format: " "\'commit1..commit2\'") - if opts.commit or opts.diff: - if not opts.force and tree_is_dirty(): + if args.commit or args.diff: + if not args.force and tree_is_dirty(): sys.exit("The current Git tree is dirty (see 'git status'). " "Running this script may\ndelete important data since it " "calls 'git reset --hard' for some performance\nreasons. " @@ -106,27 +102,27 @@ def parse_options(): "'--force' if you\nwant to ignore this warning and " "continue.") - if opts.commit: - opts.find = False + if args.commit: + args.find = False - if opts.ignore: + if args.ignore: try: - re.match(opts.ignore, "this/is/just/a/test.c") + re.match(args.ignore, "this/is/just/a/test.c") except: sys.exit("Please specify a valid Python regex.") - return opts + return args def main(): """Main function of this module.""" - opts = parse_options() + args = parse_options() global color - color = opts.color and sys.stdout.isatty() + color = args.color and sys.stdout.isatty() - if opts.sim and not opts.commit and not opts.diff: - sims = find_sims(opts.sim, opts.ignore) + if args.sim and not args.commit and not args.diff: + sims = find_sims(args.sim, args.ignore) if sims: print("%s: %s" % (yel("Similar symbols"), ', '.join(sims))) else: @@ -137,17 +133,17 @@ def main(): defined = {} undefined = {} - if opts.commit or opts.diff: + if args.commit or args.diff: head = get_head() # get commit range commit_a = None commit_b = None - if opts.commit: - commit_a = opts.commit + "~" - commit_b = opts.commit - elif opts.diff: - split = opts.diff.split("..") + if args.commit: + commit_a = args.commit + "~" + commit_b = args.commit + elif args.diff: + split = args.diff.split("..") commit_a = split[0] commit_b = split[1] undefined_a = {} @@ -155,11 +151,11 @@ def main(): # get undefined items before the commit execute("git reset --hard %s" % commit_a) - undefined_a, _ = check_symbols(opts.ignore) + undefined_a, _ = check_symbols(args.ignore) # get undefined items for the commit execute("git reset --hard %s" % commit_b) - undefined_b, defined = check_symbols(opts.ignore) + undefined_b, defined = check_symbols(args.ignore) # report cases that are present for the commit but not before for feature in sorted(undefined_b): @@ -179,7 +175,7 @@ def main(): # default to check the entire tree else: - undefined, defined = check_symbols(opts.ignore) + undefined, defined = check_symbols(args.ignore) # now print the output for feature in sorted(undefined): @@ -188,16 +184,16 @@ def main(): files = sorted(undefined.get(feature)) print("%s: %s" % (yel("Referencing files"), ", ".join(files))) - sims = find_sims(feature, opts.ignore, defined) + sims = find_sims(feature, args.ignore, defined) sims_out = yel("Similar symbols") if sims: print("%s: %s" % (sims_out, ', '.join(sims))) else: print("%s: %s" % (sims_out, "no similar symbols found")) - if opts.find: + if args.find: print("%s:" % yel("Commits changing symbol")) - commits = find_commits(feature, opts.diff) + commits = find_commits(feature, args.diff) if commits: for commit in commits: commit = commit.split(" ", 1) -- cgit v1.2.3 From 36c79c7face54ca10e2b57f42cfc956a53246c10 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Sun, 28 Aug 2016 08:51:30 +0200 Subject: checkkconfigsymbols.py: fix pylint and pep8 warnings Fix pylint and pep8 warnings to have a consistent syntax and style. Signed-off-by: Valentin Rothberg Signed-off-by: Greg Kroah-Hartman --- scripts/checkkconfigsymbols.py | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'scripts') diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index 322c5e817b4c..4111746b5110 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -16,7 +16,6 @@ import signal import subprocess import sys from multiprocessing import Pool, cpu_count -from subprocess import Popen, PIPE, STDOUT # regex expressions @@ -118,8 +117,8 @@ def main(): """Main function of this module.""" args = parse_options() - global color - color = args.color and sys.stdout.isatty() + global COLOR + COLOR = args.color and sys.stdout.isatty() if args.sim and not args.commit and not args.diff: sims = find_sims(args.sim, args.ignore) @@ -160,7 +159,7 @@ def main(): # report cases that are present for the commit but not before for feature in sorted(undefined_b): # feature has not been undefined before - if not feature in undefined_a: + if feature not in undefined_a: files = sorted(undefined_b.get(feature)) undefined[feature] = files # check if there are new files that reference the undefined feature @@ -200,21 +199,21 @@ def main(): print("\t- %s (\"%s\")" % (yel(commit[0]), commit[1])) else: print("\t- no commit found") - print() # new line + print() # new line def yel(string): """ Color %string yellow. """ - return "\033[33m%s\033[0m" % string if color else string + return "\033[33m%s\033[0m" % string if COLOR else string def red(string): """ Color %string red. """ - return "\033[31m%s\033[0m" % string if color else string + return "\033[31m%s\033[0m" % string if COLOR else string def execute(cmd): @@ -261,7 +260,7 @@ def init_worker(): signal.signal(signal.SIGINT, signal.SIG_IGN) -def find_sims(symbol, ignore, defined = []): +def find_sims(symbol, ignore, defined=[]): """Return a list of max. ten Kconfig symbols that are string-similar to @symbol.""" if defined: @@ -335,7 +334,6 @@ def check_symbols_helper(pool, ignore): for res in pool.map(parse_source_files, arglist): referenced_features.update(res) - # parse kconfig files arglist = [] for part in partition(kconfig_files, cpu_count()): @@ -389,7 +387,7 @@ def parse_source_file(sfile): lines = stream.readlines() for line in lines: - if not "CONFIG_" in line: + if "CONFIG_" not in line: continue features = REGEX_SOURCE_FEATURE.findall(line) for feature in features: -- cgit v1.2.3 From ef3f55438d95f0bfc5d4730db6e59058647832e2 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Sun, 28 Aug 2016 08:51:31 +0200 Subject: checkkconfigsymblos: consistent symbol terminology 'symbol' and 'feature' are used synonymously to refer to Kconfig symbols (configs, menus, etc.). Use the term 'symbol' to have a consistent terminology and to make the code more comprehensible. Signed-off-by: Valentin Rothberg Signed-off-by: Greg Kroah-Hartman --- scripts/checkkconfigsymbols.py | 134 ++++++++++++++++++++--------------------- 1 file changed, 67 insertions(+), 67 deletions(-) (limited to 'scripts') diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index 4111746b5110..4b54aa342ac9 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -20,22 +20,22 @@ from multiprocessing import Pool, cpu_count # regex expressions OPERATORS = r"&|\(|\)|\||\!" -FEATURE = r"(?:\w*[A-Z0-9]\w*){2,}" -DEF = r"^\s*(?:menu){,1}config\s+(" + FEATURE + r")\s*" -EXPR = r"(?:" + OPERATORS + r"|\s|" + FEATURE + r")+" +SYMBOL = r"(?:\w*[A-Z0-9]\w*){2,}" +DEF = r"^\s*(?:menu){,1}config\s+(" + SYMBOL + r")\s*" +EXPR = r"(?:" + OPERATORS + r"|\s|" + SYMBOL + r")+" DEFAULT = r"default\s+.*?(?:if\s.+){,1}" STMT = r"^\s*(?:if|select|depends\s+on|(?:" + DEFAULT + r"))\s+" + EXPR -SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")" +SOURCE_SYMBOL = r"(?:\W|\b)+[D]{,1}CONFIG_(" + SYMBOL + r")" # regex objects REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") -REGEX_FEATURE = re.compile(r'(?!\B)' + FEATURE + r'(?!\B)') -REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE) +REGEX_SYMBOL = re.compile(r'(?!\B)' + SYMBOL + r'(?!\B)') +REGEX_SOURCE_SYMBOL = re.compile(SOURCE_SYMBOL) REGEX_KCONFIG_DEF = re.compile(DEF) REGEX_KCONFIG_EXPR = re.compile(EXPR) REGEX_KCONFIG_STMT = re.compile(STMT) REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") -REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") +REGEX_FILTER_SYMBOLS = re.compile(r"[A-Za-z0-9]$") REGEX_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") REGEX_QUOTES = re.compile("(\"(.*?)\")") @@ -157,17 +157,17 @@ def main(): undefined_b, defined = check_symbols(args.ignore) # report cases that are present for the commit but not before - for feature in sorted(undefined_b): - # feature has not been undefined before - if feature not in undefined_a: - files = sorted(undefined_b.get(feature)) - undefined[feature] = files - # check if there are new files that reference the undefined feature + for symbol in sorted(undefined_b): + # symbol has not been undefined before + if symbol not in undefined_a: + files = sorted(undefined_b.get(symbol)) + undefined[symbol] = files + # check if there are new files that reference the undefined symbol else: - files = sorted(undefined_b.get(feature) - - undefined_a.get(feature)) + files = sorted(undefined_b.get(symbol) - + undefined_a.get(symbol)) if files: - undefined[feature] = files + undefined[symbol] = files # reset to head execute("git reset --hard %s" % head) @@ -177,13 +177,13 @@ def main(): undefined, defined = check_symbols(args.ignore) # now print the output - for feature in sorted(undefined): - print(red(feature)) + for symbol in sorted(undefined): + print(red(symbol)) - files = sorted(undefined.get(feature)) + files = sorted(undefined.get(symbol)) print("%s: %s" % (yel("Referencing files"), ", ".join(files))) - sims = find_sims(feature, args.ignore, defined) + sims = find_sims(symbol, args.ignore, defined) sims_out = yel("Similar symbols") if sims: print("%s: %s" % (sims_out, ', '.join(sims))) @@ -192,7 +192,7 @@ def main(): if args.find: print("%s:" % yel("Commits changing symbol")) - commits = find_commits(feature, args.diff) + commits = find_commits(symbol, args.diff) if commits: for commit in commits: commit = commit.split(" ", 1) @@ -317,8 +317,8 @@ def check_symbols_helper(pool, ignore): check_symbols() in order to properly terminate running worker processes.""" source_files = [] kconfig_files = [] - defined_features = [] - referenced_features = dict() # {file: [features]} + defined_symbols = [] + referenced_symbols = dict() # {file: [symbols]} for gitfile in get_files(): if REGEX_FILE_KCONFIG.match(gitfile): @@ -332,51 +332,51 @@ def check_symbols_helper(pool, ignore): # parse source files arglist = partition(source_files, cpu_count()) for res in pool.map(parse_source_files, arglist): - referenced_features.update(res) + referenced_symbols.update(res) # parse kconfig files arglist = [] for part in partition(kconfig_files, cpu_count()): arglist.append((part, ignore)) for res in pool.map(parse_kconfig_files, arglist): - defined_features.extend(res[0]) - referenced_features.update(res[1]) - defined_features = set(defined_features) + defined_symbols.extend(res[0]) + referenced_symbols.update(res[1]) + defined_symbols = set(defined_symbols) - # inverse mapping of referenced_features to dict(feature: [files]) + # inverse mapping of referenced_symbols to dict(symbol: [files]) inv_map = dict() - for _file, features in referenced_features.items(): - for feature in features: - inv_map[feature] = inv_map.get(feature, set()) - inv_map[feature].add(_file) - referenced_features = inv_map - - undefined = {} # {feature: [files]} - for feature in sorted(referenced_features): + for _file, symbols in referenced_symbols.items(): + for symbol in symbols: + inv_map[symbol] = inv_map.get(symbol, set()) + inv_map[symbol].add(_file) + referenced_symbols = inv_map + + undefined = {} # {symbol: [files]} + for symbol in sorted(referenced_symbols): # filter some false positives - if feature == "FOO" or feature == "BAR" or \ - feature == "FOO_BAR" or feature == "XXX": + if symbol == "FOO" or symbol == "BAR" or \ + symbol == "FOO_BAR" or symbol == "XXX": continue - if feature not in defined_features: - if feature.endswith("_MODULE"): + if symbol not in defined_symbols: + if symbol.endswith("_MODULE"): # avoid false positives for kernel modules - if feature[:-len("_MODULE")] in defined_features: + if symbol[:-len("_MODULE")] in defined_symbols: continue - undefined[feature] = referenced_features.get(feature) - return undefined, defined_features + undefined[symbol] = referenced_symbols.get(symbol) + return undefined, defined_symbols def parse_source_files(source_files): """Parse each source file in @source_files and return dictionary with source files as keys and lists of references Kconfig symbols as values.""" - referenced_features = dict() + referenced_symbols = dict() for sfile in source_files: - referenced_features[sfile] = parse_source_file(sfile) - return referenced_features + referenced_symbols[sfile] = parse_source_file(sfile) + return referenced_symbols def parse_source_file(sfile): - """Parse @sfile and return a list of referenced Kconfig features.""" + """Parse @sfile and return a list of referenced Kconfig symbols.""" lines = [] references = [] @@ -389,18 +389,18 @@ def parse_source_file(sfile): for line in lines: if "CONFIG_" not in line: continue - features = REGEX_SOURCE_FEATURE.findall(line) - for feature in features: - if not REGEX_FILTER_FEATURES.search(feature): + symbols = REGEX_SOURCE_SYMBOL.findall(line) + for symbol in symbols: + if not REGEX_FILTER_SYMBOLS.search(symbol): continue - references.append(feature) + references.append(symbol) return references -def get_features_in_line(line): - """Return mentioned Kconfig features in @line.""" - return REGEX_FEATURE.findall(line) +def get_symbols_in_line(line): + """Return mentioned Kconfig symbols in @line.""" + return REGEX_SYMBOL.findall(line) def parse_kconfig_files(args): @@ -409,21 +409,21 @@ def parse_kconfig_files(args): pattern.""" kconfig_files = args[0] ignore = args[1] - defined_features = [] - referenced_features = dict() + defined_symbols = [] + referenced_symbols = dict() for kfile in kconfig_files: defined, references = parse_kconfig_file(kfile) - defined_features.extend(defined) + defined_symbols.extend(defined) if ignore and re.match(ignore, kfile): # do not collect references for files that match the ignore pattern continue - referenced_features[kfile] = references - return (defined_features, referenced_features) + referenced_symbols[kfile] = references + return (defined_symbols, referenced_symbols) def parse_kconfig_file(kfile): - """Parse @kfile and update feature definitions and references.""" + """Parse @kfile and update symbol definitions and references.""" lines = [] defined = [] references = [] @@ -441,8 +441,8 @@ def parse_kconfig_file(kfile): line = line.split("#")[0] # ignore comments if REGEX_KCONFIG_DEF.match(line): - feature_def = REGEX_KCONFIG_DEF.findall(line) - defined.append(feature_def[0]) + symbol_def = REGEX_KCONFIG_DEF.findall(line) + defined.append(symbol_def[0]) skip = False elif REGEX_KCONFIG_HELP.match(line): skip = True @@ -451,18 +451,18 @@ def parse_kconfig_file(kfile): pass elif REGEX_KCONFIG_STMT.match(line): line = REGEX_QUOTES.sub("", line) - features = get_features_in_line(line) + symbols = get_symbols_in_line(line) # multi-line statements while line.endswith("\\"): i += 1 line = lines[i] line = line.strip('\n') - features.extend(get_features_in_line(line)) - for feature in set(features): - if REGEX_NUMERIC.match(feature): + symbols.extend(get_symbols_in_line(line)) + for symbol in set(symbols): + if REGEX_NUMERIC.match(symbol): # ignore numeric values continue - references.append(feature) + references.append(symbol) return defined, references -- cgit v1.2.3 From 2f9cc12bb34a4a90f18839a5ce35e1e4d33d6413 Mon Sep 17 00:00:00 2001 From: Valentin Rothberg Date: Sun, 28 Aug 2016 08:51:32 +0200 Subject: checkkconfigsymbols: use arglist instead of cmd string Splitting a command string could lead to unintended arguments. Use an argument list in the execute() function instead. Signed-off-by: Valentin Rothberg Signed-off-by: Greg Kroah-Hartman --- scripts/checkkconfigsymbols.py | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) (limited to 'scripts') diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index 4b54aa342ac9..a32e4da4c117 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -149,11 +149,11 @@ def main(): undefined_b = {} # get undefined items before the commit - execute("git reset --hard %s" % commit_a) + reset(commit_a) undefined_a, _ = check_symbols(args.ignore) # get undefined items for the commit - execute("git reset --hard %s" % commit_b) + reset(commit_b) undefined_b, defined = check_symbols(args.ignore) # report cases that are present for the commit but not before @@ -170,7 +170,7 @@ def main(): undefined[symbol] = files # reset to head - execute("git reset --hard %s" % head) + reset(head) # default to check the entire tree else: @@ -202,6 +202,11 @@ def main(): print() # new line +def reset(commit): + """Reset current git tree to %commit.""" + execute(["git", "reset", "--hard", commit]) + + def yel(string): """ Color %string yellow. @@ -219,25 +224,25 @@ def red(string): def execute(cmd): """Execute %cmd and return stdout. Exit in case of error.""" try: - cmdlist = cmd.split(" ") - stdout = subprocess.check_output(cmdlist, stderr=subprocess.STDOUT, shell=False) + stdout = subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=False) stdout = stdout.decode(errors='replace') except subprocess.CalledProcessError as fail: - exit("Failed to execute %s\n%s" % (cmd, fail)) + exit(fail) return stdout def find_commits(symbol, diff): """Find commits changing %symbol in the given range of %diff.""" - commits = execute("git log --pretty=oneline --abbrev-commit -G %s %s" - % (symbol, diff)) + commits = execute(["git", "log", "--pretty=oneline", + "--abbrev-commit", "-G", + symbol, diff]) return [x for x in commits.split("\n") if x] def tree_is_dirty(): """Return true if the current working tree is dirty (i.e., if any file has been added, deleted, modified, renamed or copied but not committed).""" - stdout = execute("git status --porcelain") + stdout = execute(["git", "status", "--porcelain"]) for line in stdout: if re.findall(r"[URMADC]{1}", line[:2]): return True @@ -246,7 +251,7 @@ def tree_is_dirty(): def get_head(): """Return commit hash of current HEAD.""" - stdout = execute("git rev-parse HEAD") + stdout = execute(["git", "rev-parse", "HEAD"]) return stdout.strip('\n') @@ -285,7 +290,7 @@ def find_sims(symbol, ignore, defined=[]): def get_files(): """Return a list of all files in the current git directory.""" # use 'git ls-files' to get the worklist - stdout = execute("git ls-files") + stdout = execute(["git", "ls-files"]) if len(stdout) > 0 and stdout[-1] == "\n": stdout = stdout[:-1] -- cgit v1.2.3 From 2d187d58553becd61677a2db0181ff2c7b07c8a3 Mon Sep 17 00:00:00 2001 From: Alexander Kapshuk Date: Mon, 22 Aug 2016 21:19:17 +0300 Subject: ver_linux: complete awk implementation The algorithm that extracts the version number of the utility being queried, and prints the name of the utility and its version number is currently implemented in awk. The code is used throughout the script, making its use repetative. The proposed implementation confines the algorithm in question to a function, which makes the script easier to read overall, as well as considerably reduces the number of lines of code. Every attempt has been made to retain the look and the format generated by the current implementation. Signed-off-by: Alexander Kapshuk Signed-off-by: Greg Kroah-Hartman --- scripts/ver_linux.awk | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100755 scripts/ver_linux.awk (limited to 'scripts') diff --git a/scripts/ver_linux.awk b/scripts/ver_linux.awk new file mode 100755 index 000000000000..430b201f3e25 --- /dev/null +++ b/scripts/ver_linux.awk @@ -0,0 +1,89 @@ +#!/bin/awk -f +# Before running this script please ensure that your PATH is +# typical as you use for compilation/installation. I use +# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may +# differ on your system. + +BEGIN { + usage = "If some fields are empty or look unusual you may have an old version.\n" + usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n" + print usage + + system("uname -a") + printf("\n") + + printversion("GNU C", version("gcc -dumpversion 2>&1")) + printversion("GNU Make", version("make --version 2>&1")) + printversion("Binutils", version("ld -v 2>&1")) + printversion("Util-linux", version("mount --version 2>&1")) + printversion("Mount", version("mount --version 2>&1")) + printversion("Module-init-tools", version("depmod -V 2>&1")) + printversion("E2fsprogs", version("tune2fs 2>&1")) + printversion("Jfsutils", version("fsck.jfs -V 2>&1")) + printversion("Reiserfsprogs", version("reiserfsck -V 2>&1")) + printversion("Reiser4fsprogs", version("fsck.reiser4 -V 2>&1")) + printversion("Xfsprogs", version("xfs_db -V 2>&1")) + printversion("Pcmciautils", version("pccardctl -V 2>&1")) + printversion("Pcmcia-cs", version("cardmgr -V 2>&1")) + printversion("Quota-tools", version("quota -V 2>&1")) + printversion("PPP", version("pppd --version 2>&1")) + printversion("Isdn4k-utils", version("isdnctrl 2>&1")) + printversion("Nfs-utils", version("showmount --version 2>&1")) + + if (system("test -r /proc/self/maps") == 0) { + while (getline <"/proc/self/maps" > 0) { + n = split($0, procmaps, "/") + if (/libc.*so$/ && match(procmaps[n], /[0-9]+([.]?[0-9]+)+/)) { + ver = substr(procmaps[n], RSTART, RLENGTH) + printversion("Linux C Library", ver) + break + } + } + } + + printversion("Dynamic linker (ldd)", version("ldd --version 2>&1")) + + while ("ldconfig -p 2>/dev/null" | getline > 0) { + if (/(libg|stdc)[+]+\.so/) { + libcpp = $NF + break + } + } + if (system("test -r " libcpp) == 0) + printversion("Linux C++ Library", version("readlink " libcpp)) + + printversion("Procps", version("ps --version 2>&1")) + printversion("Net-tools", version("ifconfig --version 2>&1")) + printversion("Kbd", version("loadkeys -V 2>&1")) + printversion("Console-tools", version("loadkeys -V 2>&1")) + printversion("Oprofile", version("oprofiled --version 2>&1")) + printversion("Sh-utils", version("expr --v 2>&1")) + printversion("Udev", version("udevadm --version 2>&1")) + printversion("Wireless-tools", version("iwconfig --version 2>&1")) + + if (system("test -r /proc/modules") == 0) { + while ("sort /proc/modules" | getline > 0) { + mods = mods sep $1 + sep = " " + } + printversion("Modules Loaded", mods) + } +} + +function version(cmd, ver) { + while (cmd | getline > 0) { + if (!/ver_linux/ && match($0, /[0-9]+([.]?[0-9]+)+/)) { + ver = substr($0, RSTART, RLENGTH) + break + } + } + close(cmd) + return ver +} + +function printversion(name, value, ofmt) { + if (value != "") { + ofmt = "%-20s\t%s\n" + printf(ofmt, name, value) + } +} -- cgit v1.2.3 From b88396e41794dc3873d9a819f374d369356a6cc6 Mon Sep 17 00:00:00 2001 From: Alexander Kapshuk Date: Mon, 22 Aug 2016 21:19:18 +0300 Subject: ver_linux: shell implementation removed The shell implementation removed. To be replaced with an all-awk implementation via consecutive patch. Signed-off-by: Alexander Kapshuk Signed-off-by: Greg Kroah-Hartman --- scripts/ver_linux | 193 ------------------------------------------------------ 1 file changed, 193 deletions(-) delete mode 100755 scripts/ver_linux (limited to 'scripts') diff --git a/scripts/ver_linux b/scripts/ver_linux deleted file mode 100755 index 0d8bd29b1bd6..000000000000 --- a/scripts/ver_linux +++ /dev/null @@ -1,193 +0,0 @@ -#!/bin/sh -# Before running this script please ensure that your PATH is -# typical as you use for compilation/installation. I use -# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may -# differ on your system. -# -echo 'If some fields are empty or look unusual you may have an old version.' -echo 'Compare to the current minimal requirements in Documentation/Changes.' -echo ' ' - -uname -a -echo ' ' - -gcc -dumpversion 2>&1 | -awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("GNU C\t\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -make --version 2>&1 | -awk '/GNU Make/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("GNU Make\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -ld -v 2>&1 | -awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Binutils\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -mount --version 2>&1 | -awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - $0 = substr($0,RSTART,RLENGTH) - printf("Util-linux\t\t%s\nMount\t\t\t%s\n",$0,$0) -}' - -depmod -V 2>&1 | -awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Module-init-tools\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -tune2fs 2>&1 | -awk '/^tune2fs/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("E2fsprogs\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -fsck.jfs -V 2>&1 | -awk '/version/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Jfsutils\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -reiserfsck -V 2>&1 | -awk '/^reiserfsck/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Reiserfsprogs\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -fsck.reiser4 -V 2>&1 | grep ^fsck.reiser4 | awk \ -'NR==1{print "reiser4progs ", $2}' - -xfs_db -V 2>&1 | -awk '/version/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Xfsprogs\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -pccardctl -V 2>&1 | -awk '/pcmciautils/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Pcmciautils\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -cardmgr -V 2>&1| grep version | awk \ -'NR==1{print "pcmcia-cs ", $3}' - -quota -V 2>&1 | -awk '/version/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Quota-tools\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -pppd --version 2>&1 | -awk '/version/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("PPP\t\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -isdnctrl 2>&1 | grep version | awk \ -'NR==1{print "isdn4k-utils ", $NF}' - -showmount --version 2>&1 | grep nfs-utils | awk \ -'NR==1{print "nfs-utils ", $NF}' - -test -r /proc/self/maps && -sed ' - /.*libc-\(.*\)\.so$/!d - s//Linux C Library\t\t\1/ - q -' /proc/self/maps - -ldd --version 2>&1 | -awk '/^ldd/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Dynamic linker (ldd)\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -libcpp=`ldconfig -p 2>/dev/null | - awk '/(libg|stdc)[+]+\.so/ { - print $NF - exit - } -'` -test -r "$libcpp" && -ls -l $libcpp | -sed ' - s!.*so\.!! - s!^!Linux C++ Library\t! -' -ps --version 2>&1 | -awk '/version/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Procps\t\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -ifconfig --version 2>&1 | -awk '/tools/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Net-tools\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -loadkeys -V 2>&1 | -awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - $0 = substr($0,RSTART,RLENGTH) - printf("Kbd\t\t\t%s\nConsole-tools\t\t%s\n",$0,$0) -}' - -oprofiled --version 2>&1 | awk \ -'(NR==1 && ($2 == "oprofile")) {print "oprofile ", $3}' - -expr --v 2>&1 | -awk '/^expr/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Sh-utils\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -udevadm --version 2>&1 | -awk '/[0-9]+([.]?[0-9]+)+/ && !/not found$/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Udev\t\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -iwconfig --version 2>&1 | -awk '/version/{ - match($0, /[0-9]+([.]?[0-9]+)+/) - printf("Wireless-tools\t\t%s\n", - substr($0,RSTART,RLENGTH)) -}' - -test -e /proc/modules && -sort /proc/modules | -sed ' - s/ .*// - H -${ - g - s/^\n/Modules Loaded\t\t/ - y/\n/ / - q -} - d -' -- cgit v1.2.3 From 9b9e7d36bdeef2842fd53b2172e95a264c27d362 Mon Sep 17 00:00:00 2001 From: Alexander Kapshuk Date: Mon, 22 Aug 2016 21:19:19 +0300 Subject: ver_linux: rename ver_linux.awk to ver_linux ver_linux.awk renamed to ver_linux. Signed-off-by: Alexander Kapshuk Signed-off-by: Greg Kroah-Hartman --- scripts/ver_linux | 89 +++++++++++++++++++++++++++++++++++++++++++++++++++ scripts/ver_linux.awk | 89 --------------------------------------------------- 2 files changed, 89 insertions(+), 89 deletions(-) create mode 100755 scripts/ver_linux delete mode 100755 scripts/ver_linux.awk (limited to 'scripts') diff --git a/scripts/ver_linux b/scripts/ver_linux new file mode 100755 index 000000000000..430b201f3e25 --- /dev/null +++ b/scripts/ver_linux @@ -0,0 +1,89 @@ +#!/bin/awk -f +# Before running this script please ensure that your PATH is +# typical as you use for compilation/installation. I use +# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may +# differ on your system. + +BEGIN { + usage = "If some fields are empty or look unusual you may have an old version.\n" + usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n" + print usage + + system("uname -a") + printf("\n") + + printversion("GNU C", version("gcc -dumpversion 2>&1")) + printversion("GNU Make", version("make --version 2>&1")) + printversion("Binutils", version("ld -v 2>&1")) + printversion("Util-linux", version("mount --version 2>&1")) + printversion("Mount", version("mount --version 2>&1")) + printversion("Module-init-tools", version("depmod -V 2>&1")) + printversion("E2fsprogs", version("tune2fs 2>&1")) + printversion("Jfsutils", version("fsck.jfs -V 2>&1")) + printversion("Reiserfsprogs", version("reiserfsck -V 2>&1")) + printversion("Reiser4fsprogs", version("fsck.reiser4 -V 2>&1")) + printversion("Xfsprogs", version("xfs_db -V 2>&1")) + printversion("Pcmciautils", version("pccardctl -V 2>&1")) + printversion("Pcmcia-cs", version("cardmgr -V 2>&1")) + printversion("Quota-tools", version("quota -V 2>&1")) + printversion("PPP", version("pppd --version 2>&1")) + printversion("Isdn4k-utils", version("isdnctrl 2>&1")) + printversion("Nfs-utils", version("showmount --version 2>&1")) + + if (system("test -r /proc/self/maps") == 0) { + while (getline <"/proc/self/maps" > 0) { + n = split($0, procmaps, "/") + if (/libc.*so$/ && match(procmaps[n], /[0-9]+([.]?[0-9]+)+/)) { + ver = substr(procmaps[n], RSTART, RLENGTH) + printversion("Linux C Library", ver) + break + } + } + } + + printversion("Dynamic linker (ldd)", version("ldd --version 2>&1")) + + while ("ldconfig -p 2>/dev/null" | getline > 0) { + if (/(libg|stdc)[+]+\.so/) { + libcpp = $NF + break + } + } + if (system("test -r " libcpp) == 0) + printversion("Linux C++ Library", version("readlink " libcpp)) + + printversion("Procps", version("ps --version 2>&1")) + printversion("Net-tools", version("ifconfig --version 2>&1")) + printversion("Kbd", version("loadkeys -V 2>&1")) + printversion("Console-tools", version("loadkeys -V 2>&1")) + printversion("Oprofile", version("oprofiled --version 2>&1")) + printversion("Sh-utils", version("expr --v 2>&1")) + printversion("Udev", version("udevadm --version 2>&1")) + printversion("Wireless-tools", version("iwconfig --version 2>&1")) + + if (system("test -r /proc/modules") == 0) { + while ("sort /proc/modules" | getline > 0) { + mods = mods sep $1 + sep = " " + } + printversion("Modules Loaded", mods) + } +} + +function version(cmd, ver) { + while (cmd | getline > 0) { + if (!/ver_linux/ && match($0, /[0-9]+([.]?[0-9]+)+/)) { + ver = substr($0, RSTART, RLENGTH) + break + } + } + close(cmd) + return ver +} + +function printversion(name, value, ofmt) { + if (value != "") { + ofmt = "%-20s\t%s\n" + printf(ofmt, name, value) + } +} diff --git a/scripts/ver_linux.awk b/scripts/ver_linux.awk deleted file mode 100755 index 430b201f3e25..000000000000 --- a/scripts/ver_linux.awk +++ /dev/null @@ -1,89 +0,0 @@ -#!/bin/awk -f -# Before running this script please ensure that your PATH is -# typical as you use for compilation/installation. I use -# /bin /sbin /usr/bin /usr/sbin /usr/local/bin, but it may -# differ on your system. - -BEGIN { - usage = "If some fields are empty or look unusual you may have an old version.\n" - usage = usage "Compare to the current minimal requirements in Documentation/Changes.\n" - print usage - - system("uname -a") - printf("\n") - - printversion("GNU C", version("gcc -dumpversion 2>&1")) - printversion("GNU Make", version("make --version 2>&1")) - printversion("Binutils", version("ld -v 2>&1")) - printversion("Util-linux", version("mount --version 2>&1")) - printversion("Mount", version("mount --version 2>&1")) - printversion("Module-init-tools", version("depmod -V 2>&1")) - printversion("E2fsprogs", version("tune2fs 2>&1")) - printversion("Jfsutils", version("fsck.jfs -V 2>&1")) - printversion("Reiserfsprogs", version("reiserfsck -V 2>&1")) - printversion("Reiser4fsprogs", version("fsck.reiser4 -V 2>&1")) - printversion("Xfsprogs", version("xfs_db -V 2>&1")) - printversion("Pcmciautils", version("pccardctl -V 2>&1")) - printversion("Pcmcia-cs", version("cardmgr -V 2>&1")) - printversion("Quota-tools", version("quota -V 2>&1")) - printversion("PPP", version("pppd --version 2>&1")) - printversion("Isdn4k-utils", version("isdnctrl 2>&1")) - printversion("Nfs-utils", version("showmount --version 2>&1")) - - if (system("test -r /proc/self/maps") == 0) { - while (getline <"/proc/self/maps" > 0) { - n = split($0, procmaps, "/") - if (/libc.*so$/ && match(procmaps[n], /[0-9]+([.]?[0-9]+)+/)) { - ver = substr(procmaps[n], RSTART, RLENGTH) - printversion("Linux C Library", ver) - break - } - } - } - - printversion("Dynamic linker (ldd)", version("ldd --version 2>&1")) - - while ("ldconfig -p 2>/dev/null" | getline > 0) { - if (/(libg|stdc)[+]+\.so/) { - libcpp = $NF - break - } - } - if (system("test -r " libcpp) == 0) - printversion("Linux C++ Library", version("readlink " libcpp)) - - printversion("Procps", version("ps --version 2>&1")) - printversion("Net-tools", version("ifconfig --version 2>&1")) - printversion("Kbd", version("loadkeys -V 2>&1")) - printversion("Console-tools", version("loadkeys -V 2>&1")) - printversion("Oprofile", version("oprofiled --version 2>&1")) - printversion("Sh-utils", version("expr --v 2>&1")) - printversion("Udev", version("udevadm --version 2>&1")) - printversion("Wireless-tools", version("iwconfig --version 2>&1")) - - if (system("test -r /proc/modules") == 0) { - while ("sort /proc/modules" | getline > 0) { - mods = mods sep $1 - sep = " " - } - printversion("Modules Loaded", mods) - } -} - -function version(cmd, ver) { - while (cmd | getline > 0) { - if (!/ver_linux/ && match($0, /[0-9]+([.]?[0-9]+)+/)) { - ver = substr($0, RSTART, RLENGTH) - break - } - } - close(cmd) - return ver -} - -function printversion(name, value, ofmt) { - if (value != "") { - ofmt = "%-20s\t%s\n" - printf(ofmt, name, value) - } -} -- cgit v1.2.3 From d37c43ce1975c1c3f28064bf3ebd2876e177bad8 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Aug 2016 20:20:57 -0300 Subject: docs-rst: improve typedef parser Improve the parser to handle typedefs like: typedef bool v4l2_check_dv_timings_fnc(const struct v4l2_dv_timings *t, void *handle); Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- scripts/kernel-doc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/kernel-doc b/scripts/kernel-doc index d225e178aa1b..ad6d4e495f3f 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -2190,7 +2190,9 @@ sub dump_typedef($$) { $x =~ s@/\*.*?\*/@@gos; # strip comments. # Parse function prototypes - if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/) { + if ($x =~ /typedef\s+(\w+)\s*\(\*\s*(\w\S+)\s*\)\s*\((.*)\);/ || + $x =~ /typedef\s+(\w+)\s*(\w\S+)\s*\s*\((.*)\);/) { + # Function typedefs $return_type = $1; $declaration_name = $2; -- cgit v1.2.3 From 82801d065b4915d030e7f63212d146a75042aa91 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 30 Aug 2016 20:20:58 -0300 Subject: docs-rst: kernel-doc: fix typedef output in RST format When using a typedef function like this one: typedef bool v4l2_check_dv_timings_fnc (const struct v4l2_dv_timings * t, void * handle); The Sphinx C domain expects it to create a c:type: reference, as that's the way it creates the type references when parsing a c:function:: declaration. So, a declaration like: .. c:function:: bool v4l2_valid_dv_timings (const struct v4l2_dv_timings * t, const struct v4l2_dv_timings_cap * cap, v4l2_check_dv_timings_fnc fnc, void * fnc_handle) Will create a cross reference for :c:type:`v4l2_check_dv_timings_fnc`. So, when outputting such typedefs in RST format, we need to handle this special case, as otherwise it will produce those warnings: ./include/media/v4l2-dv-timings.h:43: WARNING: c:type reference target not found: v4l2_check_dv_timings_fnc ./include/media/v4l2-dv-timings.h:60: WARNING: c:type reference target not found: v4l2_check_dv_timings_fnc ./include/media/v4l2-dv-timings.h:81: WARNING: c:type reference target not found: v4l2_check_dv_timings_fnc So, change the kernel-doc script to produce a RST output for the above typedef as: .. c:type:: v4l2_check_dv_timings_fnc **Typedef**: timings check callback **Syntax** ``bool v4l2_check_dv_timings_fnc (const struct v4l2_dv_timings * t, void * handle);`` Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Jonathan Corbet --- 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 ad6d4e495f3f..301bf874cac8 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1831,13 +1831,22 @@ sub output_function_rst(%) { my %args = %{$_[0]}; my ($parameter, $section); my $oldprefix = $lineprefix; - my $start; - - print ".. c:function:: "; + my $start = ""; + + 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:: "; + } if ($args{'functiontype'} ne "") { - $start = $args{'functiontype'} . " " . $args{'function'} . " ("; + $start .= $args{'functiontype'} . " " . $args{'function'} . " ("; } else { - $start = $args{'function'} . " ("; + $start .= $args{'function'} . " ("; } print $start; @@ -1856,11 +1865,15 @@ sub output_function_rst(%) { print $type . " " . $parameter; } } - print ")\n\n"; - print_lineno($declaration_start_line); - $lineprefix = " "; - output_highlight_rst($args{'purpose'}); - print "\n"; + if ($args{'typedef'}) { + print ");``\n\n"; + } else { + print ")\n\n"; + print_lineno($declaration_start_line); + $lineprefix = " "; + output_highlight_rst($args{'purpose'}); + print "\n"; + } print "**Parameters**\n\n"; $lineprefix = " "; @@ -2203,6 +2216,7 @@ sub dump_typedef($$) { output_declaration($declaration_name, 'function', {'function' => $declaration_name, + 'typedef' => 1, 'module' => $modulename, 'functiontype' => $return_type, 'parameterlist' => \@parameterlist, -- cgit v1.2.3 From ef00028b20481647431ca8bffe5469fb86cf154f Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 26 Aug 2016 07:14:08 -0600 Subject: docs: make kernel-doc handle varargs properly As far as I can tell, the handling of "..." arguments has never worked right, so any documentation provided was ignored in favor of "variable arguments." This makes kernel-doc handle "@...:" as documented. It does *not* fix spots in kerneldoc comments that don't follow that convention, but they are no more broken than before. 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 301bf874cac8..c5918951a8d3 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -412,7 +412,7 @@ my $doc_com_body = '\s*\* ?'; my $doc_decl = $doc_com . '(\w+)'; # @params and a strictly limited set of supported section names my $doc_sect = $doc_com . - '\s*(\@\w+|description|context|returns?|notes?|examples?)\s*:(.*)'; + '\s*(\@[.\w]+|\@\.\.\.|description|context|returns?|notes?|examples?)\s*:(.*)'; my $doc_content = $doc_com_body . '(.*)'; my $doc_block = $doc_com . 'DOC:\s*(.*)?'; my $doc_inline_start = '^\s*/\*\*\s*$'; @@ -2351,6 +2351,7 @@ sub push_parameter($$$) { if ($type eq "" && $param =~ /\.\.\.$/) { + $param = "..."; if (!defined $parameterdescs{$param} || $parameterdescs{$param} eq "") { $parameterdescs{$param} = "variable arguments"; } -- cgit v1.2.3 From 5219f18aaf00f9f9ba572b3817e394043388d4ef Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Wed, 24 Aug 2016 16:31:15 -0600 Subject: docs: Special-case function-pointer parameters in kernel-doc Add yet another regex to kernel-doc to trap @param() references separately and not produce corrupt RST markup. 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 c5918951a8d3..93721f3c91bf 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -212,6 +212,7 @@ my $anon_struct_union = 0; my $type_constant = '\%([-_\w]+)'; my $type_func = '(\w+)\(\)'; my $type_param = '\@(\w+)'; +my $type_fp_param = '\@(\w+)\(\)'; # Special RST handling for func ptr params my $type_struct = '\&((struct\s*)*[_\w]+)'; my $type_struct_xml = '\\&((struct\s*)*[_\w]+)'; my $type_env = '(\$\w+)'; @@ -292,6 +293,7 @@ my @highlights_rst = ( # Note: need to escape () to avoid func matching later [$type_member_func, "\\:c\\:type\\:`\$1\$2\\\\(\\\\) <\$1>`"], [$type_member, "\\:c\\:type\\:`\$1\$2 <\$1>`"], + [$type_fp_param, "**\$1\\\\(\\\\)**"], [$type_func, "\\:c\\:func\\:`\$1()`"], [$type_struct_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], [$type_enum_full, "\\:c\\:type\\:`\$1 \$2 <\$2>`"], -- cgit v1.2.3 From a5967db9af51a84f5e181600954714a9e4c69f1f Mon Sep 17 00:00:00 2001 From: Stephen Rothwell Date: Wed, 24 Aug 2016 22:29:19 +1000 Subject: kbuild: allow architectures to use thin archives instead of ld -r ld -r is an incremental link used to create built-in.o files in build subdirectories. It produces relocatable object files containing all its input files, and these are are then pulled together and relocated in the final link. Aside from the bloat, this constrains the final link relocations, which has bitten large powerpc builds with unresolvable relocations in the final link. Alan Modra has recommended the kernel use thin archives for linking. This is an alternative and means that the linker has more information available to it when it links the kernel. This patch enables a config option architectures can select, which causes all built-in.o files to be built as thin archives. built-in.o files in subdirectories do not get symbol table or index attached, which improves speed and size. The final link pass creates a built-in.o archive in the root output directory which includes the symbol table and index. The linker then uses takes this file to link. The --whole-archive linker option is required, because the linker now has visibility to every individual object file, and it will otherwise just completely avoid including those without external references (consider a file with EXPORT_SYMBOL or initcall or hardware exceptions as its only entry points). The traditional built works "by luck" as built-in.o files are large enough that they're going to get external references. However this optimisation is unpredictable for the kernel (due to above external references), ineffective at culling unused, and costly because the .o files have to be searched for references. Superior alternatives for link-time culling should be used instead. Build characteristics for inclink vs thinarc, on a small powerpc64le pseries VM with a modest .config: inclink thinarc sizes vmlinux 15 618 680 15 625 028 sum of all built-in.o 56 091 808 1 054 334 sum excluding root built-in.o 151 430 find -name built-in.o | xargs rm ; time make vmlinux real 22.772s 21.143s user 13.280s 13.430s sys 4.310s 2.750s - Final kernel pulled in only about 6K more, which shows how ineffective the object file culling is. - Build performance looks improved due to less pagecache activity. On IO constrained systems it could be a bigger win. - Build size saving is significant. Side note, the toochain understands archives, so there's some tricks, $ ar t built-in.o # list all files you linked with $ size built-in.o # and their sizes $ objdump -d built-in.o # disassembly (unrelocated) with filenames Implementation by sfr, minor tweaks by npiggin. Signed-off-by: Stephen Rothwell Signed-off-by: Nicholas Piggin Signed-off-by: Michal Marek --- arch/Kconfig | 6 +++++ scripts/Makefile.build | 23 +++++++++++++--- scripts/link-vmlinux.sh | 71 +++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 85 insertions(+), 15 deletions(-) (limited to 'scripts') diff --git a/arch/Kconfig b/arch/Kconfig index bd8056b5b246..6842154813e5 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -461,6 +461,12 @@ config CC_STACKPROTECTOR_STRONG endchoice +config THIN_ARCHIVES + bool + help + Select this if the architecture wants to use thin archives + instead of ld -r to create the built-in.o files. + config HAVE_CONTEXT_TRACKING bool help diff --git a/scripts/Makefile.build b/scripts/Makefile.build index cd9bf22bb027..de46ab03f063 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -359,12 +359,22 @@ $(sort $(subdir-obj-y)): $(subdir-ym) ; # Rule to compile a set of .o files into one .o file # ifdef builtin-target -quiet_cmd_link_o_target = LD $@ + +ifdef CONFIG_THIN_ARCHIVES + cmd_make_builtin = rm -f $@; $(AR) rcST$(KBUILD_ARFLAGS) + cmd_make_empty_builtin = rm -f $@; $(AR) rcST$(KBUILD_ARFLAGS) + quiet_cmd_link_o_target = AR $@ +else + cmd_make_builtin = $(LD) $(ld_flags) -r -o + cmd_make_empty_builtin = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) + quiet_cmd_link_o_target = LD $@ +endif + # If the list of objects to link is empty, just create an empty built-in.o cmd_link_o_target = $(if $(strip $(obj-y)),\ - $(LD) $(ld_flags) -r -o $@ $(filter $(obj-y), $^) \ + $(cmd_make_builtin) $@ $(filter $(obj-y), $^) \ $(cmd_secanalysis),\ - rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@) + $(cmd_make_empty_builtin) $@) $(builtin-target): $(obj-y) FORCE $(call if_changed,link_o_target) @@ -390,7 +400,12 @@ $(modorder-target): $(subdir-ym) FORCE # ifdef lib-target quiet_cmd_link_l_target = AR $@ -cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) + +ifdef CONFIG_THIN_ARCHIVES + cmd_link_l_target = rm -f $@; $(AR) rcsT$(KBUILD_ARFLAGS) $@ $(lib-y) +else + cmd_link_l_target = rm -f $@; $(AR) rcs$(KBUILD_ARFLAGS) $@ $(lib-y) +endif $(lib-target): $(lib-y) FORCE $(call if_changed,link_l_target) diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index 4f727eb5ec43..f742c65108b9 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -37,12 +37,40 @@ info() fi } +# Thin archive build here makes a final archive with +# symbol table and indexes from vmlinux objects, which can be +# used as input to linker. +# +# Traditional incremental style of link does not require this step +# +# built-in.o output file +# +archive_builtin() +{ + if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then + info AR built-in.o + rm -f built-in.o; + ${AR} rcsT${KBUILD_ARFLAGS} built-in.o \ + ${KBUILD_VMLINUX_INIT} \ + ${KBUILD_VMLINUX_MAIN} + fi +} + # Link of vmlinux.o used for section mismatch analysis # ${1} output file modpost_link() { - ${LD} ${LDFLAGS} -r -o ${1} ${KBUILD_VMLINUX_INIT} \ - --start-group ${KBUILD_VMLINUX_MAIN} --end-group + local objects + + if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then + objects="--whole-archive built-in.o" + else + objects="${KBUILD_VMLINUX_INIT} \ + --start-group \ + ${KBUILD_VMLINUX_MAIN} \ + --end-group" + fi + ${LD} ${LDFLAGS} -r -o ${1} ${objects} } # Link of vmlinux @@ -51,18 +79,36 @@ modpost_link() vmlinux_link() { local lds="${objtree}/${KBUILD_LDS}" + local objects if [ "${SRCARCH}" != "um" ]; then - ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ - -T ${lds} ${KBUILD_VMLINUX_INIT} \ - --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1} + if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then + objects="--whole-archive built-in.o ${1}" + else + objects="${KBUILD_VMLINUX_INIT} \ + --start-group \ + ${KBUILD_VMLINUX_MAIN} \ + --end-group \ + ${1}" + fi + + ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \ + -T ${lds} ${objects} else - ${CC} ${CFLAGS_vmlinux} -o ${2} \ - -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT} \ - -Wl,--start-group \ - ${KBUILD_VMLINUX_MAIN} \ - -Wl,--end-group \ - -lutil -lrt -lpthread ${1} + if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then + objects="-Wl,--whole-archive built-in.o ${1}" + else + objects="${KBUILD_VMLINUX_INIT} \ + -Wl,--start-group \ + ${KBUILD_VMLINUX_MAIN} \ + -Wl,--end-group \ + ${1}" + fi + + ${CC} ${CFLAGS_vmlinux} -o ${2} \ + -Wl,-T,${lds} \ + ${objects} \ + -lutil -lrt -lpthread rm -f linux fi } @@ -119,6 +165,7 @@ cleanup() rm -f .tmp_kallsyms* rm -f .tmp_version rm -f .tmp_vmlinux* + rm -f built-in.o rm -f System.map rm -f vmlinux rm -f vmlinux.o @@ -162,6 +209,8 @@ case "${KCONFIG_CONFIG}" in . "./${KCONFIG_CONFIG}" esac +archive_builtin + #link vmlinux.o info LD vmlinux.o modpost_link vmlinux.o -- cgit v1.2.3 From fbe6e37dab974dd0fc3660c001895f7bfd771c9a Mon Sep 17 00:00:00 2001 From: Nicholas Piggin Date: Wed, 24 Aug 2016 22:29:21 +1000 Subject: kbuild: add arch specific post-link Makefile Allow architectures to create arch/xxx/Makefile.postlink with targets for vmlinux, modules.ko, and clean, which will be invoked after final linking of vmlinux and modules. powerpc will use this to check vmlinux linker relocations for sanity, and may use it to fix up alternate instruction patch branch addresses. Signed-off-by: Nicholas Piggin Signed-off-by: Michal Marek --- Documentation/kbuild/makefiles.txt | 16 ++++++++++++++++ Makefile | 10 +++++++--- scripts/Makefile.modpost | 14 +++++++++----- 3 files changed, 32 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/Documentation/kbuild/makefiles.txt b/Documentation/kbuild/makefiles.txt index 385a5ef41c17..9b9c4797fc55 100644 --- a/Documentation/kbuild/makefiles.txt +++ b/Documentation/kbuild/makefiles.txt @@ -41,6 +41,7 @@ This document describes the Linux kernel Makefiles. --- 6.8 Custom kbuild commands --- 6.9 Preprocessing linker scripts --- 6.10 Generic header files + --- 6.11 Post-link pass === 7 Kbuild syntax for exported headers --- 7.1 header-y @@ -1237,6 +1238,21 @@ When kbuild executes, the following steps are followed (roughly): to list the file in the Kbuild file. See "7.4 generic-y" for further info on syntax etc. +--- 6.11 Post-link pass + + If the file arch/xxx/Makefile.postlink exists, this makefile + will be invoked for post-link objects (vmlinux and modules.ko) + for architectures to run post-link passes on. Must also handle + the clean target. + + This pass runs after kallsyms generation. If the architecture + needs to modify symbol locations, rather than manipulate the + kallsyms, it may be easier to add another postlink target for + .tmp_vmlinux? targets to be called from link-vmlinux.sh. + + For example, powerpc uses this to check relocation sanity of + the linked vmlinux file. + === 7 Kbuild syntax for exported headers The kernel includes a set of headers that is exported to userspace. diff --git a/Makefile b/Makefile index 6d40f3a3a8cc..83dae63df91a 100644 --- a/Makefile +++ b/Makefile @@ -957,9 +957,12 @@ endif include/generated/autoksyms.h: FORCE $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh true -# Final link of vmlinux - cmd_link-vmlinux = $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) -quiet_cmd_link-vmlinux = LINK $@ +ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink) + +# Final link of vmlinux with optional arch pass after final link + cmd_link-vmlinux = \ + $(CONFIG_SHELL) $< $(LD) $(LDFLAGS) $(LDFLAGS_vmlinux) ; \ + $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true) vmlinux: scripts/link-vmlinux.sh vmlinux_prereq $(vmlinux-deps) FORCE +$(call if_changed,link-vmlinux) @@ -1286,6 +1289,7 @@ $(clean-dirs): vmlinuxclean: $(Q)$(CONFIG_SHELL) $(srctree)/scripts/link-vmlinux.sh clean + $(Q)$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) clean) clean: archclean vmlinuxclean diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 1366a94b6c39..16923ba4b5b1 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -115,14 +115,18 @@ $(modules:.ko=.mod.o): %.mod.o: %.mod.c FORCE targets += $(modules:.ko=.mod.o) -# Step 6), final link of the modules +ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(SRCARCH)/Makefile.postlink) + +# Step 6), final link of the modules with optional arch pass after final link quiet_cmd_ld_ko_o = LD [M] $@ - cmd_ld_ko_o = $(LD) -r $(LDFLAGS) \ - $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ - -o $@ $(filter-out FORCE,$^) + cmd_ld_ko_o = \ + $(LD) -r $(LDFLAGS) \ + $(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \ + -o $@ $(filter-out FORCE,$^) ; \ + $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true) $(modules): %.ko :%.o %.mod.o FORCE - $(call if_changed,ld_ko_o) + +$(call if_changed,ld_ko_o) targets += $(modules) -- cgit v1.2.3 From 725c4d22bbc4fcac5779963e0ff9cdf232afbb90 Mon Sep 17 00:00:00 2001 From: Christian Borntraeger Date: Mon, 12 Sep 2016 14:37:19 +0200 Subject: ubsan: allow to disable the null sanitizer Some architectures use a hardware defined structure at address zero. Checking for a null pointer will result in many ubsan reports. Allow users to disable the null sanitizer. Signed-off-by: Christian Borntraeger Acked-by: Andrey Ryabinin Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- lib/Kconfig.ubsan | 11 +++++++++++ scripts/Makefile.ubsan | 5 ++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/lib/Kconfig.ubsan b/lib/Kconfig.ubsan index 39494af9a84a..bc6e651df68c 100644 --- a/lib/Kconfig.ubsan +++ b/lib/Kconfig.ubsan @@ -1,6 +1,9 @@ config ARCH_HAS_UBSAN_SANITIZE_ALL bool +config ARCH_WANTS_UBSAN_NO_NULL + def_bool n + config UBSAN bool "Undefined behaviour sanity checker" help @@ -34,3 +37,11 @@ config UBSAN_ALIGNMENT This option enables detection of unaligned memory accesses. Enabling this option on architectures that support unaligned accesses may produce a lot of false positives. + +config UBSAN_NULL + bool "Enable checking of null pointers" + depends on UBSAN + default y if !ARCH_WANTS_UBSAN_NO_NULL + help + This option enables detection of memory accesses via a + null pointer. diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan index 8ab68679cfb5..dd779c40c8e6 100644 --- a/scripts/Makefile.ubsan +++ b/scripts/Makefile.ubsan @@ -3,7 +3,6 @@ ifdef CONFIG_UBSAN CFLAGS_UBSAN += $(call cc-option, -fsanitize=integer-divide-by-zero) CFLAGS_UBSAN += $(call cc-option, -fsanitize=unreachable) CFLAGS_UBSAN += $(call cc-option, -fsanitize=vla-bound) - CFLAGS_UBSAN += $(call cc-option, -fsanitize=null) CFLAGS_UBSAN += $(call cc-option, -fsanitize=signed-integer-overflow) CFLAGS_UBSAN += $(call cc-option, -fsanitize=bounds) CFLAGS_UBSAN += $(call cc-option, -fsanitize=object-size) @@ -14,4 +13,8 @@ ifdef CONFIG_UBSAN ifdef CONFIG_UBSAN_ALIGNMENT CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) endif + +ifdef CONFIG_UBSAN_NULL + CFLAGS_UBSAN += $(call cc-option, -fsanitize=null) +endif endif -- cgit v1.2.3 From 951dbf500aa7df051d7cde15b9ac05608c0bb16f Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (Red Hat)" Date: Wed, 21 Sep 2016 13:43:48 -0400 Subject: ftrace/scripts: Add helper script to bisect function tracing problem functions Every so often, with a special config or a architecture change, running function or function_graph tracing can cause the machien to hard reboot, crash, or simply hard lockup. There's some functions in the function graph tracer that can not be traced otherwise it causes the function tracer to recurse before the recursion protection mechanisms are in place. When this occurs, using the dynamic ftrace featuer that allows limiting what actually gets traced can be used to bisect down to the problem function. This adds a script that helps with this process in the scripts/tracing directory, called ftrace-bisect.sh The set up is to read all the functions that can be traced from available_filter_functions into a file (full_file). Then run this script passing it the full_file and a "test_file" and "non_test_file", where the test_file will be add to set_ftrace_filter. What ftarce_bisect.sh does, is to copy half of the functions in full_file into the test_file and the other half into the non_test_file. This way, one can cat the test_file into the set_ftrace_filter functions and only test the functions that are in that file. If it works, then we run the process again after copying non_test_file to full_file and repeating the process. If the system crashed, then the bad function is in the test_file and after a reboot, the test_file becomes the new full_file in the next iteration. When we get down to a single function in the full_file, then ftrace_bisect.sh will report that as the bad function. Full documentation of how to use this simple script is within the script file itself. Link: http://lkml.kernel.org/r/20160920100716.131d3647@gandalf.local.home Signed-off-by: Steven Rostedt --- scripts/tracing/ftrace-bisect.sh | 115 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100755 scripts/tracing/ftrace-bisect.sh (limited to 'scripts') diff --git a/scripts/tracing/ftrace-bisect.sh b/scripts/tracing/ftrace-bisect.sh new file mode 100755 index 000000000000..9ff8ac5fc53c --- /dev/null +++ b/scripts/tracing/ftrace-bisect.sh @@ -0,0 +1,115 @@ +#!/bin/bash +# +# Here's how to use this: +# +# This script is used to help find functions that are being traced by function +# tracer or function graph tracing that causes the machine to reboot, hang, or +# crash. Here's the steps to take. +# +# First, determine if function tracing is working with a single function: +# +# (note, if this is a problem with function_graph tracing, then simply +# replace "function" with "function_graph" in the following steps). +# +# # cd /sys/kernel/debug/tracing +# # echo schedule > set_ftrace_filter +# # echo function > current_tracer +# +# If this works, then we know that something is being traced that shouldn't be. +# +# # echo nop > current_tracer +# +# # cat available_filter_functions > ~/full-file +# # ftrace-bisect ~/full-file ~/test-file ~/non-test-file +# # cat ~/test-file > set_ftrace_filter +# +# *** Note *** this will take several minutes. Setting multiple functions is +# an O(n^2) operation, and we are dealing with thousands of functions. So go +# have coffee, talk with your coworkers, read facebook. And eventually, this +# operation will end. +# +# # echo function > current_tracer +# +# If it crashes, we know that ~/test-file has a bad function. +# +# Reboot back to test kernel. +# +# # cd /sys/kernel/debug/tracing +# # mv ~/test-file ~/full-file +# +# If it didn't crash. +# +# # echo nop > current_tracer +# # mv ~/non-test-file ~/full-file +# +# Get rid of the other test file from previous run (or save them off somewhere). +# # rm -f ~/test-file ~/non-test-file +# +# And start again: +# +# # ftrace-bisect ~/full-file ~/test-file ~/non-test-file +# +# The good thing is, because this cuts the number of functions in ~/test-file +# by half, the cat of it into set_ftrace_filter takes half as long each +# iteration, so don't talk so much at the water cooler the second time. +# +# Eventually, if you did this correctly, you will get down to the problem +# function, and all we need to do is to notrace it. +# +# The way to figure out if the problem function is bad, just do: +# +# # echo > set_ftrace_notrace +# # echo > set_ftrace_filter +# # echo function > current_tracer +# +# And if it doesn't crash, we are done. +# +# If it does crash, do this again (there's more than one problem function) +# but you need to echo the problem function(s) into set_ftrace_notrace before +# enabling function tracing in the above steps. Or if you can compile the +# kernel, annotate the problem functions with "notrace" and start again. +# + + +if [ $# -ne 3 ]; then + echo 'usage: ftrace-bisect full-file test-file non-test-file' + exit +fi + +full=$1 +test=$2 +nontest=$3 + +x=`cat $full | wc -l` +if [ $x -eq 1 ]; then + echo "There's only one function left, must be the bad one" + cat $full + exit 0 +fi + +let x=$x/2 +let y=$x+1 + +if [ ! -f $full ]; then + echo "$full does not exist" + exit 1 +fi + +if [ -f $test ]; then + echo -n "$test exists, delete it? [y/N]" + read a + if [ "$a" != "y" -a "$a" != "Y" ]; then + exit 1 + fi +fi + +if [ -f $nontest ]; then + echo -n "$nontest exists, delete it? [y/N]" + read a + if [ "$a" != "y" -a "$a" != "Y" ]; then + exit 1 + fi +fi + +sed -ne "1,${x}p" $full > $test +sed -ne "$y,\$p" $full > $nontest -- cgit v1.2.3 From 590abbdd273304b55824bcb9ea91840ea375575d Mon Sep 17 00:00:00 2001 From: Michal Marek Date: Fri, 23 Sep 2016 09:56:05 +0200 Subject: initramfs: Escape colons in depfile Special characters are problematic in depfiles, but we can fix colons easily. Reported-by: Florian Fainelli Signed-off-by: Michal Marek --- scripts/gen_initramfs_list.sh | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 17fa901418ae..0055b07b03b6 100755 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -97,7 +97,10 @@ print_mtime() { } list_parse() { - [ ! -L "$1" ] && echo "$1 \\" || : + if [ -L "$1" ]; then + return + fi + echo "$1" | sed 's/:/\\:/g; s/$/ \\/' } # for each file print a line in following format -- cgit v1.2.3 From 43d96390d57aa0e61d15ce2bcb887df8516d58f5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Wed, 21 Sep 2016 17:48:39 +0200 Subject: Coccinelle: limit memdup_user transformation to GFP_KERNEL case Memdup_user encapsulates a memory allocation with the flag GFP_KERNEL, so only allow this flag in the original code. Signed-off-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/api/memdup_user.cocci | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'scripts') diff --git a/scripts/coccinelle/api/memdup_user.cocci b/scripts/coccinelle/api/memdup_user.cocci index c606231b0e46..2a5aea8e8487 100644 --- a/scripts/coccinelle/api/memdup_user.cocci +++ b/scripts/coccinelle/api/memdup_user.cocci @@ -15,11 +15,11 @@ virtual org virtual report @depends on patch@ -expression from,to,size,flag; +expression from,to,size; identifier l1,l2; @@ -- to = \(kmalloc\|kzalloc\)(size,flag); +- to = \(kmalloc\|kzalloc\)(size,GFP_KERNEL); + to = memdup_user(from,size); if ( - to==NULL @@ -37,12 +37,12 @@ identifier l1,l2; - } @r depends on !patch@ -expression from,to,size,flag; +expression from,to,size; position p; statement S1,S2; @@ -* to = \(kmalloc@p\|kzalloc@p\)(size,flag); +* to = \(kmalloc@p\|kzalloc@p\)(size,GFP_KERNEL); if (to==NULL || ...) S1 if (copy_from_user(to, from, size) != 0) S2 -- cgit v1.2.3 From d97629f1686574a800a76eb0d2ce65e3f3d3ef92 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Thu, 22 Sep 2016 10:28:55 +0200 Subject: Coccinelle: pm_runtime: ensure relevance of pm_runtime reports pm_runtime.cocci starts with one rule that searches for a variety of functions calls, followed by various rules that report errors. Previously, the only connection between the first rule and the rest was to check that the first rule had matched somewhere. Change the rules to propagate a position from the first rule to the others, to make sure that the sites reported on are the same as the sites that were identified as having the relevant functions. Signed-off-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccinelle/api/pm_runtime.cocci | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/coccinelle/api/pm_runtime.cocci b/scripts/coccinelle/api/pm_runtime.cocci index 89b98a2f7a6f..d67ccf5f8227 100644 --- a/scripts/coccinelle/api/pm_runtime.cocci +++ b/scripts/coccinelle/api/pm_runtime.cocci @@ -17,9 +17,10 @@ virtual report @runtime_bad_err_handle exists@ expression ret; +position p; @@ ( -ret = \(pm_runtime_idle\| +ret@p = \(pm_runtime_idle\| pm_runtime_suspend\| pm_runtime_autosuspend\| pm_runtime_resume\| @@ -47,12 +48,13 @@ IS_ERR_VALUE(ret) // For context mode //---------------------------------------------------------- -@depends on runtime_bad_err_handle && context@ +@depends on context@ identifier pm_runtime_api; expression ret; +position runtime_bad_err_handle.p; @@ ( -ret = pm_runtime_api(...); +ret@p = pm_runtime_api(...); ... * IS_ERR_VALUE(ret) ... @@ -62,12 +64,13 @@ ret = pm_runtime_api(...); // For patch mode //---------------------------------------------------------- -@depends on runtime_bad_err_handle && patch@ +@depends on patch@ identifier pm_runtime_api; expression ret; +position runtime_bad_err_handle.p; @@ ( -ret = pm_runtime_api(...); +ret@p = pm_runtime_api(...); ... - IS_ERR_VALUE(ret) + ret < 0 @@ -78,13 +81,14 @@ ret = pm_runtime_api(...); // For org and report mode //---------------------------------------------------------- -@r depends on runtime_bad_err_handle && (org || report) exists@ +@r depends on (org || report) exists@ position p1, p2; identifier pm_runtime_api; expression ret; +position runtime_bad_err_handle.p; @@ ( -ret = pm_runtime_api@p1(...); +ret@p = pm_runtime_api@p1(...); ... IS_ERR_VALUE@p2(ret) ... -- cgit v1.2.3 From 6727ad9e206cc08b80d8000a4d67f8417e53539d Mon Sep 17 00:00:00 2001 From: Chris Metcalf Date: Fri, 7 Oct 2016 17:02:55 -0700 Subject: nmi_backtrace: generate one-line reports for idle cpus When doing an nmi backtrace of many cores, most of which are idle, the output is a little overwhelming and very uninformative. Suppress messages for cpus that are idling when they are interrupted and just emit one line, "NMI backtrace for N skipped: idling at pc 0xNNN". We do this by grouping all the cpuidle code together into a new .cpuidle.text section, and then checking the address of the interrupted PC to see if it lies within that section. This commit suitably tags x86 and tile idle routines, and only adds in the minimal framework for other architectures. Link: http://lkml.kernel.org/r/1472487169-14923-5-git-send-email-cmetcalf@mellanox.com Signed-off-by: Chris Metcalf Acked-by: Peter Zijlstra (Intel) Tested-by: Peter Zijlstra (Intel) Tested-by: Daniel Thompson [arm] Tested-by: Petr Mladek Cc: Aaron Tomlin Cc: Peter Zijlstra (Intel) Cc: "Rafael J. Wysocki" Cc: Russell King Cc: Thomas Gleixner Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/alpha/kernel/vmlinux.lds.S | 1 + arch/arc/kernel/vmlinux.lds.S | 1 + arch/arm/kernel/vmlinux-xip.lds.S | 1 + arch/arm/kernel/vmlinux.lds.S | 1 + arch/arm64/kernel/vmlinux.lds.S | 1 + arch/avr32/kernel/vmlinux.lds.S | 1 + arch/blackfin/kernel/vmlinux.lds.S | 1 + arch/c6x/kernel/vmlinux.lds.S | 1 + arch/cris/kernel/vmlinux.lds.S | 1 + arch/frv/kernel/vmlinux.lds.S | 1 + arch/h8300/kernel/vmlinux.lds.S | 1 + arch/hexagon/kernel/vmlinux.lds.S | 1 + arch/ia64/kernel/vmlinux.lds.S | 1 + arch/m32r/kernel/vmlinux.lds.S | 1 + arch/m68k/kernel/vmlinux-nommu.lds | 1 + arch/m68k/kernel/vmlinux-std.lds | 1 + arch/m68k/kernel/vmlinux-sun3.lds | 1 + arch/metag/kernel/vmlinux.lds.S | 1 + arch/microblaze/kernel/vmlinux.lds.S | 1 + arch/mips/kernel/vmlinux.lds.S | 1 + arch/mn10300/kernel/vmlinux.lds.S | 1 + arch/nios2/kernel/vmlinux.lds.S | 1 + arch/openrisc/kernel/vmlinux.lds.S | 1 + arch/parisc/kernel/vmlinux.lds.S | 1 + arch/powerpc/kernel/vmlinux.lds.S | 1 + arch/s390/kernel/vmlinux.lds.S | 1 + arch/score/kernel/vmlinux.lds.S | 1 + arch/sh/kernel/vmlinux.lds.S | 1 + arch/sparc/kernel/vmlinux.lds.S | 1 + arch/tile/kernel/entry.S | 2 +- arch/tile/kernel/vmlinux.lds.S | 1 + arch/um/kernel/dyn.lds.S | 1 + arch/um/kernel/uml.lds.S | 1 + arch/unicore32/kernel/vmlinux.lds.S | 1 + arch/x86/include/asm/irqflags.h | 12 ++++++++---- arch/x86/kernel/acpi/cstate.c | 2 +- arch/x86/kernel/process.c | 4 ++-- arch/x86/kernel/vmlinux.lds.S | 1 + arch/xtensa/kernel/vmlinux.lds.S | 3 +++ drivers/acpi/processor_idle.c | 5 +++-- drivers/cpuidle/driver.c | 5 +++-- drivers/idle/intel_idle.c | 4 ++-- include/asm-generic/vmlinux.lds.h | 6 ++++++ include/linux/cpu.h | 5 +++++ kernel/sched/idle.c | 13 +++++++++++-- lib/nmi_backtrace.c | 16 +++++++++++----- scripts/mod/modpost.c | 2 +- scripts/recordmcount.c | 1 + scripts/recordmcount.pl | 1 + 49 files changed, 93 insertions(+), 22 deletions(-) (limited to 'scripts') diff --git a/arch/alpha/kernel/vmlinux.lds.S b/arch/alpha/kernel/vmlinux.lds.S index 647b84c15382..cebecfb76fbf 100644 --- a/arch/alpha/kernel/vmlinux.lds.S +++ b/arch/alpha/kernel/vmlinux.lds.S @@ -22,6 +22,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.gnu.warning) diff --git a/arch/arc/kernel/vmlinux.lds.S b/arch/arc/kernel/vmlinux.lds.S index 36611072305f..f35ed578e007 100644 --- a/arch/arc/kernel/vmlinux.lds.S +++ b/arch/arc/kernel/vmlinux.lds.S @@ -89,6 +89,7 @@ SECTIONS _text = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT *(.fixup) diff --git a/arch/arm/kernel/vmlinux-xip.lds.S b/arch/arm/kernel/vmlinux-xip.lds.S index cba1ec899a69..7fa487ef7e2f 100644 --- a/arch/arm/kernel/vmlinux-xip.lds.S +++ b/arch/arm/kernel/vmlinux-xip.lds.S @@ -98,6 +98,7 @@ SECTIONS IRQENTRY_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT *(.gnu.warning) diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S index d24e5dd2aa7a..f7f55df0bf7b 100644 --- a/arch/arm/kernel/vmlinux.lds.S +++ b/arch/arm/kernel/vmlinux.lds.S @@ -111,6 +111,7 @@ SECTIONS SOFTIRQENTRY_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT HYPERVISOR_TEXT KPROBES_TEXT diff --git a/arch/arm64/kernel/vmlinux.lds.S b/arch/arm64/kernel/vmlinux.lds.S index 5ce9b2929e0d..1105aab1e6d6 100644 --- a/arch/arm64/kernel/vmlinux.lds.S +++ b/arch/arm64/kernel/vmlinux.lds.S @@ -122,6 +122,7 @@ SECTIONS ENTRY_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT HYPERVISOR_TEXT diff --git a/arch/avr32/kernel/vmlinux.lds.S b/arch/avr32/kernel/vmlinux.lds.S index a4589176bed5..17f2730eb497 100644 --- a/arch/avr32/kernel/vmlinux.lds.S +++ b/arch/avr32/kernel/vmlinux.lds.S @@ -52,6 +52,7 @@ SECTIONS KPROBES_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.gnu.warning) diff --git a/arch/blackfin/kernel/vmlinux.lds.S b/arch/blackfin/kernel/vmlinux.lds.S index d920b959ff3a..68069a120055 100644 --- a/arch/blackfin/kernel/vmlinux.lds.S +++ b/arch/blackfin/kernel/vmlinux.lds.S @@ -33,6 +33,7 @@ SECTIONS #ifndef CONFIG_SCHEDULE_L1 SCHED_TEXT #endif + CPUIDLE_TEXT LOCK_TEXT IRQENTRY_TEXT SOFTIRQENTRY_TEXT diff --git a/arch/c6x/kernel/vmlinux.lds.S b/arch/c6x/kernel/vmlinux.lds.S index 50bc10f97bcb..a1a5c166bc9b 100644 --- a/arch/c6x/kernel/vmlinux.lds.S +++ b/arch/c6x/kernel/vmlinux.lds.S @@ -70,6 +70,7 @@ SECTIONS _stext = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT IRQENTRY_TEXT SOFTIRQENTRY_TEXT diff --git a/arch/cris/kernel/vmlinux.lds.S b/arch/cris/kernel/vmlinux.lds.S index 7552c2557506..979586261520 100644 --- a/arch/cris/kernel/vmlinux.lds.S +++ b/arch/cris/kernel/vmlinux.lds.S @@ -43,6 +43,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.text.__*) diff --git a/arch/frv/kernel/vmlinux.lds.S b/arch/frv/kernel/vmlinux.lds.S index 7e958d829ec9..aa6e573d57da 100644 --- a/arch/frv/kernel/vmlinux.lds.S +++ b/arch/frv/kernel/vmlinux.lds.S @@ -63,6 +63,7 @@ SECTIONS *(.text..tlbmiss) TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT #ifdef CONFIG_DEBUG_INFO INIT_TEXT diff --git a/arch/h8300/kernel/vmlinux.lds.S b/arch/h8300/kernel/vmlinux.lds.S index cb5dfb02c88d..7f11da1b895e 100644 --- a/arch/h8300/kernel/vmlinux.lds.S +++ b/arch/h8300/kernel/vmlinux.lds.S @@ -29,6 +29,7 @@ SECTIONS _stext = . ; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT #if defined(CONFIG_ROMKERNEL) *(.int_redirect) diff --git a/arch/hexagon/kernel/vmlinux.lds.S b/arch/hexagon/kernel/vmlinux.lds.S index 5f268c1071b3..ec87e67feb19 100644 --- a/arch/hexagon/kernel/vmlinux.lds.S +++ b/arch/hexagon/kernel/vmlinux.lds.S @@ -50,6 +50,7 @@ SECTIONS _text = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT *(.fixup) diff --git a/arch/ia64/kernel/vmlinux.lds.S b/arch/ia64/kernel/vmlinux.lds.S index dc506b05ffbd..f89d20c97412 100644 --- a/arch/ia64/kernel/vmlinux.lds.S +++ b/arch/ia64/kernel/vmlinux.lds.S @@ -46,6 +46,7 @@ SECTIONS { __end_ivt_text = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT *(.gnu.linkonce.t*) diff --git a/arch/m32r/kernel/vmlinux.lds.S b/arch/m32r/kernel/vmlinux.lds.S index 018e4a711d79..ad1fe56455aa 100644 --- a/arch/m32r/kernel/vmlinux.lds.S +++ b/arch/m32r/kernel/vmlinux.lds.S @@ -31,6 +31,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.gnu.warning) diff --git a/arch/m68k/kernel/vmlinux-nommu.lds b/arch/m68k/kernel/vmlinux-nommu.lds index 06a763f49fd3..d2c8abf1c8c4 100644 --- a/arch/m68k/kernel/vmlinux-nommu.lds +++ b/arch/m68k/kernel/vmlinux-nommu.lds @@ -45,6 +45,7 @@ SECTIONS { HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) . = ALIGN(16); diff --git a/arch/m68k/kernel/vmlinux-std.lds b/arch/m68k/kernel/vmlinux-std.lds index d0993594f558..5b5ce1e4d1ed 100644 --- a/arch/m68k/kernel/vmlinux-std.lds +++ b/arch/m68k/kernel/vmlinux-std.lds @@ -16,6 +16,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.gnu.warning) diff --git a/arch/m68k/kernel/vmlinux-sun3.lds b/arch/m68k/kernel/vmlinux-sun3.lds index 8080469ee6c1..fe5ea1974b16 100644 --- a/arch/m68k/kernel/vmlinux-sun3.lds +++ b/arch/m68k/kernel/vmlinux-sun3.lds @@ -16,6 +16,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.gnu.warning) diff --git a/arch/metag/kernel/vmlinux.lds.S b/arch/metag/kernel/vmlinux.lds.S index 150ace92c7ad..e6c700eaf207 100644 --- a/arch/metag/kernel/vmlinux.lds.S +++ b/arch/metag/kernel/vmlinux.lds.S @@ -21,6 +21,7 @@ SECTIONS .text : { TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/microblaze/kernel/vmlinux.lds.S b/arch/microblaze/kernel/vmlinux.lds.S index 0a47f0410554..289d0e7f3e3a 100644 --- a/arch/microblaze/kernel/vmlinux.lds.S +++ b/arch/microblaze/kernel/vmlinux.lds.S @@ -33,6 +33,7 @@ SECTIONS { EXIT_TEXT EXIT_CALL SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S index a82c178d0bb9..d5de67591735 100644 --- a/arch/mips/kernel/vmlinux.lds.S +++ b/arch/mips/kernel/vmlinux.lds.S @@ -55,6 +55,7 @@ SECTIONS .text : { TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/mn10300/kernel/vmlinux.lds.S b/arch/mn10300/kernel/vmlinux.lds.S index 13c4814c29f8..2d5f1c3f1afb 100644 --- a/arch/mn10300/kernel/vmlinux.lds.S +++ b/arch/mn10300/kernel/vmlinux.lds.S @@ -30,6 +30,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT *(.fixup) diff --git a/arch/nios2/kernel/vmlinux.lds.S b/arch/nios2/kernel/vmlinux.lds.S index e23e89539967..6a8045bb1a77 100644 --- a/arch/nios2/kernel/vmlinux.lds.S +++ b/arch/nios2/kernel/vmlinux.lds.S @@ -37,6 +37,7 @@ SECTIONS .text : { TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT IRQENTRY_TEXT SOFTIRQENTRY_TEXT diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S index d936de4c07ca..d68b9ede8423 100644 --- a/arch/openrisc/kernel/vmlinux.lds.S +++ b/arch/openrisc/kernel/vmlinux.lds.S @@ -47,6 +47,7 @@ SECTIONS _stext = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/parisc/kernel/vmlinux.lds.S b/arch/parisc/kernel/vmlinux.lds.S index f3ead0b6ce46..9ec8ec075dae 100644 --- a/arch/parisc/kernel/vmlinux.lds.S +++ b/arch/parisc/kernel/vmlinux.lds.S @@ -69,6 +69,7 @@ SECTIONS .text ALIGN(PAGE_SIZE) : { TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S index b5fba689fca6..7ed59f0d947f 100644 --- a/arch/powerpc/kernel/vmlinux.lds.S +++ b/arch/powerpc/kernel/vmlinux.lds.S @@ -52,6 +52,7 @@ SECTIONS /* careful! __ftr_alt_* sections need to be close to .text */ *(.text .fixup __ftr_alt_* .ref.text) SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S index 429bfd111961..000e6e91f6a0 100644 --- a/arch/s390/kernel/vmlinux.lds.S +++ b/arch/s390/kernel/vmlinux.lds.S @@ -35,6 +35,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/score/kernel/vmlinux.lds.S b/arch/score/kernel/vmlinux.lds.S index 7274b5c4287e..4117890b1db1 100644 --- a/arch/score/kernel/vmlinux.lds.S +++ b/arch/score/kernel/vmlinux.lds.S @@ -40,6 +40,7 @@ SECTIONS _text = .; /* Text and read-only data */ TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT *(.text.*) diff --git a/arch/sh/kernel/vmlinux.lds.S b/arch/sh/kernel/vmlinux.lds.S index 235a4101999f..5b9a3cc90c58 100644 --- a/arch/sh/kernel/vmlinux.lds.S +++ b/arch/sh/kernel/vmlinux.lds.S @@ -36,6 +36,7 @@ SECTIONS TEXT_TEXT EXTRA_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S index d79b3b734245..572db686f845 100644 --- a/arch/sparc/kernel/vmlinux.lds.S +++ b/arch/sparc/kernel/vmlinux.lds.S @@ -49,6 +49,7 @@ SECTIONS HEAD_TEXT TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/tile/kernel/entry.S b/arch/tile/kernel/entry.S index 670a3569450f..101de132e363 100644 --- a/arch/tile/kernel/entry.S +++ b/arch/tile/kernel/entry.S @@ -50,7 +50,7 @@ STD_ENTRY(smp_nap) * When interrupted at _cpu_idle_nap, we bump the PC forward 8, and * as a result return to the function that called _cpu_idle(). */ -STD_ENTRY(_cpu_idle) +STD_ENTRY_SECTION(_cpu_idle, .cpuidle.text) movei r1, 1 IRQ_ENABLE_LOAD(r2, r3) mtspr INTERRUPT_CRITICAL_SECTION, r1 diff --git a/arch/tile/kernel/vmlinux.lds.S b/arch/tile/kernel/vmlinux.lds.S index 9d449caf8910..e1baf094fba4 100644 --- a/arch/tile/kernel/vmlinux.lds.S +++ b/arch/tile/kernel/vmlinux.lds.S @@ -42,6 +42,7 @@ SECTIONS .text : AT (ADDR(.text) - LOAD_OFFSET) { HEAD_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT IRQENTRY_TEXT diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index adde088aeeff..4fdbcf958cd5 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -68,6 +68,7 @@ SECTIONS _stext = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) *(.stub .text.* .gnu.linkonce.t.*) diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S index 6899195602b7..1840f55ed042 100644 --- a/arch/um/kernel/uml.lds.S +++ b/arch/um/kernel/uml.lds.S @@ -28,6 +28,7 @@ SECTIONS _stext = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) /* .gnu.warning sections are handled specially by elf32.em. */ diff --git a/arch/unicore32/kernel/vmlinux.lds.S b/arch/unicore32/kernel/vmlinux.lds.S index 77e407e49a63..56e788e8ee83 100644 --- a/arch/unicore32/kernel/vmlinux.lds.S +++ b/arch/unicore32/kernel/vmlinux.lds.S @@ -37,6 +37,7 @@ SECTIONS .text : { /* Real text segment */ TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT *(.fixup) diff --git a/arch/x86/include/asm/irqflags.h b/arch/x86/include/asm/irqflags.h index b77f5edb03b0..ac7692dcfa2e 100644 --- a/arch/x86/include/asm/irqflags.h +++ b/arch/x86/include/asm/irqflags.h @@ -4,6 +4,10 @@ #include #ifndef __ASSEMBLY__ + +/* Provide __cpuidle; we can't safely include */ +#define __cpuidle __attribute__((__section__(".cpuidle.text"))) + /* * Interrupt control: */ @@ -44,12 +48,12 @@ static inline void native_irq_enable(void) asm volatile("sti": : :"memory"); } -static inline void native_safe_halt(void) +static inline __cpuidle void native_safe_halt(void) { asm volatile("sti; hlt": : :"memory"); } -static inline void native_halt(void) +static inline __cpuidle void native_halt(void) { asm volatile("hlt": : :"memory"); } @@ -86,7 +90,7 @@ static inline notrace void arch_local_irq_enable(void) * Used in the idle loop; sti takes one instruction cycle * to complete: */ -static inline void arch_safe_halt(void) +static inline __cpuidle void arch_safe_halt(void) { native_safe_halt(); } @@ -95,7 +99,7 @@ static inline void arch_safe_halt(void) * Used when interrupts are already enabled or to * shutdown the processor: */ -static inline void halt(void) +static inline __cpuidle void halt(void) { native_halt(); } diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c index bdfad642123f..af15f4444330 100644 --- a/arch/x86/kernel/acpi/cstate.c +++ b/arch/x86/kernel/acpi/cstate.c @@ -152,7 +152,7 @@ int acpi_processor_ffh_cstate_probe(unsigned int cpu, } EXPORT_SYMBOL_GPL(acpi_processor_ffh_cstate_probe); -void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) +void __cpuidle acpi_processor_ffh_cstate_enter(struct acpi_processor_cx *cx) { unsigned int cpu = smp_processor_id(); struct cstate_entry *percpu_entry; diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 4002b475171c..28cea7802ecb 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -302,7 +302,7 @@ void arch_cpu_idle(void) /* * We use this if we don't have any better idle routine.. */ -void default_idle(void) +void __cpuidle default_idle(void) { trace_cpu_idle_rcuidle(1, smp_processor_id()); safe_halt(); @@ -417,7 +417,7 @@ static int prefer_mwait_c1_over_halt(const struct cpuinfo_x86 *c) * with interrupts enabled and no flags, which is backwards compatible with the * original MWAIT implementation. */ -static void mwait_idle(void) +static __cpuidle void mwait_idle(void) { if (!current_set_polling_and_test()) { trace_cpu_idle_rcuidle(1, smp_processor_id()); diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S index 9297a002d8e5..dbf67f64d5ec 100644 --- a/arch/x86/kernel/vmlinux.lds.S +++ b/arch/x86/kernel/vmlinux.lds.S @@ -97,6 +97,7 @@ SECTIONS _stext = .; TEXT_TEXT SCHED_TEXT + CPUIDLE_TEXT LOCK_TEXT KPROBES_TEXT ENTRY_TEXT diff --git a/arch/xtensa/kernel/vmlinux.lds.S b/arch/xtensa/kernel/vmlinux.lds.S index 72cfe3587dd8..31411fc82662 100644 --- a/arch/xtensa/kernel/vmlinux.lds.S +++ b/arch/xtensa/kernel/vmlinux.lds.S @@ -89,6 +89,9 @@ SECTIONS VMLINUX_SYMBOL(__sched_text_start) = .; *(.sched.literal .sched.text) VMLINUX_SYMBOL(__sched_text_end) = .; + VMLINUX_SYMBOL(__cpuidle_text_start) = .; + *(.cpuidle.literal .cpuidle.text) + VMLINUX_SYMBOL(__cpuidle_text_end) = .; VMLINUX_SYMBOL(__lock_text_start) = .; *(.spinlock.literal .spinlock.text) VMLINUX_SYMBOL(__lock_text_end) = .; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index cea52528aa18..2237d3f24f0e 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -31,6 +31,7 @@ #include /* need_resched() */ #include #include +#include #include /* @@ -115,7 +116,7 @@ static const struct dmi_system_id processor_power_dmi_table[] = { * Callers should disable interrupts before the call and enable * interrupts after return. */ -static void acpi_safe_halt(void) +static void __cpuidle acpi_safe_halt(void) { if (!tif_need_resched()) { safe_halt(); @@ -645,7 +646,7 @@ static int acpi_idle_bm_check(void) * * Caller disables interrupt before call and enables interrupt after return. */ -static void acpi_idle_do_entry(struct acpi_processor_cx *cx) +static void __cpuidle acpi_idle_do_entry(struct acpi_processor_cx *cx) { if (cx->entry_method == ACPI_CSTATE_FFH) { /* Call into architectural FFH based C-state */ diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index 389ade4572be..ab264d393233 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "cpuidle.h" @@ -178,8 +179,8 @@ static void __cpuidle_driver_init(struct cpuidle_driver *drv) } #ifdef CONFIG_ARCH_HAS_CPU_RELAX -static int poll_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) +static int __cpuidle poll_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { local_irq_enable(); if (!current_set_polling_and_test()) { diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 67ec58f9ef99..4466a2f969d7 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c @@ -863,8 +863,8 @@ static struct cpuidle_state dnv_cstates[] = { * * Must be called under local_irq_disable(). */ -static int intel_idle(struct cpuidle_device *dev, - struct cpuidle_driver *drv, int index) +static __cpuidle int intel_idle(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) { unsigned long ecx = 1; /* break on interrupt flag */ struct cpuidle_state *state = &drv->states[index]; diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h index 24563970ff7b..3e42bcdd014b 100644 --- a/include/asm-generic/vmlinux.lds.h +++ b/include/asm-generic/vmlinux.lds.h @@ -454,6 +454,12 @@ *(.spinlock.text) \ VMLINUX_SYMBOL(__lock_text_end) = .; +#define CPUIDLE_TEXT \ + ALIGN_FUNCTION(); \ + VMLINUX_SYMBOL(__cpuidle_text_start) = .; \ + *(.cpuidle.text) \ + VMLINUX_SYMBOL(__cpuidle_text_end) = .; + #define KPROBES_TEXT \ ALIGN_FUNCTION(); \ VMLINUX_SYMBOL(__kprobes_text_start) = .; \ diff --git a/include/linux/cpu.h b/include/linux/cpu.h index 7572d9e9dced..b886dc17f2f3 100644 --- a/include/linux/cpu.h +++ b/include/linux/cpu.h @@ -231,6 +231,11 @@ void cpu_startup_entry(enum cpuhp_state state); void cpu_idle_poll_ctrl(bool enable); +/* Attach to any functions which should be considered cpuidle. */ +#define __cpuidle __attribute__((__section__(".cpuidle.text"))) + +bool cpu_in_idle(unsigned long pc); + void arch_cpu_idle(void); void arch_cpu_idle_prepare(void); void arch_cpu_idle_enter(void); diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c index 9fb873cfc75c..1d8718d5300d 100644 --- a/kernel/sched/idle.c +++ b/kernel/sched/idle.c @@ -16,6 +16,9 @@ #include "sched.h" +/* Linker adds these: start and end of __cpuidle functions */ +extern char __cpuidle_text_start[], __cpuidle_text_end[]; + /** * sched_idle_set_state - Record idle state for the current CPU. * @idle_state: State to record. @@ -53,7 +56,7 @@ static int __init cpu_idle_nopoll_setup(char *__unused) __setup("hlt", cpu_idle_nopoll_setup); #endif -static inline int cpu_idle_poll(void) +static noinline int __cpuidle cpu_idle_poll(void) { rcu_idle_enter(); trace_cpu_idle_rcuidle(0, smp_processor_id()); @@ -84,7 +87,7 @@ void __weak arch_cpu_idle(void) * * To use when the cpuidle framework cannot be used. */ -void default_idle_call(void) +void __cpuidle default_idle_call(void) { if (current_clr_polling_and_test()) { local_irq_enable(); @@ -271,6 +274,12 @@ static void cpu_idle_loop(void) } } +bool cpu_in_idle(unsigned long pc) +{ + return pc >= (unsigned long)__cpuidle_text_start && + pc < (unsigned long)__cpuidle_text_end; +} + void cpu_startup_entry(enum cpuhp_state state) { /* diff --git a/lib/nmi_backtrace.c b/lib/nmi_backtrace.c index 393a3cca1f47..75554754eadf 100644 --- a/lib/nmi_backtrace.c +++ b/lib/nmi_backtrace.c @@ -16,6 +16,7 @@ #include #include #include +#include #ifdef arch_trigger_cpumask_backtrace /* For reliability, we're prepared to waste bits here. */ @@ -87,11 +88,16 @@ bool nmi_cpu_backtrace(struct pt_regs *regs) int cpu = smp_processor_id(); if (cpumask_test_cpu(cpu, to_cpumask(backtrace_mask))) { - pr_warn("NMI backtrace for cpu %d\n", cpu); - if (regs) - show_regs(regs); - else - dump_stack(); + if (regs && cpu_in_idle(instruction_pointer(regs))) { + pr_warn("NMI backtrace for cpu %d skipped: idling at pc %#lx\n", + cpu, instruction_pointer(regs)); + } else { + pr_warn("NMI backtrace for cpu %d\n", cpu); + if (regs) + show_regs(regs); + else + dump_stack(); + } cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask)); return true; } diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 48958d3cec9e..bd8349759095 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -888,7 +888,7 @@ static void check_section(const char *modname, struct elf_info *elf, #define DATA_SECTIONS ".data", ".data.rel" #define TEXT_SECTIONS ".text", ".text.unlikely", ".sched.text", \ - ".kprobes.text" + ".kprobes.text", ".cpuidle.text" #define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \ ".fixup", ".entry.text", ".exception.text", ".text.*", \ ".coldtext" diff --git a/scripts/recordmcount.c b/scripts/recordmcount.c index a68f03133df9..5423a58d1b06 100644 --- a/scripts/recordmcount.c +++ b/scripts/recordmcount.c @@ -365,6 +365,7 @@ is_mcounted_section_name(char const *const txtname) strcmp(".irqentry.text", txtname) == 0 || strcmp(".softirqentry.text", txtname) == 0 || strcmp(".kprobes.text", txtname) == 0 || + strcmp(".cpuidle.text", txtname) == 0 || strcmp(".text.unlikely", txtname) == 0; } diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 2d48011bc362..faac4b10d8ea 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -136,6 +136,7 @@ my %text_sections = ( ".irqentry.text" => 1, ".softirqentry.text" => 1, ".kprobes.text" => 1, + ".cpuidle.text" => 1, ".text.unlikely" => 1, ); -- cgit v1.2.3 From 470164572dc2f9e76e078e08498dfe32ae2faa6f Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Fri, 7 Oct 2016 17:02:58 -0700 Subject: spelling.txt: "modeled" is spelt correctly No need to correct the correct. Link: http://lkml.kernel.org/r/1472490791.3425.38.camel@perches.com Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/spelling.txt | 1 - 1 file changed, 1 deletion(-) (limited to 'scripts') diff --git a/scripts/spelling.txt b/scripts/spelling.txt index fa79c6d2a5b8..163c720d3f2b 100644 --- a/scripts/spelling.txt +++ b/scripts/spelling.txt @@ -629,7 +629,6 @@ mispelt||misspelt miximum||maximum mmnemonic||mnemonic mnay||many -modeled||modelled modulues||modules monochorome||monochrome monochromo||monochrome -- cgit v1.2.3 From 38addce8b600ca335dc86fa3d48c890f1c6fa1f4 Mon Sep 17 00:00:00 2001 From: Emese Revfy Date: Mon, 20 Jun 2016 20:41:19 +0200 Subject: gcc-plugins: Add latent_entropy plugin This adds a new gcc plugin named "latent_entropy". It is designed to extract as much possible uncertainty from a running system at boot time as possible, hoping to capitalize on any possible variation in CPU operation (due to runtime data differences, hardware differences, SMP ordering, thermal timing variation, cache behavior, etc). At the very least, this plugin is a much more comprehensive example for how to manipulate kernel code using the gcc plugin internals. The need for very-early boot entropy tends to be very architecture or system design specific, so this plugin is more suited for those sorts of special cases. The existing kernel RNG already attempts to extract entropy from reliable runtime variation, but this plugin takes the idea to a logical extreme by permuting a global variable based on any variation in code execution (e.g. a different value (and permutation function) is used to permute the global based on loop count, case statement, if/then/else branching, etc). To do this, the plugin starts by inserting a local variable in every marked function. The plugin then adds logic so that the value of this variable is modified by randomly chosen operations (add, xor and rol) and random values (gcc generates separate static values for each location at compile time and also injects the stack pointer at runtime). The resulting value depends on the control flow path (e.g., loops and branches taken). Before the function returns, the plugin mixes this local variable into the latent_entropy global variable. The value of this global variable is added to the kernel entropy pool in do_one_initcall() and _do_fork(), though it does not credit any bytes of entropy to the pool; the contents of the global are just used to mix the pool. Additionally, the plugin can pre-initialize arrays with build-time random contents, so that two different kernel builds running on identical hardware will not have the same starting values. Signed-off-by: Emese Revfy [kees: expanded commit message and code comments] Signed-off-by: Kees Cook --- arch/Kconfig | 18 + arch/powerpc/kernel/Makefile | 5 + include/linux/random.h | 11 + init/main.c | 1 + kernel/fork.c | 1 + mm/page_alloc.c | 5 + scripts/Makefile.gcc-plugins | 9 +- scripts/gcc-plugins/latent_entropy_plugin.c | 640 ++++++++++++++++++++++++++++ 8 files changed, 689 insertions(+), 1 deletion(-) create mode 100644 scripts/gcc-plugins/latent_entropy_plugin.c (limited to 'scripts') diff --git a/arch/Kconfig b/arch/Kconfig index fd6e9712af81..ae80cd24e8f0 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -383,6 +383,24 @@ config GCC_PLUGIN_SANCOV gcc-4.5 on). It is based on the commit "Add fuzzing coverage support" by Dmitry Vyukov . +config GCC_PLUGIN_LATENT_ENTROPY + bool "Generate some entropy during boot and runtime" + depends on GCC_PLUGINS + help + By saying Y here the kernel will instrument some kernel code to + extract some entropy from both original and artificially created + program state. This will help especially embedded systems where + there is little 'natural' source of entropy normally. The cost + is some slowdown of the boot process (about 0.5%) and fork and + irq processing. + + Note that entropy extracted this way is not cryptographically + secure! + + This plugin was ported from grsecurity/PaX. More information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + config HAVE_CC_STACKPROTECTOR bool help diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index fe4c075bcf50..62df36c3f138 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -14,6 +14,11 @@ CFLAGS_prom_init.o += -fPIC CFLAGS_btext.o += -fPIC endif +CFLAGS_cputable.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) +CFLAGS_init.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) +CFLAGS_btext.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) +CFLAGS_prom.o += $(DISABLE_LATENT_ENTROPY_PLUGIN) + ifdef CONFIG_FUNCTION_TRACER # Do not trace early boot code CFLAGS_REMOVE_cputable.o = -mno-sched-epilog $(CC_FLAGS_FTRACE) diff --git a/include/linux/random.h b/include/linux/random.h index 3d6e9815cd85..a59c74cdb1eb 100644 --- a/include/linux/random.h +++ b/include/linux/random.h @@ -18,6 +18,17 @@ struct random_ready_callback { }; extern void add_device_randomness(const void *, unsigned int); + +#if defined(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) && !defined(__CHECKER__) +static inline void add_latent_entropy(void) +{ + add_device_randomness((const void *)&latent_entropy, + sizeof(latent_entropy)); +} +#else +static inline void add_latent_entropy(void) {} +#endif + extern void add_input_randomness(unsigned int type, unsigned int code, unsigned int value); extern void add_interrupt_randomness(int irq, int irq_flags); diff --git a/init/main.c b/init/main.c index a8a58e2794a5..2858be732f6d 100644 --- a/init/main.c +++ b/init/main.c @@ -789,6 +789,7 @@ int __init_or_module do_one_initcall(initcall_t fn) } WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf); + add_latent_entropy(); return ret; } diff --git a/kernel/fork.c b/kernel/fork.c index beb31725f7e2..001b18473a07 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -1780,6 +1780,7 @@ long _do_fork(unsigned long clone_flags, p = copy_process(clone_flags, stack_start, stack_size, child_tidptr, NULL, trace, tls, NUMA_NO_NODE); + add_latent_entropy(); /* * Do this prior waking up the new thread - the thread pointer * might get invalid after that point, if the thread exits quickly. diff --git a/mm/page_alloc.c b/mm/page_alloc.c index a2214c64ed3c..248851d1fc86 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -91,6 +91,11 @@ EXPORT_PER_CPU_SYMBOL(_numa_mem_); int _node_numa_mem_[MAX_NUMNODES]; #endif +#ifdef CONFIG_GCC_PLUGIN_LATENT_ENTROPY +volatile u64 latent_entropy; +EXPORT_SYMBOL(latent_entropy); +#endif + /* * Array of node states. */ diff --git a/scripts/Makefile.gcc-plugins b/scripts/Makefile.gcc-plugins index 61f0e6db909b..060d2cb373db 100644 --- a/scripts/Makefile.gcc-plugins +++ b/scripts/Makefile.gcc-plugins @@ -6,6 +6,12 @@ ifdef CONFIG_GCC_PLUGINS gcc-plugin-$(CONFIG_GCC_PLUGIN_CYC_COMPLEXITY) += cyc_complexity_plugin.so + gcc-plugin-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += latent_entropy_plugin.so + gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_LATENT_ENTROPY) += -DLATENT_ENTROPY_PLUGIN + ifdef CONFIG_PAX_LATENT_ENTROPY + DISABLE_LATENT_ENTROPY_PLUGIN += -fplugin-arg-latent_entropy_plugin-disable + endif + ifdef CONFIG_GCC_PLUGIN_SANCOV ifeq ($(CFLAGS_KCOV),) # It is needed because of the gcc-plugin.sh and gcc version checks. @@ -21,7 +27,8 @@ ifdef CONFIG_GCC_PLUGINS GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) - export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR SANCOV_PLUGIN + export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR + export SANCOV_PLUGIN DISABLE_LATENT_ENTROPY_PLUGIN ifneq ($(PLUGINCC),) # SANCOV_PLUGIN can be only in CFLAGS_KCOV because avoid duplication. diff --git a/scripts/gcc-plugins/latent_entropy_plugin.c b/scripts/gcc-plugins/latent_entropy_plugin.c new file mode 100644 index 000000000000..ff1939b804ae --- /dev/null +++ b/scripts/gcc-plugins/latent_entropy_plugin.c @@ -0,0 +1,640 @@ +/* + * Copyright 2012-2016 by the PaX Team + * Copyright 2016 by Emese Revfy + * Licensed under the GPL v2 + * + * Note: the choice of the license means that the compilation process is + * NOT 'eligible' as defined by gcc's library exception to the GPL v3, + * but for the kernel it doesn't matter since it doesn't link against + * any of the gcc libraries + * + * This gcc plugin helps generate a little bit of entropy from program state, + * used throughout the uptime of the kernel. Here is an instrumentation example: + * + * before: + * void __latent_entropy test(int argc, char *argv[]) + * { + * if (argc <= 1) + * printf("%s: no command arguments :(\n", *argv); + * else + * printf("%s: %d command arguments!\n", *argv, args - 1); + * } + * + * after: + * void __latent_entropy test(int argc, char *argv[]) + * { + * // latent_entropy_execute() 1. + * unsigned long local_entropy; + * // init_local_entropy() 1. + * void *local_entropy_frameaddr; + * // init_local_entropy() 3. + * unsigned long tmp_latent_entropy; + * + * // init_local_entropy() 2. + * local_entropy_frameaddr = __builtin_frame_address(0); + * local_entropy = (unsigned long) local_entropy_frameaddr; + * + * // init_local_entropy() 4. + * tmp_latent_entropy = latent_entropy; + * // init_local_entropy() 5. + * local_entropy ^= tmp_latent_entropy; + * + * // latent_entropy_execute() 3. + * if (argc <= 1) { + * // perturb_local_entropy() + * local_entropy += 4623067384293424948; + * printf("%s: no command arguments :(\n", *argv); + * // perturb_local_entropy() + * } else { + * local_entropy ^= 3896280633962944730; + * printf("%s: %d command arguments!\n", *argv, args - 1); + * } + * + * // latent_entropy_execute() 4. + * tmp_latent_entropy = rol(tmp_latent_entropy, local_entropy); + * latent_entropy = tmp_latent_entropy; + * } + * + * TODO: + * - add ipa pass to identify not explicitly marked candidate functions + * - mix in more program state (function arguments/return values, + * loop variables, etc) + * - more instrumentation control via attribute parameters + * + * BUGS: + * - none known + * + * Options: + * -fplugin-arg-latent_entropy_plugin-disable + * + * Attribute: __attribute__((latent_entropy)) + * The latent_entropy gcc attribute can be only on functions and variables. + * If it is on a function then the plugin will instrument it. If the attribute + * is on a variable then the plugin will initialize it with a random value. + * The variable must be an integer, an integer array type or a structure + * with integer fields. + */ + +#include "gcc-common.h" + +int plugin_is_GPL_compatible; + +static GTY(()) tree latent_entropy_decl; + +static struct plugin_info latent_entropy_plugin_info = { + .version = "201606141920vanilla", + .help = "disable\tturn off latent entropy instrumentation\n", +}; + +static unsigned HOST_WIDE_INT seed; +/* + * get_random_seed() (this is a GCC function) generates the seed. + * This is a simple random generator without any cryptographic security because + * the entropy doesn't come from here. + */ +static unsigned HOST_WIDE_INT get_random_const(void) +{ + unsigned int i; + unsigned HOST_WIDE_INT ret = 0; + + for (i = 0; i < 8 * sizeof(ret); i++) { + ret = (ret << 1) | (seed & 1); + seed >>= 1; + if (ret & 1) + seed ^= 0xD800000000000000ULL; + } + + return ret; +} + +static tree tree_get_random_const(tree type) +{ + unsigned long long mask; + + mask = 1ULL << (TREE_INT_CST_LOW(TYPE_SIZE(type)) - 1); + mask = 2 * (mask - 1) + 1; + + if (TYPE_UNSIGNED(type)) + return build_int_cstu(type, mask & get_random_const()); + return build_int_cst(type, mask & get_random_const()); +} + +static tree handle_latent_entropy_attribute(tree *node, tree name, + tree args __unused, + int flags __unused, + bool *no_add_attrs) +{ + tree type; +#if BUILDING_GCC_VERSION <= 4007 + VEC(constructor_elt, gc) *vals; +#else + vec *vals; +#endif + + switch (TREE_CODE(*node)) { + default: + *no_add_attrs = true; + error("%qE attribute only applies to functions and variables", + name); + break; + + case VAR_DECL: + if (DECL_INITIAL(*node)) { + *no_add_attrs = true; + error("variable %qD with %qE attribute must not be initialized", + *node, name); + break; + } + + if (!TREE_STATIC(*node)) { + *no_add_attrs = true; + error("variable %qD with %qE attribute must not be local", + *node, name); + break; + } + + type = TREE_TYPE(*node); + switch (TREE_CODE(type)) { + default: + *no_add_attrs = true; + error("variable %qD with %qE attribute must be an integer or a fixed length integer array type or a fixed sized structure with integer fields", + *node, name); + break; + + case RECORD_TYPE: { + tree fld, lst = TYPE_FIELDS(type); + unsigned int nelt = 0; + + for (fld = lst; fld; nelt++, fld = TREE_CHAIN(fld)) { + tree fieldtype; + + fieldtype = TREE_TYPE(fld); + if (TREE_CODE(fieldtype) == INTEGER_TYPE) + continue; + + *no_add_attrs = true; + error("structure variable %qD with %qE attribute has a non-integer field %qE", + *node, name, fld); + break; + } + + if (fld) + break; + +#if BUILDING_GCC_VERSION <= 4007 + vals = VEC_alloc(constructor_elt, gc, nelt); +#else + vec_alloc(vals, nelt); +#endif + + for (fld = lst; fld; fld = TREE_CHAIN(fld)) { + tree random_const, fld_t = TREE_TYPE(fld); + + random_const = tree_get_random_const(fld_t); + CONSTRUCTOR_APPEND_ELT(vals, fld, random_const); + } + + /* Initialize the fields with random constants */ + DECL_INITIAL(*node) = build_constructor(type, vals); + break; + } + + /* Initialize the variable with a random constant */ + case INTEGER_TYPE: + DECL_INITIAL(*node) = tree_get_random_const(type); + break; + + case ARRAY_TYPE: { + tree elt_type, array_size, elt_size; + unsigned int i, nelt; + HOST_WIDE_INT array_size_int, elt_size_int; + + elt_type = TREE_TYPE(type); + elt_size = TYPE_SIZE_UNIT(TREE_TYPE(type)); + array_size = TYPE_SIZE_UNIT(type); + + if (TREE_CODE(elt_type) != INTEGER_TYPE || !array_size + || TREE_CODE(array_size) != INTEGER_CST) { + *no_add_attrs = true; + error("array variable %qD with %qE attribute must be a fixed length integer array type", + *node, name); + break; + } + + array_size_int = TREE_INT_CST_LOW(array_size); + elt_size_int = TREE_INT_CST_LOW(elt_size); + nelt = array_size_int / elt_size_int; + +#if BUILDING_GCC_VERSION <= 4007 + vals = VEC_alloc(constructor_elt, gc, nelt); +#else + vec_alloc(vals, nelt); +#endif + + for (i = 0; i < nelt; i++) { + tree cst = size_int(i); + tree rand_cst = tree_get_random_const(elt_type); + + CONSTRUCTOR_APPEND_ELT(vals, cst, rand_cst); + } + + /* + * Initialize the elements of the array with random + * constants + */ + DECL_INITIAL(*node) = build_constructor(type, vals); + break; + } + } + break; + + case FUNCTION_DECL: + break; + } + + return NULL_TREE; +} + +static struct attribute_spec latent_entropy_attr = { + .name = "latent_entropy", + .min_length = 0, + .max_length = 0, + .decl_required = true, + .type_required = false, + .function_type_required = false, + .handler = handle_latent_entropy_attribute, +#if BUILDING_GCC_VERSION >= 4007 + .affects_type_identity = false +#endif +}; + +static void register_attributes(void *event_data __unused, void *data __unused) +{ + register_attribute(&latent_entropy_attr); +} + +static bool latent_entropy_gate(void) +{ + tree list; + + /* don't bother with noreturn functions for now */ + if (TREE_THIS_VOLATILE(current_function_decl)) + return false; + + /* gcc-4.5 doesn't discover some trivial noreturn functions */ + if (EDGE_COUNT(EXIT_BLOCK_PTR_FOR_FN(cfun)->preds) == 0) + return false; + + list = DECL_ATTRIBUTES(current_function_decl); + return lookup_attribute("latent_entropy", list) != NULL_TREE; +} + +static tree create_var(tree type, const char *name) +{ + tree var; + + var = create_tmp_var(type, name); + add_referenced_var(var); + mark_sym_for_renaming(var); + return var; +} + +/* + * Set up the next operation and its constant operand to use in the latent + * entropy PRNG. When RHS is specified, the request is for perturbing the + * local latent entropy variable, otherwise it is for perturbing the global + * latent entropy variable where the two operands are already given by the + * local and global latent entropy variables themselves. + * + * The operation is one of add/xor/rol when instrumenting the local entropy + * variable and one of add/xor when perturbing the global entropy variable. + * Rotation is not used for the latter case because it would transmit less + * entropy to the global variable than the other two operations. + */ +static enum tree_code get_op(tree *rhs) +{ + static enum tree_code op; + unsigned HOST_WIDE_INT random_const; + + random_const = get_random_const(); + + switch (op) { + case BIT_XOR_EXPR: + op = PLUS_EXPR; + break; + + case PLUS_EXPR: + if (rhs) { + op = LROTATE_EXPR; + /* + * This code limits the value of random_const to + * the size of a wide int for the rotation + */ + random_const &= HOST_BITS_PER_WIDE_INT - 1; + break; + } + + case LROTATE_EXPR: + default: + op = BIT_XOR_EXPR; + break; + } + if (rhs) + *rhs = build_int_cstu(unsigned_intDI_type_node, random_const); + return op; +} + +static gimple create_assign(enum tree_code code, tree lhs, tree op1, + tree op2) +{ + return gimple_build_assign_with_ops(code, lhs, op1, op2); +} + +static void perturb_local_entropy(basic_block bb, tree local_entropy) +{ + gimple_stmt_iterator gsi; + gimple assign; + tree rhs; + enum tree_code op; + + op = get_op(&rhs); + assign = create_assign(op, local_entropy, local_entropy, rhs); + gsi = gsi_after_labels(bb); + gsi_insert_before(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); +} + +static void __perturb_latent_entropy(gimple_stmt_iterator *gsi, + tree local_entropy) +{ + gimple assign; + tree temp; + enum tree_code op; + + /* 1. create temporary copy of latent_entropy */ + temp = create_var(unsigned_intDI_type_node, "tmp_latent_entropy"); + + /* 2. read... */ + add_referenced_var(latent_entropy_decl); + mark_sym_for_renaming(latent_entropy_decl); + assign = gimple_build_assign(temp, latent_entropy_decl); + gsi_insert_before(gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + /* 3. ...modify... */ + op = get_op(NULL); + assign = create_assign(op, temp, temp, local_entropy); + gsi_insert_after(gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + /* 4. ...write latent_entropy */ + assign = gimple_build_assign(latent_entropy_decl, temp); + gsi_insert_after(gsi, assign, GSI_NEW_STMT); + update_stmt(assign); +} + +static bool handle_tail_calls(basic_block bb, tree local_entropy) +{ + gimple_stmt_iterator gsi; + + for (gsi = gsi_start_bb(bb); !gsi_end_p(gsi); gsi_next(&gsi)) { + gcall *call; + gimple stmt = gsi_stmt(gsi); + + if (!is_gimple_call(stmt)) + continue; + + call = as_a_gcall(stmt); + if (!gimple_call_tail_p(call)) + continue; + + __perturb_latent_entropy(&gsi, local_entropy); + return true; + } + + return false; +} + +static void perturb_latent_entropy(tree local_entropy) +{ + edge_iterator ei; + edge e, last_bb_e; + basic_block last_bb; + + gcc_assert(single_pred_p(EXIT_BLOCK_PTR_FOR_FN(cfun))); + last_bb_e = single_pred_edge(EXIT_BLOCK_PTR_FOR_FN(cfun)); + + FOR_EACH_EDGE(e, ei, last_bb_e->src->preds) { + if (ENTRY_BLOCK_PTR_FOR_FN(cfun) == e->src) + continue; + if (EXIT_BLOCK_PTR_FOR_FN(cfun) == e->src) + continue; + + handle_tail_calls(e->src, local_entropy); + } + + last_bb = single_pred(EXIT_BLOCK_PTR_FOR_FN(cfun)); + if (!handle_tail_calls(last_bb, local_entropy)) { + gimple_stmt_iterator gsi = gsi_last_bb(last_bb); + + __perturb_latent_entropy(&gsi, local_entropy); + } +} + +static void init_local_entropy(basic_block bb, tree local_entropy) +{ + gimple assign, call; + tree frame_addr, rand_const, tmp, fndecl, udi_frame_addr; + enum tree_code op; + unsigned HOST_WIDE_INT rand_cst; + gimple_stmt_iterator gsi = gsi_after_labels(bb); + + /* 1. create local_entropy_frameaddr */ + frame_addr = create_var(ptr_type_node, "local_entropy_frameaddr"); + + /* 2. local_entropy_frameaddr = __builtin_frame_address() */ + fndecl = builtin_decl_implicit(BUILT_IN_FRAME_ADDRESS); + call = gimple_build_call(fndecl, 1, integer_zero_node); + gimple_call_set_lhs(call, frame_addr); + gsi_insert_before(&gsi, call, GSI_NEW_STMT); + update_stmt(call); + + udi_frame_addr = fold_convert(unsigned_intDI_type_node, frame_addr); + assign = gimple_build_assign(local_entropy, udi_frame_addr); + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + /* 3. create temporary copy of latent_entropy */ + tmp = create_var(unsigned_intDI_type_node, "tmp_latent_entropy"); + + /* 4. read the global entropy variable into local entropy */ + add_referenced_var(latent_entropy_decl); + mark_sym_for_renaming(latent_entropy_decl); + assign = gimple_build_assign(tmp, latent_entropy_decl); + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + /* 5. mix local_entropy_frameaddr into local entropy */ + assign = create_assign(BIT_XOR_EXPR, local_entropy, local_entropy, tmp); + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); + + rand_cst = get_random_const(); + rand_const = build_int_cstu(unsigned_intDI_type_node, rand_cst); + op = get_op(NULL); + assign = create_assign(op, local_entropy, local_entropy, rand_const); + gsi_insert_after(&gsi, assign, GSI_NEW_STMT); + update_stmt(assign); +} + +static bool create_latent_entropy_decl(void) +{ + varpool_node_ptr node; + + if (latent_entropy_decl != NULL_TREE) + return true; + + FOR_EACH_VARIABLE(node) { + tree name, var = NODE_DECL(node); + + if (DECL_NAME_LENGTH(var) < sizeof("latent_entropy") - 1) + continue; + + name = DECL_NAME(var); + if (strcmp(IDENTIFIER_POINTER(name), "latent_entropy")) + continue; + + latent_entropy_decl = var; + break; + } + + return latent_entropy_decl != NULL_TREE; +} + +static unsigned int latent_entropy_execute(void) +{ + basic_block bb; + tree local_entropy; + + if (!create_latent_entropy_decl()) + return 0; + + /* prepare for step 2 below */ + gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); + bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); + if (!single_pred_p(bb)) { + split_edge(single_succ_edge(ENTRY_BLOCK_PTR_FOR_FN(cfun))); + gcc_assert(single_succ_p(ENTRY_BLOCK_PTR_FOR_FN(cfun))); + bb = single_succ(ENTRY_BLOCK_PTR_FOR_FN(cfun)); + } + + /* 1. create the local entropy variable */ + local_entropy = create_var(unsigned_intDI_type_node, "local_entropy"); + + /* 2. initialize the local entropy variable */ + init_local_entropy(bb, local_entropy); + + bb = bb->next_bb; + + /* + * 3. instrument each BB with an operation on the + * local entropy variable + */ + while (bb != EXIT_BLOCK_PTR_FOR_FN(cfun)) { + perturb_local_entropy(bb, local_entropy); + bb = bb->next_bb; + }; + + /* 4. mix local entropy into the global entropy variable */ + perturb_latent_entropy(local_entropy); + return 0; +} + +static void latent_entropy_start_unit(void *gcc_data __unused, + void *user_data __unused) +{ + tree type, id; + int quals; + + seed = get_random_seed(false); + + if (in_lto_p) + return; + + /* extern volatile u64 latent_entropy */ + gcc_assert(TYPE_PRECISION(long_long_unsigned_type_node) == 64); + quals = TYPE_QUALS(long_long_unsigned_type_node) | TYPE_QUAL_VOLATILE; + type = build_qualified_type(long_long_unsigned_type_node, quals); + id = get_identifier("latent_entropy"); + latent_entropy_decl = build_decl(UNKNOWN_LOCATION, VAR_DECL, id, type); + + TREE_STATIC(latent_entropy_decl) = 1; + TREE_PUBLIC(latent_entropy_decl) = 1; + TREE_USED(latent_entropy_decl) = 1; + DECL_PRESERVE_P(latent_entropy_decl) = 1; + TREE_THIS_VOLATILE(latent_entropy_decl) = 1; + DECL_EXTERNAL(latent_entropy_decl) = 1; + DECL_ARTIFICIAL(latent_entropy_decl) = 1; + lang_hooks.decls.pushdecl(latent_entropy_decl); +} + +#define PASS_NAME latent_entropy +#define PROPERTIES_REQUIRED PROP_gimple_leh | PROP_cfg +#define TODO_FLAGS_FINISH TODO_verify_ssa | TODO_verify_stmts | TODO_dump_func \ + | TODO_update_ssa +#include "gcc-generate-gimple-pass.h" + +int plugin_init(struct plugin_name_args *plugin_info, + struct plugin_gcc_version *version) +{ + bool enabled = true; + const char * const plugin_name = plugin_info->base_name; + const int argc = plugin_info->argc; + const struct plugin_argument * const argv = plugin_info->argv; + int i; + + struct register_pass_info latent_entropy_pass_info; + + latent_entropy_pass_info.pass = make_latent_entropy_pass(); + latent_entropy_pass_info.reference_pass_name = "optimized"; + latent_entropy_pass_info.ref_pass_instance_number = 1; + latent_entropy_pass_info.pos_op = PASS_POS_INSERT_BEFORE; + static const struct ggc_root_tab gt_ggc_r_gt_latent_entropy[] = { + { + .base = &latent_entropy_decl, + .nelt = 1, + .stride = sizeof(latent_entropy_decl), + .cb = >_ggc_mx_tree_node, + .pchw = >_pch_nx_tree_node + }, + LAST_GGC_ROOT_TAB + }; + + if (!plugin_default_version_check(version, &gcc_version)) { + error(G_("incompatible gcc/plugin versions")); + return 1; + } + + for (i = 0; i < argc; ++i) { + if (!(strcmp(argv[i].key, "disable"))) { + enabled = false; + continue; + } + error(G_("unkown option '-fplugin-arg-%s-%s'"), plugin_name, argv[i].key); + } + + register_callback(plugin_name, PLUGIN_INFO, NULL, + &latent_entropy_plugin_info); + if (enabled) { + register_callback(plugin_name, PLUGIN_START_UNIT, + &latent_entropy_start_unit, NULL); + register_callback(plugin_name, PLUGIN_REGISTER_GGC_ROOTS, + NULL, (void *)>_ggc_r_gt_latent_entropy); + register_callback(plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, + &latent_entropy_pass_info); + } + register_callback(plugin_name, PLUGIN_ATTRIBUTES, register_attributes, + NULL); + + return 0; +} -- cgit v1.2.3 From 1e01892e7ad521a96760da0d791b42badf755d3f Mon Sep 17 00:00:00 2001 From: Markus Elfring Date: Fri, 7 Oct 2016 16:06:15 +0200 Subject: scripts/coccicheck: Update reference for the corresponding documentation Use the current name (in a comment at the beginning of this script) for the file which was converted to the documentation format "reStructuredText" in August 2016. Fixes: 4b9033a33494 ("docs: sphinxify coccinelle.txt and add it to dev-tools") Signed-off-by: Markus Elfring Acked-by: Julia Lawall Signed-off-by: Michal Marek --- scripts/coccicheck | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/coccicheck b/scripts/coccicheck index c92c1528a54d..ec487b8e7051 100755 --- a/scripts/coccicheck +++ b/scripts/coccicheck @@ -1,7 +1,7 @@ #!/bin/bash # Linux kernel coccicheck # -# Read Documentation/coccinelle.txt +# Read Documentation/dev-tools/coccinelle.rst # # This script requires at least spatch # version 1.0.0-rc11. -- cgit v1.2.3 From c8990359d4b12f14656386526ddf904635076902 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 8 Oct 2016 17:51:45 +0200 Subject: Coccinelle: flag conditions with no effect Report code constructs where the if and else branch are functionally identical. In cases where this is intended it really should be documented - most reported cases probably are bugs. Signed-off-by: Nicholas Mc Guire Signed-off-by: Michal Marek --- scripts/coccinelle/misc/cond_no_effect.cocci | 64 ++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 scripts/coccinelle/misc/cond_no_effect.cocci (limited to 'scripts') diff --git a/scripts/coccinelle/misc/cond_no_effect.cocci b/scripts/coccinelle/misc/cond_no_effect.cocci new file mode 100644 index 000000000000..8467dbd1c465 --- /dev/null +++ b/scripts/coccinelle/misc/cond_no_effect.cocci @@ -0,0 +1,64 @@ +///Find conditions where if and else branch are functionally +// identical. +// +// There can be false positives in cases where the positional +// information is used (as with lockdep) or where the identity +// is a placeholder for not yet handled cases. +// Unfortunately there also seems to be a tendency to use +// the last if else/else as a "default behavior" - which some +// might consider a legitimate coding pattern. From discussion +// on kernelnewbies though it seems that this is not really an +// accepted pattern and if at all it would need to be commented +// +// In the Linux kernel it does not seem to actually report +// false positives except for those that were documented as +// being intentional. +// the two known cases are: +// arch/sh/kernel/traps_64.c:read_opcode() +// } else if ((pc & 1) == 0) { +// /* SHcompact */ +// /* TODO : provide handling for this. We don't really support +// user-mode SHcompact yet, and for a kernel fault, this would +// have to come from a module built for SHcompact. */ +// return -EFAULT; +// } else { +// /* misaligned */ +// return -EFAULT; +// } +// fs/kernfs/file.c:kernfs_fop_open() +// * Both paths of the branch look the same. They're supposed to +// * look that way and give @of->mutex different static lockdep keys. +// */ +// if (has_mmap) +// mutex_init(&of->mutex); +// else +// mutex_init(&of->mutex); +// +// All other cases look like bugs or at least lack of documentation +// +// Confidence: Moderate +// Copyright: (C) 2016 Nicholas Mc Guire, OSADL. GPLv2. +// Comments: +// Options: --no-includes --include-headers + +virtual org +virtual report + +@cond@ +statement S1; +position p; +@@ + +* if@p (...) S1 else S1 + +@script:python depends on org@ +p << cond.p; +@@ + +cocci.print_main("WARNING: possible condition with no effect (if == else)",p) + +@script:python depends on report@ +p << cond.p; +@@ + +coccilib.report.print_report(p[0],"WARNING: possible condition with no effect (if == else)") -- cgit v1.2.3 From 85b0ee18bbf82cb3e1880c718749149c6ed61058 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:51:44 -0700 Subject: checkpatch: see if modified files are marked obsolete in MAINTAINERS Use get_maintainer to check the status of individual files. If "obsolete", suggest leaving the files alone. Link: http://lkml.kernel.org/r/7ceaa510dc9d2df05ec4b456baed7bb1415550b3.1471889575.git.joe@perches.com Signed-off-by: Joe Perches Cc: SF Markus Elfring Signed-off-by: Andrew Morton 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 206a6b346a8d..34b445574011 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -704,6 +704,16 @@ sub seed_camelcase_file { } } +sub is_maintained_obsolete { + my ($filename) = @_; + + return 0 if (!(-e "$root/scripts/get_maintainer.pl")); + + my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback $filename 2>&1`; + + return $status =~ /obsolete/i; +} + my $camelcase_seeded = 0; sub seed_camelcase_includes { return if ($camelcase_seeded); @@ -2289,6 +2299,10 @@ sub process { } if ($found_file) { + if (is_maintained_obsolete($realfile)) { + WARN("OBSOLETE", + "$realfile is marked as 'obsolete' in the MAINTAINERS hierarchy. No unnecessary modifications please.\n"); + } if ($realfile =~ m@^(?:drivers/net/|net/|drivers/staging/)@) { $check = 1; } else { -- cgit v1.2.3 From f90774e1fd2700de4a6e0d62866d34a26c544bd0 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:51:47 -0700 Subject: checkpatch: look for symbolic permissions and suggest octal instead S_ uses should be avoided where octal is more intelligible. Linus didst say: : It's *much* easier to parse and understand the octal numbers, while the : symbolic macro names are just random line noise and hard as hell to : understand. You really have to think about it. : : So we should rather go the other way: convert existing bad symbolic : permission bit macro use to just use the octal numbers. : : The symbolic names are good for the *other* bits (ie sticky bit, and the : inode mode _type_ numbers etc), but for the permission bits, the symbolic : names are just insane crap. Nobody sane should ever use them. Not in the : kernel, not in user space. (http://lkml.kernel.org/r/CA+55aFw5v23T-zvDZp-MmD_EYxF8WbafwwB59934FV7g21uMGQ@mail.gmail.com) Link: http://lkml.kernel.org/r/7232ef011d05a92f4caa86a5e9830d87966a2eaf.1470180926.git.joe@perches.com Signed-off-by: Joe Perches Cc: Linus Torvalds Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 49 +++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 43 insertions(+), 6 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 34b445574011..1c82b01d581a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -541,6 +541,32 @@ our $mode_perms_world_writable = qr{ 0[0-7][0-7][2367] }x; +our %mode_permission_string_types = ( + "S_IRWXU" => 0700, + "S_IRUSR" => 0400, + "S_IWUSR" => 0200, + "S_IXUSR" => 0100, + "S_IRWXG" => 0070, + "S_IRGRP" => 0040, + "S_IWGRP" => 0020, + "S_IXGRP" => 0010, + "S_IRWXO" => 0007, + "S_IROTH" => 0004, + "S_IWOTH" => 0002, + "S_IXOTH" => 0001, + "S_IRWXUGO" => 0777, + "S_IRUGO" => 0444, + "S_IWUGO" => 0222, + "S_IXUGO" => 0111, +); + +#Create a search pattern for all these strings to speed up a loop below +our $mode_perms_string_search = ""; +foreach my $entry (keys %mode_permission_string_types) { + $mode_perms_string_search .= '|' if ($mode_perms_string_search ne ""); + $mode_perms_string_search .= $entry; +} + our $allowed_asm_includes = qr{(?x: irq| memory| @@ -6003,20 +6029,31 @@ sub process { $arg_pos--; $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; } - my $test = "\\b$func\\s*\\(${skip_args}([\\d]+)\\s*[,\\)]"; + my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]"; if ($line =~ /$test/) { my $val = $1; $val = $6 if ($skip_args ne ""); - - if ($val !~ /^0$/ && - (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || - length($val) ne 4)) { + if (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || + ($val =~ /^$Octal$/ && length($val) ne 4)) { ERROR("NON_OCTAL_PERMISSIONS", "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr); - } elsif ($val =~ /^$Octal$/ && (oct($val) & 02)) { + } + if ($val =~ /^$Octal$/ && (oct($val) & 02)) { ERROR("EXPORTED_WORLD_WRITABLE", "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); } + if ($val =~ /\b$mode_perms_string_search\b/) { + my $to = 0; + while ($val =~ /\b($mode_perms_string_search)\b(?:\s*\|\s*)?\s*/g) { + $to |= $mode_permission_string_types{$1}; + } + my $new = sprintf("%04o", $to); + if (WARN("SYMBOLIC_PERMS", + "Symbolic permissions are not preferred. Consider using octal permissions $new.\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/\Q$val\E/$new/; + } + } } } } -- cgit v1.2.3 From 08eb9b8016b18f53fa8900f3d1c9359f9edeb724 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:51:50 -0700 Subject: checkpatch: test multiple line block comment alignment Warn when block comments are not aligned on the * /* * block comment, no warning */ /* * block comment, emit warning */ Link: http://lkml.kernel.org/r/edb57bd330adfe024b95ec2a807d4aa7f0c8b112.1472261299.git.joe@perches.com Signed-off-by: Joe Perches Reported-by: Sudip Mukherjee Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 1c82b01d581a..894f8c616573 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2979,6 +2979,25 @@ sub process { "Block comments use a trailing */ on a separate line\n" . $herecurr); } +# Block comment * alignment + if ($prevline =~ /$;[ \t]*$/ && #ends in comment + (($prevrawline =~ /^\+.*?\/\*/ && #starting /* + $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ + $prevrawline =~ /^\+[ \t]*\*/) && #starting * + $rawline =~ /^\+[ \t]*\*/) { #rawline * + $prevrawline =~ m@^\+([ \t]*/?)\*@; + my $oldindent = expand_tabs($1); + $rawline =~ m@^\+([ \t]*)\*@; + my $newindent = $1; + my $test_comment = '^\\+' . "$;" x (length($newindent) + 1); + $newindent = expand_tabs($newindent); + if ($line =~ /$test_comment/ && + length($oldindent) ne length($newindent)) { + WARN("BLOCK_COMMENT_STYLE", + "Block comments should align the * on each line\n" . $hereprev); + } + } + # check for missing blank lines after struct/union declarations # with exceptions for various attributes and macros if ($prevline =~ /^[\+ ]};?\s*$/ && -- cgit v1.2.3 From f333195d41e15e7b105ca270c7662204a1a9d0f5 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:51:53 -0700 Subject: checkpatch: don't test for prefer ether_addr_ < sigh > Comment these tests out. These are just too enticing to people that don't verify that both source and dest addresses really must be __aligned(2). It helps make Dan Carpenter happy too. Link: http://lkml.kernel.org/r/dc32ec66d24647f4cdf824c8dfbbc59aa7ce7b7d.1472665676.git.joe@perches.com Signed-off-by: Joe Perches Cc: Dan Carpenter Cc: Greg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 70 +++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 894f8c616573..37d8b91ac198 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5554,46 +5554,46 @@ sub process { } # Check for memcpy(foo, bar, ETH_ALEN) that could be ether_addr_copy(foo, bar) - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - if (WARN("PREFER_ETHER_ADDR_COPY", - "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; - } - } +# if ($^V && $^V ge 5.10.0 && +# defined $stat && +# $stat =~ /^\+(?:.*?)\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { +# if (WARN("PREFER_ETHER_ADDR_COPY", +# "Prefer ether_addr_copy() over memcpy() if the Ethernet addresses are __aligned(2)\n" . "$here\n$stat\n") && +# $fix) { +# $fixed[$fixlinenr] =~ s/\bmemcpy\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/ether_addr_copy($2, $7)/; +# } +# } # Check for memcmp(foo, bar, ETH_ALEN) that could be ether_addr_equal*(foo, bar) - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - WARN("PREFER_ETHER_ADDR_EQUAL", - "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") - } +# if ($^V && $^V ge 5.10.0 && +# defined $stat && +# $stat =~ /^\+(?:.*?)\bmemcmp\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { +# WARN("PREFER_ETHER_ADDR_EQUAL", +# "Prefer ether_addr_equal() or ether_addr_equal_unaligned() over memcmp()\n" . "$here\n$stat\n") +# } # check for memset(foo, 0x0, ETH_ALEN) that could be eth_zero_addr # check for memset(foo, 0xFF, ETH_ALEN) that could be eth_broadcast_addr - if ($^V && $^V ge 5.10.0 && - defined $stat && - $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { - - my $ms_val = $7; - - if ($ms_val =~ /^(?:0x|)0+$/i) { - if (WARN("PREFER_ETH_ZERO_ADDR", - "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; - } - } elsif ($ms_val =~ /^(?:0xff|255)$/i) { - if (WARN("PREFER_ETH_BROADCAST_ADDR", - "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && - $fix) { - $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; - } - } - } +# if ($^V && $^V ge 5.10.0 && +# defined $stat && +# $stat =~ /^\+(?:.*?)\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*\,\s*ETH_ALEN\s*\)/) { +# +# my $ms_val = $7; +# +# if ($ms_val =~ /^(?:0x|)0+$/i) { +# if (WARN("PREFER_ETH_ZERO_ADDR", +# "Prefer eth_zero_addr over memset()\n" . "$here\n$stat\n") && +# $fix) { +# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_zero_addr($2)/; +# } +# } elsif ($ms_val =~ /^(?:0xff|255)$/i) { +# if (WARN("PREFER_ETH_BROADCAST_ADDR", +# "Prefer eth_broadcast_addr() over memset()\n" . "$here\n$stat\n") && +# $fix) { +# $fixed[$fixlinenr] =~ s/\bmemset\s*\(\s*$FuncArg\s*,\s*$FuncArg\s*,\s*ETH_ALEN\s*\)/eth_broadcast_addr($2)/; +# } +# } +# } # typecasts on min/max could be min_t/max_t if ($^V && $^V ge 5.10.0 && -- cgit v1.2.3 From bf1fa1dae68e1b58b7b7fd61bde654d37da1de57 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:51:56 -0700 Subject: checkpatch: externalize the structs that should be const Make it easier to add new structs that should be const. Link: http://lkml.kernel.org/r/e5a8da43e7c11525bafbda1ca69a8323614dd942.1472664220.git.joe@perches.com Signed-off-by: Joe Perches Cc: Julia Lawall Cc: Kees Cook Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 64 +++++++++++++++------------------------- scripts/const_structs.checkpatch | 39 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 40 deletions(-) create mode 100644 scripts/const_structs.checkpatch (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 37d8b91ac198..4ecb66c595f4 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -54,6 +54,7 @@ my $min_conf_desc_length = 4; my $spelling_file = "$D/spelling.txt"; my $codespell = 0; my $codespellfile = "/usr/share/codespell/dictionary.txt"; +my $conststructsfile = "$D/const_structs.checkpatch"; my $color = 1; my $allow_c99_comments = 1; @@ -624,6 +625,29 @@ if ($codespell) { $misspellings = join("|", sort keys %spelling_fix) if keys %spelling_fix; +my $const_structs = ""; +if (open(my $conststructs, '<', $conststructsfile)) { + while (<$conststructs>) { + my $line = $_; + + $line =~ s/\s*\n?$//g; + $line =~ s/^\s*//g; + + next if ($line =~ m/^\s*#/); + next if ($line =~ m/^\s*$/); + if ($line =~ /\s/) { + print("$conststructsfile: '$line' invalid - ignored\n"); + next; + } + + $const_structs .= '|' if ($const_structs ne ""); + $const_structs .= $line; + } + close($conststructsfile); +} else { + warn "No structs that should be const will be found - file '$conststructsfile': $!\n"; +} + sub build_types { my $mods = "(?x: \n" . join("|\n ", (@modifierList, @modifierListFile)) . "\n)"; my $all = "(?x: \n" . join("|\n ", (@typeList, @typeListFile)) . "\n)"; @@ -5912,46 +5936,6 @@ sub process { } # check for various structs that are normally const (ops, kgdb, device_tree) - my $const_structs = qr{ - acpi_dock_ops| - address_space_operations| - backlight_ops| - block_device_operations| - dentry_operations| - dev_pm_ops| - dma_map_ops| - extent_io_ops| - file_lock_operations| - file_operations| - hv_ops| - ide_dma_ops| - intel_dvo_dev_ops| - item_operations| - iwl_ops| - kgdb_arch| - kgdb_io| - kset_uevent_ops| - lock_manager_operations| - microcode_ops| - mtrr_ops| - neigh_ops| - nlmsvc_binding| - of_device_id| - pci_raw_ops| - pipe_buf_operations| - platform_hibernation_ops| - platform_suspend_ops| - proto_ops| - rpc_pipe_ops| - seq_operations| - snd_ac97_build_ops| - soc_pcmcia_socket_ops| - stacktrace_ops| - sysfs_ops| - tty_operations| - uart_ops| - usb_mon_operations| - wd_ops}x; if ($line !~ /\bconst\b/ && $line =~ /\bstruct\s+($const_structs)\b/) { WARN("CONST_STRUCT", diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch new file mode 100644 index 000000000000..1b54425f6c89 --- /dev/null +++ b/scripts/const_structs.checkpatch @@ -0,0 +1,39 @@ +acpi_dock_ops +address_space_operations +backlight_ops +block_device_operations +dentry_operations +dev_pm_ops +dma_map_ops +extent_io_ops +file_lock_operations +file_operations +hv_ops +ide_dma_ops +intel_dvo_dev_ops +item_operations +iwl_ops +kgdb_arch +kgdb_io +kset_uevent_ops +lock_manager_operations +microcode_ops +mtrr_ops +neigh_ops +nlmsvc_binding +of_device_id +pci_raw_ops +pipe_buf_operations +platform_hibernation_ops +platform_suspend_ops +proto_ops +rpc_pipe_ops +seq_operations +snd_ac97_build_ops +soc_pcmcia_socket_ops +stacktrace_ops +sysfs_ops +tty_operations +uart_ops +usb_mon_operations +wd_ops -- cgit v1.2.3 From 15c03cfeabff447abec9e05b5830922099b89943 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:51:59 -0700 Subject: const_structs.checkpatch: add frequently used from Julia Lawall's list Using const is generally a good idea. Julia Lawall has created a list of always const and almost always const structs in the kernel sources. Link: https://lkml.org/lkml/2016/8/28/95 Add the most frequently used (> 50 cases) that are almost always or always const. Link: http://lkml.kernel.org/r/1e16020f8027654db0095bbfbcc11da51025365c.1472664220.git.joe@perches.com Signed-off-by: Joe Perches Acked-by: Kees Cook Cc: Julia Lawall Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/const_structs.checkpatch | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'scripts') diff --git a/scripts/const_structs.checkpatch b/scripts/const_structs.checkpatch index 1b54425f6c89..ac5f1267151d 100644 --- a/scripts/const_structs.checkpatch +++ b/scripts/const_structs.checkpatch @@ -2,38 +2,63 @@ acpi_dock_ops address_space_operations backlight_ops block_device_operations +clk_ops +comedi_lrange +component_ops dentry_operations dev_pm_ops dma_map_ops +driver_info +drm_connector_funcs +drm_encoder_funcs +drm_encoder_helper_funcs +ethtool_ops extent_io_ops file_lock_operations file_operations hv_ops ide_dma_ops +ide_port_ops +inode_operations intel_dvo_dev_ops +irq_domain_ops item_operations +iwl_cfg iwl_ops kgdb_arch kgdb_io kset_uevent_ops lock_manager_operations +machine_desc microcode_ops +mlxsw_reg_info mtrr_ops neigh_ops +net_device_ops nlmsvc_binding +nvkm_device_chip of_device_id pci_raw_ops pipe_buf_operations platform_hibernation_ops platform_suspend_ops proto_ops +regmap_access_table rpc_pipe_ops +rtc_class_ops +sd_desc seq_operations +sirfsoc_padmux snd_ac97_build_ops +snd_soc_component_driver soc_pcmcia_socket_ops stacktrace_ops sysfs_ops tty_operations uart_ops usb_mon_operations +v4l2_ctrl_ops +v4l2_ioctl_ops +vm_operations_struct +wacom_features wd_ops -- cgit v1.2.3 From 0616efa45af493a259d25c1716102173f10bd789 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:52:02 -0700 Subject: checkpatch: speed up checking for filenames in sections marked obsolete Adding -f to the get_maintainer.pl invocation means git isn't invoked by get_maintainer.pl for known filenames. This reduces the overall time to run checkpatch. Link: http://lkml.kernel.org/r/22991e3a295aeb399b43af0478b6e5809106ccee.1472684066.git.joe@perches.com Signed-off-by: Joe Perches Signed-off-by: Andrew Morton 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 4ecb66c595f4..e44dc0c75d54 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -759,7 +759,7 @@ sub is_maintained_obsolete { return 0 if (!(-e "$root/scripts/get_maintainer.pl")); - my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback $filename 2>&1`; + my $status = `perl $root/scripts/get_maintainer.pl --status --nom --nol --nogit --nogit-fallback -f $filename 2>&1`; return $status =~ /obsolete/i; } -- cgit v1.2.3 From af207524a49c3d70af0a9196072ab3b6d690fcf7 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:52:05 -0700 Subject: checkpatch: improve the block comment * alignment test An "uninitialized value" is emitted when a block comment starts on the same line as a statement. Fix this and make the test use a little fewer cpu cycles too. Link: http://lkml.kernel.org/r/3c9993320c2182d37f53ac540878cfef59c3f62d.1473365956.git.joe@perches.com Signed-off-by: Joe Perches Reported-by: Charlemagne Lasse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index e44dc0c75d54..3fa2b2e973eb 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -3005,18 +3005,23 @@ sub process { # Block comment * alignment if ($prevline =~ /$;[ \t]*$/ && #ends in comment - (($prevrawline =~ /^\+.*?\/\*/ && #starting /* + $line =~ /^\+[ \t]*$;/ && #leading comment + $rawline =~ /^\+[ \t]*\*/ && #leading * + (($prevrawline =~ /^\+.*?\/\*/ && #leading /* $prevrawline !~ /\*\/[ \t]*$/) || #no trailing */ - $prevrawline =~ /^\+[ \t]*\*/) && #starting * - $rawline =~ /^\+[ \t]*\*/) { #rawline * + $prevrawline =~ /^\+[ \t]*\*/)) { #leading * + my $oldindent; $prevrawline =~ m@^\+([ \t]*/?)\*@; - my $oldindent = expand_tabs($1); + if (defined($1)) { + $oldindent = expand_tabs($1); + } else { + $prevrawline =~ m@^\+(.*/?)\*@; + $oldindent = expand_tabs($1); + } $rawline =~ m@^\+([ \t]*)\*@; my $newindent = $1; - my $test_comment = '^\\+' . "$;" x (length($newindent) + 1); $newindent = expand_tabs($newindent); - if ($line =~ /$test_comment/ && - length($oldindent) ne length($newindent)) { + if (length($oldindent) ne length($newindent)) { WARN("BLOCK_COMMENT_STYLE", "Block comments should align the * on each line\n" . $hereprev); } -- cgit v1.2.3 From f59b64bffe163431b4ec61f3b00c1aeb846948f3 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:52:08 -0700 Subject: checkpatch: add --strict test for macro argument reuse If a macro argument is used multiple times in the macro definition, the macro argument may have an unexpected side-effect. Add a test (MACRO_ARG_REUSE) for that condition which is only emitted with command-line option --strict. Link: http://lkml.kernel.org/r/b6d67a87cafcafd15499e91780dc63b15dec0aa0.1473744906.git.joe@perches.com Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Julia Lawall Cc: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3fa2b2e973eb..f135f8e4d069 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4753,7 +4753,17 @@ sub process { $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); - $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; + $dstat =~ s/^.\s*\#\s*define\s+$Ident(\([^\)]*\))?\s*//; + my $define_args = $1; + my $define_stmt = $dstat; + my @def_args = (); + + if (defined $define_args && $define_args ne "") { + $define_args = substr($define_args, 1, length($define_args) - 2); + $define_args =~ s/\s*//g; + @def_args = split(",", $define_args); + } + $dstat =~ s/$;//g; $dstat =~ s/\\\n.//g; $dstat =~ s/^\s*//s; @@ -4789,6 +4799,15 @@ sub process { ^\[ }x; #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; + + $ctx =~ s/\n*$//; + my $herectx = $here . "\n"; + my $stmt_cnt = statement_rawlines($ctx); + + for (my $n = 0; $n < $stmt_cnt; $n++) { + $herectx .= raw_line($linenr, $n) . "\n"; + } + if ($dstat ne '' && $dstat !~ /^(?:$Ident|-?$Constant),$/ && # 10, // foo(), $dstat !~ /^(?:$Ident|-?$Constant);$/ && # foo(); @@ -4804,13 +4823,6 @@ sub process { $dstat !~ /^\(\{/ && # ({... $ctx !~ /^.\s*#\s*define\s+TRACE_(?:SYSTEM|INCLUDE_FILE|INCLUDE_PATH)\b/) { - $ctx =~ s/\n*$//; - my $herectx = $here . "\n"; - my $cnt = statement_rawlines($ctx); - - for (my $n = 0; $n < $cnt; $n++) { - $herectx .= raw_line($linenr, $n) . "\n"; - } if ($dstat =~ /;/) { ERROR("MULTISTATEMENT_MACRO_USE_DO_WHILE", @@ -4819,6 +4831,21 @@ sub process { ERROR("COMPLEX_MACRO", "Macros with complex values should be enclosed in parentheses\n" . "$herectx"); } + + } +# check if any macro arguments are reused (ignore '...' and 'type') + foreach my $arg (@def_args) { + next if ($arg =~ /\.\.\./); + next if ($arg =~ /^type$/); + my $tmp = $define_stmt; + $tmp =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; + $tmp =~ s/\#\s*$arg\b//g; + $tmp =~ s/\b$arg\s*\#\#//g; + my $use_cnt = $tmp =~ s/\b$arg\b//g; + if ($use_cnt > 1) { + CHK("MACRO_ARG_REUSE", + "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx"); + } } # check for macros with flow control, but without ## concatenation -- cgit v1.2.3 From 9192d41a3f0b98844860f1de5b82f729bbe07c61 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:52:11 -0700 Subject: checkpatch: add --strict test for precedence challenged macro arguments Add a test for macro arguents that have a non-comma leading or trailing operator where the argument isn't parenthesized to avoid possible precedence issues. Link: http://lkml.kernel.org/r/47715508972f8d786f435e583ff881dbeee3a114.1473745855.git.joe@perches.com Signed-off-by: Joe Perches Cc: Andy Whitcroft Cc: Julia Lawall Cc: Dan Carpenter Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index f135f8e4d069..ea1a7adce406 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4836,7 +4836,7 @@ sub process { # check if any macro arguments are reused (ignore '...' and 'type') foreach my $arg (@def_args) { next if ($arg =~ /\.\.\./); - next if ($arg =~ /^type$/); + next if ($arg =~ /^type$/i); my $tmp = $define_stmt; $tmp =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; $tmp =~ s/\#\s*$arg\b//g; @@ -4845,6 +4845,13 @@ sub process { if ($use_cnt > 1) { CHK("MACRO_ARG_REUSE", "Macro argument reuse '$arg' - possible side-effects?\n" . "$herectx"); + } +# check if any macro arguments may have other precedence issues + if ($define_stmt =~ m/($Operators)?\s*\b$arg\b\s*($Operators)?/m && + ((defined($1) && $1 ne ',') || + (defined($2) && $2 ne ','))) { + CHK("MACRO_ARG_PRECEDENCE", + "Macro argument '$arg' may be better as '($arg)' to avoid precedence issues\n" . "$herectx"); } } -- cgit v1.2.3 From 5207649b7b1d2b1e1f8c97df91debfaa8de37669 Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:52:14 -0700 Subject: checkpatch: improve MACRO_ARG_PRECEDENCE test It is possible for a multiple line macro definition to have a false positive report when an argument is used on a line after a continuation \. This line might have a leading '+' as the initial character that could be confused by checkpatch as an operator. Avoid the leading character on multiple line macro definitions. Link: http://lkml.kernel.org/r/60229d13399f9b6509db5a32e30d4c16951a60cd.1473836073.git.joe@perches.com Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index ea1a7adce406..0ef3d837f2aa 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -4833,13 +4833,31 @@ sub process { } } + + # Make $define_stmt single line, comment-free, etc + my @stmt_array = split('\n', $define_stmt); + my $first = 1; + $define_stmt = ""; + foreach my $l (@stmt_array) { + $l =~ s/\\$//; + if ($first) { + $define_stmt = $l; + $first = 0; + } elsif ($l =~ /^[\+ ]/) { + $define_stmt .= substr($l, 1); + } + } + $define_stmt =~ s/$;//g; + $define_stmt =~ s/\s+/ /g; + $define_stmt = trim($define_stmt); + # check if any macro arguments are reused (ignore '...' and 'type') foreach my $arg (@def_args) { next if ($arg =~ /\.\.\./); next if ($arg =~ /^type$/i); my $tmp = $define_stmt; $tmp =~ s/\b(typeof|__typeof__|__builtin\w+|typecheck\s*\(\s*$Type\s*,|\#+)\s*\(*\s*$arg\s*\)*\b//g; - $tmp =~ s/\#\s*$arg\b//g; + $tmp =~ s/\#+\s*$arg\b//g; $tmp =~ s/\b$arg\s*\#\#//g; my $use_cnt = $tmp =~ s/\b$arg\b//g; if ($use_cnt > 1) { -- cgit v1.2.3 From ca0d8929e75ab1f860f61208d46955f280a1b05e Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:52:16 -0700 Subject: checkpatch: add warning for unnamed function definition arguments Function definitions without identifiers like int foo(int) are not preferred. Emit a warning when they occur. Link: http://lkml.kernel.org/r/94fe6378504745991b650f48fc92bb4648f25706.1474925354.git.joe@perches.com Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0ef3d837f2aa..3373c65fef1c 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -5794,6 +5794,19 @@ sub process { "externs should be avoided in .c files\n" . $herecurr); } + if ($realfile =~ /\.[ch]$/ && defined $stat && + $stat =~ /^.\s*(?:extern\s+)?$Type\s*$Ident\s*\(\s*([^{]+)\s*\)\s*;/s && + $1 ne "void") { + my $args = trim($1); + while ($args =~ m/\s*($Type\s*(?:$Ident|\(\s*\*\s*$Ident?\s*\)\s*$balanced_parens)?)/g) { + my $arg = trim($1); + if ($arg =~ /^$Type$/ && $arg !~ /enum\s+$Ident$/) { + WARN("FUNCTION_ARGUMENTS", + "function definition argument '$arg' should also have an identifier name\n" . $herecurr); + } + } + } + # checks for new __setup's if ($rawline =~ /\b__setup\("([^"]*)"/) { my $name = $1; -- cgit v1.2.3 From 459cf0ae5d6600592a539bc861c84e14ed1a5bcb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Tue, 11 Oct 2016 13:52:19 -0700 Subject: checkpatch: improve the octal permissions tests The function calls with octal permissions commonly span multiple lines. The current test is line oriented and fails to find some matches. Make the test use the $stat variable instead of the $line variable to span multiple lines. Also add a few functions to the known functions with permissions list. Move the SYMBOLIC_PERMS test to a separate section to find all the S_ permissions in any form not just those that have specific function names. This can now find and fix permissions uses like: .mode = S_ | S_; Link: http://lkml.kernel.org/r/b51bab60530912aae4ac420119d465c5b206f19f.1475030406.git.joe@perches.com Signed-off-by: Joe Perches Tested-by: Ramiro Oliveira Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/checkpatch.pl | 60 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 44 insertions(+), 16 deletions(-) (limited to 'scripts') diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 3373c65fef1c..a8368d1c4348 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -524,7 +524,11 @@ our @mode_permission_funcs = ( ["module_param_array_named", 5], ["debugfs_create_(?:file|u8|u16|u32|u64|x8|x16|x32|x64|size_t|atomic_t|bool|blob|regset32|u32_array)", 2], ["proc_create(?:_data|)", 2], - ["(?:CLASS|DEVICE|SENSOR)_ATTR", 2], + ["(?:CLASS|DEVICE|SENSOR|SENSOR_DEVICE|IIO_DEVICE)_ATTR", 2], + ["IIO_DEV_ATTR_[A-Z_]+", 1], + ["SENSOR_(?:DEVICE_|)ATTR_2", 2], + ["SENSOR_TEMPLATE(?:_2|)", 3], + ["__ATTR", 2], ); #Create a search pattern for all these functions to speed up a loop below @@ -6092,45 +6096,69 @@ sub process { # Mode permission misuses where it seems decimal should be octal # This uses a shortcut match to avoid unnecessary uses of a slow foreach loop if ($^V && $^V ge 5.10.0 && + defined $stat && $line =~ /$mode_perms_search/) { foreach my $entry (@mode_permission_funcs) { my $func = $entry->[0]; my $arg_pos = $entry->[1]; + my $lc = $stat =~ tr@\n@@; + $lc = $lc + $linenr; + my $stat_real = raw_line($linenr, 0); + for (my $count = $linenr + 1; $count <= $lc; $count++) { + $stat_real = $stat_real . "\n" . raw_line($count, 0); + } + my $skip_args = ""; if ($arg_pos > 1) { $arg_pos--; $skip_args = "(?:\\s*$FuncArg\\s*,\\s*){$arg_pos,$arg_pos}"; } my $test = "\\b$func\\s*\\(${skip_args}($FuncArg(?:\\|\\s*$FuncArg)*)\\s*[,\\)]"; - if ($line =~ /$test/) { + if ($stat =~ /$test/) { my $val = $1; $val = $6 if ($skip_args ne ""); if (($val =~ /^$Int$/ && $val !~ /^$Octal$/) || ($val =~ /^$Octal$/ && length($val) ne 4)) { ERROR("NON_OCTAL_PERMISSIONS", - "Use 4 digit octal (0777) not decimal permissions\n" . $herecurr); + "Use 4 digit octal (0777) not decimal permissions\n" . "$here\n" . $stat_real); } if ($val =~ /^$Octal$/ && (oct($val) & 02)) { ERROR("EXPORTED_WORLD_WRITABLE", - "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . $herecurr); - } - if ($val =~ /\b$mode_perms_string_search\b/) { - my $to = 0; - while ($val =~ /\b($mode_perms_string_search)\b(?:\s*\|\s*)?\s*/g) { - $to |= $mode_permission_string_types{$1}; - } - my $new = sprintf("%04o", $to); - if (WARN("SYMBOLIC_PERMS", - "Symbolic permissions are not preferred. Consider using octal permissions $new.\n" . $herecurr) && - $fix) { - $fixed[$fixlinenr] =~ s/\Q$val\E/$new/; - } + "Exporting writable files is usually an error. Consider more restrictive permissions.\n" . "$here\n" . $stat_real); } } } } +# check for uses of S_ that could be octal for readability + if ($line =~ /\b$mode_perms_string_search\b/) { + my $val = ""; + my $oval = ""; + my $to = 0; + my $curpos = 0; + my $lastpos = 0; + while ($line =~ /\b(($mode_perms_string_search)\b(?:\s*\|\s*)?\s*)/g) { + $curpos = pos($line); + my $match = $2; + my $omatch = $1; + last if ($lastpos > 0 && ($curpos - length($omatch) != $lastpos)); + $lastpos = $curpos; + $to |= $mode_permission_string_types{$match}; + $val .= '\s*\|\s*' if ($val ne ""); + $val .= $match; + $oval .= $omatch; + } + $oval =~ s/^\s*\|\s*//; + $oval =~ s/\s*\|\s*$//; + my $octal = sprintf("%04o", $to); + if (WARN("SYMBOLIC_PERMS", + "Symbolic permissions '$oval' are not preferred. Consider using octal permissions '$octal'.\n" . $herecurr) && + $fix) { + $fixed[$fixlinenr] =~ s/$val/$octal/; + } + } + # validate content of MODULE_LICENSE against list from include/linux/module.h if ($line =~ /\bMODULE_LICENSE\s*\(\s*($String)\s*\)/) { my $extracted_string = get_quoted_string($line, $rawline); -- cgit v1.2.3 From d0c75f33f065bf58833c43ac7b5ccfcb60131510 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Tue, 11 Oct 2016 13:55:14 -0700 Subject: scripts/tags.sh: enable code completion in VIM Vim, with the omnicppcomplete(#1) plugin, can do code completion using information build by ctags. Add flags needed by omnicppcomplete(#2) to have completion on member of structure. 1: https://github.com/vim-scripts/omnicppcomplete 2: https://github.com/vim-scripts/OmniCppComplete/blob/master/doc/omnicppcomplete.txt#L93 Link: http://lkml.kernel.org/r/20160830191546.4469-1-mathieu.maret@gmail.com Signed-off-by: Mathieu Maret Cc: Michal Marek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/tags.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'scripts') diff --git a/scripts/tags.sh b/scripts/tags.sh index b3775a9604ea..a2ff3388e5ea 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -263,7 +263,8 @@ exuberant() -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL,ACPI_EXPORT_SYMBOL \ -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \ -I static,const \ - --extra=+f --c-kinds=+px --langmap=c:+.h "${regex[@]}" + --extra=+fq --c-kinds=+px --fields=+iaS --langmap=c:+.h \ + "${regex[@]}" setup_regex exuberant kconfig all_kconfigs | xargs $1 -a \ -- cgit v1.2.3