| Index: tools/valgrind/asan/third_party/asan_symbolize.py
|
| diff --git a/tools/valgrind/asan/third_party/asan_symbolize.py b/tools/valgrind/asan/third_party/asan_symbolize.py
|
| index 59fceaaed814c031fc08ea301f146cfe862a3e8a..1a56e44127c1e507eb31f6cd1df573183adf14e0 100755
|
| --- a/tools/valgrind/asan/third_party/asan_symbolize.py
|
| +++ b/tools/valgrind/asan/third_party/asan_symbolize.py
|
| @@ -23,6 +23,8 @@ sysroot_path = None
|
| binary_name_filter = None
|
| fix_filename_patterns = None
|
| logfile = sys.stdin
|
| +allow_system_symbolizer = True
|
| +force_system_symbolizer = False
|
|
|
| # FIXME: merge the code that calls fix_filename().
|
| def fix_filename(file_name):
|
| @@ -36,6 +38,10 @@ def fix_filename(file_name):
|
| def sysroot_path_filter(binary_name):
|
| return sysroot_path + binary_name
|
|
|
| +def is_valid_arch(s):
|
| + return s in ["i386", "x86_64", "x86_64h", "arm", "armv6", "armv7", "armv7s",
|
| + "armv7k", "arm64", "powerpc64", "powerpc64le", "s390x", "s390"]
|
| +
|
| def guess_arch(addr):
|
| # Guess which arch we're running. 10 = len('0x') + 8 hex digits.
|
| if len(addr) > 10:
|
| @@ -76,17 +82,19 @@ class LLVMSymbolizer(Symbolizer):
|
| cmd = [self.symbolizer_path,
|
| '--use-symbol-table=true',
|
| '--demangle=%s' % demangle,
|
| - '--functions=short',
|
| + '--functions=linkage',
|
| '--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)
|
| + print(' '.join(cmd))
|
| try:
|
| result = subprocess.Popen(cmd, stdin=subprocess.PIPE,
|
| - stdout=subprocess.PIPE)
|
| + stdout=subprocess.PIPE,
|
| + bufsize=0,
|
| + universal_newlines=True)
|
| except OSError:
|
| result = None
|
| return result
|
| @@ -99,8 +107,8 @@ class LLVMSymbolizer(Symbolizer):
|
| try:
|
| symbolizer_input = '"%s" %s' % (binary, offset)
|
| if DEBUG:
|
| - print symbolizer_input
|
| - print >> self.pipe.stdin, symbolizer_input
|
| + print(symbolizer_input)
|
| + self.pipe.stdin.write("%s\n" % symbolizer_input)
|
| while True:
|
| function_name = self.pipe.stdout.readline().rstrip()
|
| if not function_name:
|
| @@ -134,34 +142,44 @@ class Addr2LineSymbolizer(Symbolizer):
|
| super(Addr2LineSymbolizer, self).__init__()
|
| self.binary = binary
|
| self.pipe = self.open_addr2line()
|
| + self.output_terminator = -1
|
|
|
| def open_addr2line(self):
|
| addr2line_tool = 'addr2line'
|
| if binutils_prefix:
|
| addr2line_tool = binutils_prefix + addr2line_tool
|
| - cmd = [addr2line_tool, '-f']
|
| + cmd = [addr2line_tool, '-fi']
|
| if demangle:
|
| cmd += ['--demangle']
|
| cmd += ['-e', self.binary]
|
| if DEBUG:
|
| - print ' '.join(cmd)
|
| + print(' '.join(cmd))
|
| return subprocess.Popen(cmd,
|
| - stdin=subprocess.PIPE, stdout=subprocess.PIPE)
|
| + stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
| + bufsize=0,
|
| + universal_newlines=True)
|
|
|
| def symbolize(self, addr, binary, offset):
|
| """Overrides Symbolizer.symbolize."""
|
| if self.binary != binary:
|
| return None
|
| + lines = []
|
| try:
|
| - print >> self.pipe.stdin, offset
|
| - function_name = self.pipe.stdout.readline().rstrip()
|
| - file_name = self.pipe.stdout.readline().rstrip()
|
| + self.pipe.stdin.write("%s\n" % offset)
|
| + self.pipe.stdin.write("%s\n" % self.output_terminator)
|
| + is_first_frame = True
|
| + while True:
|
| + function_name = self.pipe.stdout.readline().rstrip()
|
| + file_name = self.pipe.stdout.readline().rstrip()
|
| + if is_first_frame:
|
| + is_first_frame = False
|
| + elif function_name in ['', '??']:
|
| + assert file_name == function_name
|
| + break
|
| + lines.append((function_name, file_name));
|
| except Exception:
|
| - function_name = ''
|
| - file_name = ''
|
| - file_name = fix_filename(file_name)
|
| - return ['%s in %s %s' % (addr, function_name, file_name)]
|
| -
|
| + lines.append(('??', '??:0'))
|
| + return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines]
|
|
|
| class UnbufferedLineConverter(object):
|
| """
|
| @@ -197,15 +215,15 @@ class UnbufferedLineConverter(object):
|
|
|
|
|
| class DarwinSymbolizer(Symbolizer):
|
| - def __init__(self, addr, binary):
|
| + def __init__(self, addr, binary, arch):
|
| super(DarwinSymbolizer, self).__init__()
|
| self.binary = binary
|
| - self.arch = guess_arch(addr)
|
| + self.arch = arch
|
| self.open_atos()
|
|
|
| def open_atos(self):
|
| if DEBUG:
|
| - print 'atos -o %s -arch %s' % (self.binary, self.arch)
|
| + 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)
|
|
|
| @@ -220,7 +238,7 @@ class DarwinSymbolizer(Symbolizer):
|
| # foo(type1, type2) (in object.name) (filename.cc:80)
|
| match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line)
|
| if DEBUG:
|
| - print 'atos_line: ', atos_line
|
| + print('atos_line: ', atos_line)
|
| if match:
|
| function_name = match.group(1)
|
| function_name = re.sub('\(.*?\)', '', function_name)
|
| @@ -259,10 +277,10 @@ def BreakpadSymbolizerFactory(binary):
|
| return None
|
|
|
|
|
| -def SystemSymbolizerFactory(system, addr, binary):
|
| +def SystemSymbolizerFactory(system, addr, binary, arch):
|
| if system == 'Darwin':
|
| - return DarwinSymbolizer(addr, binary)
|
| - elif system == 'Linux':
|
| + return DarwinSymbolizer(addr, binary, arch)
|
| + elif system == 'Linux' or system == 'FreeBSD':
|
| return Addr2LineSymbolizer(binary)
|
|
|
|
|
| @@ -334,7 +352,7 @@ class BreakpadSymbolizer(Symbolizer):
|
| function_name, file_name, line_no = res
|
| result = ['%s in %s %s:%d' % (
|
| addr, function_name, file_name, line_no)]
|
| - print result
|
| + print(result)
|
| return result
|
| else:
|
| return None
|
| @@ -360,7 +378,7 @@ class SymbolizationLoop(object):
|
| self.frame_no = 0
|
| self.process_line = self.process_line_posix
|
|
|
| - def symbolize_address(self, addr, binary, offset):
|
| + def symbolize_address(self, addr, binary, offset, arch):
|
| # 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:
|
| @@ -372,29 +390,35 @@ class SymbolizationLoop(object):
|
| # 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:
|
| + result = None
|
| + if not force_system_symbolizer:
|
| + 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, arch, self.dsym_hints)
|
| 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)
|
| + # 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)
|
| + else:
|
| + symbolizers[binary] = ChainSymbolizer([])
|
| if result is None:
|
| + if not allow_system_symbolizer:
|
| + raise Exception('Failed to launch or use llvm-symbolizer.')
|
| # Initialize system symbolizer only if other symbolizers failed.
|
| symbolizers[binary].append_symbolizer(
|
| - SystemSymbolizerFactory(self.system, addr, binary))
|
| + SystemSymbolizerFactory(self.system, addr, binary, arch))
|
| result = symbolizers[binary].symbolize(addr, binary, offset)
|
| # The system symbolizer must produce some result.
|
| assert result
|
| @@ -414,7 +438,7 @@ class SymbolizationLoop(object):
|
| self.frame_no = 0
|
| for line in logfile:
|
| processed = self.process_line(line)
|
| - print '\n'.join(processed)
|
| + print('\n'.join(processed))
|
|
|
| def process_line_echo(self, line):
|
| return [line.rstrip()]
|
| @@ -428,18 +452,28 @@ class SymbolizationLoop(object):
|
| if not match:
|
| return [self.current_line]
|
| if DEBUG:
|
| - print line
|
| + print(line)
|
| _, frameno_str, addr, binary, offset = match.groups()
|
| + arch = ""
|
| + # Arch can be embedded in the filename, e.g.: "libabc.dylib:x86_64h"
|
| + colon_pos = binary.rfind(":")
|
| + if colon_pos != -1:
|
| + maybe_arch = binary[colon_pos+1:]
|
| + if is_valid_arch(maybe_arch):
|
| + arch = maybe_arch
|
| + binary = binary[0:colon_pos]
|
| + if arch == "":
|
| + arch = guess_arch(addr)
|
| 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)
|
| - symbolized_line = self.symbolize_address(addr, binary, offset)
|
| + symbolized_line = self.symbolize_address(addr, binary, offset, arch)
|
| if not symbolized_line:
|
| if original_binary != binary:
|
| - symbolized_line = self.symbolize_address(addr, binary, offset)
|
| + symbolized_line = self.symbolize_address(addr, binary, offset, arch)
|
| return self.get_symbolized_lines(symbolized_line)
|
|
|
|
|
| @@ -461,6 +495,8 @@ if __name__ == '__main__':
|
| 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('--force-system-symbolizer', action='store_true',
|
| + help='don\'t use llvm-symbolizer')
|
| args = parser.parse_args()
|
| if args.path_to_cut:
|
| fix_filename_patterns = args.path_to_cut
|
| @@ -475,5 +511,9 @@ if __name__ == '__main__':
|
| logfile = args.logfile
|
| else:
|
| logfile = sys.stdin
|
| + if args.force_system_symbolizer:
|
| + force_system_symbolizer = True
|
| + if force_system_symbolizer:
|
| + assert(allow_system_symbolizer)
|
| loop = SymbolizationLoop(binary_name_filter)
|
| loop.process_logfile()
|
|
|