diff options
Diffstat (limited to 'contrib/compiler-rt/lib/sanitizer_common/scripts')
5 files changed, 148 insertions, 37 deletions
diff --git a/contrib/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh b/contrib/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh index 7ed05d7..9108a81 100755 --- a/contrib/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh +++ b/contrib/compiler-rt/lib/sanitizer_common/scripts/check_lint.sh @@ -17,7 +17,6 @@ fi # Filters # TODO: remove some of these filters -LLVM_LINT_FILTER=-,+whitespace COMMON_LINT_FILTER=-build/include,-build/header_guard,-legal/copyright,-whitespace/comments,-readability/casting,\ -build/namespaces ASAN_RTL_LINT_FILTER=${COMMON_LINT_FILTER},-runtime/int @@ -60,9 +59,6 @@ run_lint() { ${LITLINT} "$@" 2>>$ERROR_LOG } -run_lint ${LLVM_LINT_FILTER} --filter=${LLVM_LINT_FILTER} \ - lib/Transforms/Instrumentation/*Sanitizer.cpp & - if [ "${COMPILER_RT}" = "" ]; then COMPILER_RT=projects/compiler-rt fi diff --git a/contrib/compiler-rt/lib/sanitizer_common/scripts/cpplint.py b/contrib/compiler-rt/lib/sanitizer_common/scripts/cpplint.py index 742459a..d45c47f 100755 --- a/contrib/compiler-rt/lib/sanitizer_common/scripts/cpplint.py +++ b/contrib/compiler-rt/lib/sanitizer_common/scripts/cpplint.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # Copyright (c) 2009 Google Inc. All rights reserved. # diff --git a/contrib/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py b/contrib/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py index 7bab230..f055bb4 100755 --- a/contrib/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py +++ b/contrib/compiler-rt/lib/sanitizer_common/scripts/gen_dynamic_list.py @@ -14,15 +14,24 @@ # gen_dynamic_list.py libclang_rt.*san*.a [ files ... ] # #===------------------------------------------------------------------------===# +import argparse import os import re import subprocess import sys -new_delete = set(['_ZdaPv', '_ZdaPvRKSt9nothrow_t', - '_ZdlPv', '_ZdlPvRKSt9nothrow_t', - '_Znam', '_ZnamRKSt9nothrow_t', - '_Znwm', '_ZnwmRKSt9nothrow_t']) +new_delete = set([ + '_Znam', '_ZnamRKSt9nothrow_t', # operator new[](unsigned long) + '_Znwm', '_ZnwmRKSt9nothrow_t', # operator new(unsigned long) + '_Znaj', '_ZnajRKSt9nothrow_t', # operator new[](unsigned int) + '_Znwj', '_ZnwjRKSt9nothrow_t', # operator new(unsigned int) + '_ZdaPv', '_ZdaPvRKSt9nothrow_t', # operator delete[](void *) + '_ZdlPv', '_ZdlPvRKSt9nothrow_t', # operator delete(void *) + '_ZdaPvm', # operator delete[](void*, unsigned long) + '_ZdlPvm', # operator delete(void*, unsigned long) + '_ZdaPvj', # operator delete[](void*, unsigned int) + '_ZdlPvj', # operator delete(void*, unsigned int) + ]) versioned_functions = set(['memcpy', 'pthread_attr_getaffinity_np', 'pthread_cond_broadcast', @@ -49,10 +58,17 @@ def get_global_functions(library): return functions def main(argv): + parser = argparse.ArgumentParser() + parser.add_argument('--version-list', action='store_true') + parser.add_argument('--extra', default=[], action='append') + parser.add_argument('libraries', default=[], nargs='+') + args = parser.parse_args() + result = [] - library = argv[1] - all_functions = get_global_functions(library) + all_functions = [] + for library in args.libraries: + all_functions.extend(get_global_functions(library)) function_set = set(all_functions) for func in all_functions: # Export new/delete operators. @@ -66,7 +82,7 @@ def main(argv): # We have to avoid exporting the interceptors for versioned library # functions due to gold internal error. orig_name = match.group(1) - if orig_name in function_set and orig_name not in versioned_functions: + if orig_name in function_set and (args.version_list or orig_name not in versioned_functions): result.append(orig_name) continue # Export sanitizer interface functions. @@ -74,15 +90,20 @@ def main(argv): result.append(func) # Additional exported functions from files. - for fname in argv[2:]: + for fname in args.extra: f = open(fname, 'r') for line in f: result.append(line.rstrip()) # Print the resulting list in the format recognized by ld. print('{') + if args.version_list: + print('global:') result.sort() for f in result: - print(' ' + f + ';') + print(' ' + f.encode('utf-8') + ';') + if args.version_list: + print('local:') + print(' *;') print('};') if __name__ == '__main__': diff --git a/contrib/compiler-rt/lib/sanitizer_common/scripts/litlint.py b/contrib/compiler-rt/lib/sanitizer_common/scripts/litlint.py index 1e78448..81b89c2 100755 --- a/contrib/compiler-rt/lib/sanitizer_common/scripts/litlint.py +++ b/contrib/compiler-rt/lib/sanitizer_common/scripts/litlint.py @@ -1,4 +1,4 @@ -#!/usr/bin/python +#!/usr/bin/env python # # litlint # diff --git a/contrib/compiler-rt/lib/sanitizer_common/scripts/sancov.py b/contrib/compiler-rt/lib/sanitizer_common/scripts/sancov.py index 566116e..a5ae957 100755 --- a/contrib/compiler-rt/lib/sanitizer_common/scripts/sancov.py +++ b/contrib/compiler-rt/lib/sanitizer_common/scripts/sancov.py @@ -4,40 +4,85 @@ # We need to merge these integers into a set and then # either print them (as hex) or dump them into another file. import array -import struct -import sys import bisect +import glob import os.path +import struct +import subprocess +import sys -prog_name = ""; +prog_name = "" def Usage(): print >> sys.stderr, "Usage: \n" + \ - " " + prog_name + " merge file1 [file2 ...] > output\n" \ - " " + prog_name + " print file1 [file2 ...]\n" \ - " " + prog_name + " unpack file1 [file2 ...]\n" \ - " " + prog_name + " rawunpack file1 [file2 ...]\n" + " " + prog_name + " merge FILE [FILE...] > OUTPUT\n" \ + " " + prog_name + " print FILE [FILE...]\n" \ + " " + prog_name + " unpack FILE [FILE...]\n" \ + " " + prog_name + " rawunpack FILE [FILE ...]\n" \ + " " + prog_name + " missing BINARY < LIST_OF_PCS\n" exit(1) +def CheckBits(bits): + if bits != 32 and bits != 64: + raise Exception("Wrong bitness: %d" % bits) + +def TypeCodeForBits(bits): + CheckBits(bits) + return 'L' if bits == 64 else 'I' + +kMagic32SecondHalf = 0xFFFFFF32; +kMagic64SecondHalf = 0xFFFFFF64; +kMagicFirstHalf = 0xC0BFFFFF; + +def MagicForBits(bits): + CheckBits(bits) + if sys.byteorder == 'little': + return [kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf, kMagicFirstHalf] + else: + return [kMagicFirstHalf, kMagic64SecondHalf if bits == 64 else kMagic32SecondHalf] + +def ReadMagicAndReturnBitness(f, path): + magic_bytes = f.read(8) + magic_words = struct.unpack('II', magic_bytes); + bits = 0 + idx = 1 if sys.byteorder == 'little' else 0 + if magic_words[idx] == kMagicFirstHalf: + if magic_words[1-idx] == kMagic64SecondHalf: + bits = 64 + elif magic_words[1-idx] == kMagic32SecondHalf: + bits = 32 + if bits == 0: + raise Exception('Bad magic word in %s' % path) + return bits + def ReadOneFile(path): with open(path, mode="rb") as f: f.seek(0, 2) size = f.tell() f.seek(0, 0) - s = set(array.array('I', f.read(size))) - print >>sys.stderr, "%s: read %d PCs from %s" % (prog_name, size / 4, path) + if size < 8: + raise Exception('File %s is short (< 8 bytes)' % path) + bits = ReadMagicAndReturnBitness(f, path) + size -= 8 + s = array.array(TypeCodeForBits(bits), f.read(size)) + print >>sys.stderr, "%s: read %d %d-bit PCs from %s" % (prog_name, size * 8 / bits, bits, path) return s def Merge(files): s = set() for f in files: - s = s.union(ReadOneFile(f)) + s = s.union(set(ReadOneFile(f))) print >> sys.stderr, "%s: %d files merged; %d PCs total" % \ (prog_name, len(files), len(s)) return sorted(s) def PrintFiles(files): - s = Merge(files) + if len(files) > 1: + s = Merge(files) + else: # If there is just on file, print the PCs in order. + s = ReadOneFile(files[0]) + print >> sys.stderr, "%s: 1 file merged; %d PCs total" % \ + (prog_name, len(s)) for i in s: print "0x%x" % i @@ -45,7 +90,11 @@ def MergeAndPrint(files): if sys.stdout.isatty(): Usage() s = Merge(files) - a = array.array('I', s) + bits = 32 + if max(s) > 0xFFFFFFFF: + bits = 64 + array.array('I', MagicForBits(bits)).tofile(sys.stdout) + a = array.array(TypeCodeForBits(bits), s) a.tofile(sys.stdout) @@ -82,6 +131,8 @@ def UnpackOneRawFile(path, map_path): with open(map_path, mode="rt") as f_map: print >> sys.stderr, "%s: reading map %s" % (prog_name, map_path) bits = int(f_map.readline()) + if bits != 32 and bits != 64: + raise Exception('Wrong bits size in the map') for line in f_map: parts = line.rstrip().split() mem_map.append((int(parts[0], 16), @@ -97,11 +148,7 @@ def UnpackOneRawFile(path, map_path): f.seek(0, 2) size = f.tell() f.seek(0, 0) - if bits == 64: - typecode = 'L' - else: - typecode = 'I' - pcs = array.array(typecode, f.read(size)) + pcs = array.array(TypeCodeForBits(bits), f.read(size)) mem_map_pcs = [[] for i in range(0, len(mem_map))] for pc in pcs: @@ -119,9 +166,10 @@ def UnpackOneRawFile(path, map_path): assert path.endswith('.sancov.raw') dst_path = module_path + '.' + os.path.basename(path)[:-4] print >> sys.stderr, "%s: writing %d PCs to %s" % (prog_name, len(pc_list), dst_path) - arr = array.array('I') + arr = array.array(TypeCodeForBits(bits)) arr.fromlist(sorted(pc_list)) with open(dst_path, 'ab') as f2: + array.array('I', MagicForBits(bits)).tofile(f2) arr.tofile(f2) def RawUnpack(files): @@ -131,17 +179,63 @@ def RawUnpack(files): f_map = f[:-3] + 'map' UnpackOneRawFile(f, f_map) +def GetInstrumentedPCs(binary): + # This looks scary, but all it does is extract all offsets where we call: + # - __sanitizer_cov() or __sanitizer_cov_with_check(), + # - with call or callq, + # - directly or via PLT. + cmd = "objdump -d %s | " \ + "grep '^\s\+[0-9a-f]\+:.*\scall\(q\|\)\s\+[0-9a-f]\+ <__sanitizer_cov\(_with_check\|\)\(@plt\|\)>' | " \ + "grep '^\s\+[0-9a-f]\+' -o" % binary + proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE, + shell=True) + proc.stdin.close() + # The PCs we get from objdump are off by 4 bytes, as they point to the + # beginning of the callq instruction. Empirically this is true on x86 and + # x86_64. + return set(int(line.strip(), 16) + 4 for line in proc.stdout) + +def PrintMissing(binary): + if not os.path.isfile(binary): + raise Exception('File not found: %s' % binary) + instrumented = GetInstrumentedPCs(binary) + print >> sys.stderr, "%s: found %d instrumented PCs in %s" % (prog_name, + len(instrumented), + binary) + covered = set(int(line, 16) for line in sys.stdin) + print >> sys.stderr, "%s: read %d PCs from stdin" % (prog_name, len(covered)) + missing = instrumented - covered + print >> sys.stderr, "%s: %d PCs missing from coverage" % (prog_name, len(missing)) + if (len(missing) > len(instrumented) - len(covered)): + print >> sys.stderr, \ + "%s: WARNING: stdin contains PCs not found in binary" % prog_name + for pc in sorted(missing): + print "0x%x" % pc + if __name__ == '__main__': prog_name = sys.argv[0] if len(sys.argv) <= 2: Usage(); + + if sys.argv[1] == "missing": + if len(sys.argv) != 3: + Usage() + PrintMissing(sys.argv[2]) + exit(0) + + file_list = [] + for f in sys.argv[2:]: + file_list += glob.glob(f) + if not file_list: + Usage() + if sys.argv[1] == "print": - PrintFiles(sys.argv[2:]) + PrintFiles(file_list) elif sys.argv[1] == "merge": - MergeAndPrint(sys.argv[2:]) + MergeAndPrint(file_list) elif sys.argv[1] == "unpack": - Unpack(sys.argv[2:]) + Unpack(file_list) elif sys.argv[1] == "rawunpack": - RawUnpack(sys.argv[2:]) + RawUnpack(file_list) else: Usage() |