Updated script asan_symbolize.py.
--HG-- branch : develop
This commit is contained in:
parent
ce720450f0
commit
2e25a12b91
|
@ -11,11 +11,9 @@ import argparse
|
||||||
import bisect
|
import bisect
|
||||||
import getopt
|
import getopt
|
||||||
import os
|
import os
|
||||||
import pty
|
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import termios
|
|
||||||
|
|
||||||
symbolizers = {}
|
symbolizers = {}
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
|
@ -25,6 +23,7 @@ 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
|
||||||
|
|
||||||
# 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):
|
||||||
|
@ -78,7 +77,7 @@ 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':
|
||||||
|
@ -136,12 +135,13 @@ 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]
|
||||||
|
@ -154,16 +154,23 @@ class Addr2LineSymbolizer(Symbolizer):
|
||||||
"""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
|
print >> self.pipe.stdin, offset
|
||||||
function_name = self.pipe.stdout.readline().rstrip()
|
print >> self.pipe.stdin, self.output_terminator
|
||||||
file_name = self.pipe.stdout.readline().rstrip()
|
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:
|
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):
|
||||||
"""
|
"""
|
||||||
|
@ -171,6 +178,9 @@ class UnbufferedLineConverter(object):
|
||||||
output. Uses pty to trick the child into providing unbuffered output.
|
output. Uses pty to trick the child into providing unbuffered output.
|
||||||
"""
|
"""
|
||||||
def __init__(self, args, close_stderr=False):
|
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()
|
pid, fd = pty.fork()
|
||||||
if pid == 0:
|
if pid == 0:
|
||||||
# We're the child. Transfer control to command.
|
# We're the child. Transfer control to command.
|
||||||
|
@ -261,7 +271,7 @@ def BreakpadSymbolizerFactory(binary):
|
||||||
def SystemSymbolizerFactory(system, addr, binary):
|
def SystemSymbolizerFactory(system, addr, binary):
|
||||||
if system == 'Darwin':
|
if system == 'Darwin':
|
||||||
return DarwinSymbolizer(addr, binary)
|
return DarwinSymbolizer(addr, binary)
|
||||||
elif system == 'Linux':
|
elif system == 'Linux' or system == 'FreeBSD':
|
||||||
return Addr2LineSymbolizer(binary)
|
return Addr2LineSymbolizer(binary)
|
||||||
|
|
||||||
|
|
||||||
|
@ -341,17 +351,23 @@ class BreakpadSymbolizer(Symbolizer):
|
||||||
|
|
||||||
class SymbolizationLoop(object):
|
class SymbolizationLoop(object):
|
||||||
def __init__(self, binary_name_filter=None, dsym_hint_producer=None):
|
def __init__(self, binary_name_filter=None, dsym_hint_producer=None):
|
||||||
# Used by clients who may want to supply a different binary name.
|
if sys.platform == 'win32':
|
||||||
# E.g. in Chrome several binaries may share a single .dSYM.
|
# ASan on Windows uses dbghelp.dll to symbolize in-process, which works
|
||||||
self.binary_name_filter = binary_name_filter
|
# even in sandboxed processes. Nothing needs to be done here.
|
||||||
self.dsym_hint_producer = dsym_hint_producer
|
self.process_line = self.process_line_echo
|
||||||
self.system = os.uname()[0]
|
else:
|
||||||
if self.system not in ['Linux', 'Darwin', 'FreeBSD']:
|
# Used by clients who may want to supply a different binary name.
|
||||||
raise Exception('Unknown system')
|
# E.g. in Chrome several binaries may share a single .dSYM.
|
||||||
self.llvm_symbolizers = {}
|
self.binary_name_filter = binary_name_filter
|
||||||
self.last_llvm_symbolizer = None
|
self.dsym_hint_producer = dsym_hint_producer
|
||||||
self.dsym_hints = set([])
|
self.system = os.uname()[0]
|
||||||
self.frame_no = 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):
|
def symbolize_address(self, addr, binary, offset):
|
||||||
# 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
|
||||||
|
@ -385,6 +401,8 @@ class SymbolizationLoop(object):
|
||||||
[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)
|
||||||
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))
|
||||||
|
@ -405,14 +423,14 @@ class SymbolizationLoop(object):
|
||||||
|
|
||||||
def process_logfile(self):
|
def process_logfile(self):
|
||||||
self.frame_no = 0
|
self.frame_no = 0
|
||||||
while True:
|
for line in logfile:
|
||||||
line = logfile.readline()
|
|
||||||
if not line:
|
|
||||||
break
|
|
||||||
processed = self.process_line(line)
|
processed = self.process_line(line)
|
||||||
print '\n'.join(processed)
|
print '\n'.join(processed)
|
||||||
|
|
||||||
def process_line(self, line):
|
def process_line_echo(self, line):
|
||||||
|
return [line.rstrip()]
|
||||||
|
|
||||||
|
def process_line_posix(self, line):
|
||||||
self.current_line = line.rstrip()
|
self.current_line = line.rstrip()
|
||||||
#0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45)
|
#0 0x7f6e35cf2e45 (/blah/foo.so+0x11fe45)
|
||||||
stack_trace_line_format = (
|
stack_trace_line_format = (
|
||||||
|
@ -437,20 +455,23 @@ class SymbolizationLoop(object):
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
parser = argparse.ArgumentParser(
|
||||||
description='ASan symbolization script',
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
epilog='''Example of use:
|
description='ASan symbolization script',
|
||||||
asan_symbolize.py -c "$HOME/opt/cross/bin/arm-linux-gnueabi-" -s "$HOME/SymbolFiles" < asan.log''')
|
epilog='Example of use:\n'
|
||||||
|
'asan_symbolize.py -c "$HOME/opt/cross/bin/arm-linux-gnueabi-" '
|
||||||
|
'-s "$HOME/SymbolFiles" < asan.log')
|
||||||
parser.add_argument('path_to_cut', nargs='*',
|
parser.add_argument('path_to_cut', nargs='*',
|
||||||
help='pattern to be cut from the result file path ')
|
help='pattern to be cut from the result file path ')
|
||||||
parser.add_argument('-d','--demangle', action='store_true',
|
parser.add_argument('-d','--demangle', action='store_true',
|
||||||
help='demangle function names')
|
help='demangle function names')
|
||||||
parser.add_argument('-s', metavar='SYSROOT',
|
parser.add_argument('-s', metavar='SYSROOT',
|
||||||
help='set path to sysroot for sanitized binaries')
|
help='set path to sysroot for sanitized binaries')
|
||||||
parser.add_argument('-c', metavar='CROSS_COMPILE',
|
parser.add_argument('-c', metavar='CROSS_COMPILE',
|
||||||
help='set prefix for binutils')
|
help='set prefix for binutils')
|
||||||
parser.add_argument('-l','--logfile', default=sys.stdin, type=argparse.FileType('r'),
|
parser.add_argument('-l','--logfile', default=sys.stdin,
|
||||||
help='set log file name to parse, default is stdin')
|
type=argparse.FileType('r'),
|
||||||
|
help='set log file name to parse, default is stdin')
|
||||||
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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user