summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rwxr-xr-xscripts/checkkconfigsymbols.py234
-rwxr-xr-xscripts/ld-version.sh4
-rwxr-xr-xscripts/link-vmlinux.sh2
-rw-r--r--scripts/mod/file2alias.c2
-rw-r--r--scripts/recordmcount.c137
5 files changed, 304 insertions, 75 deletions
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/ld-version.sh b/scripts/ld-version.sh
index 198580d245e0..d154f0877fd8 100755
--- a/scripts/ld-version.sh
+++ b/scripts/ld-version.sh
@@ -2,7 +2,9 @@
# extract linker version number from stdin and turn into single number
{
gsub(".*)", "");
+ gsub(".*version ", "");
+ gsub("-.*", "");
split($1,a, ".");
- print a[1]*10000000 + a[2]*100000 + a[3]*10000 + a[4]*100 + a[5];
+ print a[1]*100000000 + a[2]*1000000 + a[3]*10000 + a[4]*100 + a[5];
exit
}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index 1a10d8ac8162..ba6c34ea5429 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -62,7 +62,7 @@ vmlinux_link()
-Wl,--start-group \
${KBUILD_VMLINUX_MAIN} \
-Wl,--end-group \
- -lutil ${1}
+ -lutil -lrt -lpthread ${1}
rm -f linux
fi
}
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index 5b96206e9aab..8adca4406198 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -917,7 +917,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/recordmcount.c b/scripts/recordmcount.c
index 698768bdc581..e167592793a7 100644
--- a/scripts/recordmcount.c
+++ b/scripts/recordmcount.c
@@ -48,12 +48,17 @@
static int fd_map; /* File descriptor for file being modified. */
static int mmap_failed; /* Boolean flag. */
-static void *ehdr_curr; /* current ElfXX_Ehdr * for resource cleanup */
static char gpfx; /* prefix for global symbol name (sometimes '_') */
static struct stat sb; /* Remember .st_size, etc. */
static jmp_buf jmpenv; /* setjmp/longjmp per-file error escape */
static const char *altmcount; /* alternate mcount symbol name */
static int warn_on_notrace_sect; /* warn when section has mcount not being recorded */
+static void *file_map; /* pointer of the mapped file */
+static void *file_end; /* pointer to the end of the mapped file */
+static int file_updated; /* flag to state file was changed */
+static void *file_ptr; /* current file pointer location */
+static void *file_append; /* added to the end of the file */
+static size_t file_append_size; /* how much is added to end of file */
/* setjmp() return values */
enum {
@@ -67,10 +72,14 @@ static void
cleanup(void)
{
if (!mmap_failed)
- munmap(ehdr_curr, sb.st_size);
+ munmap(file_map, sb.st_size);
else
- free(ehdr_curr);
- close(fd_map);
+ free(file_map);
+ file_map = NULL;
+ free(file_append);
+ file_append = NULL;
+ file_append_size = 0;
+ file_updated = 0;
}
static void __attribute__((noreturn))
@@ -92,12 +101,22 @@ succeed_file(void)
static off_t
ulseek(int const fd, off_t const offset, int const whence)
{
- off_t const w = lseek(fd, offset, whence);
- if (w == (off_t)-1) {
- perror("lseek");
+ switch (whence) {
+ case SEEK_SET:
+ file_ptr = file_map + offset;
+ break;
+ case SEEK_CUR:
+ file_ptr += offset;
+ break;
+ case SEEK_END:
+ file_ptr = file_map + (sb.st_size - offset);
+ break;
+ }
+ if (file_ptr < file_map) {
+ fprintf(stderr, "lseek: seek before file\n");
fail_file();
}
- return w;
+ return file_ptr - file_map;
}
static size_t
@@ -114,12 +133,38 @@ uread(int const fd, void *const buf, size_t const count)
static size_t
uwrite(int const fd, void const *const buf, size_t const count)
{
- size_t const n = write(fd, buf, count);
- if (n != count) {
- perror("write");
- fail_file();
+ size_t cnt = count;
+ off_t idx = 0;
+
+ file_updated = 1;
+
+ if (file_ptr + count >= file_end) {
+ off_t aoffset = (file_ptr + count) - file_end;
+
+ if (aoffset > file_append_size) {
+ file_append = realloc(file_append, aoffset);
+ file_append_size = aoffset;
+ }
+ if (!file_append) {
+ perror("write");
+ fail_file();
+ }
+ if (file_ptr < file_end) {
+ cnt = file_end - file_ptr;
+ } else {
+ cnt = 0;
+ idx = aoffset - count;
+ }
}
- return n;
+
+ if (cnt)
+ memcpy(file_ptr, buf, cnt);
+
+ if (cnt < count)
+ memcpy(file_append + idx, buf + cnt, count - cnt);
+
+ file_ptr += count;
+ return count;
}
static void *
@@ -192,9 +237,7 @@ static int make_nop_arm64(void *map, size_t const offset)
*/
static void *mmap_file(char const *fname)
{
- void *addr;
-
- fd_map = open(fname, O_RDWR);
+ fd_map = open(fname, O_RDONLY);
if (fd_map < 0 || fstat(fd_map, &sb) < 0) {
perror(fname);
fail_file();
@@ -203,15 +246,58 @@ static void *mmap_file(char const *fname)
fprintf(stderr, "not a regular file: %s\n", fname);
fail_file();
}
- addr = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
- fd_map, 0);
+ file_map = mmap(0, sb.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE,
+ fd_map, 0);
mmap_failed = 0;
- if (addr == MAP_FAILED) {
+ if (file_map == MAP_FAILED) {
mmap_failed = 1;
- addr = umalloc(sb.st_size);
- uread(fd_map, addr, sb.st_size);
+ file_map = umalloc(sb.st_size);
+ uread(fd_map, file_map, sb.st_size);
+ }
+ close(fd_map);
+
+ file_end = file_map + sb.st_size;
+
+ return file_map;
+}
+
+static void write_file(const char *fname)
+{
+ char tmp_file[strlen(fname) + 4];
+ size_t n;
+
+ if (!file_updated)
+ return;
+
+ sprintf(tmp_file, "%s.rc", fname);
+
+ /*
+ * After reading the entire file into memory, delete it
+ * and write it back, to prevent weird side effects of modifying
+ * an object file in place.
+ */
+ fd_map = open(tmp_file, O_WRONLY | O_TRUNC | O_CREAT, sb.st_mode);
+ if (fd_map < 0) {
+ perror(fname);
+ fail_file();
+ }
+ n = write(fd_map, file_map, sb.st_size);
+ if (n != sb.st_size) {
+ perror("write");
+ fail_file();
+ }
+ if (file_append_size) {
+ n = write(fd_map, file_append, file_append_size);
+ if (n != file_append_size) {
+ perror("write");
+ fail_file();
+ }
+ }
+ close(fd_map);
+ if (rename(tmp_file, fname) < 0) {
+ perror(fname);
+ fail_file();
}
- return addr;
}
/* w8rev, w8nat, ...: Handle endianness. */
@@ -318,7 +404,6 @@ do_file(char const *const fname)
Elf32_Ehdr *const ehdr = mmap_file(fname);
unsigned int reltype = 0;
- ehdr_curr = ehdr;
w = w4nat;
w2 = w2nat;
w8 = w8nat;
@@ -441,6 +526,7 @@ do_file(char const *const fname)
}
} /* end switch */
+ write_file(fname);
cleanup();
}
@@ -493,11 +579,14 @@ main(int argc, char *argv[])
case SJ_SETJMP: /* normal sequence */
/* Avoid problems if early cleanup() */
fd_map = -1;
- ehdr_curr = NULL;
mmap_failed = 1;
+ file_map = NULL;
+ file_ptr = NULL;
+ file_updated = 0;
do_file(file);
break;
case SJ_FAIL: /* error in do_file or below */
+ fprintf(stderr, "%s: failed\n", file);
++n_error;
break;
case SJ_SUCCEED: /* premature success */