diff options
Diffstat (limited to 'scripts')
32 files changed, 1265 insertions, 302 deletions
diff --git a/scripts/.gitignore b/scripts/.gitignore index 1f78169d4254..e063daa3ec4a 100644 --- a/scripts/.gitignore +++ b/scripts/.gitignore @@ -13,3 +13,4 @@ sortextable asn1_compiler extract-cert sign-file +insert-sys-cert diff --git a/scripts/Makefile b/scripts/Makefile index fd0d53d4a234..822ab4a6a4aa 100644 --- a/scripts/Makefile +++ b/scripts/Makefile @@ -19,6 +19,7 @@ hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable hostprogs-$(CONFIG_ASN1) += asn1_compiler hostprogs-$(CONFIG_MODULE_SIG) += sign-file hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert +hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include diff --git a/scripts/Makefile.build b/scripts/Makefile.build index 01df30af4d4a..2c47f9c305aa 100644 --- a/scripts/Makefile.build +++ b/scripts/Makefile.build @@ -372,10 +372,14 @@ endif # <composite-object>-objs := <list of .o files> # or # <composite-object>-y := <list of .o files> +# or +# <composite-object>-m := <list of .o files> +# The -m syntax only works if <composite object> is a module link_multi_deps = \ $(filter $(addprefix $(obj)/, \ $($(subst $(obj)/,,$(@:.o=-objs))) \ -$($(subst $(obj)/,,$(@:.o=-y)))), $^) +$($(subst $(obj)/,,$(@:.o=-y))) \ +$($(subst $(obj)/,,$(@:.o=-m)))), $^) quiet_cmd_link_multi-y = LD $@ cmd_link_multi-y = $(LD) $(ld_flags) -r -o $@ $(link_multi_deps) $(cmd_secanalysis) @@ -390,7 +394,7 @@ $(call multi_depend, $(multi-used-y), .o, -objs -y) $(multi-used-m): FORCE $(call if_changed,link_multi-m) @{ echo $(@:.o=.ko); echo $(link_multi_deps); } > $(MODVERDIR)/$(@F:.o=.mod) -$(call multi_depend, $(multi-used-m), .o, -objs -y) +$(call multi_depend, $(multi-used-m), .o, -objs -y -m) targets += $(multi-used-y) $(multi-used-m) diff --git a/scripts/Makefile.extrawarn b/scripts/Makefile.extrawarn index 4efedcbe4165..f9e47a70509c 100644 --- a/scripts/Makefile.extrawarn +++ b/scripts/Makefile.extrawarn @@ -25,6 +25,7 @@ warning-1 += -Wold-style-definition warning-1 += $(call cc-option, -Wmissing-include-dirs) warning-1 += $(call cc-option, -Wunused-but-set-variable) warning-1 += $(call cc-disable-warning, missing-field-initializers) +warning-1 += $(call cc-disable-warning, sign-compare) warning-2 := -Waggregate-return warning-2 += -Wcast-align @@ -33,6 +34,7 @@ warning-2 += -Wnested-externs warning-2 += -Wshadow warning-2 += $(call cc-option, -Wlogical-op) warning-2 += $(call cc-option, -Wmissing-field-initializers) +warning-2 += $(call cc-option, -Wsign-compare) warning-3 := -Wbad-function-cast warning-3 += -Wcast-qual diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 79e86613712f..2edbcadb3d7f 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -48,7 +48,7 @@ subdir-ym := $(sort $(subdir-y) $(subdir-m)) # if $(foo-objs) exists, foo.o is a composite object multi-used-y := $(sort $(foreach m,$(obj-y), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) -multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))), $(m)))) +multi-used-m := $(sort $(foreach m,$(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))), $(m)))) multi-used := $(multi-used-y) $(multi-used-m) single-used-m := $(sort $(filter-out $(multi-used-m),$(obj-m))) @@ -67,7 +67,7 @@ obj-dirs := $(dir $(multi-objs) $(obj-y)) # Replace multi-part objects by their individual parts, look at local dir only real-objs-y := $(foreach m, $(filter-out $(subdir-obj-y), $(obj-y)), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) $(extra-y) -real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y))),$($(m:.o=-objs)) $($(m:.o=-y)),$(m))) +real-objs-m := $(foreach m, $(obj-m), $(if $(strip $($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m))),$($(m:.o=-objs)) $($(m:.o=-y)) $($(m:.o=-m)),$(m))) # Add subdir path @@ -104,8 +104,9 @@ modname_flags = $(if $(filter 1,$(words $(modname))),\ orig_c_flags = $(KBUILD_CPPFLAGS) $(KBUILD_CFLAGS) $(KBUILD_SUBDIR_CCFLAGS) \ $(ccflags-y) $(CFLAGS_$(basetarget).o) _c_flags = $(filter-out $(CFLAGS_REMOVE_$(basetarget).o), $(orig_c_flags)) -_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \ +orig_a_flags = $(KBUILD_CPPFLAGS) $(KBUILD_AFLAGS) $(KBUILD_SUBDIR_ASFLAGS) \ $(asflags-y) $(AFLAGS_$(basetarget).o) +_a_flags = $(filter-out $(AFLAGS_REMOVE_$(basetarget).o), $(orig_a_flags)) _cpp_flags = $(KBUILD_CPPFLAGS) $(cppflags-y) $(CPPFLAGS_$(@F)) # @@ -129,6 +130,12 @@ _c_flags += $(if $(patsubst n%,, \ $(CFLAGS_KASAN)) endif +ifeq ($(CONFIG_UBSAN),y) +_c_flags += $(if $(patsubst n%,, \ + $(UBSAN_SANITIZE_$(basetarget).o)$(UBSAN_SANITIZE)$(CONFIG_UBSAN_SANITIZE_ALL)), \ + $(CFLAGS_UBSAN)) +endif + # If building the kernel in a separate objtree expand all occurrences # of -Idir to -I$(srctree)/dir except for absolute paths (starting with '/'). diff --git a/scripts/Makefile.ubsan b/scripts/Makefile.ubsan new file mode 100644 index 000000000000..8ab68679cfb5 --- /dev/null +++ b/scripts/Makefile.ubsan @@ -0,0 +1,17 @@ +ifdef CONFIG_UBSAN + CFLAGS_UBSAN += $(call cc-option, -fsanitize=shift) + 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) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=returns-nonnull-attribute) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=bool) + CFLAGS_UBSAN += $(call cc-option, -fsanitize=enum) + +ifdef CONFIG_UBSAN_ALIGNMENT + CFLAGS_UBSAN += $(call cc-option, -fsanitize=alignment) +endif +endif diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c index c68fd61fdc42..5b327c67a828 100644 --- a/scripts/basic/fixdep.c +++ b/scripts/basic/fixdep.c @@ -251,7 +251,7 @@ static void parse_config_file(const char *map, size_t len) } /* test is s ends in sub */ -static int strrcmp(char *s, char *sub) +static int strrcmp(const char *s, const char *sub) { int slen = strlen(s); int sublen = strlen(sub); diff --git a/scripts/bloat-o-meter b/scripts/bloat-o-meter index 23e78dcd12bf..38b64f487315 100755 --- a/scripts/bloat-o-meter +++ b/scripts/bloat-o-meter @@ -58,8 +58,8 @@ for name in common: delta.sort() delta.reverse() -print "add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \ - (add, remove, grow, shrink, up, -down, up-down) -print "%-40s %7s %7s %+7s" % ("function", "old", "new", "delta") +print("add/remove: %s/%s grow/shrink: %s/%s up/down: %s/%s (%s)" % \ + (add, remove, grow, shrink, up, -down, up-down)) +print("%-40s %7s %7s %+7s" % ("function", "old", "new", "delta")) for d, n in delta: - if d: print "%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d) + if d: print("%-40s %7s %7s %+7d" % (n, old.get(n,"-"), new.get(n,"-"), d)) diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index 2f4b7ffd5570..d8f6c094cce5 100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -8,11 +8,14 @@ # Licensed under the terms of the GNU GPL License version 2 +import difflib import os import re +import signal import sys -from subprocess import Popen, PIPE, STDOUT +from multiprocessing import Pool, cpu_count from optparse import OptionParser +from subprocess import Popen, PIPE, STDOUT # regex expressions @@ -26,7 +29,7 @@ SOURCE_FEATURE = r"(?:\W|\b)+[D]{,1}CONFIG_(" + FEATURE + r")" # regex objects REGEX_FILE_KCONFIG = re.compile(r".*Kconfig[\.\w+\-]*$") -REGEX_FEATURE = re.compile(r'(?!\B"[^"]*)' + FEATURE + r'(?![^"]*"\B)') +REGEX_FEATURE = re.compile(r'(?!\B)' + FEATURE + r'(?!\B)') REGEX_SOURCE_FEATURE = re.compile(SOURCE_FEATURE) REGEX_KCONFIG_DEF = re.compile(DEF) REGEX_KCONFIG_EXPR = re.compile(EXPR) @@ -34,6 +37,7 @@ 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_NUMERIC = re.compile(r"0[xX][0-9a-fA-F]+|[0-9]+") +REGEX_QUOTES = re.compile("(\"(.*?)\")") def parse_options(): @@ -71,6 +75,9 @@ def parse_options(): "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.") @@ -109,6 +116,18 @@ def main(): """Main function of this module.""" opts = parse_options() + 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)) + else: + print "%s: no similar symbols found" % yel("Similar symbols") + sys.exit(0) + + # dictionary of (un)defined symbols + defined = {} + undefined = {} + if opts.commit or opts.diff: head = get_head() @@ -127,40 +146,56 @@ 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(opts.ignore) # get undefined items for the commit execute("git reset --hard %s" % commit_b) - undefined_b = check_symbols(opts.ignore) + undefined_b, defined = check_symbols(opts.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 not feature in undefined_a: files = sorted(undefined_b.get(feature)) - print "%s\t%s" % (yel(feature), ", ".join(files)) - if opts.find: - commits = find_commits(feature, opts.diff) - print red(commits) + undefined[feature] = files # check if there are new files that reference the undefined feature else: files = sorted(undefined_b.get(feature) - undefined_a.get(feature)) if files: - print "%s\t%s" % (yel(feature), ", ".join(files)) - if opts.find: - commits = find_commits(feature, opts.diff) - print red(commits) + undefined[feature] = files # reset to head execute("git reset --hard %s" % head) # default to check the entire tree else: - undefined = check_symbols(opts.ignore) - for feature in sorted(undefined): - files = sorted(undefined.get(feature)) - print "%s\t%s" % (yel(feature), ", ".join(files)) + undefined, defined = check_symbols(opts.ignore) + + # now print the output + for feature in sorted(undefined): + print red(feature) + + files = sorted(undefined.get(feature)) + 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)) + else: + print "%s: %s" % (sims_out, "no similar symbols found") + + if opts.find: + 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]) + else: + print "\t- no commit found" + print # new line def yel(string): @@ -190,7 +225,7 @@ 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)) - return commits + return [x for x in commits.split("\n") if x] def tree_is_dirty(): @@ -209,43 +244,107 @@ def get_head(): return stdout.strip('\n') -def check_symbols(ignore): - """Find undefined Kconfig symbols and return a dict with the symbol as key - and a list of referencing files as value. Files matching %ignore are not - checked for undefined symbols.""" - source_files = [] - kconfig_files = [] - defined_features = set() - referenced_features = dict() # {feature: [files]} +def partition(lst, size): + """Partition list @lst into eveni-sized lists of size @size.""" + return [lst[i::size] for i in xrange(size)] + + +def init_worker(): + """Set signal handler to ignore SIGINT.""" + signal.signal(signal.SIGINT, signal.SIG_IGN) + + +def find_sims(symbol, ignore, defined = []): + """Return a list of max. ten Kconfig symbols that are string-similar to + @symbol.""" + if defined: + return sorted(difflib.get_close_matches(symbol, set(defined), 10)) + + pool = Pool(cpu_count(), init_worker) + kfiles = [] + for gitfile in get_files(): + if REGEX_FILE_KCONFIG.match(gitfile): + kfiles.append(gitfile) + arglist = [] + for part in partition(kfiles, cpu_count()): + arglist.append((part, ignore)) + + for res in pool.map(parse_kconfig_files, arglist): + defined.extend(res[0]) + + return sorted(difflib.get_close_matches(symbol, set(defined), 10)) + + +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") if len(stdout) > 0 and stdout[-1] == "\n": stdout = stdout[:-1] + files = [] for gitfile in stdout.rsplit("\n"): if ".git" in gitfile or "ChangeLog" in gitfile or \ ".log" in gitfile or os.path.isdir(gitfile) or \ gitfile.startswith("tools/"): continue + files.append(gitfile) + return files + + +def check_symbols(ignore): + """Find undefined Kconfig symbols and return a dict with the symbol as key + and a list of referencing files as value. Files matching %ignore are not + checked for undefined symbols.""" + pool = Pool(cpu_count(), init_worker) + try: + return check_symbols_helper(pool, ignore) + except KeyboardInterrupt: + pool.terminate() + pool.join() + sys.exit(1) + + +def check_symbols_helper(pool, ignore): + """Helper method for check_symbols(). Used to catch keyboard interrupts in + check_symbols() in order to properly terminate running worker processes.""" + source_files = [] + kconfig_files = [] + defined_features = [] + referenced_features = dict() # {file: [features]} + + for gitfile in get_files(): if REGEX_FILE_KCONFIG.match(gitfile): kconfig_files.append(gitfile) else: - # all non-Kconfig files are checked for consistency + if ignore and not re.match(ignore, gitfile): + continue + # add source files that do not match the ignore pattern source_files.append(gitfile) - for sfile in source_files: - if ignore and re.match(ignore, sfile): - # do not check files matching %ignore - continue - parse_source_file(sfile, referenced_features) + # parse source files + arglist = partition(source_files, cpu_count()) + for res in pool.map(parse_source_files, arglist): + referenced_features.update(res) - for kfile in kconfig_files: - if ignore and re.match(ignore, kfile): - # do not collect references for files matching %ignore - parse_kconfig_file(kfile, defined_features, dict()) - else: - parse_kconfig_file(kfile, defined_features, referenced_features) + + # 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) + + # inverse mapping of referenced_features to dict(feature: [files]) + inv_map = dict() + for _file, features in referenced_features.iteritems(): + 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): @@ -259,12 +358,26 @@ def check_symbols(ignore): if feature[:-len("_MODULE")] in defined_features: continue undefined[feature] = referenced_features.get(feature) - return undefined + return undefined, defined_features -def parse_source_file(sfile, referenced_features): - """Parse @sfile for referenced Kconfig features.""" +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() + for sfile in source_files: + referenced_features[sfile] = parse_source_file(sfile) + return referenced_features + + +def parse_source_file(sfile): + """Parse @sfile and return a list of referenced Kconfig features.""" lines = [] + references = [] + + if not os.path.exists(sfile): + return references + with open(sfile, "r") as stream: lines = stream.readlines() @@ -275,9 +388,9 @@ def parse_source_file(sfile, referenced_features): for feature in features: if not REGEX_FILTER_FEATURES.search(feature): continue - sfiles = referenced_features.get(feature, set()) - sfiles.add(sfile) - referenced_features[feature] = sfiles + references.append(feature) + + return references def get_features_in_line(line): @@ -285,11 +398,35 @@ def get_features_in_line(line): return REGEX_FEATURE.findall(line) -def parse_kconfig_file(kfile, defined_features, referenced_features): +def parse_kconfig_files(args): + """Parse kconfig files and return tuple of defined and references Kconfig + symbols. Note, @args is a tuple of a list of files and the @ignore + pattern.""" + kconfig_files = args[0] + ignore = args[1] + defined_features = [] + referenced_features = dict() + + for kfile in kconfig_files: + defined, references = parse_kconfig_file(kfile) + defined_features.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) + + +def parse_kconfig_file(kfile): """Parse @kfile and update feature definitions and references.""" lines = [] + defined = [] + references = [] skip = False + if not os.path.exists(kfile): + return defined, references + with open(kfile, "r") as stream: lines = stream.readlines() @@ -300,7 +437,7 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): if REGEX_KCONFIG_DEF.match(line): feature_def = REGEX_KCONFIG_DEF.findall(line) - defined_features.add(feature_def[0]) + defined.append(feature_def[0]) skip = False elif REGEX_KCONFIG_HELP.match(line): skip = True @@ -308,6 +445,7 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): # ignore content of help messages pass elif REGEX_KCONFIG_STMT.match(line): + line = REGEX_QUOTES.sub("", line) features = get_features_in_line(line) # multi-line statements while line.endswith("\\"): @@ -319,9 +457,9 @@ def parse_kconfig_file(kfile, defined_features, referenced_features): if REGEX_NUMERIC.match(feature): # ignore numeric values continue - paths = referenced_features.get(feature, set()) - paths.add(kfile) - referenced_features[feature] = paths + references.append(feature) + + return defined, references if __name__ == "__main__": diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 2b3c22808c3b..d574d13ba963 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -269,7 +269,8 @@ our $Sparse = qr{ __init_refok| __kprobes| __ref| - __rcu + __rcu| + __private }x; our $InitAttributePrefix = qr{__(?:mem|cpu|dev|net_|)}; our $InitAttributeData = qr{$InitAttributePrefix(?:initdata\b)}; @@ -433,6 +434,28 @@ our @typeList = ( qr{${Ident}_handler_fn}, @typeListMisordered, ); + +our $C90_int_types = qr{(?x: + long\s+long\s+int\s+(?:un)?signed| + long\s+long\s+(?:un)?signed\s+int| + long\s+long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+long\s+int| + (?:(?:un)?signed\s+)?long\s+long| + int\s+long\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long\s+long| + + long\s+int\s+(?:un)?signed| + long\s+(?:un)?signed\s+int| + long\s+(?:un)?signed| + (?:(?:un)?signed\s+)?long\s+int| + (?:(?:un)?signed\s+)?long| + int\s+long\s+(?:un)?signed| + int\s+(?:(?:un)?signed\s+)?long| + + int\s+(?:un)?signed| + (?:(?:un)?signed\s+)?int +)}; + our @typeListFile = (); our @typeListWithAttr = ( @typeList, @@ -3217,6 +3240,30 @@ sub process { #ignore lines not being added next if ($line =~ /^[^\+]/); +# check for declarations of signed or unsigned without int + while ($line =~ m{($Declare)\s*(?!char\b|short\b|int\b|long\b)\s*($Ident)?\s*[=,;\[\)\(]}g) { + my $type = $1; + my $var = $2; + $var = "" if (!defined $var); + if ($type =~ /^(?:(?:$Storage|$Inline|$Attribute)\s+)*((?:un)?signed)((?:\s*\*)*)\s*$/) { + my $sign = $1; + my $pointer = $2; + + $pointer = "" if (!defined $pointer); + + if (WARN("UNSPECIFIED_INT", + "Prefer '" . trim($sign) . " int" . rtrim($pointer) . "' to bare use of '$sign" . rtrim($pointer) . "'\n" . $herecurr) && + $fix) { + my $decl = trim($sign) . " int "; + my $comp_pointer = $pointer; + $comp_pointer =~ s/\s//g; + $decl .= $comp_pointer; + $decl = rtrim($decl) if ($var eq ""); + $fixed[$fixlinenr] =~ s@\b$sign\s*\Q$pointer\E\s*$var\b@$decl$var@; + } + } + } + # TEST: allow direct testing of the type matcher. if ($dbg_type) { if ($line =~ /^.\s*$Declare\s*$/) { @@ -4086,7 +4133,7 @@ sub process { ## } #need space before brace following if, while, etc - if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\){/) || + if (($line =~ /\(.*\)\{/ && $line !~ /\($Type\)\{/) || $line =~ /do\{/) { if (ERROR("SPACING", "space required before the open brace '{'\n" . $herecurr) && @@ -4517,7 +4564,7 @@ sub process { #print "LINE<$lines[$ln-1]> len<" . length($lines[$ln-1]) . "\n"; $has_flow_statement = 1 if ($ctx =~ /\b(goto|return)\b/); - $has_arg_concat = 1 if ($ctx =~ /\#\#/); + $has_arg_concat = 1 if ($ctx =~ /\#\#/ && $ctx !~ /\#\#\s*(?:__VA_ARGS__|args)\b/); $dstat =~ s/^.\s*\#\s*define\s+$Ident(?:\([^\)]*\))?\s*//; $dstat =~ s/$;//g; @@ -4528,7 +4575,7 @@ sub process { # Flatten any parentheses and braces while ($dstat =~ s/\([^\(\)]*\)/1/ || $dstat =~ s/\{[^\{\}]*\}/1/ || - $dstat =~ s/\[[^\[\]]*\]/1/) + $dstat =~ s/.\[[^\[\]]*\]/1/) { } @@ -4538,6 +4585,9 @@ sub process { { } + # Make asm volatile uses seem like a generic function + $dstat =~ s/\b_*asm_*\s+_*volatile_*\b/asm_volatile/g; + my $exceptions = qr{ $Declare| module_param_named| @@ -4548,7 +4598,8 @@ sub process { union| struct| \.$Ident\s*=\s*| - ^\"|\"$ + ^\"|\"$| + ^\[ }x; #print "REST<$rest> dstat<$dstat> ctx<$ctx>\n"; if ($dstat ne '' && @@ -5116,13 +5167,44 @@ sub process { } } # check for memory barriers without a comment. - if ($line =~ /\b(mb|rmb|wmb|read_barrier_depends|smp_mb|smp_rmb|smp_wmb|smp_read_barrier_depends)\(/) { + + my $barriers = qr{ + mb| + rmb| + wmb| + read_barrier_depends + }x; + my $barrier_stems = qr{ + mb__before_atomic| + mb__after_atomic| + store_release| + load_acquire| + store_mb| + (?:$barriers) + }x; + my $all_barriers = qr{ + (?:$barriers)| + smp_(?:$barrier_stems)| + virt_(?:$barrier_stems) + }x; + + if ($line =~ /\b(?:$all_barriers)\s*\(/) { if (!ctx_has_comment($first_line, $linenr)) { WARN("MEMORY_BARRIER", "memory barrier without comment\n" . $herecurr); } } + my $underscore_smp_barriers = qr{__smp_(?:$barrier_stems)}x; + + if ($realfile !~ m@^include/asm-generic/@ && + $realfile !~ m@/barrier\.h$@ && + $line =~ m/\b(?:$underscore_smp_barriers)\s*\(/ && + $line !~ m/^.\s*\#\s*define\s+(?:$underscore_smp_barriers)\s*\(/) { + WARN("MEMORY_BARRIER", + "__smp memory barriers shouldn't be used outside barrier.h and asm-generic\n" . $herecurr); + } + # check for waitqueue_active without a comment. if ($line =~ /\bwaitqueue_active\s*\(/) { if (!ctx_has_comment($first_line, $linenr)) { @@ -5241,6 +5323,26 @@ sub process { } } +# check for cast of C90 native int or longer types constants + if ($line =~ /(\(\s*$C90_int_types\s*\)\s*)($Constant)\b/) { + my $cast = $1; + my $const = $2; + if (WARN("TYPECAST_INT_CONSTANT", + "Unnecessary typecast of c90 int constant\n" . $herecurr) && + $fix) { + my $suffix = ""; + my $newconst = $const; + $newconst =~ s/${Int_type}$//; + $suffix .= 'U' if ($cast =~ /\bunsigned\b/); + if ($cast =~ /\blong\s+long\b/) { + $suffix .= 'LL'; + } elsif ($cast =~ /\blong\b/) { + $suffix .= 'L'; + } + $fixed[$fixlinenr] =~ s/\Q$cast\E$const\b/$newconst$suffix/; + } + } + # check for sizeof(&) if ($line =~ /\bsizeof\s*\(\s*\&/) { WARN("SIZEOF_ADDRESS", diff --git a/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci b/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci new file mode 100644 index 000000000000..8fa5a3c7b784 --- /dev/null +++ b/scripts/coccinelle/tests/unsigned_lesser_than_zero.cocci @@ -0,0 +1,75 @@ +/// Unsigned expressions cannot be lesser than zero. Presence of +/// comparisons 'unsigned (<|<=|>|>=) 0' often indicates a bug, +/// usually wrong type of variable. +/// +/// To reduce number of false positives following tests have been added: +/// - parts of range checks are skipped, eg. "if (u < 0 || u > 15) ...", +/// developers prefer to keep such code, +/// - comparisons "<= 0" and "> 0" are performed only on results of +/// signed functions/macros, +/// - hardcoded list of signed functions/macros with always non-negative +/// result is used to avoid false positives difficult to detect by other ways +/// +// Confidence: Average +// Copyright: (C) 2015 Andrzej Hajda, Samsung Electronics Co., Ltd. GPLv2. +// URL: http://coccinelle.lip6.fr/ +// Options: --all-includes + +virtual context +virtual org +virtual report + +@r_cmp@ +position p; +typedef bool, u8, u16, u32, u64; +{unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long, + size_t, bool, u8, u16, u32, u64} v; +expression e; +@@ + + \( v = e \| &v \) + ... + (\( v@p < 0 \| v@p <= 0 \| v@p >= 0 \| v@p > 0 \)) + +@r@ +position r_cmp.p; +typedef s8, s16, s32, s64; +{char, short, int, long, long long, ssize_t, s8, s16, s32, s64} vs; +expression c, e, v; +identifier f !~ "^(ata_id_queue_depth|btrfs_copy_from_user|dma_map_sg|dma_map_sg_attrs|fls|fls64|gameport_time|get_write_extents|nla_len|ntoh24|of_flat_dt_match|of_get_child_count|uart_circ_chars_pending|[A-Z0-9_]+)$"; +@@ + +( + v = f(...)@vs; + ... when != v = e; +* (\( v@p <=@e 0 \| v@p >@e 0 \)) + ... when any +| +( + (\( v@p < 0 \| v@p <= 0 \)) || ... || (\( v >= c \| v > c \)) +| + (\( v >= c \| v > c \)) || ... || (\( v@p < 0 \| v@p <= 0 \)) +| + (\( v@p >= 0 \| v@p > 0 \)) && ... && (\( v < c \| v <= c \)) +| + ((\( v < c \| v <= c \) && ... && \( v@p >= 0 \| v@p > 0 \))) +| +* (\( v@p <@e 0 \| v@p >=@e 0 \)) +) +) + +@script:python depends on org@ +p << r_cmp.p; +e << r.e; +@@ + +msg = "WARNING: Unsigned expression compared with zero: %s" % (e) +coccilib.org.print_todo(p[0], msg) + +@script:python depends on report@ +p << r_cmp.p; +e << r.e; +@@ + +msg = "WARNING: Unsigned expression compared with zero: %s" % (e) +coccilib.report.print_report(p[0], msg) diff --git a/scripts/extract-sys-certs.pl b/scripts/extract-sys-certs.pl index d476e7d1fd88..8227ca10a494 100755 --- a/scripts/extract-sys-certs.pl +++ b/scripts/extract-sys-certs.pl @@ -91,13 +91,15 @@ print "Have $nr_symbols symbols\n"; die "Can't find system certificate list" unless (exists($symbols{"__cert_list_start"}) && - exists($symbols{"__cert_list_end"})); + exists($symbols{"system_certificate_list_size"})); my $start = Math::BigInt->new($symbols{"__cert_list_start"}); -my $end = Math::BigInt->new($symbols{"__cert_list_end"}); -my $size = $end - $start; +my $end; +my $size; +my $size_sym = Math::BigInt->new($symbols{"system_certificate_list_size"}); -printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start; +open FD, "<$vmlinux" || die $vmlinux; +binmode(FD); my $s = undef; foreach my $sec (@sections) { @@ -110,11 +112,24 @@ foreach my $sec (@sections) { next unless ($start >= $s_vma); next if ($start >= $s_vend); - die "Cert object partially overflows section $s_name\n" - if ($end > $s_vend); + die "Certificate list size was not found on the same section\n" + if ($size_sym < $s_vma || $size_sym > $s_vend); die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n" if ($s); + + my $size_off = $size_sym -$s_vma + $s_foff; + my $packed; + die $vmlinux if (!defined(sysseek(FD, $size_off, SEEK_SET))); + sysread(FD, $packed, 8); + $size = unpack 'L!', $packed; + $end = $start + $size; + + printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start; + + die "Cert object partially overflows section $s_name\n" + if ($end > $s_vend); + $s = $sec; } @@ -127,8 +142,6 @@ my $foff = $start - $s->{vma} + $s->{foff}; printf "Certificate list at file offset 0x%x\n", $foff; -open FD, "<$vmlinux" || die $vmlinux; -binmode(FD); die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET))); my $buf = ""; my $len = sysread(FD, $buf, $size); diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c index 88632df4381b..dafaf96e0a34 100644 --- a/scripts/genksyms/genksyms.c +++ b/scripts/genksyms/genksyms.c @@ -423,13 +423,15 @@ static struct string_list *read_node(FILE *f) struct string_list node = { .string = buffer, .tag = SYM_NORMAL }; - int c; + int c, in_string = 0; while ((c = fgetc(f)) != EOF) { - if (c == ' ') { + if (!in_string && c == ' ') { if (node.string == buffer) continue; break; + } else if (c == '"') { + in_string = !in_string; } else if (c == '\n') { if (node.string == buffer) return NULL; diff --git a/scripts/get_maintainer.pl b/scripts/get_maintainer.pl index cab641a12dd5..1873421f2305 100755 --- a/scripts/get_maintainer.pl +++ b/scripts/get_maintainer.pl @@ -16,7 +16,9 @@ my $P = $0; my $V = '0.26'; use Getopt::Long qw(:config no_auto_abbrev); +use Cwd; +my $cur_path = fastgetcwd() . '/'; my $lk_path = "./"; my $email = 1; my $email_usename = 1; @@ -429,6 +431,8 @@ foreach my $file (@ARGV) { } } if ($from_filename) { + $file =~ s/^\Q${cur_path}\E//; #strip any absolute path + $file =~ s/^\Q${lk_path}\E//; #or the path to the lk tree push(@files, $file); if ($file ne "MAINTAINERS" && -f $file && ($keywords || $file_emails)) { open(my $f, '<', $file) diff --git a/scripts/insert-sys-cert.c b/scripts/insert-sys-cert.c new file mode 100644 index 000000000000..8902836c2342 --- /dev/null +++ b/scripts/insert-sys-cert.c @@ -0,0 +1,410 @@ +/* Write the contents of the <certfile> into kernel symbol system_extra_cert + * + * Copyright (C) IBM Corporation, 2015 + * + * Author: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com> + * + * This software may be used and distributed according to the terms + * of the GNU General Public License, incorporated herein by reference. + * + * Usage: insert-sys-cert [-s <System.map> -b <vmlinux> -c <certfile> + */ + +#define _GNU_SOURCE +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <limits.h> +#include <stdbool.h> +#include <errno.h> +#include <stdlib.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <fcntl.h> +#include <unistd.h> +#include <elf.h> + +#define CERT_SYM "system_extra_cert" +#define USED_SYM "system_extra_cert_used" +#define LSIZE_SYM "system_certificate_list_size" + +#define info(format, args...) fprintf(stderr, "INFO: " format, ## args) +#define warn(format, args...) fprintf(stdout, "WARNING: " format, ## args) +#define err(format, args...) fprintf(stderr, "ERROR: " format, ## args) + +#if UINTPTR_MAX == 0xffffffff +#define CURRENT_ELFCLASS ELFCLASS32 +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Shdr Elf32_Shdr +#define Elf_Sym Elf32_Sym +#else +#define CURRENT_ELFCLASS ELFCLASS64 +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Shdr Elf64_Shdr +#define Elf_Sym Elf64_Sym +#endif + +static unsigned char endianness(void) +{ + uint16_t two_byte = 0x00FF; + uint8_t low_address = *((uint8_t *)&two_byte); + + if (low_address == 0) + return ELFDATA2MSB; + else + return ELFDATA2LSB; +} + +struct sym { + char *name; + unsigned long address; + unsigned long offset; + void *content; + int size; +}; + +static unsigned long get_offset_from_address(Elf_Ehdr *hdr, unsigned long addr) +{ + Elf_Shdr *x; + unsigned int i, num_sections; + + x = (void *)hdr + hdr->e_shoff; + if (hdr->e_shnum == SHN_UNDEF) + num_sections = x[0].sh_size; + else + num_sections = hdr->e_shnum; + + for (i = 1; i < num_sections; i++) { + unsigned long start = x[i].sh_addr; + unsigned long end = start + x[i].sh_size; + unsigned long offset = x[i].sh_offset; + + if (addr >= start && addr <= end) + return addr - start + offset; + } + return 0; +} + + +#define LINE_SIZE 100 + +static void get_symbol_from_map(Elf_Ehdr *hdr, FILE *f, char *name, + struct sym *s) +{ + char l[LINE_SIZE]; + char *w, *p, *n; + + s->size = 0; + s->address = 0; + s->offset = 0; + if (fseek(f, 0, SEEK_SET) != 0) { + perror("File seek failed"); + exit(EXIT_FAILURE); + } + while (fgets(l, LINE_SIZE, f)) { + p = strchr(l, '\n'); + if (!p) { + err("Missing line ending.\n"); + return; + } + n = strstr(l, name); + if (n) + break; + } + if (!n) { + err("Unable to find symbol: %s\n", name); + return; + } + w = strchr(l, ' '); + if (!w) + return; + + *w = '\0'; + s->address = strtoul(l, NULL, 16); + if (s->address == 0) + return; + s->offset = get_offset_from_address(hdr, s->address); + s->name = name; + s->content = (void *)hdr + s->offset; +} + +static Elf_Sym *find_elf_symbol(Elf_Ehdr *hdr, Elf_Shdr *symtab, char *name) +{ + Elf_Sym *sym, *symtab_start; + char *strtab, *symname; + unsigned int link; + Elf_Shdr *x; + int i, n; + + x = (void *)hdr + hdr->e_shoff; + link = symtab->sh_link; + symtab_start = (void *)hdr + symtab->sh_offset; + n = symtab->sh_size / symtab->sh_entsize; + strtab = (void *)hdr + x[link].sh_offset; + + for (i = 0; i < n; i++) { + sym = &symtab_start[i]; + symname = strtab + sym->st_name; + if (strcmp(symname, name) == 0) + return sym; + } + err("Unable to find symbol: %s\n", name); + return NULL; +} + +static void get_symbol_from_table(Elf_Ehdr *hdr, Elf_Shdr *symtab, + char *name, struct sym *s) +{ + Elf_Shdr *sec; + int secndx; + Elf_Sym *elf_sym; + Elf_Shdr *x; + + x = (void *)hdr + hdr->e_shoff; + s->size = 0; + s->address = 0; + s->offset = 0; + elf_sym = find_elf_symbol(hdr, symtab, name); + if (!elf_sym) + return; + secndx = elf_sym->st_shndx; + if (!secndx) + return; + sec = &x[secndx]; + s->size = elf_sym->st_size; + s->address = elf_sym->st_value; + s->offset = s->address - sec->sh_addr + + sec->sh_offset; + s->name = name; + s->content = (void *)hdr + s->offset; +} + +static Elf_Shdr *get_symbol_table(Elf_Ehdr *hdr) +{ + Elf_Shdr *x; + unsigned int i, num_sections; + + x = (void *)hdr + hdr->e_shoff; + if (hdr->e_shnum == SHN_UNDEF) + num_sections = x[0].sh_size; + else + num_sections = hdr->e_shnum; + + for (i = 1; i < num_sections; i++) + if (x[i].sh_type == SHT_SYMTAB) + return &x[i]; + return NULL; +} + +static void *map_file(char *file_name, int *size) +{ + struct stat st; + void *map; + int fd; + + fd = open(file_name, O_RDWR); + if (fd < 0) { + perror(file_name); + return NULL; + } + if (fstat(fd, &st)) { + perror("Could not determine file size"); + close(fd); + return NULL; + } + *size = st.st_size; + map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); + if (map == MAP_FAILED) { + perror("Mapping to memory failed"); + close(fd); + return NULL; + } + close(fd); + return map; +} + +static char *read_file(char *file_name, int *size) +{ + struct stat st; + char *buf; + int fd; + + fd = open(file_name, O_RDONLY); + if (fd < 0) { + perror(file_name); + return NULL; + } + if (fstat(fd, &st)) { + perror("Could not determine file size"); + close(fd); + return NULL; + } + *size = st.st_size; + buf = malloc(*size); + if (!buf) { + perror("Allocating memory failed"); + close(fd); + return NULL; + } + if (read(fd, buf, *size) != *size) { + perror("File read failed"); + close(fd); + return NULL; + } + close(fd); + return buf; +} + +static void print_sym(Elf_Ehdr *hdr, struct sym *s) +{ + info("sym: %s\n", s->name); + info("addr: 0x%lx\n", s->address); + info("size: %d\n", s->size); + info("offset: 0x%lx\n", (unsigned long)s->offset); +} + +static void print_usage(char *e) +{ + printf("Usage %s [-s <System.map>] -b <vmlinux> -c <certfile>\n", e); +} + +int main(int argc, char **argv) +{ + char *system_map_file = NULL; + char *vmlinux_file = NULL; + char *cert_file = NULL; + int vmlinux_size; + int cert_size; + Elf_Ehdr *hdr; + char *cert; + FILE *system_map; + unsigned long *lsize; + int *used; + int opt; + Elf_Shdr *symtab = NULL; + struct sym cert_sym, lsize_sym, used_sym; + + while ((opt = getopt(argc, argv, "b:c:s:")) != -1) { + switch (opt) { + case 's': + system_map_file = optarg; + break; + case 'b': + vmlinux_file = optarg; + break; + case 'c': + cert_file = optarg; + break; + default: + break; + } + } + + if (!vmlinux_file || !cert_file) { + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + cert = read_file(cert_file, &cert_size); + if (!cert) + exit(EXIT_FAILURE); + + hdr = map_file(vmlinux_file, &vmlinux_size); + if (!hdr) + exit(EXIT_FAILURE); + + if (vmlinux_size < sizeof(*hdr)) { + err("Invalid ELF file.\n"); + exit(EXIT_FAILURE); + } + + if ((hdr->e_ident[EI_MAG0] != ELFMAG0) || + (hdr->e_ident[EI_MAG1] != ELFMAG1) || + (hdr->e_ident[EI_MAG2] != ELFMAG2) || + (hdr->e_ident[EI_MAG3] != ELFMAG3)) { + err("Invalid ELF magic.\n"); + exit(EXIT_FAILURE); + } + + if (hdr->e_ident[EI_CLASS] != CURRENT_ELFCLASS) { + err("ELF class mismatch.\n"); + exit(EXIT_FAILURE); + } + + if (hdr->e_ident[EI_DATA] != endianness()) { + err("ELF endian mismatch.\n"); + exit(EXIT_FAILURE); + } + + if (hdr->e_shoff > vmlinux_size) { + err("Could not find section header.\n"); + exit(EXIT_FAILURE); + } + + symtab = get_symbol_table(hdr); + if (!symtab) { + warn("Could not find the symbol table.\n"); + if (!system_map_file) { + err("Please provide a System.map file.\n"); + print_usage(argv[0]); + exit(EXIT_FAILURE); + } + + system_map = fopen(system_map_file, "r"); + if (!system_map) { + perror(system_map_file); + exit(EXIT_FAILURE); + } + get_symbol_from_map(hdr, system_map, CERT_SYM, &cert_sym); + get_symbol_from_map(hdr, system_map, USED_SYM, &used_sym); + get_symbol_from_map(hdr, system_map, LSIZE_SYM, &lsize_sym); + cert_sym.size = used_sym.address - cert_sym.address; + } else { + info("Symbol table found.\n"); + if (system_map_file) + warn("System.map is ignored.\n"); + get_symbol_from_table(hdr, symtab, CERT_SYM, &cert_sym); + get_symbol_from_table(hdr, symtab, USED_SYM, &used_sym); + get_symbol_from_table(hdr, symtab, LSIZE_SYM, &lsize_sym); + } + + if (!cert_sym.offset || !lsize_sym.offset || !used_sym.offset) + exit(EXIT_FAILURE); + + print_sym(hdr, &cert_sym); + print_sym(hdr, &used_sym); + print_sym(hdr, &lsize_sym); + + lsize = (unsigned long *)lsize_sym.content; + used = (int *)used_sym.content; + + if (cert_sym.size < cert_size) { + err("Certificate is larger than the reserved area!\n"); + exit(EXIT_FAILURE); + } + + /* If the existing cert is the same, don't overwrite */ + if (cert_size == *used && + strncmp(cert_sym.content, cert, cert_size) == 0) { + warn("Certificate was already inserted.\n"); + exit(EXIT_SUCCESS); + } + + if (*used > 0) + warn("Replacing previously inserted certificate.\n"); + + memcpy(cert_sym.content, cert, cert_size); + if (cert_size < cert_sym.size) + memset(cert_sym.content + cert_size, + 0, cert_sym.size - cert_size); + + *lsize = *lsize + cert_size - *used; + *used = cert_size; + info("Inserted the contents of %s into %lx.\n", cert_file, + cert_sym.address); + info("Used %d bytes out of %d bytes reserved.\n", *used, + cert_sym.size); + exit(EXIT_SUCCESS); +} diff --git a/scripts/kallsyms.c b/scripts/kallsyms.c index 8fa81e84e295..638b143ee60f 100644 --- a/scripts/kallsyms.c +++ b/scripts/kallsyms.c @@ -22,6 +22,7 @@ #include <stdlib.h> #include <string.h> #include <ctype.h> +#include <limits.h> #ifndef ARRAY_SIZE #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0])) @@ -34,6 +35,7 @@ struct sym_entry { unsigned int len; unsigned int start_pos; unsigned char *sym; + unsigned int percpu_absolute; }; struct addr_range { @@ -42,6 +44,7 @@ struct addr_range { }; static unsigned long long _text; +static unsigned long long relative_base; static struct addr_range text_ranges[] = { { "_stext", "_etext" }, { "_sinittext", "_einittext" }, @@ -61,6 +64,7 @@ static int all_symbols = 0; static int absolute_percpu = 0; static char symbol_prefix_char = '\0'; static unsigned long long kernel_start_addr = 0; +static int base_relative = 0; int token_profit[0x10000]; @@ -74,7 +78,7 @@ static void usage(void) fprintf(stderr, "Usage: kallsyms [--all-symbols] " "[--symbol-prefix=<prefix char>] " "[--page-offset=<CONFIG_PAGE_OFFSET>] " - "< in.map > out.S\n"); + "[--base-relative] < in.map > out.S\n"); exit(1); } @@ -171,6 +175,8 @@ static int read_symbol(FILE *in, struct sym_entry *s) strcpy((char *)s->sym + 1, str); s->sym[0] = stype; + s->percpu_absolute = 0; + /* Record if we've found __per_cpu_start/end. */ check_symbol_range(sym, s->addr, &percpu_range, 1); @@ -202,6 +208,8 @@ static int symbol_valid(struct sym_entry *s) */ static char *special_symbols[] = { "kallsyms_addresses", + "kallsyms_offsets", + "kallsyms_relative_base", "kallsyms_num_syms", "kallsyms_names", "kallsyms_markers", @@ -325,7 +333,7 @@ static int expand_symbol(unsigned char *data, int len, char *result) static int symbol_absolute(struct sym_entry *s) { - return toupper(s->sym[0]) == 'A'; + return s->percpu_absolute; } static void write_src(void) @@ -346,16 +354,48 @@ static void write_src(void) printf("\t.section .rodata, \"a\"\n"); - /* Provide proper symbols relocatability by their '_text' - * relativeness. The symbol names cannot be used to construct - * normal symbol references as the list of symbols contains - * symbols that are declared static and are private to their - * .o files. This prevents .tmp_kallsyms.o or any other - * object from referencing them. + /* Provide proper symbols relocatability by their relativeness + * to a fixed anchor point in the runtime image, either '_text' + * for absolute address tables, in which case the linker will + * emit the final addresses at build time. Otherwise, use the + * offset relative to the lowest value encountered of all relative + * symbols, and emit non-relocatable fixed offsets that will be fixed + * up at runtime. + * + * The symbol names cannot be used to construct normal symbol + * references as the list of symbols contains symbols that are + * declared static and are private to their .o files. This prevents + * .tmp_kallsyms.o or any other object from referencing them. */ - output_label("kallsyms_addresses"); + if (!base_relative) + output_label("kallsyms_addresses"); + else + output_label("kallsyms_offsets"); + for (i = 0; i < table_cnt; i++) { - if (!symbol_absolute(&table[i])) { + if (base_relative) { + long long offset; + int overflow; + + if (!absolute_percpu) { + offset = table[i].addr - relative_base; + overflow = (offset < 0 || offset > UINT_MAX); + } else if (symbol_absolute(&table[i])) { + offset = table[i].addr; + overflow = (offset < 0 || offset > INT_MAX); + } else { + offset = relative_base - table[i].addr - 1; + overflow = (offset < INT_MIN || offset >= 0); + } + if (overflow) { + fprintf(stderr, "kallsyms failure: " + "%s symbol value %#llx out of range in relative mode\n", + symbol_absolute(&table[i]) ? "absolute" : "relative", + table[i].addr); + exit(EXIT_FAILURE); + } + printf("\t.long\t%#x\n", (int)offset); + } else if (!symbol_absolute(&table[i])) { if (_text <= table[i].addr) printf("\tPTR\t_text + %#llx\n", table[i].addr - _text); @@ -368,6 +408,12 @@ static void write_src(void) } printf("\n"); + if (base_relative) { + output_label("kallsyms_relative_base"); + printf("\tPTR\t_text - %#llx\n", _text - relative_base); + printf("\n"); + } + output_label("kallsyms_num_syms"); printf("\tPTR\t%d\n", table_cnt); printf("\n"); @@ -681,8 +727,27 @@ static void make_percpus_absolute(void) unsigned int i; for (i = 0; i < table_cnt; i++) - if (symbol_in_range(&table[i], &percpu_range, 1)) + if (symbol_in_range(&table[i], &percpu_range, 1)) { + /* + * Keep the 'A' override for percpu symbols to + * ensure consistent behavior compared to older + * versions of this tool. + */ table[i].sym[0] = 'A'; + table[i].percpu_absolute = 1; + } +} + +/* find the minimum non-absolute symbol address */ +static void record_relative_base(void) +{ + unsigned int i; + + relative_base = -1ULL; + for (i = 0; i < table_cnt; i++) + if (!symbol_absolute(&table[i]) && + table[i].addr < relative_base) + relative_base = table[i].addr; } int main(int argc, char **argv) @@ -703,7 +768,9 @@ int main(int argc, char **argv) } else if (strncmp(argv[i], "--page-offset=", 14) == 0) { const char *p = &argv[i][14]; kernel_start_addr = strtoull(p, NULL, 16); - } else + } else if (strcmp(argv[i], "--base-relative") == 0) + base_relative = 1; + else usage(); } } else if (argc != 1) @@ -712,6 +779,8 @@ int main(int argc, char **argv) read_map(stdin); if (absolute_percpu) make_percpus_absolute(); + if (base_relative) + record_relative_base(); sort_symbols(); optimize_token_table(); write_src(); diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c index 6c204318bc94..866369f10ff8 100644 --- a/scripts/kconfig/conf.c +++ b/scripts/kconfig/conf.c @@ -5,6 +5,7 @@ #include <locale.h> #include <ctype.h> +#include <limits.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -41,7 +42,7 @@ static int tty_stdio; static int valid_stdin = 1; static int sync_kconfig; static int conf_cnt; -static char line[128]; +static char line[PATH_MAX]; static struct menu *rootEntry; static void print_help(struct menu *menu) @@ -109,7 +110,7 @@ static int conf_askvalue(struct symbol *sym, const char *def) /* fall through */ case oldaskconfig: fflush(stdout); - xfgets(line, 128, stdin); + xfgets(line, sizeof(line), stdin); if (!tty_stdio) printf("\n"); return 1; @@ -311,7 +312,7 @@ static int conf_choice(struct menu *menu) /* fall through */ case oldaskconfig: fflush(stdout); - xfgets(line, 128, stdin); + xfgets(line, sizeof(line), stdin); strip(line); if (line[0] == '?') { print_help(menu); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index b05cc3d4a9be..aed678e8a777 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -477,7 +477,7 @@ bool menu_is_visible(struct menu *menu) if (menu->visibility) { if (expr_calc_value(menu->visibility) == no) - return no; + return false; } sym = menu->sym; diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc index 91b7e6fbc364..fc5555992220 100644 --- a/scripts/kconfig/qconf.cc +++ b/scripts/kconfig/qconf.cc @@ -1863,6 +1863,8 @@ int main(int ac, char** av) configSettings->endGroup(); delete configSettings; + delete v; + delete configApp; return 0; } diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 638a38e1b419..c37255bb620d 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1816,6 +1816,8 @@ sub dump_struct($$) { $members =~ s/__attribute__\s*\(\([a-z,_\*\s\(\)]*\)\)//i; $members =~ s/__aligned\s*\([^;]*\)//gos; $members =~ s/\s*CRYPTO_MINALIGN_ATTR//gos; + # replace DECLARE_BITMAP + $members =~ s/DECLARE_BITMAP\s*\(([^,)]+), ([^,)]+)\)/unsigned long $1\[BITS_TO_LONGS($2)\]/gos; create_parameterlist($members, ';', $file); check_sections($file, $declaration_name, "struct", $sectcheck, $struct_actual, $nested); @@ -1844,7 +1846,8 @@ sub dump_enum($$) { my $file = shift; $x =~ s@/\*.*?\*/@@gos; # strip comments. - $x =~ s/^#\s*define\s+.*$//; # strip #define macros inside enums + # strip #define macros inside enums + $x =~ s@#\s*((define|ifdef)\s+|endif)[^;]*;@@gos; if ($x =~ /enum\s+(\w+)\s*{(.*)}/) { $declaration_name = $1; diff --git a/scripts/ld-version.sh b/scripts/ld-version.sh index d154f0877fd8..7bfe9fa1c8dc 100755 --- a/scripts/ld-version.sh +++ b/scripts/ld-version.sh @@ -1,7 +1,7 @@ #!/usr/bin/awk -f # extract linker version number from stdin and turn into single number { - gsub(".*)", ""); + gsub(".*\\)", ""); gsub(".*version ", ""); gsub("-.*", ""); split($1,a, "."); diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh index ba6c34ea5429..453ede9d2f3d 100755 --- a/scripts/link-vmlinux.sh +++ b/scripts/link-vmlinux.sh @@ -86,10 +86,14 @@ kallsyms() kallsymopt="${kallsymopt} --page-offset=$CONFIG_PAGE_OFFSET" fi - if [ -n "${CONFIG_X86_64}" ]; then + if [ -n "${CONFIG_KALLSYMS_ABSOLUTE_PERCPU}" ]; then kallsymopt="${kallsymopt} --absolute-percpu" fi + if [ -n "${CONFIG_KALLSYMS_BASE_RELATIVE}" ]; then + kallsymopt="${kallsymopt} --base-relative" + fi + local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL} \ ${NOSTDINC_FLAGS} ${LINUXINCLUDE} ${KBUILD_CPPFLAGS}" diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c index 5b96206e9aab..161dd0d67da8 100644 --- a/scripts/mod/file2alias.c +++ b/scripts/mod/file2alias.c @@ -125,7 +125,7 @@ do { \ sprintf(str + strlen(str), "*"); \ } while(0) -/* Always end in a wildcard, for future extension */ +/* End in a wildcard, for future extension */ static inline void add_wildcard(char *str) { int len = strlen(str); @@ -704,7 +704,6 @@ static int do_of_entry (const char *filename, void *symval, char *alias) if (isspace (*tmp)) *tmp = '_'; - add_wildcard(alias); return 1; } ADD_TO_DEVTABLE("of", of_device_id, do_of_entry); @@ -917,7 +916,7 @@ static int do_vmbus_entry(const char *filename, void *symval, char guid_name[(sizeof(*guid) + 1) * 2]; for (i = 0; i < (sizeof(*guid) * 2); i += 2) - sprintf(&guid_name[i], "%02x", TO_NATIVE((*guid)[i/2])); + sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2])); strcpy(alias, "vmbus:"); strcat(alias, guid_name); diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index e080746e1a6b..48958d3cec9e 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -594,7 +594,8 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname) if (strncmp(symname, "_restgpr0_", sizeof("_restgpr0_") - 1) == 0 || strncmp(symname, "_savegpr0_", sizeof("_savegpr0_") - 1) == 0 || strncmp(symname, "_restvr_", sizeof("_restvr_") - 1) == 0 || - strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0) + strncmp(symname, "_savevr_", sizeof("_savevr_") - 1) == 0 || + strcmp(symname, ".TOC.") == 0) return 1; /* Do not ignore this symbol */ return 0; diff --git a/scripts/namespace.pl b/scripts/namespace.pl index a71be6b7cdec..9f3c9d47a4a5 100755 --- a/scripts/namespace.pl +++ b/scripts/namespace.pl @@ -117,6 +117,8 @@ my %nameexception = ( 'kallsyms_names' => 1, 'kallsyms_num_syms' => 1, 'kallsyms_addresses'=> 1, + 'kallsyms_offsets' => 1, + 'kallsyms_relative_base'=> 1, '__this_module' => 1, '_etext' => 1, '_edata' => 1, diff --git a/scripts/package/Makefile b/scripts/package/Makefile index 1aca224e8597..c2c7389bfbab 100644 --- a/scripts/package/Makefile +++ b/scripts/package/Makefile @@ -118,12 +118,12 @@ quiet_cmd_perf_tar = TAR cmd_perf_tar = \ git --git-dir=$(srctree)/.git archive --prefix=$(perf-tar)/ \ HEAD^{tree} $$(cd $(srctree); \ - echo $$(cat $(srctree)/tools/perf/MANIFEST)) \ + echo $$(cat tools/perf/MANIFEST)) \ -o $(perf-tar).tar; \ mkdir -p $(perf-tar); \ git --git-dir=$(srctree)/.git rev-parse HEAD > $(perf-tar)/HEAD; \ (cd $(srctree)/tools/perf; \ -util/PERF-VERSION-GEN ../../$(perf-tar)/ 2>/dev/null); \ +util/PERF-VERSION-GEN $(CURDIR)/$(perf-tar)/); \ tar rf $(perf-tar).tar $(perf-tar)/HEAD $(perf-tar)/PERF-VERSION-FILE; \ rm -r $(perf-tar); \ $(if $(findstring tar-src,$@),, \ diff --git a/scripts/prune-kernel b/scripts/prune-kernel new file mode 100755 index 000000000000..ab5034e1d081 --- /dev/null +++ b/scripts/prune-kernel @@ -0,0 +1,20 @@ +#!/bin/bash + +# because I use CONFIG_LOCALVERSION_AUTO, not the same version again and +# again, /boot and /lib/modules/ eventually fill up. +# Dumb script to purge that stuff: + +for f in "$@" +do + if rpm -qf "/lib/modules/$f" >/dev/null; then + echo "keeping $f (installed from rpm)" + elif [ $(uname -r) = "$f" ]; then + echo "keeping $f (running kernel) " + else + echo "removing $f" + rm -f "/boot/initramfs-$f.img" "/boot/System.map-$f" + rm -f "/boot/vmlinuz-$f" "/boot/config-$f" + rm -rf "/lib/modules/$f" + new-kernel-pkg --remove $f + fi +done diff --git a/scripts/recordmcount.pl b/scripts/recordmcount.pl index 826470d7f000..96e2486a6fc4 100755 --- a/scripts/recordmcount.pl +++ b/scripts/recordmcount.pl @@ -263,7 +263,8 @@ if ($arch eq "x86_64") { } elsif ($arch eq "powerpc") { $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)"; - $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:"; + # See comment in the sparc64 section for why we use '\w'. + $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?\\w*?)>:"; $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$"; if ($bits == 64) { diff --git a/scripts/sign-file.c b/scripts/sign-file.c index 250a7a645033..d912d5a56a5e 100755 --- a/scripts/sign-file.c +++ b/scripts/sign-file.c @@ -2,9 +2,11 @@ * * Copyright © 2014-2015 Red Hat, Inc. All Rights Reserved. * Copyright © 2015 Intel Corporation. + * Copyright © 2016 Hewlett Packard Enterprise Development LP * * Authors: David Howells <dhowells@redhat.com> * David Woodhouse <dwmw2@infradead.org> + * Juerg Haefliger <juerg.haefliger@hpe.com> * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -39,7 +41,7 @@ * signing with anything other than SHA1 - so we're stuck with that if such is * the case. */ -#if OPENSSL_VERSION_NUMBER < 0x10000000L +#if OPENSSL_VERSION_NUMBER < 0x10000000L || defined(OPENSSL_NO_CMS) #define USE_PKCS7 #endif #ifndef USE_PKCS7 @@ -67,6 +69,8 @@ void format(void) { fprintf(stderr, "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n"); + fprintf(stderr, + " scripts/sign-file -s <raw sig> <hash algo> <x509> <module> [<dest>]\n"); exit(2); } @@ -126,26 +130,84 @@ static int pem_pw_cb(char *buf, int len, int w, void *v) return pwlen; } +static EVP_PKEY *read_private_key(const char *private_key_name) +{ + EVP_PKEY *private_key; + + if (!strncmp(private_key_name, "pkcs11:", 7)) { + ENGINE *e; + + ENGINE_load_builtin_engines(); + drain_openssl_errors(); + e = ENGINE_by_id("pkcs11"); + ERR(!e, "Load PKCS#11 ENGINE"); + if (ENGINE_init(e)) + drain_openssl_errors(); + else + ERR(1, "ENGINE_init"); + if (key_pass) + ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), + "Set PKCS#11 PIN"); + private_key = ENGINE_load_private_key(e, private_key_name, + NULL, NULL); + ERR(!private_key, "%s", private_key_name); + } else { + BIO *b; + + b = BIO_new_file(private_key_name, "rb"); + ERR(!b, "%s", private_key_name); + private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, + NULL); + ERR(!private_key, "%s", private_key_name); + BIO_free(b); + } + + return private_key; +} + +static X509 *read_x509(const char *x509_name) +{ + X509 *x509; + BIO *b; + + b = BIO_new_file(x509_name, "rb"); + ERR(!b, "%s", x509_name); + x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ + if (!x509) { + ERR(BIO_reset(b) != 1, "%s", x509_name); + x509 = PEM_read_bio_X509(b, NULL, NULL, + NULL); /* PEM encoded X.509 */ + if (x509) + drain_openssl_errors(); + } + BIO_free(b); + ERR(!x509, "%s", x509_name); + + return x509; +} + int main(int argc, char **argv) { struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 }; char *hash_algo = NULL; - char *private_key_name, *x509_name, *module_name, *dest_name; + char *private_key_name = NULL, *raw_sig_name = NULL; + char *x509_name, *module_name, *dest_name; bool save_sig = false, replace_orig; bool sign_only = false; + bool raw_sig = false; unsigned char buf[4096]; unsigned long module_size, sig_size; unsigned int use_signed_attrs; const EVP_MD *digest_algo; EVP_PKEY *private_key; #ifndef USE_PKCS7 - CMS_ContentInfo *cms; + CMS_ContentInfo *cms = NULL; unsigned int use_keyid = 0; #else - PKCS7 *pkcs7; + PKCS7 *pkcs7 = NULL; #endif X509 *x509; - BIO *b, *bd = NULL, *bm; + BIO *bd, *bm; int opt, n; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); @@ -160,8 +222,9 @@ int main(int argc, char **argv) #endif do { - opt = getopt(argc, argv, "dpk"); + opt = getopt(argc, argv, "sdpk"); switch (opt) { + case 's': raw_sig = true; break; case 'p': save_sig = true; break; case 'd': sign_only = true; save_sig = true; break; #ifndef USE_PKCS7 @@ -177,8 +240,13 @@ int main(int argc, char **argv) if (argc < 4 || argc > 5) format(); - hash_algo = argv[0]; - private_key_name = argv[1]; + if (raw_sig) { + raw_sig_name = argv[0]; + hash_algo = argv[1]; + } else { + hash_algo = argv[0]; + private_key_name = argv[1]; + } x509_name = argv[2]; module_name = argv[3]; if (argc == 5) { @@ -198,101 +266,74 @@ int main(int argc, char **argv) } #endif - /* Read the private key and the X.509 cert the PKCS#7 message - * will point to. - */ - if (!strncmp(private_key_name, "pkcs11:", 7)) { - ENGINE *e; - - ENGINE_load_builtin_engines(); - drain_openssl_errors(); - e = ENGINE_by_id("pkcs11"); - ERR(!e, "Load PKCS#11 ENGINE"); - if (ENGINE_init(e)) - drain_openssl_errors(); - else - ERR(1, "ENGINE_init"); - if (key_pass) - ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN"); - private_key = ENGINE_load_private_key(e, private_key_name, NULL, - NULL); - ERR(!private_key, "%s", private_key_name); - } else { - b = BIO_new_file(private_key_name, "rb"); - ERR(!b, "%s", private_key_name); - private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL); - ERR(!private_key, "%s", private_key_name); - BIO_free(b); - } - - b = BIO_new_file(x509_name, "rb"); - ERR(!b, "%s", x509_name); - x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ - if (!x509) { - ERR(BIO_reset(b) != 1, "%s", x509_name); - x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); /* PEM encoded X.509 */ - if (x509) - drain_openssl_errors(); - } - BIO_free(b); - ERR(!x509, "%s", x509_name); - - /* Open the destination file now so that we can shovel the module data - * across as we read it. - */ - if (!sign_only) { - bd = BIO_new_file(dest_name, "wb"); - ERR(!bd, "%s", dest_name); - } - - /* Digest the module data. */ - OpenSSL_add_all_digests(); - display_openssl_errors(__LINE__); - digest_algo = EVP_get_digestbyname(hash_algo); - ERR(!digest_algo, "EVP_get_digestbyname"); - + /* Open the module file */ bm = BIO_new_file(module_name, "rb"); ERR(!bm, "%s", module_name); + if (!raw_sig) { + /* Read the private key and the X.509 cert the PKCS#7 message + * will point to. + */ + private_key = read_private_key(private_key_name); + x509 = read_x509(x509_name); + + /* Digest the module data. */ + OpenSSL_add_all_digests(); + display_openssl_errors(__LINE__); + digest_algo = EVP_get_digestbyname(hash_algo); + ERR(!digest_algo, "EVP_get_digestbyname"); + #ifndef USE_PKCS7 - /* Load the signature message from the digest buffer. */ - cms = CMS_sign(NULL, NULL, NULL, NULL, - CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM); - ERR(!cms, "CMS_sign"); - - ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, - CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP | - use_keyid | use_signed_attrs), - "CMS_add1_signer"); - ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0, - "CMS_final"); + /* Load the signature message from the digest buffer. */ + cms = CMS_sign(NULL, NULL, NULL, NULL, + CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | + CMS_DETACHED | CMS_STREAM); + ERR(!cms, "CMS_sign"); + + ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo, + CMS_NOCERTS | CMS_BINARY | + CMS_NOSMIMECAP | use_keyid | + use_signed_attrs), + "CMS_add1_signer"); + ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0, + "CMS_final"); #else - pkcs7 = PKCS7_sign(x509, private_key, NULL, bm, - PKCS7_NOCERTS | PKCS7_BINARY | - PKCS7_DETACHED | use_signed_attrs); - ERR(!pkcs7, "PKCS7_sign"); + pkcs7 = PKCS7_sign(x509, private_key, NULL, bm, + PKCS7_NOCERTS | PKCS7_BINARY | + PKCS7_DETACHED | use_signed_attrs); + ERR(!pkcs7, "PKCS7_sign"); #endif - if (save_sig) { - char *sig_file_name; + if (save_sig) { + char *sig_file_name; + BIO *b; - ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0, - "asprintf"); - b = BIO_new_file(sig_file_name, "wb"); - ERR(!b, "%s", sig_file_name); + ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0, + "asprintf"); + b = BIO_new_file(sig_file_name, "wb"); + ERR(!b, "%s", sig_file_name); #ifndef USE_PKCS7 - ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, - "%s", sig_file_name); + ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0, + "%s", sig_file_name); #else - ERR(i2d_PKCS7_bio(b, pkcs7) < 0, - "%s", sig_file_name); + ERR(i2d_PKCS7_bio(b, pkcs7) < 0, + "%s", sig_file_name); #endif - BIO_free(b); + BIO_free(b); + } + + if (sign_only) { + BIO_free(bm); + return 0; + } } - if (sign_only) - return 0; + /* Open the destination file now so that we can shovel the module data + * across as we read it. + */ + bd = BIO_new_file(dest_name, "wb"); + ERR(!bd, "%s", dest_name); /* Append the marker and the PKCS#7 message to the destination file */ ERR(BIO_reset(bm) < 0, "%s", module_name); @@ -300,14 +341,29 @@ int main(int argc, char **argv) n > 0) { ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); } + BIO_free(bm); ERR(n < 0, "%s", module_name); module_size = BIO_number_written(bd); + if (!raw_sig) { #ifndef USE_PKCS7 - ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); + ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); #else - ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name); + ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name); #endif + } else { + BIO *b; + + /* Read the raw signature file and write the data to the + * destination file + */ + b = BIO_new_file(raw_sig_name, "rb"); + ERR(!b, "%s", raw_sig_name); + while ((n = BIO_read(b, buf, sizeof(buf))), n > 0) + ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); + BIO_free(b); + } + sig_size = BIO_number_written(bd) - module_size; sig_info.sig_len = htonl(sig_size); ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name); diff --git a/scripts/sortextable.c b/scripts/sortextable.c index c2423d913b46..7b29fb14f870 100644 --- a/scripts/sortextable.c +++ b/scripts/sortextable.c @@ -209,6 +209,35 @@ static int compare_relative_table(const void *a, const void *b) return 0; } +static void x86_sort_relative_table(char *extab_image, int image_size) +{ + int i; + + i = 0; + while (i < image_size) { + uint32_t *loc = (uint32_t *)(extab_image + i); + + w(r(loc) + i, loc); + w(r(loc + 1) + i + 4, loc + 1); + w(r(loc + 2) + i + 8, loc + 2); + + i += sizeof(uint32_t) * 3; + } + + qsort(extab_image, image_size / 12, 12, compare_relative_table); + + i = 0; + while (i < image_size) { + uint32_t *loc = (uint32_t *)(extab_image + i); + + w(r(loc) - i, loc); + w(r(loc + 1) - (i + 4), loc + 1); + w(r(loc + 2) - (i + 8), loc + 2); + + i += sizeof(uint32_t) * 3; + } +} + static void sort_relative_table(char *extab_image, int image_size) { int i; @@ -281,6 +310,9 @@ do_file(char const *const fname) break; case EM_386: case EM_X86_64: + custom_sort = x86_sort_relative_table; + break; + case EM_S390: custom_sort = sort_relative_table; break; diff --git a/scripts/tags.sh b/scripts/tags.sh index 262889046703..23ba1c6a0a59 100755 --- a/scripts/tags.sh +++ b/scripts/tags.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Generate tags or cscope files # Usage tags.sh <mode> # @@ -134,11 +134,6 @@ all_kconfigs() find_other_sources 'Kconfig*' } -all_defconfigs() -{ - find_sources $ALLSOURCE_ARCHS "defconfig" -} - docscope() { (echo \-k; echo \-q; all_target_sources) > cscope.files @@ -150,8 +145,107 @@ dogtags() all_target_sources | gtags -i -f - } +# Basic regular expressions with an optional /kind-spec/ for ctags and +# the following limitations: +# - No regex modifiers +# - Use \{0,1\} instead of \?, because etags expects an unescaped ? +# - \s is not working with etags, use a space or [ \t] +# - \w works, but does not match underscores in etags +# - etags regular expressions have to match at the start of a line; +# a ^[^#] is prepended by setup_regex unless an anchor is already present +regex_asm=( + '/^\(ENTRY\|_GLOBAL\)(\([[:alnum:]_\\]*\)).*/\2/' +) +regex_c=( + '/^SYSCALL_DEFINE[0-9](\([[:alnum:]_]*\).*/sys_\1/' + '/^COMPAT_SYSCALL_DEFINE[0-9](\([[:alnum:]_]*\).*/compat_sys_\1/' + '/^TRACE_EVENT(\([[:alnum:]_]*\).*/trace_\1/' + '/^TRACE_EVENT(\([[:alnum:]_]*\).*/trace_\1_rcuidle/' + '/^DEFINE_EVENT([^,)]*, *\([[:alnum:]_]*\).*/trace_\1/' + '/^DEFINE_EVENT([^,)]*, *\([[:alnum:]_]*\).*/trace_\1_rcuidle/' + '/^PAGEFLAG(\([[:alnum:]_]*\).*/Page\1/' + '/^PAGEFLAG(\([[:alnum:]_]*\).*/SetPage\1/' + '/^PAGEFLAG(\([[:alnum:]_]*\).*/ClearPage\1/' + '/^TESTSETFLAG(\([[:alnum:]_]*\).*/TestSetPage\1/' + '/^TESTPAGEFLAG(\([[:alnum:]_]*\).*/Page\1/' + '/^SETPAGEFLAG(\([[:alnum:]_]*\).*/SetPage\1/' + '/\<__SETPAGEFLAG(\([[:alnum:]_]*\).*/__SetPage\1/' + '/\<TESTCLEARFLAG(\([[:alnum:]_]*\).*/TestClearPage\1/' + '/\<__TESTCLEARFLAG(\([[:alnum:]_]*\).*/TestClearPage\1/' + '/\<CLEARPAGEFLAG(\([[:alnum:]_]*\).*/ClearPage\1/' + '/\<__CLEARPAGEFLAG(\([[:alnum:]_]*\).*/__ClearPage\1/' + '/^__PAGEFLAG(\([[:alnum:]_]*\).*/__SetPage\1/' + '/^__PAGEFLAG(\([[:alnum:]_]*\).*/__ClearPage\1/' + '/^PAGEFLAG_FALSE(\([[:alnum:]_]*\).*/Page\1/' + '/\<TESTSCFLAG(\([[:alnum:]_]*\).*/TestSetPage\1/' + '/\<TESTSCFLAG(\([[:alnum:]_]*\).*/TestClearPage\1/' + '/\<SETPAGEFLAG_NOOP(\([[:alnum:]_]*\).*/SetPage\1/' + '/\<CLEARPAGEFLAG_NOOP(\([[:alnum:]_]*\).*/ClearPage\1/' + '/\<__CLEARPAGEFLAG_NOOP(\([[:alnum:]_]*\).*/__ClearPage\1/' + '/\<TESTCLEARFLAG_FALSE(\([[:alnum:]_]*\).*/TestClearPage\1/' + '/^TASK_PFA_TEST([^,]*, *\([[:alnum:]_]*\))/task_\1/' + '/^TASK_PFA_SET([^,]*, *\([[:alnum:]_]*\))/task_set_\1/' + '/^TASK_PFA_CLEAR([^,]*, *\([[:alnum:]_]*\))/task_clear_\1/' + '/^DEF_MMIO_\(IN\|OUT\)_[XD](\([[:alnum:]_]*\),[^)]*)/\2/' + '/^DEBUGGER_BOILERPLATE(\([[:alnum:]_]*\))/\1/' + '/^DEF_PCI_AC_\(\|NO\)RET(\([[:alnum:]_]*\).*/\2/' + '/^PCI_OP_READ(\(\w*\).*[1-4])/pci_bus_read_config_\1/' + '/^PCI_OP_WRITE(\(\w*\).*[1-4])/pci_bus_write_config_\1/' + '/\<DEFINE_\(MUTEX\|SEMAPHORE\|SPINLOCK\)(\([[:alnum:]_]*\)/\2/v/' + '/\<DEFINE_\(RAW_SPINLOCK\|RWLOCK\|SEQLOCK\)(\([[:alnum:]_]*\)/\2/v/' + '/\<DECLARE_\(RWSEM\|COMPLETION\)(\([[:alnum:]_]\+\)/\2/v/' + '/\<DECLARE_BITMAP(\([[:alnum:]_]*\)/\1/v/' + '/\(^\|\s\)\(\|L\|H\)LIST_HEAD(\([[:alnum:]_]*\)/\3/v/' + '/\(^\|\s\)RADIX_TREE(\([[:alnum:]_]*\)/\2/v/' + '/\<DEFINE_PER_CPU([^,]*, *\([[:alnum:]_]*\)/\1/v/' + '/\<DEFINE_PER_CPU_SHARED_ALIGNED([^,]*, *\([[:alnum:]_]*\)/\1/v/' + '/\<DECLARE_WAIT_QUEUE_HEAD(\([[:alnum:]_]*\)/\1/v/' + '/\<DECLARE_\(TASKLET\|WORK\|DELAYED_WORK\)(\([[:alnum:]_]*\)/\2/v/' + '/\<DEFINE_PCI_DEVICE_TABLE(\([[:alnum:]_]*\)/\1/v/' + '/\(^\s\)OFFSET(\([[:alnum:]_]*\)/\2/v/' + '/\(^\s\)DEFINE(\([[:alnum:]_]*\)/\2/v/' + '/\<DEFINE_HASHTABLE(\([[:alnum:]_]*\)/\1/v/' +) +regex_kconfig=( + '/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/' + '/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/CONFIG_\2/' +) +setup_regex() +{ + local mode=$1 lang tmp=() r + shift + + regex=() + for lang; do + case "$lang" in + asm) tmp=("${regex_asm[@]}") ;; + c) tmp=("${regex_c[@]}") ;; + kconfig) tmp=("${regex_kconfig[@]}") ;; + esac + for r in "${tmp[@]}"; do + if test "$mode" = "exuberant"; then + regex[${#regex[@]}]="--regex-$lang=${r}b" + else + # Remove ctags /kind-spec/ + case "$r" in + /*/*/?/) + r=${r%?/} + esac + # Prepend ^[^#] unless already anchored + case "$r" in + /^*) ;; + *) + r="/^[^#]*${r#/}" + esac + regex[${#regex[@]}]="--regex=$r" + fi + done + done +} + exuberant() { + setup_regex exuberant asm c all_target_sources | xargs $1 -a \ -I __initdata,__exitdata,__initconst, \ -I __initdata_memblock \ @@ -165,118 +259,21 @@ 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 \ - --regex-asm='/^(ENTRY|_GLOBAL)\(([^)]*)\).*/\2/' \ - --regex-c='/^SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/sys_\1/' \ - --regex-c='/^COMPAT_SYSCALL_DEFINE[[:digit:]]?\(([^,)]*).*/compat_sys_\1/' \ - --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1/' \ - --regex-c++='/^TRACE_EVENT\(([^,)]*).*/trace_\1_rcuidle/' \ - --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1/' \ - --regex-c++='/^DEFINE_EVENT\([^,)]*, *([^,)]*).*/trace_\1_rcuidle/' \ - --regex-c++='/PAGEFLAG\(([^,)]*).*/Page\1/' \ - --regex-c++='/PAGEFLAG\(([^,)]*).*/SetPage\1/' \ - --regex-c++='/PAGEFLAG\(([^,)]*).*/ClearPage\1/' \ - --regex-c++='/TESTSETFLAG\(([^,)]*).*/TestSetPage\1/' \ - --regex-c++='/TESTPAGEFLAG\(([^,)]*).*/Page\1/' \ - --regex-c++='/SETPAGEFLAG\(([^,)]*).*/SetPage\1/' \ - --regex-c++='/__SETPAGEFLAG\(([^,)]*).*/__SetPage\1/' \ - --regex-c++='/TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/__TESTCLEARFLAG\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/CLEARPAGEFLAG\(([^,)]*).*/ClearPage\1/' \ - --regex-c++='/__CLEARPAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ - --regex-c++='/__PAGEFLAG\(([^,)]*).*/__SetPage\1/' \ - --regex-c++='/__PAGEFLAG\(([^,)]*).*/__ClearPage\1/' \ - --regex-c++='/PAGEFLAG_FALSE\(([^,)]*).*/Page\1/' \ - --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestSetPage\1/' \ - --regex-c++='/TESTSCFLAG\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/SETPAGEFLAG_NOOP\(([^,)]*).*/SetPage\1/' \ - --regex-c++='/CLEARPAGEFLAG_NOOP\(([^,)]*).*/ClearPage\1/' \ - --regex-c++='/__CLEARPAGEFLAG_NOOP\(([^,)]*).*/__ClearPage\1/' \ - --regex-c++='/TESTCLEARFLAG_FALSE\(([^,)]*).*/TestClearPage\1/' \ - --regex-c++='/__TESTCLEARFLAG_FALSE\(([^,)]*).*/__TestClearPage\1/' \ - --regex-c++='/_PE\(([^,)]*).*/PEVENT_ERRNO__\1/' \ - --regex-c++='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ - --regex-c++='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ - --regex-c++='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/'\ - --regex-c++='/DEF_MMIO_(IN|OUT)_(X|D)\(([^,]*),\s*[^)]*\)/\3/' \ - --regex-c++='/DEBUGGER_BOILERPLATE\(([^,]*)\)/\1/' \ - --regex-c='/PCI_OP_READ\((\w*).*[1-4]\)/pci_bus_read_config_\1/' \ - --regex-c='/PCI_OP_WRITE\((\w*).*[1-4]\)/pci_bus_write_config_\1/' \ - --regex-c='/DEFINE_(MUTEX|SEMAPHORE|SPINLOCK)\((\w*)/\2/v/' \ - --regex-c='/DEFINE_(RAW_SPINLOCK|RWLOCK|SEQLOCK)\((\w*)/\2/v/' \ - --regex-c='/DECLARE_(RWSEM|COMPLETION)\((\w*)/\2/v/' \ - --regex-c='/DECLARE_BITMAP\((\w*)/\1/v/' \ - --regex-c='/(^|\s)(|L|H)LIST_HEAD\((\w*)/\3/v/' \ - --regex-c='/(^|\s)RADIX_TREE\((\w*)/\2/v/' \ - --regex-c='/DEFINE_PER_CPU\(([^,]*,\s*)(\w*).*\)/\2/v/' \ - --regex-c='/DEFINE_PER_CPU_SHARED_ALIGNED\(([^,]*,\s*)(\w*).*\)/\2/v/' \ - --regex-c='/DECLARE_WAIT_QUEUE_HEAD\((\w*)/\1/v/' \ - --regex-c='/DECLARE_(TASKLET|WORK|DELAYED_WORK)\((\w*)/\2/v/' \ - --regex-c='/DEFINE_PCI_DEVICE_TABLE\((\w*)/\1/v/' \ - --regex-c='/(^\s)OFFSET\((\w*)/\2/v/' \ - --regex-c='/(^\s)DEFINE\((\w*)/\2/v/' \ - --regex-c='/DEFINE_HASHTABLE\((\w*)/\1/v/' + --extra=+f --c-kinds=+px --langmap=c:+.h "${regex[@]}" + setup_regex exuberant kconfig all_kconfigs | xargs $1 -a \ - --langdef=kconfig --language-force=kconfig \ - --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/\2/' + --langdef=kconfig --language-force=kconfig "${regex[@]}" - all_kconfigs | xargs $1 -a \ - --langdef=kconfig --language-force=kconfig \ - --regex-kconfig='/^[[:blank:]]*(menu|)config[[:blank:]]+([[:alnum:]_]+)/CONFIG_\2/' - - all_defconfigs | xargs -r $1 -a \ - --langdef=dotconfig --language-force=dotconfig \ - --regex-dotconfig='/^#?[[:blank:]]*(CONFIG_[[:alnum:]_]+)/\1/' } emacs() { - all_target_sources | xargs $1 -a \ - --regex='/^\(ENTRY\|_GLOBAL\)(\([^)]*\)).*/\2/' \ - --regex='/^SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/sys_\1/' \ - --regex='/^COMPAT_SYSCALL_DEFINE[0-9]?(\([^,)]*\).*/compat_sys_\1/' \ - --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1/' \ - --regex='/^TRACE_EVENT(\([^,)]*\).*/trace_\1_rcuidle/' \ - --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1/' \ - --regex='/^DEFINE_EVENT([^,)]*, *\([^,)]*\).*/trace_\1_rcuidle/' \ - --regex='/PAGEFLAG(\([^,)]*\).*/Page\1/' \ - --regex='/PAGEFLAG(\([^,)]*\).*/SetPage\1/' \ - --regex='/PAGEFLAG(\([^,)]*\).*/ClearPage\1/' \ - --regex='/TESTSETFLAG(\([^,)]*\).*/TestSetPage\1/' \ - --regex='/TESTPAGEFLAG(\([^,)]*\).*/Page\1/' \ - --regex='/SETPAGEFLAG(\([^,)]*\).*/SetPage\1/' \ - --regex='/__SETPAGEFLAG(\([^,)]*\).*/__SetPage\1/' \ - --regex='/TESTCLEARFLAG(\([^,)]*\).*/TestClearPage\1/' \ - --regex='/__TESTCLEARFLAG(\([^,)]*\).*/TestClearPage\1/' \ - --regex='/CLEARPAGEFLAG(\([^,)]*\).*/ClearPage\1/' \ - --regex='/__CLEARPAGEFLAG(\([^,)]*\).*/__ClearPage\1/' \ - --regex='/__PAGEFLAG(\([^,)]*\).*/__SetPage\1/' \ - --regex='/__PAGEFLAG(\([^,)]*\).*/__ClearPage\1/' \ - --regex='/PAGEFLAG_FALSE(\([^,)]*\).*/Page\1/' \ - --regex='/TESTSCFLAG(\([^,)]*\).*/TestSetPage\1/' \ - --regex='/TESTSCFLAG(\([^,)]*\).*/TestClearPage\1/' \ - --regex='/SETPAGEFLAG_NOOP(\([^,)]*\).*/SetPage\1/' \ - --regex='/CLEARPAGEFLAG_NOOP(\([^,)]*\).*/ClearPage\1/' \ - --regex='/__CLEARPAGEFLAG_NOOP(\([^,)]*\).*/__ClearPage\1/' \ - --regex='/TESTCLEARFLAG_FALSE(\([^,)]*\).*/TestClearPage\1/' \ - --regex='/__TESTCLEARFLAG_FALSE(\([^,)]*\).*/__TestClearPage\1/' \ - --regex='/TASK_PFA_TEST\([^,]*,\s*([^)]*)\)/task_\1/' \ - --regex='/TASK_PFA_SET\([^,]*,\s*([^)]*)\)/task_set_\1/' \ - --regex='/TASK_PFA_CLEAR\([^,]*,\s*([^)]*)\)/task_clear_\1/' \ - --regex='/_PE(\([^,)]*\).*/PEVENT_ERRNO__\1/' \ - --regex='/PCI_OP_READ(\([a-z]*[a-z]\).*[1-4])/pci_bus_read_config_\1/' \ - --regex='/PCI_OP_WRITE(\([a-z]*[a-z]\).*[1-4])/pci_bus_write_config_\1/'\ - --regex='/[^#]*DEFINE_HASHTABLE(\([^,)]*\)/\1/' - - all_kconfigs | xargs $1 -a \ - --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/\3/' - - all_kconfigs | xargs $1 -a \ - --regex='/^[ \t]*\(\(menu\)*config\)[ \t]+\([a-zA-Z0-9_]+\)/CONFIG_\3/' + setup_regex emacs asm c + all_target_sources | xargs $1 -a "${regex[@]}" - all_defconfigs | xargs -r $1 -a \ - --regex='/^#?[ \t]?\(CONFIG_[a-zA-Z0-9_]+\)/\1/' + setup_regex emacs kconfig + all_kconfigs | xargs $1 -a "${regex[@]}" } xtags() diff --git a/scripts/ver_linux b/scripts/ver_linux index 024a11ac8b97..0d8bd29b1bd6 100755 --- a/scripts/ver_linux +++ b/scripts/ver_linux @@ -1,6 +1,6 @@ #!/bin/sh # Before running this script please ensure that your PATH is -# typical as you use for compilation/istallation. I use +# 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. # |