| Index: build/android/asan_symbolize.py
|
| diff --git a/build/android/asan_symbolize.py b/build/android/asan_symbolize.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..6111498dbe408e65f812cf64955c1c10f038e946
|
| --- /dev/null
|
| +++ b/build/android/asan_symbolize.py
|
| @@ -0,0 +1,103 @@
|
| +#!/usr/bin/env python
|
| +#
|
| +# Copyright (c) 2013 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +
|
| +import collections
|
| +import optparse
|
| +import os
|
| +import re
|
| +import sys
|
| +
|
| +from pylib import constants
|
| +
|
| +# Uses symbol.py from third_party/android_platform, not python's.
|
| +sys.path.insert(0,
|
| + os.path.join(constants.DIR_SOURCE_ROOT,
|
| + 'third_party/android_platform/development/scripts'))
|
| +import symbol
|
| +
|
| +
|
| +_RE_ASAN = re.compile(r'I/asanwrapper\.sh.*?(#\S*?) (\S*?) \((.*?)\+(.*?)\)')
|
| +
|
| +def _ParseAsanLogLine(line):
|
| + m = re.match(_RE_ASAN, line)
|
| + if not m:
|
| + return None
|
| + return {
|
| + 'library': m.group(3),
|
| + 'pos': m.group(1),
|
| + 'rel_address': '%08x' % int(m.group(4), 16),
|
| + }
|
| +
|
| +
|
| +def _FindASanLibraries():
|
| + asan_lib_dir = os.path.join(constants.DIR_SOURCE_ROOT,
|
| + 'third_party', 'llvm-build',
|
| + 'Release+Asserts', 'lib')
|
| + asan_libs = []
|
| + for src_dir, _, files in os.walk(asan_lib_dir):
|
| + asan_libs += [os.path.relpath(os.path.join(src_dir, f))
|
| + for f in files
|
| + if f.endswith('.so')]
|
| + return asan_libs
|
| +
|
| +
|
| +def _TranslateLibPath(library, asan_libs):
|
| + for asan_lib in asan_libs:
|
| + if os.path.basename(library) == os.path.basename(asan_lib):
|
| + return '/' + asan_lib
|
| + return symbol.TranslateLibPath(library)
|
| +
|
| +
|
| +def _Symbolize(input):
|
| + asan_libs = _FindASanLibraries()
|
| + libraries = collections.defaultdict(list)
|
| + asan_lines = []
|
| + for asan_log_line in [a.strip() for a in input]:
|
| + m = _ParseAsanLogLine(asan_log_line)
|
| + if m:
|
| + libraries[m['library']].append(m)
|
| + asan_lines.append({'raw_log': asan_log_line, 'parsed': m})
|
| +
|
| + all_symbols = collections.defaultdict(dict)
|
| + original_symbols_dir = symbol.SYMBOLS_DIR
|
| + for library, items in libraries.iteritems():
|
| + libname = _TranslateLibPath(library, asan_libs)
|
| + lib_relative_addrs = set([i['rel_address'] for i in items])
|
| + info_dict = symbol.SymbolInformationForSet(libname,
|
| + lib_relative_addrs,
|
| + True)
|
| + if info_dict:
|
| + all_symbols[library]['symbols'] = info_dict
|
| +
|
| + for asan_log_line in asan_lines:
|
| + m = asan_log_line['parsed']
|
| + if not m:
|
| + print asan_log_line['raw_log']
|
| + continue
|
| + if (m['library'] in all_symbols and
|
| + m['rel_address'] in all_symbols[m['library']]['symbols']):
|
| + s = all_symbols[m['library']]['symbols'][m['rel_address']][0]
|
| + print s[0], s[1], s[2]
|
| + else:
|
| + print asan_log_line['raw_log']
|
| +
|
| +
|
| +def main():
|
| + parser = optparse.OptionParser()
|
| + parser.add_option('-l', '--logcat',
|
| + help='File containing adb logcat output with ASan stacks. '
|
| + 'Use stdin if not specified.')
|
| + options, args = parser.parse_args()
|
| + if options.logcat:
|
| + input = file(options.logcat, 'r')
|
| + else:
|
| + input = sys.stdin
|
| + _Symbolize(input.readlines())
|
| +
|
| +
|
| +if __name__ == "__main__":
|
| + sys.exit(main())
|
|
|