From d550c4446787884a14d3d5dd0b3dde3e6847fd8e Mon Sep 17 00:00:00 2001 From: Denis Khalikov Date: Tue, 22 Aug 2017 11:08:58 +0300 Subject: [PATCH] [TTC-6] packaging: Enable gcc-contrib package All scripts related to toolchain moved from gcc package to gcc-contrib package. Change-Id: I52019814fe8c4173241d91982e3200da88918593 Signed-off-by: Denis Khalikov Signed-off-by: Dongkyun, Son --- packaging/ASAN_OPTIONS | 1 + packaging/LSAN_OPTIONS | 1 + packaging/UBSAN_OPTIONS | 1 + packaging/asan_symbolize.py | 720 +++++++++++++++++++++++++++++++++++++++++ packaging/extract-ubsan-logs | 17 + packaging/gcc-contrib.manifest | 5 + packaging/gcc-contrib.spec | 362 +++++++++++++++++++++ packaging/gcc-force-options | 129 ++++++++ packaging/gcc-unforce-options | 19 ++ packaging/lsan.supp | 1 + packaging/macros.ubsan | 39 +++ 11 files changed, 1295 insertions(+) create mode 100644 packaging/ASAN_OPTIONS create mode 100644 packaging/LSAN_OPTIONS create mode 100644 packaging/UBSAN_OPTIONS create mode 100644 packaging/asan_symbolize.py create mode 100644 packaging/extract-ubsan-logs create mode 100644 packaging/gcc-contrib.manifest create mode 100644 packaging/gcc-contrib.spec create mode 100644 packaging/gcc-force-options create mode 100644 packaging/gcc-unforce-options create mode 100644 packaging/lsan.supp create mode 100644 packaging/macros.ubsan diff --git a/packaging/ASAN_OPTIONS b/packaging/ASAN_OPTIONS new file mode 100644 index 0000000..50d644e --- /dev/null +++ b/packaging/ASAN_OPTIONS @@ -0,0 +1 @@ +halt_on_error=false:start_deactivated=true:print_cmdline=true:quarantine_size_mb=1:detect_leaks=0:full_address_space=true diff --git a/packaging/LSAN_OPTIONS b/packaging/LSAN_OPTIONS new file mode 100644 index 0000000..db30ebc --- /dev/null +++ b/packaging/LSAN_OPTIONS @@ -0,0 +1 @@ +print_cmdline=true:detect_leaks=1:log_path=/tmp/lsan.log:log_exe_name=1:fast_unwind_on_malloc=false:malloc_context_size=5:suppressions=/lsan.supp:print_suppressions=false diff --git a/packaging/UBSAN_OPTIONS b/packaging/UBSAN_OPTIONS new file mode 100644 index 0000000..0fbf7a7 --- /dev/null +++ b/packaging/UBSAN_OPTIONS @@ -0,0 +1 @@ +print_cmdline=true:log_path=/tmp/ubsan.log \ No newline at end of file diff --git a/packaging/asan_symbolize.py b/packaging/asan_symbolize.py new file mode 100644 index 0000000..f37530b --- /dev/null +++ b/packaging/asan_symbolize.py @@ -0,0 +1,720 @@ +#!/usr/bin/env python +#===- lib/asan/scripts/asan_symbolize.py -----------------------------------===# +# +# The LLVM Compiler Infrastructure +# +# This file is distributed under the University of Illinois Open Source +# License. See https://github.com/llvm-mirror/compiler-rt/blob/master/LICENSE.TXT +# for details. +# +#===------------------------------------------------------------------------===# +import argparse +import array +import binascii +import bisect +import os +import re +import subprocess +import sys + +symbolizers = {} +DEBUG = False +demangle = False +binutils_prefix = None +sysroot_path = None +binary_name_filter = None +fix_filename_patterns = None +logfile = sys.stdin +separate_debug_dir_list = [] +prelink_offset = None + +# FIXME: merge the code that calls fix_filename(). +def fix_filename(file_name): + if fix_filename_patterns: + for path_to_cut in fix_filename_patterns: + file_name = re.sub('.*' + path_to_cut, '', file_name) + file_name = re.sub('.*asan_[a-z_]*.cc:[0-9]*', '_asan_rtl_', file_name) + file_name = re.sub('.*crtstuff.c:0', '???:0', file_name) + return file_name + +def sysroot_path_filter(binary_name): + return sysroot_path + binary_name + +def use_binutils_prefix(tool_name): + if binutils_prefix: + tool_name = binutils_prefix + tool_name + return tool_name + +def print_error_message(message): + print >> sys.stderr, 'Error occured during symbolizisation: ' + message + +class DebugInfoHandler(object): + def __init__(self, binary_name_filter=None): + self.binary_name_filter = binary_name_filter + self.global_debug_dir_list = [ self.use_name_filter("/usr/lib/debug") ] + if separate_debug_dir_list: + self.global_debug_dir_list = separate_debug_dir_list + + def use_name_filter(self, binary_name): + if self.binary_name_filter: + binary_name = self.binary_name_filter(binary_name) + return binary_name + + def calc_crc32(self, filename): + buf = open(filename,'rb').read() + buf = (binascii.crc32(buf, 0) & 0xFFFFFFFF) + return "%08X" % buf + + def readelf_binary(self, options, binary): + cmd = [use_binutils_prefix('readelf'), options,'-W', binary] + try: + process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=open(os.devnull, 'w')) + except: + print_error_message('the following command failed:\n''"' + ' '.join(cmd) + '"') + return + (readelf_out, _) = process.communicate() + if process.returncode == 0: + return readelf_out + + def has_debuginfo(self, binary): + readelf_out = self.readelf_binary('-S', binary) + return readelf_out and (".debug_" in readelf_out) + + def get_buildid(self, binary): + readelf_out = self.readelf_binary('-nw', binary) + ''' + Build ID is 40-length hex value following after "Build ID:". + e.g.: + Notes at offset 0x00000274 with length 0x00000024: + Owner Data size Description + GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring) + Build ID: 977b1d1375ba6791d5f6dd38d8d55b95f9fca33a + ''' + if readelf_out: + readelf_lines = readelf_out.split("\n"); + buildid_lines = filter(re.compile('Build ID:').search, readelf_lines) + for line in buildid_lines: + match = re.search('[a-f0-9]{40}', line) + if match: + return match.group(0) + else: + print_error_message('failed to read Build ID value from ' + binary) + + def get_debuglink_name(self, binary): + readelf_out = self.readelf_binary('--string-dump=.gnu_debuglink', binary) + ''' + "debug link" is the last word in the first line of dump. + e.g.: + String dump of section '.gnu_debuglink': + [ 0] HeapOutOfBounds.out.debug + ''' + if readelf_out: + readelf_lines = filter(None, readelf_out.split("\n")); + headline ="String dump of section '.gnu_debuglink':" + try: + debuglink_line_idx = readelf_lines.index(headline) + 1 + except ValueError: + # There is no gnu_debuglink section in this binary + return + if len(readelf_lines) > debuglink_line_idx: + return readelf_lines[debuglink_line_idx].split()[-1] + else: + print_error_message('failed to read debuglink value from ' + binary) + + def get_debuglink_crc(self, binary): + readelf_out = self.readelf_binary('--hex-dump=.gnu_debuglink', binary) + ''' + crc is the last hex group (before string representation) in the last line of dump. + e.g. (crc is f89f21c2) : + Hex dump of section '.gnu_debuglink': + 0x00000000 48656170 4f75744f 66426f75 6e64732e HeapOutOfBounds. + 0x00000010 6f75742e 64656275 67000000 f89f21c2 out.debug.....!. + ''' + if readelf_out: + # get last non-empty line + crc_line = filter(None, readelf_out.split("\n"))[-1] + # remove last 16 characters (string dump) from line + crc_line = crc_line[:-16] + # crc is last word in string + crc = crc_line.split()[-1] + match = re.match('[a-f0-9]{8}', crc) + if match: + if sys.byteorder == 'little': + crc = array.array('i', binascii.unhexlify(crc) ) + crc.byteswap() + crc = binascii.hexlify(crc) + return crc + else: + print_error_message('failed to get crc checksum from debuglink in ' + binary) + + + def is_prelinked(self, binary): + readelf_out = self.readelf_binary('-S', binary) + return readelf_out and ".gnu.prelink_undo" in readelf_out + + def get_load_address(self, binary): + readelf_out = self.readelf_binary('-l', binary) + ''' + Readelf program headers output example: + Elf file type is DYN (Shared object file) + Entry point 0xb1160668 + There are 10 program headers, starting at offset 52 + Program Headers: + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + EXIDX 0x124754 0xb126c754 0xb126c754 0x04498 0x04498 R 0x4 + [...] + LOAD 0x000000 0xb1148000 0xb1148000 0x12be9c 0x12be9c R E 0x8000 + + ''' + readelf_lines = readelf_out.split("\n"); + load_lines = filter(re.compile( + '[\s]*LOAD[\s]+0x[0]+[\s]+0x[a-fA-f\d]+').match, readelf_lines) + if load_lines: + return load_lines[0].split()[2] + else: + print_error_message('failed to get load address in ' + binary) + + def get_prelink_offset(self, orig, prelinked): + if not self.is_prelinked(prelinked): + return + orig_load_addr = self.get_load_address(orig) + prelinked_load_addr = self.get_load_address(prelinked) + return int(prelinked_load_addr, 16) - int(orig_load_addr, 16) + + def locate_in_orig_dir(self, debuglink_name, orig_binary_name): + debuginfo = os.path.join(os.path.dirname(orig_binary_name), debuglink_name) + debuginfo = self.use_name_filter(debuginfo) + return [debuginfo] + + def locate_in_debug_subdir(self, debuglink_name, orig_binary_name): + debuginfo = os.path.join(os.path.dirname(orig_binary_name), '.debug', debuglink_name) + debuginfo = self.use_name_filter(debuginfo) + return [debuginfo] + + def locate_in_global_debug_dir(self, debuglink_name, orig_binary_name): + debuginfo_list = [] + for global_debug_dir in self.global_debug_dir_list: + debuginfo = global_debug_dir + os.path.join(os.path.dirname(orig_binary_name), debuglink_name) + debuginfo_list.append(debuginfo) + return debuginfo_list + + def locate_in_buildid_dir(self, debuglink_name, orig_binary_name): + dir_name = debuglink_name[0:2] + file_name = debuglink_name[2:] + ".debug" + debuginfo_list = [] + for global_debug_dir in self.global_debug_dir_list: + debuginfo = os.path.join(global_debug_dir, ".build-id", dir_name, file_name) + debuginfo_list.append(debuginfo) + return debuginfo_list + + def get_debuginfo(self,binary_name): + global prelink_offset + prelink_offset = None + orig_binary_name = binary_name + # First apply sysroot path if defined to get real binary + real_binary = self.use_name_filter(binary_name) + if self.has_debuginfo(real_binary): + return real_binary + # Look for debuginfo file according to GDB rules + # 1) "build-id" method + buildid_name = self.get_buildid(real_binary) + debugfile_list = [] + if buildid_name: + debugfile_list = self.locate_in_buildid_dir(buildid_name, orig_binary_name) + for debugfile in debugfile_list: + if os.path.isfile(debugfile): + prelink_offset = self.get_prelink_offset(debugfile, real_binary) + return debugfile + # 2) "debug link" method + debuglink_name = self.get_debuglink_name(real_binary) + debuglink_crc = self.get_debuglink_crc(real_binary) + debugfile_list = [] + if debuglink_name and debuglink_crc: + debuglink_locate_list = [ + self.locate_in_orig_dir, + self.locate_in_debug_subdir, + self.locate_in_global_debug_dir ] + for debuglink_locate_function in debuglink_locate_list: + debugfile_list = debuglink_locate_function(debuglink_name, orig_binary_name) + for debugfile in debugfile_list: + if os.path.isfile(debugfile): + debugfile_crc = self.calc_crc32(debugfile) + if int(debuglink_crc,16) == int(debugfile_crc, 16): + prelink_offset = self.get_prelink_offset(debugfile, real_binary) + return debugfile + return real_binary + +def guess_arch(addr): + # Guess which arch we're running. 10 = len('0x') + 8 hex digits. + if len(addr) > 10: + return 'x86_64' + else: + return 'i386' + +class Symbolizer(object): + def __init__(self): + pass + + def symbolize(self, addr, binary, offset): + """Symbolize the given address (pair of binary and offset). + + Overriden in subclasses. + Args: + addr: virtual address of an instruction. + binary: path to executable/shared object containing this instruction. + offset: instruction offset in the @binary. + Returns: + list of strings (one string for each inlined frame) describing + the code locations for this instruction (that is, function name, file + name, line and column numbers). + """ + return None + + +class LLVMSymbolizer(Symbolizer): + def __init__(self, symbolizer_path, default_arch, system, dsym_hints=[]): + super(LLVMSymbolizer, self).__init__() + self.symbolizer_path = symbolizer_path + self.default_arch = default_arch + self.system = system + self.dsym_hints = dsym_hints + self.pipe = self.open_llvm_symbolizer() + + def open_llvm_symbolizer(self): + cmd = [self.symbolizer_path, + '--use-symbol-table=true', + '--demangle=%s' % demangle, + '--functions=short', + '--inlining=true', + '--default-arch=%s' % self.default_arch] + if self.system == 'Darwin': + for hint in self.dsym_hints: + cmd.append('--dsym-hint=%s' % hint) + if DEBUG: + print ' '.join(cmd) + try: + result = subprocess.Popen(cmd, stdin=subprocess.PIPE, + stdout=subprocess.PIPE) + except OSError: + result = None + return result + + def symbolize(self, addr, binary, offset): + """Overrides Symbolizer.symbolize.""" + if not self.pipe: + return None + result = [] + try: + symbolizer_input = '"%s" %s' % (binary, offset) + if DEBUG: + print symbolizer_input + print >> self.pipe.stdin, symbolizer_input + while True: + function_name = self.pipe.stdout.readline().rstrip() + if not function_name: + break + file_name = self.pipe.stdout.readline().rstrip() + file_name = fix_filename(file_name) + if (not function_name.startswith('??') or + not file_name.startswith('??')): + # Append only non-trivial frames. + result.append('%s in %s %s' % (addr, function_name, + file_name)) + except Exception: + result = [] + if not result: + result = None + return result + + +def LLVMSymbolizerFactory(system, default_arch, dsym_hints=[]): + symbolizer_path = os.getenv('LLVM_SYMBOLIZER_PATH') + if not symbolizer_path: + symbolizer_path = os.getenv('ASAN_SYMBOLIZER_PATH') + if not symbolizer_path: + # Assume llvm-symbolizer is in PATH. + symbolizer_path = 'llvm-symbolizer' + return LLVMSymbolizer(symbolizer_path, default_arch, system, dsym_hints) + + +class Addr2LineSymbolizer(Symbolizer): + def __init__(self, binary): + super(Addr2LineSymbolizer, self).__init__() + self.binary = binary + + def symbolize(self, addr, binary, offset): + """Overrides Symbolizer.symbolize.""" + cmd = [use_binutils_prefix('addr2line'), '-fi'] + if demangle: + cmd += ['--demangle'] + cmd += ['-e', self.binary, offset] + if DEBUG: + print ' '.join(cmd) + self.pipe = subprocess.Popen(cmd, stdout=subprocess.PIPE) + result = [] + if self.binary != binary: + return None + try: + lines = self.pipe.stdout.readlines() + except Exception: + lines = [] + if not lines: + lines.append('??') + lines.append('??:?') + for i in range(0, len(lines), 2): + function_name = lines[i].rstrip() + file_name = fix_filename(lines[i+1].rstrip()) + result.append('%s in %s %s' % (addr, function_name, file_name)) + return result + + +class UnbufferedLineConverter(object): + """ + Wrap a child process that responds to each line of input with one line of + output. Uses pty to trick the child into providing unbuffered output. + """ + def __init__(self, args, close_stderr=False): + # Local imports so that the script can start on Windows. + import pty + import termios + pid, fd = pty.fork() + if pid == 0: + # We're the child. Transfer control to command. + if close_stderr: + dev_null = os.open('/dev/null', 0) + os.dup2(dev_null, 2) + os.execvp(args[0], args) + else: + # Disable echoing. + attr = termios.tcgetattr(fd) + attr[3] = attr[3] & ~termios.ECHO + termios.tcsetattr(fd, termios.TCSANOW, attr) + # Set up a file()-like interface to the child process + self.r = os.fdopen(fd, "r", 1) + self.w = os.fdopen(os.dup(fd), "w", 1) + + def convert(self, line): + self.w.write(line + "\n") + return self.readline() + + def readline(self): + return self.r.readline().rstrip() + + +class DarwinSymbolizer(Symbolizer): + def __init__(self, addr, binary): + super(DarwinSymbolizer, self).__init__() + self.binary = binary + self.arch = guess_arch(addr) + self.open_atos() + + def open_atos(self): + if DEBUG: + print 'atos -o %s -arch %s' % (self.binary, self.arch) + cmdline = ['atos', '-o', self.binary, '-arch', self.arch] + self.atos = UnbufferedLineConverter(cmdline, close_stderr=True) + + def symbolize(self, addr, binary, offset): + """Overrides Symbolizer.symbolize.""" + if self.binary != binary: + return None + atos_line = self.atos.convert('0x%x' % int(offset, 16)) + while "got symbolicator for" in atos_line: + atos_line = self.atos.readline() + # A well-formed atos response looks like this: + # foo(type1, type2) (in object.name) (filename.cc:80) + match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line) + if DEBUG: + print 'atos_line: ', atos_line + if match: + function_name = match.group(1) + function_name = re.sub('\(.*?\)', '', function_name) + file_name = fix_filename(match.group(3)) + return ['%s in %s %s' % (addr, function_name, file_name)] + else: + return ['%s in %s' % (addr, atos_line)] + + +# Chain several symbolizers so that if one symbolizer fails, we fall back +# to the next symbolizer in chain. +class ChainSymbolizer(Symbolizer): + def __init__(self, symbolizer_list): + super(ChainSymbolizer, self).__init__() + self.symbolizer_list = symbolizer_list + + def symbolize(self, addr, binary, offset): + """Overrides Symbolizer.symbolize.""" + for symbolizer in self.symbolizer_list: + if symbolizer: + result = symbolizer.symbolize(addr, binary, offset) + if result: + return result + return None + + def append_symbolizer(self, symbolizer): + self.symbolizer_list.append(symbolizer) + + +def BreakpadSymbolizerFactory(binary): + suffix = os.getenv('BREAKPAD_SUFFIX') + if suffix: + filename = binary + suffix + if os.access(filename, os.F_OK): + return BreakpadSymbolizer(filename) + return None + + +def SystemSymbolizerFactory(system, addr, binary): + if system == 'Darwin': + return DarwinSymbolizer(addr, binary) + elif system == 'Linux': + return Addr2LineSymbolizer(binary) + + +class BreakpadSymbolizer(Symbolizer): + def __init__(self, filename): + super(BreakpadSymbolizer, self).__init__() + self.filename = filename + lines = file(filename).readlines() + self.files = [] + self.symbols = {} + self.address_list = [] + self.addresses = {} + # MODULE mac x86_64 A7001116478B33F18FF9BEDE9F615F190 t + fragments = lines[0].rstrip().split() + self.arch = fragments[2] + self.debug_id = fragments[3] + self.binary = ' '.join(fragments[4:]) + self.parse_lines(lines[1:]) + + def parse_lines(self, lines): + cur_function_addr = '' + for line in lines: + fragments = line.split() + if fragments[0] == 'FILE': + assert int(fragments[1]) == len(self.files) + self.files.append(' '.join(fragments[2:])) + elif fragments[0] == 'PUBLIC': + self.symbols[int(fragments[1], 16)] = ' '.join(fragments[3:]) + elif fragments[0] in ['CFI', 'STACK']: + pass + elif fragments[0] == 'FUNC': + cur_function_addr = int(fragments[1], 16) + if not cur_function_addr in self.symbols.keys(): + self.symbols[cur_function_addr] = ' '.join(fragments[4:]) + else: + # Line starting with an address. + addr = int(fragments[0], 16) + self.address_list.append(addr) + # Tuple of symbol address, size, line, file number. + self.addresses[addr] = (cur_function_addr, + int(fragments[1], 16), + int(fragments[2]), + int(fragments[3])) + self.address_list.sort() + + def get_sym_file_line(self, addr): + key = None + if addr in self.addresses.keys(): + key = addr + else: + index = bisect.bisect_left(self.address_list, addr) + if index == 0: + return None + else: + key = self.address_list[index - 1] + sym_id, size, line_no, file_no = self.addresses[key] + symbol = self.symbols[sym_id] + filename = self.files[file_no] + if addr < key + size: + return symbol, filename, line_no + else: + return None + + def symbolize(self, addr, binary, offset): + if self.binary != binary: + return None + res = self.get_sym_file_line(int(offset, 16)) + if res: + function_name, file_name, line_no = res + result = ['%s in %s %s:%d' % ( + addr, function_name, file_name, line_no)] + print result + return result + else: + return None + + +class SymbolizationLoop(object): + def __init__(self, binary_name_filter=None, dsym_hint_producer=None): + if sys.platform == 'win32': + # ASan on Windows uses dbghelp.dll to symbolize in-process, which works + # even in sandboxed processes. Nothing needs to be done here. + self.process_line = self.process_line_echo + else: + # Used by clients who may want to supply a different binary name. + # E.g. in Chrome several binaries may share a single .dSYM. + self.binary_name_filter = binary_name_filter + self.dsym_hint_producer = dsym_hint_producer + self.system = os.uname()[0] + if self.system not in ['Linux', 'Darwin', 'FreeBSD']: + raise Exception('Unknown system') + self.llvm_symbolizers = {} + self.last_llvm_symbolizer = None + self.dsym_hints = set([]) + self.frame_no = 0 + self.process_line = self.process_line_posix + + def symbolize_address(self, addr, binary, offset): + # On non-Darwin (i.e. on platforms without .dSYM debug info) always use + # a single symbolizer binary. + # On Darwin, if the dsym hint producer is present: + # 1. check whether we've seen this binary already; if so, + # use |llvm_symbolizers[binary]|, which has already loaded the debug + # info for this binary (might not be the case for + # |last_llvm_symbolizer|); + # 2. otherwise check if we've seen all the hints for this binary already; + # if so, reuse |last_llvm_symbolizer| which has the full set of hints; + # 3. otherwise create a new symbolizer and pass all currently known + # .dSYM hints to it. + if not binary in self.llvm_symbolizers: + use_new_symbolizer = True + if self.system == 'Darwin' and self.dsym_hint_producer: + dsym_hints_for_binary = set(self.dsym_hint_producer(binary)) + use_new_symbolizer = bool(dsym_hints_for_binary - self.dsym_hints) + self.dsym_hints |= dsym_hints_for_binary + if self.last_llvm_symbolizer and not use_new_symbolizer: + self.llvm_symbolizers[binary] = self.last_llvm_symbolizer + else: + self.last_llvm_symbolizer = LLVMSymbolizerFactory( + self.system, guess_arch(addr), self.dsym_hints) + self.llvm_symbolizers[binary] = self.last_llvm_symbolizer + # Use the chain of symbolizers: + # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos + # (fall back to next symbolizer if the previous one fails). + if not binary in symbolizers: + symbolizers[binary] = ChainSymbolizer( + [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]]) + result = symbolizers[binary].symbolize(addr, binary, offset) + if result is None: + # Initialize system symbolizer only if other symbolizers failed. + symbolizers[binary].append_symbolizer( + SystemSymbolizerFactory(self.system, addr, binary)) + result = symbolizers[binary].symbolize(addr, binary, offset) + # The system symbolizer must produce some result. + assert result + return result + + def get_symbolized_lines(self, symbolized_lines): + if not symbolized_lines: + return [self.current_line] + else: + result = [] + for symbolized_frame in symbolized_lines: + if '?' in symbolized_frame: + symbolized_frame += " " + re.search('\(.*?\)',self.current_line).group(0) + result.append(' #%s %s' % (str(self.frame_no), symbolized_frame.rstrip())) + self.frame_no += 1 + return result + + def process_logfile(self): + self.frame_no = 0 + for line in logfile: + processed = self.process_line(line) + print '\n'.join(processed) + + def process_line_echo(self, line): + return [line.rstrip()] + + def have_line_to_symbolize(self, line): + #0 0x7f6e35cf2e45 in func (/blah/foo.so+0x11fe45) + stack_trace_line_format = ( + '^( *#([0-9]+) *)(0x[0-9a-f]+)( *in [^/]+)? *\((.*)\+(0x[0-9a-f]+)\)') + match = re.match(stack_trace_line_format, line) + if not match: + # If already symbolized (format below) - fix given frame number + #0 0x7f6e35cf2e45 in func foo:46 + stack_trace_line_format_symbolized = ( + '^( *#([0-9]+) *)(0x[0-9a-f]+)( *in [^/]+)? *(.*)\:([0-9]+)') + match_symbolized = re.match(stack_trace_line_format_symbolized, line); + if match_symbolized: + # Frame number from line + match_frame_number = match_symbolized.group(2) + if (self.frame_no != int(match_frame_number)): + self.current_line = re.sub(match_frame_number, str(self.frame_no), line, count=1) + self.frame_no += 1 + return match + + def process_line_posix(self, line): + self.current_line = line.rstrip() + match = self.have_line_to_symbolize(line) + if not match: + return [self.current_line] + if DEBUG: + print line + _, frameno_str, addr, func, binary, offset = match.groups() + if frameno_str == '0': + # Assume that frame #0 is the first frame of new stack trace. + self.frame_no = 0 + original_binary = binary + if self.binary_name_filter: + binary = self.binary_name_filter(binary) + # Correct offset from backtrace if the binary was prelinked + # and printed address considers the prelink offset: + if prelink_offset: + real_offset = int(offset,16) + if real_offset > prelink_offset: + #FIXME: Need to check that offset fits section size + offset = hex(real_offset - prelink_offset) + if DEBUG: + print 'real address: ' + offset + symbolized_line = self.symbolize_address(addr, binary, offset) + if not symbolized_line: + if original_binary != binary: + symbolized_line = self.symbolize_address(addr, binary, offset) + return self.get_symbolized_lines(symbolized_line) + + +if __name__ == '__main__': + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description='ASan symbolization script', + epilog='Example of use:\n' + 'asan_symbolize.py -c "$HOME/opt/cross/bin/armv7l-tizen-linux-gnueabi-" ' + '-s "$HOME/SymbolFiles" < asan.log') + parser.add_argument('path_to_cut', nargs='*', + help='pattern to be cut from the result file path ') + parser.add_argument('-d','--demangle', action='store_true', + help='demangle function names') + parser.add_argument('-s', metavar='SYSROOT', + help='set path to sysroot for sanitized binaries') + parser.add_argument('-c', metavar='CROSS_COMPILE', + help='set prefix for binutils') + parser.add_argument('-l','--logfile', default=sys.stdin, + type=argparse.FileType('r'), + help='set log file name to parse, default is stdin') + parser.add_argument('-y', '--debug-file-directory', metavar='DEBUGDIR', + help='The directories for separate debug information \ + files. Multiple path components can be set concatenating \ + them by a path separator.') + args = parser.parse_args() + if args.path_to_cut: + fix_filename_patterns = args.path_to_cut + if args.demangle: + demangle = True + if args.s: + binary_name_filter = sysroot_path_filter + sysroot_path = args.s + if args.c: + binutils_prefix = args.c + if args.logfile: + logfile = args.logfile + else: + logfile = sys.stdin + if args.debug_file_directory: + separate_debug_dir_list = args.debug_file_directory.split(":") + if os.uname()[0] == 'Linux': + debug_info_handler = DebugInfoHandler(binary_name_filter) + binary_name_filter = debug_info_handler.get_debuginfo + loop = SymbolizationLoop(binary_name_filter) + loop.process_logfile() diff --git a/packaging/extract-ubsan-logs b/packaging/extract-ubsan-logs new file mode 100644 index 0000000..d7a8ddf --- /dev/null +++ b/packaging/extract-ubsan-logs @@ -0,0 +1,17 @@ +#!/bin/sh + +# /usr/lib/rpm/tizen/extract-ubsan-logs + +# If using normal root, avoid changing anything. +if [ -z "$RPM_BUILD_ROOT" -o "$RPM_BUILD_ROOT" = "/" ]; then + exit 0 +fi + +mkdir -p "$RPM_BUILD_ROOT/usr/share/ubsan" +find "/tmp/" -name 'ubsan.log*' | xargs -I {} cp {} "$RPM_BUILD_ROOT/usr/share/ubsan/" +find "$RPM_BUILD_ROOT/usr/share/ubsan/" -name 'ubsan.log*' | xargs -I {} sed -e "s#/.*rpmbuild/##" -i {} +find "$RPM_BUILD_ROOT/usr/share/ubsan/" -name 'ubsan.log*' -exec rename ubsan ${RPM_PACKAGE_NAME}-ubsan {} \; + +# Avoid empty resulting RPMs: create a placeholder if there's no logs in directory. +(find "$RPM_BUILD_ROOT/usr/share/ubsan/" -mindepth 1 -print -quit | grep -q .) || \ + touch "$RPM_BUILD_ROOT/usr/share/ubsan/ubsan.log.empty" diff --git a/packaging/gcc-contrib.manifest b/packaging/gcc-contrib.manifest new file mode 100644 index 0000000..017d22d --- /dev/null +++ b/packaging/gcc-contrib.manifest @@ -0,0 +1,5 @@ + + + + + diff --git a/packaging/gcc-contrib.spec b/packaging/gcc-contrib.spec new file mode 100644 index 0000000..f9f329c --- /dev/null +++ b/packaging/gcc-contrib.spec @@ -0,0 +1,362 @@ +# +# spec file for package gcc-contrib +# +# Copyright (c) 2017 Tizen +# Please submit bugfixes or comments via http://bugs.tizen.org/ +# +# we use %%{?macro: ... } as it is more compact + +%define quadmath_arch %ix86 x86_64 ia64 +%define tsan_arch x86_64 aarch64 +%define asan_arch x86_64 %ix86 ppc ppc64 %sparc %arm aarch64 +%define itm_arch x86_64 %ix86 %arm ppc ppc64 ppc64le s390 s390x %sparc aarch64 +%define atomic_arch x86_64 %ix86 %arm aarch64 ppc ppc64 ppc64le s390 s390x %sparc m68k +%define lsan_arch x86_64 %ix86 armv7l aarch64 +%define ubsan_arch x86_64 %ix86 ppc ppc64 %arm aarch64 +%define cilkrts_arch x86_64 %ix86 + +%ifarch armv7l +%define ARCH armv7l +%define ABI eabi +%endif +%ifarch %ix86 +%define ARCH i586 +%endif +%ifarch x86_64 +%define ARCH x86_64 +%endif +%ifarch aarch64 +%define ARCH aarch64 +%endif +%define host_arch %{ARCH}-tizen-linux-gnu%{?ABI} + +%define target_cpu %{?cross}%{!?cross:%{ARCH}} +%define target_abi %{?cross:%{?armv7l:eabi}}%{!?cross:%{?ABI}} + +%define target_arch %{target_cpu}-tizen-linux-gnu%{?target_abi} +%define libdir %{!?cross:%{_libdir}}%{?cross:%{_prefix}/lib%{?aarch64:64}} +%define libsubdir %{libdir}/gcc/%{target_arch}/%{version} + +%define asan_force_options -fsanitize-recover=address -fsanitize=address -fno-omit-frame-pointer -Wp,-U_FORTIFY_SOURCE -Wl,--as-needed -ldl -lpthread +%define ubsan_force_options -fsanitize=undefined,bounds-strict,float-divide-by-zero,float-cast-overflow +%define lsan_force_options -fsanitize=leak -fno-omit-frame-pointer -Wp,-U_FORTIFY_SOURCE + +%define asan_runtime_options halt_on_error=false:start_deactivated=true:print_cmdline=true:quarantine_size_mb=1:detect_leaks=0:log_path=/tmp/asan.log:log_exe_name=1 +%define ubsan_runtime_options print_cmdline=true:log_path=/tmp/ubsan.log +%define lsan_runtime_options print_cmdline=true:detect_leaks=1:log_path=/tmp/lsan.log:log_exe_name=1:fast_unwind_on_malloc=false:malloc_context_size=5:suppressions=/lsan.supp:print_suppressions=false + +Name: gcc-contrib%{?cross:-%{cross}} +# With generated files in src we could drop the following +## until here, but at least renaming and patching info files breaks this +%{?cross:BuildRequires: binutils-%{cross}} +# here we use %%if because OBS spec parser cannot expand +# %%{?macro:...} correctly +Version: 6.2.1 +Release: 0 +Source15: gcc-force-options +Source16: gcc-unforce-options +Source17: ASAN_OPTIONS +Source18: asan_symbolize.py +Source19: LSAN_OPTIONS +Source20: gcc-contrib.manifest +Source21: UBSAN_OPTIONS +Source22: macros.ubsan +Source23: extract-ubsan-logs +Source24: lsan.supp +Group: Development/Building +Summary: GCC related scripts +License: MIT +%{?cross:ExcludeArch: %{cross}} +%description +GCC related scripts + +%package -n asan-force-options +Summary: Scripts to enable automatic package sanitization +Group: System Environment +Requires: gcc rpm +Requires: libasan + +%description -n asan-force-options +Scripts for ASan instrumentation + +%post -n asan-force-options +# Change mode to allow all users to run gcc-force/unforce-options +chmod a+w /usr/bin +chmod a+w %{libsubdir} +[ -d /emul/ ] && chmod a+w /emul/usr/bin/ && chmod a+w /emul/home/abuild/rpmbuild/BUILD/gcc-*/obj/gcc/ \ + && find -L /emul/usr/*/gcc -name 'collect2' | xargs dirname | xargs chmod a+w +/usr/bin/gcc-force-options %asan_force_options -fno-common +# Add ASan-related macros +cat >> /usr/lib/rpm/tizen_macros << EOF + +%%asan_force_options %{asan_force_options} +%%gcc_unforce_options /usr/bin/gcc-unforce-options +%%gcc_force_options /usr/bin/gcc-force-options +%%gcc_force_default_options %%gcc_force_options %%asan_force_options -fno-common +%%restore_fcommon \\ + %%gcc_unforce_options \\ + %%gcc_force_options %%asan_force_options -fcommon +EOF +# ASan needs a whole shadow address space +# Using ulimit can only set the value for current user so we need to set /etc/security/limits.conf directly. +sed '/End of file/i\abuild\tsoft\tas\t-1\nabuild\thard\tas\t-1' -i /etc/security/limits.conf + +%preun -n asan-force-options +# Restore read-only mode +chmod a-w /usr/bin +chmod a-w %{libsubdir} +[ -d /emul/ ] && chmod a-w /emul/usr/bin/ && chmod a-w /emul/home/abuild/rpmbuild/BUILD/gcc-*/obj/gcc/ \ + && find -L /emul/usr/*/gcc -name 'collect2' | xargs dirname | xargs chmod a-w +/usr/bin/gcc-unforce-options +# Restore limit configurations set for ASan +sed '/abuild/d' -i /etc/security/limits.conf + +%package -n ubsan-force-options +Summary: Scripts to enable automatic package sanitization +Group: System Environment +Requires: gcc +Requires: libubsan + +%description -n ubsan-force-options +Scripts for UBSan instrumentation + +%post -n ubsan-force-options +# Change mode to allow all users to run gcc-force/unforce-options +chmod a+w /usr/bin +chmod a+w %{libsubdir} +[ -d /emul/ ] && chmod a+w /emul/usr/bin/ && chmod a+w /emul/home/abuild/rpmbuild/BUILD/gcc-*/obj/gcc/ \ + && find -L /emul/usr/*/gcc -name 'collect2' | xargs dirname | xargs chmod a+w +/usr/bin/gcc-force-options %ubsan_force_options +# Add UBSan-related macros +cat >> /usr/lib/rpm/tizen_macros << EOF + +%%ubsan_force_options %{ubsan_force_options} +%%gcc_unforce_options /usr/bin/gcc-unforce-options +%%gcc_force_options /usr/bin/gcc-force-options +%%gcc_force_default_options %%gcc_force_options %%ubsan_force_options +EOF + +%preun -n ubsan-force-options +# Restore read-only mode +chmod a-w /usr/bin +chmod a-w %{libsubdir} +[ -d /emul/ ] && chmod a-w /emul/usr/bin/ && chmod a-w /emul/home/abuild/rpmbuild/BUILD/gcc-*/obj/gcc/ \ + && find -L /emul/usr/*/gcc -name 'collect2' | xargs dirname | xargs chmod a-w +/usr/bin/gcc-unforce-options + +%package -n ubsan-build-env +Summary: UBSan build environment +Group: System Environment +Requires: gcc +Requires: libubsan rpm + +%description -n ubsan-build-env +UBSan build environment support files and scripts + +%post -n ubsan-build-env +cat %{_rpmconfigdir}/macros.ubsan >> %{_rpmconfigdir}/tizen_macros + +%package -n lsan-force-options +Summary: Scripts to enable automatic package sanitization +Group: System Environment +Requires: gcc +Requires: liblsan + +%description -n lsan-force-options +Scripts for LSan instrumentation + +%post -n lsan-force-options +# Change mode to allow all users to run gcc-force/unforce-options +chmod a+w /usr/bin +chmod a+w %{libsubdir} +[ -d /emul/ ] && chmod a+w /emul/usr/bin/ && chmod a+w /emul/home/abuild/rpmbuild/BUILD/gcc-*/obj/gcc/ \ + && find -L /emul/usr/*/gcc -name 'collect2' | xargs dirname | xargs chmod a+w +/usr/bin/gcc-force-options %lsan_force_options +# Add LSan-related macros +cat >> /usr/lib/rpm/tizen_macros << EOF + +%%lsan_force_options %{lsan_force_options} +%%gcc_unforce_options /usr/bin/gcc-unforce-options +%%gcc_force_options /usr/bin/gcc-force-options +%%gcc_force_default_options %%gcc_force_options %%lsan_force_options +EOF + +%preun -n lsan-force-options +# Restore read-only mode +chmod a-w /usr/bin +chmod a-w %{libsubdir} +[ -d /emul/ ] && chmod a-w /emul/usr/bin/ && chmod a-w /emul/home/abuild/rpmbuild/BUILD/gcc-*/obj/gcc/ \ + && find -L /emul/usr/*/gcc -name 'collect2' | xargs dirname | xargs chmod a-w +/usr/bin/gcc-unforce-options +[ -d /emul/ ] && chmod a-w /emul/usr/bin/ + +%package -n asan-build-env +Summary: Asan build environment +Group: Development/Libraries +Requires: libasan + +%description -n asan-build-env +Asan build environment + +%post -n asan-build-env +# Add /usr/lib/libasan.so to /etc/ld.so.preload +[ -f /etc/ld.so.preload ] && mv -v /etc/ld.so.preload /etc/ld.so.preload.orig +echo "libasan.so" > /etc/ld.so.preload +[ -f /etc/ld.so.preload.orig ] && cat /etc/ld.so.preload.orig >> /etc/ld.so.preload + +%preun -n asan-build-env +# Restore /etc/ld.so.preload +[ -f /etc/ld.so.preload.orig ] && mv -v /etc/ld.so.preload.orig /etc/ld.so.preload + +%package -n lsan-runtime-env +Summary: LSan runtime environment +Group: Development/Libraries +Requires: liblsan +Requires(post): smack + +%description -n lsan-runtime-env +LSan runtime environment + +%post -n lsan-runtime-env +# Add /usr/lib64/liblsan.so to /etc/ld.so.preload +[ -f /etc/ld.so.preload ] && mv -v /etc/ld.so.preload /etc/ld.so.preload.orig +echo "%{libdir}/liblsan.so" > /etc/ld.so.preload +[ -f /etc/ld.so.preload.orig ] && cat /etc/ld.so.preload.orig >> /etc/ld.so.preload +echo "%{lsan_runtime_options}" > /LSAN_OPTIONS +chsmack -a "_" /etc/ld.so.preload /LSAN_OPTIONS /lsan.supp + +%preun -n lsan-runtime-env +# Restore /etc/ld.so.preload +mv -v /etc/ld.so.preload.orig /etc/ld.so.preload + +%package -n sanitizer-devel +Summary: Sanitizer platform-independent tools +License: MIT +Group: Development/Tools +BuildArch: noarch +Requires: binutils python +Requires(post): smack + +%description -n sanitizer-devel +The package contatins platform-independent tools for sanitization: +- asan_symbolize.py: script for offline symbolization of asan logs + +%package -n asan-runtime-env +Summary: Asan runtime environment for target device +Group: Development/Libraries +Requires: libasan + +%description -n asan-runtime-env +Asan runtime environment + +%post -n asan-runtime-env +# Add /usr/lib/libasan.so to /etc/ld.so.preload +[ -f /etc/ld.so.preload ] && mv -v /etc/ld.so.preload /etc/ld.so.preload.orig +echo "%{libdir}/libasan.so" > /etc/ld.so.preload +[ -f /etc/ld.so.preload.orig ] && cat /etc/ld.so.preload.orig >> /etc/ld.so.preload +echo "%{asan_runtime_options}" > /ASAN_OPTIONS +chsmack -a "_" /etc/ld.so.preload /ASAN_OPTIONS + +%preun -n asan-runtime-env +# Restore /etc/ld.so.preload +[ -f /etc/ld.so.preload.orig ] && mv -v /etc/ld.so.preload.orig /etc/ld.so.preload + +%package -n ubsan-runtime-env +Summary: UBSan runtime environment for target device +Group: Development/Libraries +Requires: libubsan + +%description -n ubsan-runtime-env +UBSan runtime environment + +%post -n ubsan-runtime-env +echo "%{ubsan_runtime_options}" > /UBSAN_OPTIONS + +%package -n sanitizer-sources +Summary: Sanitizer family tools sources +License: MIT +Group: Development/Tools +BuildArch: noarch + +%description -n sanitizer-sources +Sanitizer family tools sources for external tools. + +%prep + +%build + +%install +mkdir -p %buildroot%_prefix +mkdir -p %buildroot%_prefix/bin +sed -e 's|GCC_LIBSUBDIR|%{libsubdir}|' -i %{SOURCE15} + +cp %{SOURCE15} %{SOURCE16} %{SOURCE18} %{buildroot}%{_prefix}/bin +chmod a+x %{buildroot}%{_prefix}/bin/gcc-force-options +chmod a+x %{buildroot}%{_prefix}/bin/gcc-unforce-options +chmod a+x %{buildroot}%{_prefix}/bin/asan_symbolize.py + +cp %{SOURCE17} %{buildroot} +chmod 644 %{buildroot}/ASAN_OPTIONS + +%ifarch %lsan_arch +cp %{SOURCE19} %{SOURCE24} %{buildroot} +chmod 644 %{buildroot}/LSAN_OPTIONS +chmod 644 %{buildroot}/lsan.supp +%endif + +mkdir -p %{buildroot}/%{_rpmconfigdir}/tizen/ +install -m 0644 %{SOURCE21} %{buildroot}/ +install -m 0644 %{SOURCE22} %{buildroot}/%{_rpmconfigdir}/ +install -m 0755 %{SOURCE23} %{buildroot}/%{_rpmconfigdir}/tizen/ + +%files +#%manifest gcc-contrib.manifest + +%files -n asan-force-options +%defattr(-,root,root,-) +%{_prefix}/bin/gcc-force-options +%{_prefix}/bin/gcc-unforce-options + +%files -n ubsan-force-options +%defattr(-,root,root,-) +%{_prefix}/bin/gcc-force-options +%{_prefix}/bin/gcc-unforce-options + +%ifarch %lsan_arch +%files -n lsan-force-options +#%manifest gcc-contrib.manifest +%defattr(-,root,root,-) +%{_prefix}/bin/gcc-force-options +%{_prefix}/bin/gcc-unforce-options +%endif + +%files -n asan-build-env +%defattr(-,root,root,-) +/ASAN_OPTIONS + +%files -n asan-runtime-env +%defattr(-,root,root,-) + +%ifarch %lsan_arch +%files -n lsan-runtime-env +%defattr(-,root,root,-) +/LSAN_OPTIONS +/lsan.supp +%endif + +%ifarch %ubsan_arch +%files -n ubsan-build-env +%defattr(-,root,root,-) +/UBSAN_OPTIONS +%{_rpmconfigdir}/macros.ubsan +%{_rpmconfigdir}/tizen/extract-ubsan-logs + +%files -n ubsan-runtime-env +%defattr(-,root,root,-) +%endif + +%files -n sanitizer-devel +%defattr(-,root,root,-) +%{_prefix}/bin/asan_symbolize.py + +%changelog diff --git a/packaging/gcc-force-options b/packaging/gcc-force-options new file mode 100644 index 0000000..5813d78 --- /dev/null +++ b/packaging/gcc-force-options @@ -0,0 +1,129 @@ +#!/bin/sh + +set -e + +if [ $# -eq 0 ]; then + cat << EOF +Syntax: + $(basename $0) OPT1 [OPT2...]" + +Example: + $(basename $0) [prepend|append] -fsanitize=address -fno-common -U_FORTIFY_SOURCE + By default flags are appending. +EOF + exit 1 +fi + +if [ $(find $(dirname $0) -name \*-real | wc -l) -gt 0 ]; then + echo >&2 "$(basename $0): directory was already processed, aborting" + exit 1 +fi + +FLAGS="" +LD_FLAGS="" + +function divide_flags { + NEED_LIB_NAME="N" + for f in "$@"; do + case $f in + -l) + NEED_LIB_NAME="Y" + ;; + + -l*) + LDFLAGS="$LDFLAGS $f" + ;; + + -Wl,*) + LDFLAGS="$LDFLAGS ${f:4}" + ;; + + *) + if [ "$NEED_LIB_NAME" = "Y" ]; then + LDFLAGS="$LDFLAGS -l$f" + NEED_LIB_NAME="N" + else + FLAGS="$FLAGS $f" + fi + esac + done +} + +case "$1" in +prepend) + shift + divide_flags $@ + PREFLAGS=$FLAGS + POSTFLAGS= + LD_PREFLAGS=$LDFLAGS + LD_POSTFLAGS= + ;; +append) + shift + divide_flags $@ + PREFLAGS= + POSTFLAGS=$FLAGS + LD_PREFLAGS= + LD_POSTFLAGS=$LDFLAGS + ;; +*) + divide_flags $@ + PREFLAGS= + POSTFLAGS=$FLAGS + LD_PREFLAGS= + LD_POSTFLAGS=$LDFLAGS + ;; +esac + +TMP=$(pwd)/tmp.$$ +cat > $TMP << EOF +#!/bin/sh +if echo "$PREFLAGS "\$@" $POSTFLAGS" | grep -q -- "-fsanitize=undefined" && echo "\$@" | grep -q "\.gch\>"; then + # UBSan doesn't support precompiled headers. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66343 + echo "Precompiled headers currently not supported by UBSan" >&2 + # Don't instrument kernel modules + # Don't instrument with "-nostdlib" linking +elif ! echo "\$@" | grep -q -e __KERNEL__ -e \-nostdlib; then + # Use readlink in order to follow symlinks if any + \$(readlink -f \$0)-real $PREFLAGS "\$@" $POSTFLAGS +else + # -Wl,--tizen-no-force-options is used to tell collect2 to not add force + # options. It will be removed in collect2. + \$(readlink -f \$0)-real "\$@" -Wl,--tizen-no-force-options +fi +EOF +chmod +x $TMP + +find -L $(dirname $0) -type f -a -perm -a=x | grep -E '(gcc|g\+\+|c\+\+)$' | while read tool; do + mv $tool $tool-real + cp $TMP $tool +done + +LD_TMP=$(pwd)/ld_tmp.$$ +cat > $LD_TMP << EOF +#!/bin/sh +if ! echo "\$@" | grep -q -e \-\-tizen\-no\-force\-options; then + # Use readlink in order to follow symlinks if any + \$(readlink -f \$0)-real $LD_PREFLAGS "\$@" $LD_POSTFLAGS +else + # Remove --tizen-no-force-options from the argument list + FLAGS=\$(echo \$@ | sed -e 's/--tizen-no-force-options//g') + \$(readlink -f \$0)-real \$FLAGS +fi +EOF +chmod +x $LD_TMP + +find -L GCC_LIBSUBDIR -type f -a -perm -a=x -name 'collect2' | while read tool; do + mv $tool $tool-real + cp $LD_TMP $tool +done + +if [ -d /emul ]; then + find -L /emul -type f -a -perm -a=x | grep -E '(gcc|g\+\+|c\+\+|collect2)$' | while read tool; do + ln -sf $(basename $tool) $tool-real + done +fi + +rm $TMP +rm $LD_TMP + diff --git a/packaging/gcc-unforce-options b/packaging/gcc-unforce-options new file mode 100644 index 0000000..7e85b75 --- /dev/null +++ b/packaging/gcc-unforce-options @@ -0,0 +1,19 @@ +#!/bin/sh + +set -e + +if [ $# -gt 0 ]; then + echo >&2 "$(basename $0): unexpected arguments" + exit 1 +fi + +find $(dirname $0) /usr/*/gcc -name \*-real | while read tool_real; do + tool=$(echo "$tool_real" | sed -e 's/-real$//') + mv $tool_real $tool +done +if [ -d /emul ]; then + find /emul -name \*-real | while read tool_real; do + rm $tool_real + done +fi + diff --git a/packaging/lsan.supp b/packaging/lsan.supp new file mode 100644 index 0000000..7189406 --- /dev/null +++ b/packaging/lsan.supp @@ -0,0 +1 @@ +leak:g_hash_table_new_full diff --git a/packaging/macros.ubsan b/packaging/macros.ubsan new file mode 100644 index 0000000..652a49b --- /dev/null +++ b/packaging/macros.ubsan @@ -0,0 +1,39 @@ +# /etc/rpm/macros.ubsan + +%_enable_ubsan_packages 1 + +%__ubsan_install_post %{_rpmconfigdir}/tizen/extract-ubsan-logs + +# See original macro (before expansion) and correct lines after the first one. +# Mine is from Fedora RPM macros, YMMV. +%__spec_install_post\ + %{?__ubsan_package:%{__ubsan_install_post}}\ + %{?__debug_package:%{__debug_install_post}}\ + %{__arch_install_post}\ + %{__os_install_post}\ +%{nil} + +# Same goes here, see your original macro. +%install %{?_enable_ubsan_packages:%{ubsan_package}}\ +%{?_enable_debug_packages:%{debug_package}}\ +%%install\ +LANG=C\ +export LANG\ +unset DISPLAY\ +rm -rf %{?buildroot:%{buildroot}} \ +mkdir -p %{?buildroot:%{buildroot}} \ +%{nil} + +# Template for ubsan logs sub-package. +%ubsan_package \ +%global __ubsan_package 1\ +%package ubsan-logs\ +Summary: UBSan logs for package %{name}\ +Group: Development/UBSan\ +AutoReqProv: 0\ +%description ubsan-logs\ +This package provides UBSan log files for package %{name}.\ +%files ubsan-logs\ +%defattr(-,root,root)\ +/usr/share/ubsan/*ubsan.log*\ +%{nil} -- 2.7.4