diff options
| author | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-09-03 10:01:44 -0700 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2015-09-03 10:01:44 -0700 |
| commit | 01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba (patch) | |
| tree | 85f506cf9fce3d8fd47cf624dd8698472bffc13f /scripts | |
| parent | e51e38494a8ecc18650efb0c840600637891de2c (diff) | |
| parent | 58f1eae48e5372200553de07b5ecc7574803ee91 (diff) | |
| download | linux-01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba.tar.gz linux-01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba.tar.bz2 linux-01b944fe1cd4e21a2a9ed51adbdbafe2d5e905ba.zip | |
Merge branch 'next' into for-linus
Prepare first round of input updates for 4.3 merge window.
Diffstat (limited to 'scripts')
78 files changed, 3920 insertions, 2448 deletions
diff --git a/scripts/Makefile.dtbinst b/scripts/Makefile.dtbinst index 909ed7a2ac61..1c15717e0d56 100644 --- a/scripts/Makefile.dtbinst +++ b/scripts/Makefile.dtbinst @@ -18,7 +18,7 @@ export dtbinst-root ?= $(obj) include include/config/auto.conf include scripts/Kbuild.include -include $(srctree)/$(obj)/Makefile +include $(src)/Makefile PHONY += __dtbs_install_prep __dtbs_install_prep: diff --git a/scripts/Makefile.fwinst b/scripts/Makefile.fwinst index 5b698add4f31..b27290035253 100644 --- a/scripts/Makefile.fwinst +++ b/scripts/Makefile.fwinst @@ -13,7 +13,7 @@ src := $(obj) -include $(objtree)/.config include scripts/Kbuild.include -include $(srctree)/$(obj)/Makefile +include $(src)/Makefile include scripts/Makefile.host diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index 631619b2b118..3f874d24234f 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -13,12 +13,16 @@ CFLAGS_KASAN := $(call cc-option, -fsanitize=kernel-address \ --param asan-instrumentation-with-call-threshold=$(call_threshold)) ifeq ($(call cc-option, $(CFLAGS_KASAN_MINIMAL) -Werror),) + ifneq ($(CONFIG_COMPILE_TEST),y) $(warning Cannot use CONFIG_KASAN: \ -fsanitize=kernel-address is not supported by compiler) + endif else ifeq ($(CFLAGS_KASAN),) - $(warning CONFIG_KASAN: compiler does not support all options.\ - Trying minimal configuration) + ifneq ($(CONFIG_COMPILE_TEST),y) + $(warning CONFIG_KASAN: compiler does not support all options.\ + Trying minimal configuration) + endif CFLAGS_KASAN := $(CFLAGS_KASAN_MINIMAL) endif endif diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 044eb4f89a91..79e86613712f 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -282,7 +282,8 @@ $(obj)/%.dtb.S: $(obj)/%.dtb $(call cmd,dt_S_dtb) quiet_cmd_dtc = DTC $@ -cmd_dtc = $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ +cmd_dtc = mkdir -p $(dir ${dtc-tmp}) ; \ + $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) $< ; \ $(objtree)/scripts/dtc/dtc -O dtb -o $@ -b 0 \ -i $(dir $<) $(DTC_FLAGS) \ -d $(depfile).dtc.tmp $(dtc-tmp) ; \ diff --git a/scripts/check_extable.sh b/scripts/check_extable.sh new file mode 100755 index 000000000000..0fb6b1c97c27 --- /dev/null +++ b/scripts/check_extable.sh @@ -0,0 +1,146 @@ +#! /bin/bash +# (c) 2015, Quentin Casasnovas <quentin.casasnovas@oracle.com> + +obj=$1 + +file ${obj} | grep -q ELF || (echo "${obj} is not and ELF file." 1>&2 ; exit 0) + +# Bail out early if there isn't an __ex_table section in this object file. +objdump -hj __ex_table ${obj} 2> /dev/null > /dev/null +[ $? -ne 0 ] && exit 0 + +white_list=.text,.fixup + +suspicious_relocs=$(objdump -rj __ex_table ${obj} | tail -n +6 | + grep -v $(eval echo -e{${white_list}}) | awk '{print $3}') + +# No suspicious relocs in __ex_table, jobs a good'un +[ -z "${suspicious_relocs}" ] && exit 0 + + +# After this point, something is seriously wrong since we just found out we +# have some relocations in __ex_table which point to sections which aren't +# white listed. If you're adding a new section in the Linux kernel, and +# you're expecting this section to contain code which can fault (i.e. the +# __ex_table relocation to your new section is expected), simply add your +# new section to the white_list variable above. If not, you're probably +# doing something wrong and the rest of this code is just trying to print +# you more information about it. + +function find_section_offset_from_symbol() +{ + eval $(objdump -t ${obj} | grep ${1} | sed 's/\([0-9a-f]\+\) .\{7\} \([^ \t]\+\).*/section="\2"; section_offset="0x\1" /') + + # addr2line takes addresses in hexadecimal... + section_offset=$(printf "0x%016x" $(( ${section_offset} + $2 )) ) +} + +function find_symbol_and_offset_from_reloc() +{ + # Extract symbol and offset from the objdump output + eval $(echo $reloc | sed 's/\([^+]\+\)+\?\(0x[0-9a-f]\+\)\?/symbol="\1"; symbol_offset="\2"/') + + # When the relocation points to the begining of a symbol or section, it + # won't print the offset since it is zero. + if [ -z "${symbol_offset}" ]; then + symbol_offset=0x0 + fi +} + +function find_alt_replacement_target() +{ + # The target of the .altinstr_replacement is the relocation just before + # the .altinstr_replacement one. + eval $(objdump -rj .altinstructions ${obj} | grep -B1 "${section}+${section_offset}" | head -n1 | awk '{print $3}' | + sed 's/\([^+]\+\)+\(0x[0-9a-f]\+\)/alt_target_section="\1"; alt_target_offset="\2"/') +} + +function handle_alt_replacement_reloc() +{ + # This will define alt_target_section and alt_target_section_offset + find_alt_replacement_target ${section} ${section_offset} + + echo "Error: found a reference to .altinstr_replacement in __ex_table:" + addr2line -fip -j ${alt_target_section} -e ${obj} ${alt_target_offset} | awk '{print "\t" $0}' + + error=true +} + +function is_executable_section() +{ + objdump -hwj ${section} ${obj} | grep -q CODE + return $? +} + +function handle_suspicious_generic_reloc() +{ + if is_executable_section ${section}; then + # We've got a relocation to a non white listed _executable_ + # section, print a warning so the developper adds the section to + # the white list or fix his code. We try to pretty-print the file + # and line number where that relocation was added. + echo "Warning: found a reference to section \"${section}\" in __ex_table:" + addr2line -fip -j ${section} -e ${obj} ${section_offset} | awk '{print "\t" $0}' + else + # Something is definitively wrong here since we've got a relocation + # to a non-executable section, there's no way this would ever be + # running in the kernel. + echo "Error: found a reference to non-executable section \"${section}\" in __ex_table at offset ${section_offset}" + error=true + fi +} + +function handle_suspicious_reloc() +{ + case "${section}" in + ".altinstr_replacement") + handle_alt_replacement_reloc ${section} ${section_offset} + ;; + *) + handle_suspicious_generic_reloc ${section} ${section_offset} + ;; + esac +} + +function diagnose() +{ + + for reloc in ${suspicious_relocs}; do + # Let's find out where the target of the relocation in __ex_table + # is, this will define ${symbol} and ${symbol_offset} + find_symbol_and_offset_from_reloc ${reloc} + + # When there's a global symbol at the place of the relocation, + # objdump will use it instead of giving us a section+offset, so + # let's find out which section is this symbol in and the total + # offset withing that section. + find_section_offset_from_symbol ${symbol} ${symbol_offset} + + # In this case objdump was presenting us with a reloc to a symbol + # rather than a section. Now that we've got the actual section, + # we can skip it if it's in the white_list. + if [ -z "$( echo $section | grep -v $(eval echo -e{${white_list}}))" ]; then + continue; + fi + + # Will either print a warning if the relocation happens to be in a + # section we do not know but has executable bit set, or error out. + handle_suspicious_reloc + done +} + +function check_debug_info() { + objdump -hj .debug_info ${obj} 2> /dev/null > /dev/null || + echo -e "${obj} does not contain debug information, the addr2line output will be limited.\n" \ + "Recompile ${obj} with CONFIG_DEBUG_INFO to get a more useful output." +} + +check_debug_info + +diagnose + +if [ "${error}" ]; then + exit 1 +fi + +exit 0 diff --git a/scripts/checkkconfigsymbols.py b/scripts/checkkconfigsymbols.py index e9cc689033fe..c89fdcaf06e8 100644..100755 --- a/scripts/checkkconfigsymbols.py +++ b/scripts/checkkconfigsymbols.py @@ -1,8 +1,8 @@ -#!/usr/bin/env python +#!/usr/bin/env python2 -"""Find Kconfig identifiers that are referenced but not defined.""" +"""Find Kconfig symbols that are referenced but not defined.""" -# (c) 2014 Valentin Rothberg <valentinrothberg@gmail.com> +# (c) 2014-2015 Valentin Rothberg <Valentin.Rothberg@lip6.fr> # (c) 2014 Stefan Hengelein <stefan.hengelein@fau.de> # # Licensed under the terms of the GNU GPL License version 2 @@ -10,7 +10,9 @@ import os import re +import sys from subprocess import Popen, PIPE, STDOUT +from optparse import OptionParser # regex expressions @@ -32,22 +34,162 @@ REGEX_KCONFIG_HELP = re.compile(r"^\s+(help|---help---)\s*$") REGEX_FILTER_FEATURES = re.compile(r"[A-Za-z0-9]$") +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('-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('', '--force', dest='force', action='store_true', + default=False, + help="Reset current Git tree even when it's dirty.") + + (opts, _) = parser.parse_args() + + if opts.commit and opts.diff: + sys.exit("Please specify only one option at once.") + + if opts.diff and not re.match(r"^[\w\-\.]+\.\.[\w\-\.]+$", opts.diff): + sys.exit("Please specify valid input in the following format: " + "\'commmit1..commit2\'") + + if opts.commit or opts.diff: + if not opts.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. " + " Please run this script in a clean Git tree or pass " + "'--force' if you\nwant to ignore this warning and " + "continue.") + + if opts.ignore: + try: + re.match(opts.ignore, "this/is/just/a/test.c") + except: + sys.exit("Please specify a valid Python regex.") + + return opts + + def main(): """Main function of this module.""" + opts = parse_options() + + if opts.commit or opts.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("..") + commit_a = split[0] + commit_b = split[1] + undefined_a = {} + undefined_b = {} + + # get undefined items before the commit + execute("git reset --hard %s" % commit_a) + 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) + + # 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" % (feature, ", ".join(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" % (feature, ", ".join(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" % (feature, ", ".join(files)) + + +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) + return stdout + + +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") + for line in stdout: + if re.findall(r"[URMADC]{1}", line[:2]): + return True + return False + + +def get_head(): + """Return commit hash of current HEAD.""" + stdout = execute("git rev-parse 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]} # use 'git ls-files' to get the worklist - pop = Popen("git ls-files", stdout=PIPE, stderr=STDOUT, shell=True) - (stdout, _) = pop.communicate() # wait until finished + stdout = execute("git ls-files") if len(stdout) > 0 and stdout[-1] == "\n": stdout = stdout[:-1] for gitfile in stdout.rsplit("\n"): - if ".git" in gitfile or "ChangeLog" in gitfile or \ - ".log" in gitfile or os.path.isdir(gitfile): + if ".git" in gitfile or "ChangeLog" in gitfile or \ + ".log" in gitfile or os.path.isdir(gitfile) or \ + gitfile.startswith("tools/"): continue if REGEX_FILE_KCONFIG.match(gitfile): kconfig_files.append(gitfile) @@ -56,12 +198,19 @@ def main(): source_files.append(gitfile) for sfile in source_files: + if ignore and re.match(ignore, sfile): + # do not check files matching %ignore + |
