summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/Makefile.headersinst2
-rw-r--r--scripts/Makefile.lib20
-rw-r--r--scripts/Makefile.ubsan17
-rwxr-xr-xscripts/build-all.py425
-rw-r--r--scripts/check-config-debug-exemptions58
-rw-r--r--scripts/check-config-perf-exemptions61
-rwxr-xr-xscripts/check-config.py147
-rwxr-xr-xscripts/checkpatch.pl278
-rw-r--r--scripts/dtc/libfdt/fdt.c14
-rw-r--r--scripts/dtc/libfdt/fdt_rw.c2
-rwxr-xr-xscripts/gcc-wrapper.py99
-rwxr-xr-xscripts/setlocalversion23
12 files changed, 1125 insertions, 21 deletions
diff --git a/scripts/Makefile.headersinst b/scripts/Makefile.headersinst
index 1106d6ca3a38..ed95cb4e515f 100644
--- a/scripts/Makefile.headersinst
+++ b/scripts/Makefile.headersinst
@@ -124,7 +124,7 @@ endif
# Recursion
.PHONY: $(subdirs)
$(subdirs):
- $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$@
+ $(Q)$(MAKE) $(hdr-inst)=$(obj)/$@ dst=$(_dst)/$(subst drivers/staging,usr/include/linux/staging,$@)
targets := $(wildcard $(sort $(targets)))
cmd_files := $(wildcard \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index c84080885ad4..861a2acd8cba 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -125,10 +125,16 @@ endif
#
ifeq ($(CONFIG_KASAN),y)
_c_flags += $(if $(patsubst n%,, \
- $(KASAN_SANITIZE_$(basetarget).o)$(KASAN_SANITIZE)y), \
+ $(KASAN_SANITIZE_$(basetarget).o)$(KASAN_SANITIZE)$(CONFIG_KASAN_SANITIZE_ALL)), \
$(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 '/').
@@ -294,6 +300,18 @@ $(obj)/%.dtb: $(src)/%.dts FORCE
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
+# Helper targets for Installing DTBs into the boot directory
+quiet_cmd_dtb_install = INSTALL $<
+ cmd_dtb_install = cp $< $(2)
+
+_dtbinst_pre_:
+ $(Q)if [ -d $(INSTALL_DTBS_PATH).old ]; then rm -rf $(INSTALL_DTBS_PATH).old; fi
+ $(Q)if [ -d $(INSTALL_DTBS_PATH) ]; then mv $(INSTALL_DTBS_PATH) $(INSTALL_DTBS_PATH).old; fi
+ $(Q)mkdir -p $(INSTALL_DTBS_PATH)
+
+%.dtb_dtbinst_: $(obj)/%.dtb _dtbinst_pre_
+ $(call cmd,dtb_install,$(INSTALL_DTBS_PATH))
+
# cat
# ---------------------------------------------------------------------------
# Concatentate multiple files together
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/build-all.py b/scripts/build-all.py
new file mode 100755
index 000000000000..9e4942d21da9
--- /dev/null
+++ b/scripts/build-all.py
@@ -0,0 +1,425 @@
+#! /usr/bin/env python2
+
+# Copyright (c) 2009-2015, The Linux Foundation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of The Linux Foundation nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Build the kernel for all targets using the Android build environment.
+
+from collections import namedtuple
+import glob
+from optparse import OptionParser
+import os
+import re
+import shutil
+import subprocess
+import sys
+import threading
+import Queue
+
+version = 'build-all.py, version 1.99'
+
+build_dir = '../all-kernels'
+make_command = ["vmlinux", "modules", "dtbs"]
+all_options = {}
+compile64 = os.environ.get('CROSS_COMPILE64')
+
+def error(msg):
+ sys.stderr.write("error: %s\n" % msg)
+
+def fail(msg):
+ """Fail with a user-printed message"""
+ error(msg)
+ sys.exit(1)
+
+if not os.environ.get('CROSS_COMPILE'):
+ fail("CROSS_COMPILE must be set in the environment")
+
+def check_kernel():
+ """Ensure that PWD is a kernel directory"""
+ if (not os.path.isfile('MAINTAINERS') or
+ not os.path.isfile('arch/arm64/configs/msm_defconfig')):
+ fail("This doesn't seem to be an MSM kernel dir")
+
+def check_build():
+ """Ensure that the build directory is present."""
+ if not os.path.isdir(build_dir):
+ try:
+ os.makedirs(build_dir)
+ except OSError as exc:
+ if exc.errno == errno.EEXIST:
+ pass
+ else:
+ raise
+
+failed_targets = []
+
+BuildResult = namedtuple('BuildResult', ['status', 'messages'])
+
+class BuildSequence(namedtuple('BuildSequence', ['log_name', 'short_name', 'steps'])):
+
+ def set_width(self, width):
+ self.width = width
+
+ def __enter__(self):
+ self.log = open(self.log_name, 'w')
+ def __exit__(self, type, value, traceback):
+ self.log.close()
+
+ def run(self):
+ self.status = None
+ messages = ["Building: " + self.short_name]
+ def printer(line):
+ text = "[%-*s] %s" % (self.width, self.short_name, line)
+ messages.append(text)
+ self.log.write(text)
+ self.log.write('\n')
+ for step in self.steps:
+ st = step.run(printer)
+ if st:
+ self.status = BuildResult(self.short_name, messages)
+ break
+ if not self.status:
+ self.status = BuildResult(None, messages)
+
+class BuildTracker:
+ """Manages all of the steps necessary to perform a build. The
+ build consists of one or more sequences of steps. The different
+ sequences can be processed independently, while the steps within a
+ sequence must be done in order."""
+
+ def __init__(self, parallel_builds):
+ self.sequence = []
+ self.lock = threading.Lock()
+ self.parallel_builds = parallel_builds
+
+ def add_sequence(self, log_name, short_name, steps):
+ self.sequence.append(BuildSequence(log_name, short_name, steps))
+
+ def longest_name(self):
+ longest = 0
+ for seq in self.sequence:
+ longest = max(longest, len(seq.short_name))
+ return longest
+
+ def __repr__(self):
+ return "BuildTracker(%s)" % self.sequence
+
+ def run_child(self, seq):
+ seq.set_width(self.longest)
+ tok = self.build_tokens.get()
+ with self.lock:
+ print "Building:", seq.short_name
+ with seq:
+ seq.run()
+ self.results.put(seq.status)
+ self.build_tokens.put(tok)
+
+ def run(self):
+ self.longest = self.longest_name()
+ self.results = Queue.Queue()
+ children = []
+ errors = []
+ self.build_tokens = Queue.Queue()
+ nthreads = self.parallel_builds
+ print "Building with", nthreads, "threads"
+ for i in range(nthreads):
+ self.build_tokens.put(True)
+ for seq in self.sequence:
+ child = threading.Thread(target=self.run_child, args=[seq])
+ children.append(child)
+ child.start()
+ for child in children:
+ stats = self.results.get()
+ if all_options.verbose:
+ with self.lock:
+ for line in stats.messages:
+ print line
+ sys.stdout.flush()
+ if stats.status:
+ errors.append(stats.status)
+ for child in children:
+ child.join()
+ if errors:
+ fail("\n ".join(["Failed targets:"] + errors))
+
+class PrintStep:
+ """A step that just prints a message"""
+ def __init__(self, message):
+ self.message = message
+
+ def run(self, outp):
+ outp(self.message)
+
+class MkdirStep:
+ """A step that makes a directory"""
+ def __init__(self, direc):
+ self.direc = direc
+
+ def run(self, outp):
+ outp("mkdir %s" % self.direc)
+ os.mkdir(self.direc)
+
+class RmtreeStep:
+ def __init__(self, direc):
+ self.direc = direc
+
+ def run(self, outp):
+ outp("rmtree %s" % self.direc)
+ shutil.rmtree(self.direc, ignore_errors=True)
+
+class CopyfileStep:
+ def __init__(self, src, dest):
+ self.src = src
+ self.dest = dest
+
+ def run(self, outp):
+ outp("cp %s %s" % (self.src, self.dest))
+ shutil.copyfile(self.src, self.dest)
+
+class ExecStep:
+ def __init__(self, cmd, **kwargs):
+ self.cmd = cmd
+ self.kwargs = kwargs
+
+ def run(self, outp):
+ outp("exec: %s" % (" ".join(self.cmd),))
+ with open('/dev/null', 'r') as devnull:
+ proc = subprocess.Popen(self.cmd, stdin=devnull,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.STDOUT,
+ **self.kwargs)
+ stdout = proc.stdout
+ while True:
+ line = stdout.readline()
+ if not line:
+ break
+ line = line.rstrip('\n')
+ outp(line)
+ result = proc.wait()
+ if result != 0:
+ return ('error', result)
+ else:
+ return None
+
+class Builder():
+
+ def __init__(self, name, defconfig):
+ self.name = name
+ self.defconfig = defconfig
+
+ self.confname = self.defconfig.split('/')[-1]
+
+ # Determine if this is a 64-bit target based on the location
+ # of the defconfig.
+ self.make_env = os.environ.copy()
+ if "/arm64/" in defconfig:
+ if compile64:
+ self.make_env['CROSS_COMPILE'] = compile64
+ else:
+ fail("Attempting to build 64-bit, without setting CROSS_COMPILE64")
+ self.make_env['ARCH'] = 'arm64'
+ else:
+ self.make_env['ARCH'] = 'arm'
+ self.make_env['KCONFIG_NOTIMESTAMP'] = 'true'
+ self.log_name = "%s/log-%s.log" % (build_dir, self.name)
+
+ def build(self):
+ steps = []
+ dest_dir = os.path.join(build_dir, self.name)
+ log_name = "%s/log-%s.log" % (build_dir, self.name)
+ steps.append(PrintStep('Building %s in %s log %s' %
+ (self.name, dest_dir, log_name)))
+ if not os.path.isdir(dest_dir):
+ steps.append(MkdirStep(dest_dir))
+ defconfig = self.defconfig
+ dotconfig = '%s/.config' % dest_dir
+ savedefconfig = '%s/defconfig' % dest_dir
+
+ staging_dir = 'install_staging'
+ modi_dir = '%s' % staging_dir
+ hdri_dir = '%s/usr' % staging_dir
+ steps.append(RmtreeStep(os.path.join(dest_dir, staging_dir)))
+
+ steps.append(ExecStep(['make', 'O=%s' % dest_dir,
+ self.confname], env=self.make_env))
+
+ if not all_options.updateconfigs:
+ # Build targets can be dependent upon the completion of
+ # previous build targets, so build them one at a time.
+ cmd_line = ['make',
+ 'INSTALL_HDR_PATH=%s' % hdri_dir,
+ 'INSTALL_MOD_PATH=%s' % modi_dir,
+ 'O=%s' % dest_dir]
+ build_targets = []
+ for c in make_command:
+ if re.match(r'^-{1,2}\w', c):
+ cmd_line.append(c)
+ else:
+ build_targets.append(c)
+ for t in build_targets:
+ steps.append(ExecStep(cmd_line + [t], env=self.make_env))
+
+ # Copy the defconfig back.
+ if all_options.configs or all_options.updateconfigs:
+ steps.append(ExecStep(['make', 'O=%s' % dest_dir,
+ 'savedefconfig'], env=self.make_env))
+ steps.append(CopyfileStep(savedefconfig, defconfig))
+
+ return steps
+
+def update_config(file, str):
+ print 'Updating %s with \'%s\'\n' % (file, str)
+ with open(file, 'a') as defconfig:
+ defconfig.write(str + '\n')
+
+def scan_configs():
+ """Get the full list of defconfigs appropriate for this tree."""
+ names = []
+ arch_pats = (
+ r'[fm]sm[0-9]*_defconfig',
+ r'apq*_defconfig',
+ r'qsd*_defconfig',
+ r'mpq*_defconfig',
+ )
+ arch64_pats = (
+ r'msm*_defconfig',
+ )
+ for p in arch_pats:
+ for n in glob.glob('arch/arm/configs/' + p):
+ name = os.path.basename(n)[:-10]
+ names.append(Builder(name, n))
+ if 'CROSS_COMPILE64' in os.environ:
+ for p in arch64_pats:
+ for n in glob.glob('arch/arm64/configs/' + p):
+ name = os.path.basename(n)[:-10] + "-64"
+ names.append(Builder(name, n))
+ return names
+
+def build_many(targets):
+ print "Building %d target(s)" % len(targets)
+
+ # To try and make up for the link phase being serial, try to do
+ # two full builds in parallel. Don't do too many because lots of
+ # parallel builds tends to use up available memory rather quickly.
+ parallel = 2
+ if all_options.jobs and all_options.jobs > 1:
+ j = max(all_options.jobs / parallel, 2)
+ make_command.append("-j" + str(j))
+
+ tracker = BuildTracker(parallel)
+ for target in targets:
+ if all_options.updateconfigs:
+ update_config(target.defconfig, all_options.updateconfigs)
+ steps = target.build()
+ tracker.add_sequence(target.log_name, target.name, steps)
+ tracker.run()
+
+def main():
+ global make_command
+
+ check_kernel()
+ check_build()
+
+ configs = scan_configs()
+
+ usage = ("""
+ %prog [options] all -- Build all targets
+ %prog [options] target target ... -- List specific targets
+ %prog [options] perf -- Build all perf targets
+ %prog [options] noperf -- Build all non-perf targets""")
+ parser = OptionParser(usage=usage, version=version)
+ parser.add_option('--configs', action='store_true',
+ dest='configs',
+ help="Copy configs back into tree")
+ parser.add_option('--list', action='store_true',
+ dest='list',
+ help='List available targets')
+ parser.add_option('-v', '--verbose', action='store_true',
+ dest='verbose',
+ help='Output to stdout in addition to log file')
+ parser.add_option('--oldconfig', action='store_true',
+ dest='oldconfig',
+ help='Only process "make oldconfig"')
+ parser.add_option('--updateconfigs',
+ dest='updateconfigs',
+ help="Update defconfigs with provided option setting, "
+ "e.g. --updateconfigs=\'CONFIG_USE_THING=y\'")
+ parser.add_option('-j', '--jobs', type='int', dest="jobs",
+ help="Number of simultaneous jobs")
+ parser.add_option('-l', '--load-average', type='int',
+ dest='load_average',
+ help="Don't start multiple jobs unless load is below LOAD_AVERAGE")
+ parser.add_option('-k', '--keep-going', action='store_true',
+ dest='keep_going', default=False,
+ help="Keep building other targets if a target fails")
+ parser.add_option('-m', '--make-target', action='append',
+ help='Build the indicated make target (default: %s)' %
+ ' '.join(make_command))
+
+ (options, args) = parser.parse_args()
+ global all_options
+ all_options = options
+
+ if options.list:
+ print "Available targets:"
+ for target in configs:
+ print " %s" % target.name
+ sys.exit(0)
+
+ if options.oldconfig:
+ make_command = ["oldconfig"]
+ elif options.make_target:
+ make_command = options.make_target
+
+ if args == ['all']:
+ build_many(configs)
+ elif args == ['perf']:
+ targets = []
+ for t in configs:
+ if "perf" in t.name:
+ targets.append(t)
+ build_many(targets)
+ elif args == ['noperf']:
+ targets = []
+ for t in configs:
+ if "perf" not in t.name:
+ targets.append(t)
+ build_many(targets)
+ elif len(args) > 0:
+ all_configs = {}
+ for t in configs:
+ all_configs[t.name] = t
+ targets = []
+ for t in args:
+ if t not in all_configs:
+ parser.error("Target '%s' not one of %s" % (t, all_configs.keys()))
+ targets.append(all_configs[t])
+ build_many(targets)
+ else:
+ parser.error("Must specify a target to build, or 'all'")
+
+if __name__ == "__main__":
+ main()
diff --git a/scripts/check-config-debug-exemptions b/scripts/check-config-debug-exemptions
new file mode 100644
index 000000000000..331a924e3612
--- /dev/null
+++ b/scripts/check-config-debug-exemptions
@@ -0,0 +1,58 @@
+CP15_BARRIER_EMULATION
+DEVKMEM
+DEVMEM
+HID_A4TECH
+HID_ACRUX
+HID_BELKIN
+HID_CHERRY
+HID_CHICONY
+HID_CYPRESS
+HID_DRAGONRISE
+HID_EMS_FF
+HID_EZKEY
+HID_GREENASIA
+HID_GYRATION
+HID_HOLTEK
+HID_KENSINGTON
+HID_KEYTOUCH
+HID_KYE
+HID_LCPOWER
+HID_LOGITECH
+HID_MONTEREY
+HID_NTRIG
+HID_ORTEK
+HID_PANTHERLORD
+HID_PETALYNX
+HID_PICOLCD
+HID_PRIMAX
+HID_PRODIKEYS
+HID_ROCCAT
+HID_SAITEK
+HID_SAMSUNG
+HID_SMARTJOYPLUS
+HID_SONY
+HID_SPEEDLINK
+HID_SUNPLUS
+HID_THRUSTMASTER
+HID_TIVO
+HID_TOPSEED
+HID_TWINHAN
+HID_UCLOGIC
+HID_WACOM
+HID_WALTOP
+HID_WIIMOTE
+HID_ZEROPLUS
+HID_ZYDACRON
+JOYSTICK_XPAD_FF
+JOYSTICK_XPAD_LEDS
+KSM
+MODULES
+PSTORE
+SETEND_EMULATION
+TABLET_USB_ACECAD
+TABLET_USB_AIPTEK
+TABLET_USB_GTCO
+TABLET_USB_HANWANG
+TABLET_USB_KBTAB
+USB_CONFIGFS
+USB_OTG_WAKELOCK
diff --git a/scripts/check-config-perf-exemptions b/scripts/check-config-perf-exemptions
new file mode 100644
index 000000000000..d499f5abeb1e
--- /dev/null
+++ b/scripts/check-config-perf-exemptions
@@ -0,0 +1,61 @@
+CGROUP_DEBUG
+CP15_BARRIER_EMULATION
+DEVKMEM
+DEVMEM
+HID_A4TECH
+HID_ACRUX
+HID_BELKIN
+HID_CHERRY
+HID_CHICONY
+HID_CYPRESS
+HID_DRAGONRISE
+HID_EMS_FF
+HID_EZKEY
+HID_GREENASIA
+HID_GYRATION
+HID_HOLTEK
+HID_KENSINGTON
+HID_KEYTOUCH
+HID_KYE
+HID_LCPOWER
+HID_LOGITECH
+HID_MONTEREY
+HID_NTRIG
+HID_ORTEK
+HID_PANTHERLORD
+HID_PETALYNX
+HID_PICOLCD
+HID_PRIMAX
+HID_PRODIKEYS
+HID_ROCCAT
+HID_SAITEK
+HID_SAMSUNG
+HID_SMARTJOYPLUS
+HID_SONY
+HID_SPEEDLINK
+HID_SUNPLUS
+HID_THRUSTMASTER
+HID_TIVO
+HID_TOPSEED
+HID_TWINHAN
+HID_UCLOGIC
+HID_WACOM
+HID_WALTOP
+HID_WIIMOTE
+HID_ZEROPLUS
+HID_ZYDACRON
+JOYSTICK_XPAD_FF
+JOYSTICK_XPAD_LEDS
+KSM
+MODULES
+PM_DEBUG
+PSTORE
+SETEND_EMULATION
+SUSPEND_TIME
+TABLET_USB_ACECAD
+TABLET_USB_AIPTEK
+TABLET_USB_GTCO
+TABLET_USB_HANWANG
+TABLET_USB_KBTAB
+USB_CONFIGFS
+USB_OTG_WAKELOCK
diff --git a/scripts/check-config.py b/scripts/check-config.py
new file mode 100755
index 000000000000..79c2bdf59759
--- /dev/null
+++ b/scripts/check-config.py
@@ -0,0 +1,147 @@
+#! /usr/bin/env python
+
+# Copyright (c) 2015, The Linux Foundation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of The Linux Foundation nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""
+Android kernel configuration validator.
+
+The Android kernel reference trees contain some config stubs of
+configuration options that are required for Android to function
+correctly, and additional ones that are recommended.
+
+This script can help compare these base configs with the ".config"
+output of the compiler to determine if the proper configs are defined.
+"""
+
+from collections import namedtuple
+from optparse import OptionParser
+import re
+import sys
+
+version = "check-config.py, version 0.0.1"
+
+req_re = re.compile(r'''^CONFIG_(.*)=(.*)$''')
+forb_re = re.compile(r'''^# CONFIG_(.*) is not set$''')
+comment_re = re.compile(r'''^(#.*|)$''')
+
+Enabled = namedtuple('Enabled', ['name', 'value'])
+Disabled = namedtuple('Disabled', ['name'])
+
+def walk_config(name):
+ with open(name, 'r') as fd:
+ for line in fd:
+ line = line.rstrip()
+ m = req_re.match(line)
+ if m:
+ yield Enabled(m.group(1), m.group(2))
+ continue
+
+ m = forb_re.match(line)
+ if m:
+ yield Disabled(m.group(1))
+ continue
+
+ m = comment_re.match(line)
+ if m:
+ continue
+
+ print "WARNING: Unknown .config line: ", line
+
+class Checker():
+ def __init__(self):
+ self.required = {}
+ self.exempted = set()
+ self.forbidden = set()
+
+ def add_required(self, fname):
+ for ent in walk_config(fname):
+ if type(ent) is Enabled:
+ self.required[ent.name] = ent.value
+ elif type(ent) is Disabled:
+ if ent.name in self.required:
+ del self.required[ent.name]
+ self.forbidden.add(ent.name)
+
+ def add_exempted(self, fname):
+ with open(fname, 'r') as fd:
+ for line in fd:
+ line = line.rstrip()
+ self.exempted.add(line)
+
+ def check(self, path):
+ failure = False
+
+ # Don't run this for mdm targets
+ if re.search('mdm', path):
+ print "Not applicable to mdm targets... bypassing"
+ else:
+ for ent in walk_config(path):
+ # Go to the next iteration if this config is exempt
+ if ent.name in self.exempted:
+ continue
+
+ if type(ent) is Enabled:
+ if ent.name in self.forbidden:
+ print "error: Config should not be present: %s" %ent.name
+ failure = True
+
+ if ent.name in self.required and ent.value != self.required[ent.name]:
+ print "error: Config has wrong value: %s %s expecting: %s" \
+ %(ent.name, ent.value, self.required[ent.name])
+ failure = True
+
+ elif type(ent) is Disabled:
+ if ent.name in self.required:
+ print "error: Config should be present, but is disabled: %s" %ent.name
+ failure = True
+
+ if failure:
+ sys.exit(1)
+
+def main():
+ usage = """%prog [options] path/to/.config"""
+ parser = OptionParser(usage=usage, version=version)
+ parser.add_option('-r', '--required', dest="required",
+ action="append")
+ parser.add_option('-e', '--exempted', dest="exempted",
+ action="append")
+ (options, args) = parser.parse_args()
+ if len(args) != 1:
+ parser.error("Expecting a single path argument to .config")
+ elif options.required is None or options.exempted is None:
+ parser.error("Expecting a file containing required configurations")
+
+ ch = Checker()
+ for r in options.required:
+ ch.add_required(r)
+ for e in options.exempted:
+ ch.add_exempted(e)
+
+ ch.check(args[0])
+
+if __name__ == '__main__':
+ main()
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 2b3c22808c3b..17a3a6d1785c 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -11,6 +11,13 @@ use File::Basename;
use Cwd 'abs_path';
use Term::ANSIColor qw(:constants);
+use constant BEFORE_SHORTTEXT => 0;
+use constant IN_SHORTTEXT_BLANKLINE => 1;
+use constant IN_SHORTTEXT => 2;
+use constant AFTER_SHORTTEXT => 3;
+use constant CHECK_NEXT_SHORTTEXT => 4;
+use constant SHORTTEXT_LIMIT => 75;
+
my $P = $0;
my $D = dirname(abs_path($P));
@@ -22,6 +29,7 @@ my $quiet = 0;
my $tree = 1;
my $chk_signoff = 1;
my $chk_patch = 1;
+my $chk_author = 1;
my $tst_only;
my $emacs = 0;
my $terse = 0;
@@ -64,6 +72,7 @@ Options:
-q, --quiet quiet
--no-tree run without a kernel tree
--no-signoff do not check for 'Signed-off-by' line
+ --no-author do not check for unexpected authors
--patch treat FILE as patchfile (default)
--emacs emacs compile window format
--terse one line per report
@@ -137,6 +146,7 @@ GetOptions(
'tree!' => \$tree,
'signoff!' => \$chk_signoff,
'patch!' => \$chk_patch,
+ 'author!' => \$chk_author,
'emacs!' => \$emacs,
'terse!' => \$terse,
'showfile!' => \$showfile,
@@ -1909,6 +1919,33 @@ sub tabify {
return "$leading";
}
+sub cleanup_continuation_headers {
+ # Collapse any header-continuation lines into a single line so they
+ # can be parsed meaningfully, as the parser only has one line
+ # of context to work with.
+ my $again;
+ do {
+ $again = 0;
+ foreach my $n (0 .. scalar(@rawlines) - 2) {
+ if ($rawlines[$n]=~/^\s*$/) {
+ # A blank line means there's no more chance
+ # of finding headers. Shortcut to done.
+ return;
+ }
+ if ($rawlines[$n]=~/^[\x21-\x39\x3b-\x7e]+:/ &&
+ $rawlines[$n+1]=~/^\s+/) {
+ # Continuation header. Collapse it.
+ my $line = splice @rawlines, $n+1, 1;
+ $line=~s/^\s+/ /;
+ $rawlines[$n] .= $line;
+ # We've 'destabilized' the list, so restart.
+ $again = 1;
+ last;
+ }
+ }
+ } while ($again);
+}
+
sub pos_last_openparen {
my ($line) = @_;
@@ -1947,6 +1984,8 @@ sub process {
my $prevrawline="";
my $stashline="";
my $stashrawline="";
+ my $subjectline="";
+ my $sublinenr="";
my $length;
my $indent;
@@ -2000,9 +2039,14 @@ sub process {
my $setup_docs = 0;
my $camelcase_file_seeded = 0;
+ my $shorttext = BEFORE_SHORTTEXT;
+ my $shorttext_exspc = 0;
+ my $commit_text_present = 0;
sanitise_line_reset();
+ cleanup_continuation_headers();
my $line;
+
foreach my $rawline (@rawlines) {
$linenr++;
$line = $rawline;
@@ -2184,13 +2228,115 @@ sub process {
}
next;
}
-
$here .= "FILE: $realfile:$realline:" if ($realcnt != 0);
my $hereline = "$here\n$rawline\n";
my $herecurr = "$here\n$rawline\n";
my $hereprev = "$here\n$prevrawline\n$rawline\n";
+ if ($shorttext != AFTER_SHORTTEXT) {
+ if ($shorttext == IN_SHORTTEXT_BLANKLINE && $line=~/\S/) {
+ # the subject line was just processed,
+ # a blank line must be next
+ WARN("NONBLANK_AFTER_SUMMARY",
+ "non-blank line after summary line\n" . $herecurr);
+ $shorttext = IN_SHORTTEXT;
+ # this non-blank line may or may not be commit text -
+ # a warning has been generated so assume it is commit
+ # text and move on
+ $commit_text_present = 1;
+ # fall through and treat this line as IN_SHORTTEXT
+ }
+ if ($shorttext == IN_SHORTTEXT) {
+ if ($line=~/^---/ || $line=~/^diff.*/) {
+ if ($commit_text_present == 0) {
+ WARN("NO_COMMIT_TEXT",
+ "please add commit text explaining " .
+ "*why* the change is needed\n" .
+ $herecurr);
+ }
+ $shorttext = AFTER_SHORTTEXT;
+ } elsif (length($line) > (SHORTTEXT_LIMIT +
+ $shorttext_exspc)
+ && $line !~ /^:([0-7]{6}\s){2}
+ ([[:xdigit:]]+\.*
+ \s){2}\w+\s\w+/xms) {
+ WARN("LONG_COMMIT_TEXT",
+ "commit text line over " .
+ SHORTTEXT_LIMIT .
+ " characters\n" . $herecurr);
+ } elsif ($line=~/^\s*change-id:/i ||
+ $line=~/^\s*signed-off-by:/i ||
+ $line=~/^\s*crs-fixed:/i ||
+ $line=~/^\s*acked-by:/i) {
+ # this is a tag, there must be commit
+ # text by now
+ if ($commit_text_present == 0) {
+ WARN("NO_COMMIT_TEXT",
+ "please add commit text explaining " .
+ "*why* the change is needed\n" .
+ $herecurr);
+ # prevent duplicate warnings
+ $commit_text_present = 1;
+ }
+ } elsif ($line=~/\S/) {
+ $commit_text_present = 1;
+ }
+ } elsif ($shorttext == IN_SHORTTEXT_BLANKLINE) {
+ # case of non-blank line in this state handled above
+ $shorttext = IN_SHORTTEXT;
+ } elsif ($shorttext == CHECK_NEXT_SHORTTEXT) {
+# The Subject line doesn't have to be the last header in the patch.
+# Avoid moving to the IN_SHORTTEXT state until clear of all headers.
+# Per RFC5322, continuation lines must be folded, so any left-justified
+# text which looks like a header is definitely a header.
+ if ($line!~/^[\x21-\x39\x3b-\x7e]+:/) {
+ $shorttext = IN_SHORTTEXT;
+ # Check for Subject line followed by a blank line.
+ if (length($line) != 0) {
+ WARN("NONBLANK_AFTER_SUMMARY",
+ "non-blank line after " .
+ "summary line\n" .
+ $sublinenr . $here .
+ "\n" . $subjectline .
+ "\n" . $line . "\n");
+ # this non-blank line may or may not
+ # be commit text - a warning has been
+ # generated so assume it is commit
+ # text and move on
+ $commit_text_present = 1;
+ }
+ }
+ # The next two cases are BEFORE_SHORTTEXT.
+ } elsif ($line=~/^Subject: \[[^\]]*\] (.*)/) {
+ # This is the subject line. Go to
+ # CHECK_NEXT_SHORTTEXT to wait for the commit
+ # text to show up.
+ $shorttext = CHECK_NEXT_SHORTTEXT;
+ $subjectline = $line;
+ $sublinenr = "#$linenr & ";
+# Check for Subject line less than line limit
+ if (length($1) > SHORTTEXT_LIMIT && !($1 =~ m/Revert\ \"/)) {
+ WARN("LONG_SUMMARY_LINE",
+ "summary line over " .
+ SHORTTEXT_LIMIT .
+ " characters\n" . $herecurr);
+ }
+ } elsif ($line=~/^ (.*)/) {
+ # Indented format, this must be the summary
+ # line (i.e. git show). There will be no more
+ # headers so we are now in the shorttext.
+ $shorttext = IN_SHORTTEXT_BLANKLINE;
+ $shorttext_exspc = 4;
+ if (length($1) > SHORTTEXT_LIMIT && !($1 =~ m/Revert\ \"/)) {
+ WARN("LONG_SUMMARY_LINE",
+ "summary line over " .
+ SHORTTEXT_LIMIT .
+ " characters\n" . $herecurr);
+ }
+ }
+ }
+
$cnt_lines++ if ($realcnt != 0);
# Check if the commit log has what seems like a diff which can confuse patch
@@ -2283,6 +2429,10 @@ sub process {
"email address '$email' might be better as '$suggested_email$comment'\n" . $herecurr);
}
}
+ if ($chk_author && $line =~ /^\s*signed-off-by:.*(quicinc|qualcomm)\.com/i) {
+ WARN("BAD_SIGN_OFF",
+ "invalid Signed-off-by identity\n" . $line );
+ }
# Check for duplicate signatures
my $sig_nospace = $line;
@@ -2309,12 +2459,6 @@ sub process {
"The 'stable' address should be 'stable\@vger.kernel.org'\n" . $herecurr);
}
-# Check for unwanted Gerrit info
- if ($in_commit_log && $line =~ /^\s*change-id:/i) {
- ERROR("GERRIT_CHANGE_ID",
- "Remove Gerrit Change-Id's before submitting upstream.\n" . $herecurr);
- }
-
# Check if the commit log is in a possible stack dump
if ($in_commit_log && !$commit_log_possible_stack_dump &&
($line =~ /^\s*(?:WARNING:|BUG:)/ ||
@@ -2413,6 +2557,11 @@ sub process {
"added, moved or deleted file(s), does MAINTAINERS need updating?\n" . $herecurr);
}
+#check the patch for invalid author credentials
+ if ($chk_author && $line =~ /^From:.*(quicinc|qualcomm)\.com/) {
+ WARN("BAD_AUTHOR", "invalid author identity\n" . $line );
+ }
+
# Check for wrappage within a valid hunk of the file
if ($realcnt != 0 && $line !~ m{^(?:\+|-| |\\ No newline|$)}) {
ERROR("CORRUPTED_PATCH",
@@ -2639,8 +2788,7 @@ sub process {
#
# if LONG_LINE is ignored, the other 2 types are also ignored
#
-
- if ($line =~ /^\+/ && $length > $max_line_length) {
+ if ($line =~ /^\+/ && $length > $max_line_length && $realfile ne "scripts/checkpatch.pl") {
my $msg_type = "LONG_LINE";
# Check the allowed long line types first
@@ -4134,7 +4282,7 @@ sub process {
# check spacing on parentheses
if ($line =~ /\(\s/ && $line !~ /\(\s*(?:\\)?$/ &&
- $line !~ /for\s*\(\s+;/) {
+ $line !~ /for\s*\(\s+;/ && $line !~ /^\+\s*[A-Z_][A-Z\d_]*\(\s*\d+(\,.*)?\)\,?$/) {
if (ERROR("SPACING",
"space prohibited after that open parenthesis '('\n" . $herecurr) &&
$fix) {
@@ -4505,7 +4653,7 @@ sub process {
if ($realfile !~ m@/vmlinux.lds.h$@ &&
$line =~ /^.\s*\#\s*define\s*$Ident(\()?/) {
my $ln = $linenr;
- my $cnt = $realcnt;
+ my $cnt = $realcnt - 1;
my ($off, $dstat, $dcond, $rest);
my $ctx = '';
my $has_flow_statement = 0;
@@ -4532,6 +4680,12 @@ sub process {
{
}
+ # Extremely long macros may fall off the end of the
+ # available context without closing. Give a dangling
+ # backslash the benefit of the doubt and allow it
+ # to gobble any hanging open-parens.
+ $dstat =~ s/\(.+\\$/1/;
+
# Flatten any obvious string concatentation.
while ($dstat =~ s/($String)\s*$Ident/$1/ ||
$dstat =~ s/$Ident\s*($String)/$1/)
@@ -4544,6 +4698,7 @@ sub process {
MODULE_PARM_DESC|
DECLARE_PER_CPU|
DEFINE_PER_CPU|
+ CLK_[A-Z\d_]+|
__typeof__\(|
union|
struct|
@@ -4894,11 +5049,94 @@ sub process {
"Avoid line continuations in quoted strings\n" . $herecurr);
}
+# sys_open/read/write/close are not allowed in the kernel
+ if ($line =~ /\b(sys_(?:open|read|write|close))\b/) {
+ ERROR("FILE_OPS",
+ "$1 is inappropriate in kernel code.\n" .
+ $herecurr);
+ }
+
+# filp_open is a backdoor for sys_open
+ if ($line =~ /\b(filp_open)\b/) {
+ ERROR("FILE_OPS",
+ "$1 is inappropriate in kernel code.\n" .
+ $herecurr);
+ }
+
+# read[bwl] & write[bwl] use too many barriers, use the _relaxed variants
+ if ($line =~ /\b((?:read|write)[bwl])\b/) {
+ ERROR("NON_RELAXED_IO",
+ "Use of $1 is deprecated: use $1_relaxed\n\t" .
+ "with appropriate memory barriers instead.\n" .
+ $herecurr);
+ }
+
+# likewise, in/out[bwl] should be __raw_read/write[bwl]...
+ if ($line =~ /\b((in|out)([bwl]))\b/) {
+ my ($all, $pref, $suf) = ($1, $2, $3);
+ $pref =~ s/in/read/;
+ $pref =~ s/out/write/;
+ ERROR("NON_RELAXED_IO",
+ "Use of $all is deprecated: use " .
+ "__raw_$pref$suf\n\t" .
+ "with appropriate memory barriers instead.\n" .
+ $herecurr);
+ }
+
+# dsb is too ARMish, and should usually be mb.
+ if ($line =~ /[^-_>*\.]\bdsb\b[^-_\.;]/) {
+ WARN("ARM_BARRIER",
+ "Use of dsb is discouranged: prefer mb.\n" .
+ $herecurr);
+ }
+
+# MSM - check if a non board-gpiomux file has any gpiomux declarations
+ if ($realfile =~ /\/mach-msm\/board-[0-9]+/ &&
+ $realfile !~ /camera/ && $realfile !~ /gpiomux/ &&
+ $line =~ /\s*struct msm_gpiomux_config\s*/ ) {
+ WARN("GPIOMUX_IN_BOARD",
+ "Non gpiomux board file cannot have a gpiomux config declarations. Please declare gpiomux configs in board-*-gpiomux.c file.\n" . $herecurr);
+ }
+
+# MSM - check if vreg_xxx function are used
+ if ($line =~ /\b(vreg_(get|put|set_level|enable|disable))\b/) {
+ WARN("DEPRECATED_VREG_APIS",
+ "Use of $1 API is deprecated: " .
+ "use regulator APIs\n" . $herecurr);
+ }
+
+# unbounded string functions are overflow risks
+ my %str_fns = (
+ "sprintf" => "snprintf",
+ "strcpy" => "strlcpy",
+ "strncpy" => "strlcpy",
+ "strcat" => "strlcat",
+ "strncat" => "strlcat",
+ "vsprintf" => "vsnprintf",
+ "strchr" => "strnchr",
+ "strstr" => "strnstr",
+ );
+ foreach my $k (keys %str_fns) {
+ if ($line =~ /\b$k\b/) {
+ ERROR("UNBOUNDED_STRING_FNS",
+ "Use of $k is deprecated: " .
+ "use $str_fns{$k} instead.\n" .
+ $herecurr);
+ }
+ }
+
# warn about #if 0
if ($line =~ /^.\s*\#\s*if\s+0\b/) {
- CHK("REDUNDANT_CODE",
- "if this code is redundant consider removing it\n" .
- $herecurr);
+ WARN("IF_0",
+ "if this code is redundant consider removing it\n"
+ . $herecurr);
+ }
+
+# warn about #if 1
+ if ($line =~ /^.\s*\#\s*if\s+1\b/) {
+ WARN("IF_1",
+ "if this code is required consider removing"
+ . " #if 1\n" . $herecurr);
}
# check for needless "if (<foo>) fn(<foo>)" uses
@@ -5088,6 +5326,12 @@ sub process {
"Comparing get_jiffies_64() is almost always wrong; prefer time_after64, time_before64 and friends\n" . $herecurr);
}
+# check the patch for use of mdelay
+ if ($line =~ /\bmdelay\s*\(/) {
+ WARN("MDELAY",
+ "use of mdelay() found: msleep() is the preferred API.\n" . $herecurr );
+ }
+
# warn about #ifdefs in C files
# if ($line =~ /^.\s*\#\s*if(|n)def/ && ($realfile =~ /\.c$/)) {
# print "#ifdef in C files should be avoided\n";
@@ -5574,6 +5818,12 @@ sub process {
"switch default: should use break\n" . $herectx);
}
+# check for return codes on error paths
+ if ($line =~ /\breturn\s+-\d+/) {
+ ERROR("NO_ERROR_CODE",
+ "illegal return value, please use an error code\n" . $herecurr);
+ }
+
# check for gcc specific __FUNCTION__
if ($line =~ /\b__FUNCTION__\b/) {
if (WARN("USE_FUNC",
diff --git a/scripts/dtc/libfdt/fdt.c b/scripts/dtc/libfdt/fdt.c
index 2ce6a44179de..d96ed24509c7 100644
--- a/scripts/dtc/libfdt/fdt.c
+++ b/scripts/dtc/libfdt/fdt.c
@@ -71,6 +71,20 @@ int fdt_check_header(const void *fdt)
return -FDT_ERR_BADMAGIC;
}
+ if (fdt_off_dt_struct(fdt) > (UINT_MAX - fdt_size_dt_struct(fdt)))
+ return FDT_ERR_BADOFFSET;
+
+ if (fdt_off_dt_strings(fdt) > (UINT_MAX - fdt_size_dt_strings(fdt)))
+ return FDT_ERR_BADOFFSET;
+
+ if ((fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt))
+ > fdt_totalsize(fdt))
+ return FDT_ERR_BADOFFSET;
+
+ if ((fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))
+ > fdt_totalsize(fdt))
+ return FDT_ERR_BADOFFSET;
+
return 0;
}
diff --git a/scripts/dtc/libfdt/fdt_rw.c b/scripts/dtc/libfdt/fdt_rw.c
index 70adec6c371b..4463c10f59e3 100644
--- a/scripts/dtc/libfdt/fdt_rw.c
+++ b/scripts/dtc/libfdt/fdt_rw.c
@@ -394,7 +394,7 @@ int fdt_del_node(void *fdt, int nodeoffset)
static void _fdt_packblocks(const char *old, char *new,
int mem_rsv_size, int struct_size)
{
- int mem_rsv_off, struct_off, strings_off;
+ uint32_t mem_rsv_off, struct_off, strings_off;
mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8);
struct_off = mem_rsv_off + mem_rsv_size;
diff --git a/scripts/gcc-wrapper.py b/scripts/gcc-wrapper.py
new file mode 100755
index 000000000000..8a0e0af1c39a
--- /dev/null
+++ b/scripts/gcc-wrapper.py
@@ -0,0 +1,99 @@
+#! /usr/bin/env python2
+# -*- coding: utf-8 -*-
+
+# Copyright (c) 2011-2016, The Linux Foundation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# * Neither the name of The Linux Foundation nor
+# the names of its contributors may be used to endorse or promote
+# products derived from this software without specific prior written
+# permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+# OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+# WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+# OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# Invoke gcc, looking for warnings, and causing a failure if there are
+# non-whitelisted warnings.
+
+import errno
+import re
+import os
+import sys
+import subprocess
+
+# Note that gcc uses unicode, which may depend on the locale. TODO:
+# force LANG to be set to en_US.UTF-8 to get consistent warnings.
+
+allowed_warnings = set([
+ "core.c:144",
+ "inet_connection_sock.c:430",
+ "inet_connection_sock.c:467",
+ "inet6_connection_sock.c:89",
+ ])
+
+# Capture the name of the object file, can find it.
+ofile = None
+
+warning_re = re.compile(r'''(.*/|)([^/]+\.[a-z]+:\d+):(\d+:)? warning:''')
+def interpret_warning(line):
+ """Decode the message from gcc. The messages we care about have a filename, and a warning"""
+ line = line.rstrip('\n')
+ m = warning_re.match(line)
+ if m and m.group(2) not in allowed_warnings:
+ print "error, forbidden warning:", m.group(2)
+
+ # If there is a warning, remove any object if it exists.
+ if ofile:
+ try:
+ os.remove(ofile)
+ except OSError:
+ pass
+ sys.exit(1)
+
+def run_gcc():
+ args = sys.argv[1:]
+ # Look for -o
+ try:
+ i = args.index('-o')
+ global ofile
+ ofile = args[i+1]
+ except (ValueError, IndexError):
+ pass
+
+ compiler = sys.argv[0]
+
+ try:
+ proc = subprocess.Popen(args, stderr=subprocess.PIPE)
+ for line in proc.stderr:
+ print line,
+ interpret_warning(line)
+
+ result = proc.wait()
+ except OSError as e:
+ result = e.errno
+ if result == errno.ENOENT:
+ print args[0] + ':',e.strerror
+ print 'Is your PATH set correctly?'
+ else:
+ print ' '.join(args), str(e)
+
+ return result
+
+if __name__ == '__main__':
+ status = run_gcc()
+ sys.exit(status)
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 63d91e22ed7c..43f29132a28c 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -48,7 +48,20 @@ scm_version()
# If we are at a tagged commit (like "v2.6.30-rc6"), we ignore
# it, because this version is defined in the top level Makefile.
- if [ -z "`git describe --exact-match 2>/dev/null`" ]; then
+ if atag="`git describe --exact-match --abbrev=0 2>/dev/null`"; then
+ # Make sure we're at the tag that matches the Makefile.
+ # If not place the hash of the tag as well for
+ # v2.6.30-rc5-g314aef
+ if [ "x$atag" != "x$VERSION" ]; then
+ # If only the short version is requested,
+ # don't bother running further git commands
+ if $short; then
+ echo "+"
+ return
+ fi
+ printf '%s%s' -g "`git show-ref -s --abbrev --tags $atag 2>/dev/null`"
+ fi
+ else
# If only the short version is requested, don't bother
# running further git commands
@@ -57,10 +70,12 @@ scm_version()
return
fi
# If we are past a tagged commit (like
- # "v2.6.30-rc5-302-g72357d5"), we pretty print it.
+ # "v2.6.30-rc5-302-g72357d5"), we pretty print it and
+ # include the hash of any new tag on top.
if atag="`git describe 2>/dev/null`"; then
- echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'
-
+ tag="`git describe --abbrev=0 2>/dev/null`"
+ commit="`echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}'`"
+ printf '%s%s%s' -g "`git show-ref -s --abbrev --tags $tag 2>/dev/null`" $commit
# If we don't have a tag at all we print -g{commitish}.
else
printf '%s%s' -g $head