Commit 75865e43 authored by thakis's avatar thakis Committed by Commit bot

Roll tools/valgrind/asan/third_party/asan_symbolize.py 227327:294450

The ASan runtime recently changed to print slice information in
stacks (https://reviews.llvm.org/D27390). The last clang roll included
that change.

The upstream asan_symbolize script was changed to be able to understand
slice information in https://reviews.llvm.org/rL291280. We need to
merge in that change to make symbolizing asan stacks work again on Mac.

This roll brings in the following changes:
https://reviews.llvm.org/rL294450
https://reviews.llvm.org/rL294303
https://reviews.llvm.org/rL291280
https://reviews.llvm.org/rL256578
https://reviews.llvm.org/rL251356
https://reviews.llvm.org/rL248962
https://reviews.llvm.org/rL247642
https://reviews.llvm.org/rL231492

BUG=686113,699062

Review-Url: https://codereview.chromium.org/2739213005
Cr-Commit-Position: refs/heads/master@{#456195}
parent b833579e
...@@ -23,6 +23,8 @@ sysroot_path = None ...@@ -23,6 +23,8 @@ sysroot_path = None
binary_name_filter = None binary_name_filter = None
fix_filename_patterns = None fix_filename_patterns = None
logfile = sys.stdin logfile = sys.stdin
allow_system_symbolizer = True
force_system_symbolizer = False
# FIXME: merge the code that calls fix_filename(). # FIXME: merge the code that calls fix_filename().
def fix_filename(file_name): def fix_filename(file_name):
...@@ -36,6 +38,10 @@ def fix_filename(file_name): ...@@ -36,6 +38,10 @@ def fix_filename(file_name):
def sysroot_path_filter(binary_name): def sysroot_path_filter(binary_name):
return sysroot_path + 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): def guess_arch(addr):
# Guess which arch we're running. 10 = len('0x') + 8 hex digits. # Guess which arch we're running. 10 = len('0x') + 8 hex digits.
if len(addr) > 10: if len(addr) > 10:
...@@ -76,17 +82,19 @@ class LLVMSymbolizer(Symbolizer): ...@@ -76,17 +82,19 @@ class LLVMSymbolizer(Symbolizer):
cmd = [self.symbolizer_path, cmd = [self.symbolizer_path,
'--use-symbol-table=true', '--use-symbol-table=true',
'--demangle=%s' % demangle, '--demangle=%s' % demangle,
'--functions=short', '--functions=linkage',
'--inlining=true', '--inlining=true',
'--default-arch=%s' % self.default_arch] '--default-arch=%s' % self.default_arch]
if self.system == 'Darwin': if self.system == 'Darwin':
for hint in self.dsym_hints: for hint in self.dsym_hints:
cmd.append('--dsym-hint=%s' % hint) cmd.append('--dsym-hint=%s' % hint)
if DEBUG: if DEBUG:
print ' '.join(cmd) print(' '.join(cmd))
try: try:
result = subprocess.Popen(cmd, stdin=subprocess.PIPE, result = subprocess.Popen(cmd, stdin=subprocess.PIPE,
stdout=subprocess.PIPE) stdout=subprocess.PIPE,
bufsize=0,
universal_newlines=True)
except OSError: except OSError:
result = None result = None
return result return result
...@@ -99,8 +107,8 @@ class LLVMSymbolizer(Symbolizer): ...@@ -99,8 +107,8 @@ class LLVMSymbolizer(Symbolizer):
try: try:
symbolizer_input = '"%s" %s' % (binary, offset) symbolizer_input = '"%s" %s' % (binary, offset)
if DEBUG: if DEBUG:
print symbolizer_input print(symbolizer_input)
print >> self.pipe.stdin, symbolizer_input self.pipe.stdin.write("%s\n" % symbolizer_input)
while True: while True:
function_name = self.pipe.stdout.readline().rstrip() function_name = self.pipe.stdout.readline().rstrip()
if not function_name: if not function_name:
...@@ -134,34 +142,44 @@ class Addr2LineSymbolizer(Symbolizer): ...@@ -134,34 +142,44 @@ class Addr2LineSymbolizer(Symbolizer):
super(Addr2LineSymbolizer, self).__init__() super(Addr2LineSymbolizer, self).__init__()
self.binary = binary self.binary = binary
self.pipe = self.open_addr2line() self.pipe = self.open_addr2line()
self.output_terminator = -1
def open_addr2line(self): def open_addr2line(self):
addr2line_tool = 'addr2line' addr2line_tool = 'addr2line'
if binutils_prefix: if binutils_prefix:
addr2line_tool = binutils_prefix + addr2line_tool addr2line_tool = binutils_prefix + addr2line_tool
cmd = [addr2line_tool, '-f'] cmd = [addr2line_tool, '-fi']
if demangle: if demangle:
cmd += ['--demangle'] cmd += ['--demangle']
cmd += ['-e', self.binary] cmd += ['-e', self.binary]
if DEBUG: if DEBUG:
print ' '.join(cmd) print(' '.join(cmd))
return subprocess.Popen(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): def symbolize(self, addr, binary, offset):
"""Overrides Symbolizer.symbolize.""" """Overrides Symbolizer.symbolize."""
if self.binary != binary: if self.binary != binary:
return None return None
lines = []
try: try:
print >> self.pipe.stdin, offset 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() function_name = self.pipe.stdout.readline().rstrip()
file_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: except Exception:
function_name = '' lines.append(('??', '??:0'))
file_name = '' return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines]
file_name = fix_filename(file_name)
return ['%s in %s %s' % (addr, function_name, file_name)]
class UnbufferedLineConverter(object): class UnbufferedLineConverter(object):
""" """
...@@ -197,15 +215,15 @@ class UnbufferedLineConverter(object): ...@@ -197,15 +215,15 @@ class UnbufferedLineConverter(object):
class DarwinSymbolizer(Symbolizer): class DarwinSymbolizer(Symbolizer):
def __init__(self, addr, binary): def __init__(self, addr, binary, arch):
super(DarwinSymbolizer, self).__init__() super(DarwinSymbolizer, self).__init__()
self.binary = binary self.binary = binary
self.arch = guess_arch(addr) self.arch = arch
self.open_atos() self.open_atos()
def open_atos(self): def open_atos(self):
if DEBUG: 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] cmdline = ['atos', '-o', self.binary, '-arch', self.arch]
self.atos = UnbufferedLineConverter(cmdline, close_stderr=True) self.atos = UnbufferedLineConverter(cmdline, close_stderr=True)
...@@ -220,7 +238,7 @@ class DarwinSymbolizer(Symbolizer): ...@@ -220,7 +238,7 @@ class DarwinSymbolizer(Symbolizer):
# foo(type1, type2) (in object.name) (filename.cc:80) # foo(type1, type2) (in object.name) (filename.cc:80)
match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line) match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line)
if DEBUG: if DEBUG:
print 'atos_line: ', atos_line print('atos_line: ', atos_line)
if match: if match:
function_name = match.group(1) function_name = match.group(1)
function_name = re.sub('\(.*?\)', '', function_name) function_name = re.sub('\(.*?\)', '', function_name)
...@@ -259,10 +277,10 @@ def BreakpadSymbolizerFactory(binary): ...@@ -259,10 +277,10 @@ def BreakpadSymbolizerFactory(binary):
return None return None
def SystemSymbolizerFactory(system, addr, binary): def SystemSymbolizerFactory(system, addr, binary, arch):
if system == 'Darwin': if system == 'Darwin':
return DarwinSymbolizer(addr, binary) return DarwinSymbolizer(addr, binary, arch)
elif system == 'Linux': elif system == 'Linux' or system == 'FreeBSD':
return Addr2LineSymbolizer(binary) return Addr2LineSymbolizer(binary)
...@@ -334,7 +352,7 @@ class BreakpadSymbolizer(Symbolizer): ...@@ -334,7 +352,7 @@ class BreakpadSymbolizer(Symbolizer):
function_name, file_name, line_no = res function_name, file_name, line_no = res
result = ['%s in %s %s:%d' % ( result = ['%s in %s %s:%d' % (
addr, function_name, file_name, line_no)] addr, function_name, file_name, line_no)]
print result print(result)
return result return result
else: else:
return None return None
...@@ -360,7 +378,7 @@ class SymbolizationLoop(object): ...@@ -360,7 +378,7 @@ class SymbolizationLoop(object):
self.frame_no = 0 self.frame_no = 0
self.process_line = self.process_line_posix 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 # On non-Darwin (i.e. on platforms without .dSYM debug info) always use
# a single symbolizer binary. # a single symbolizer binary.
# On Darwin, if the dsym hint producer is present: # On Darwin, if the dsym hint producer is present:
...@@ -372,6 +390,8 @@ class SymbolizationLoop(object): ...@@ -372,6 +390,8 @@ class SymbolizationLoop(object):
# if so, reuse |last_llvm_symbolizer| which has the full set of hints; # if so, reuse |last_llvm_symbolizer| which has the full set of hints;
# 3. otherwise create a new symbolizer and pass all currently known # 3. otherwise create a new symbolizer and pass all currently known
# .dSYM hints to it. # .dSYM hints to it.
result = None
if not force_system_symbolizer:
if not binary in self.llvm_symbolizers: if not binary in self.llvm_symbolizers:
use_new_symbolizer = True use_new_symbolizer = True
if self.system == 'Darwin' and self.dsym_hint_producer: if self.system == 'Darwin' and self.dsym_hint_producer:
...@@ -382,7 +402,7 @@ class SymbolizationLoop(object): ...@@ -382,7 +402,7 @@ class SymbolizationLoop(object):
self.llvm_symbolizers[binary] = self.last_llvm_symbolizer self.llvm_symbolizers[binary] = self.last_llvm_symbolizer
else: else:
self.last_llvm_symbolizer = LLVMSymbolizerFactory( self.last_llvm_symbolizer = LLVMSymbolizerFactory(
self.system, guess_arch(addr), self.dsym_hints) self.system, arch, self.dsym_hints)
self.llvm_symbolizers[binary] = self.last_llvm_symbolizer self.llvm_symbolizers[binary] = self.last_llvm_symbolizer
# Use the chain of symbolizers: # Use the chain of symbolizers:
# Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos
...@@ -391,10 +411,14 @@ class SymbolizationLoop(object): ...@@ -391,10 +411,14 @@ class SymbolizationLoop(object):
symbolizers[binary] = ChainSymbolizer( symbolizers[binary] = ChainSymbolizer(
[BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]]) [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
result = symbolizers[binary].symbolize(addr, binary, offset) result = symbolizers[binary].symbolize(addr, binary, offset)
else:
symbolizers[binary] = ChainSymbolizer([])
if result is None: 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. # Initialize system symbolizer only if other symbolizers failed.
symbolizers[binary].append_symbolizer( symbolizers[binary].append_symbolizer(
SystemSymbolizerFactory(self.system, addr, binary)) SystemSymbolizerFactory(self.system, addr, binary, arch))
result = symbolizers[binary].symbolize(addr, binary, offset) result = symbolizers[binary].symbolize(addr, binary, offset)
# The system symbolizer must produce some result. # The system symbolizer must produce some result.
assert result assert result
...@@ -414,7 +438,7 @@ class SymbolizationLoop(object): ...@@ -414,7 +438,7 @@ class SymbolizationLoop(object):
self.frame_no = 0 self.frame_no = 0
for line in logfile: for line in logfile:
processed = self.process_line(line) processed = self.process_line(line)
print '\n'.join(processed) print('\n'.join(processed))
def process_line_echo(self, line): def process_line_echo(self, line):
return [line.rstrip()] return [line.rstrip()]
...@@ -428,18 +452,28 @@ class SymbolizationLoop(object): ...@@ -428,18 +452,28 @@ class SymbolizationLoop(object):
if not match: if not match:
return [self.current_line] return [self.current_line]
if DEBUG: if DEBUG:
print line print(line)
_, frameno_str, addr, binary, offset = match.groups() _, 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': if frameno_str == '0':
# Assume that frame #0 is the first frame of new stack trace. # Assume that frame #0 is the first frame of new stack trace.
self.frame_no = 0 self.frame_no = 0
original_binary = binary original_binary = binary
if self.binary_name_filter: if self.binary_name_filter:
binary = self.binary_name_filter(binary) 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 not symbolized_line:
if original_binary != binary: 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) return self.get_symbolized_lines(symbolized_line)
...@@ -461,6 +495,8 @@ if __name__ == '__main__': ...@@ -461,6 +495,8 @@ if __name__ == '__main__':
parser.add_argument('-l','--logfile', default=sys.stdin, parser.add_argument('-l','--logfile', default=sys.stdin,
type=argparse.FileType('r'), type=argparse.FileType('r'),
help='set log file name to parse, default is stdin') 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() args = parser.parse_args()
if args.path_to_cut: if args.path_to_cut:
fix_filename_patterns = args.path_to_cut fix_filename_patterns = args.path_to_cut
...@@ -475,5 +511,9 @@ if __name__ == '__main__': ...@@ -475,5 +511,9 @@ if __name__ == '__main__':
logfile = args.logfile logfile = args.logfile
else: else:
logfile = sys.stdin 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 = SymbolizationLoop(binary_name_filter)
loop.process_logfile() loop.process_logfile()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment