17dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#!/usr/bin/env python
27dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#
37dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Copyright 2013 The Chromium Authors. All rights reserved.
47dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Use of this source code is governed by a BSD-style license that can be
57dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# found in the LICENSE file.
67dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
77dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
87dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport collections
97dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport optparse
107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport os
117dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport re
127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport sys
137dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochfrom pylib import constants
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
167dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch# Uses symbol.py from third_party/android_platform, not python's.
177dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochsys.path.insert(0,
187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                os.path.join(constants.DIR_SOURCE_ROOT,
197dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                            'third_party/android_platform/development/scripts'))
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochimport symbol
217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)_RE_ASAN = re.compile(r'(.*?)(#\S*?) (\S*?) \((.*?)\+(.*?)\)')
247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef _ParseAsanLogLine(line):
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  m = re.match(_RE_ASAN, line)
277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if not m:
287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return None
297dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return {
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      'prefix': m.group(1),
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      'library': m.group(4),
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      'pos': m.group(2),
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      'rel_address': '%08x' % int(m.group(5), 16),
347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
357dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
367dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef _FindASanLibraries():
387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  asan_lib_dir = os.path.join(constants.DIR_SOURCE_ROOT,
397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                              'third_party', 'llvm-build',
407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                              'Release+Asserts', 'lib')
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  asan_libs = []
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for src_dir, _, files in os.walk(asan_lib_dir):
437dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    asan_libs += [os.path.relpath(os.path.join(src_dir, f))
447dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  for f in files
457dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                  if f.endswith('.so')]
467dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return asan_libs
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef _TranslateLibPath(library, asan_libs):
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for asan_lib in asan_libs:
517dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if os.path.basename(library) == os.path.basename(asan_lib):
527dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      return '/' + asan_lib
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return symbol.TranslateLibPath(library)
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochdef _Symbolize(asan_input):
577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  asan_libs = _FindASanLibraries()
587dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  libraries = collections.defaultdict(list)
597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  asan_lines = []
60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  for asan_log_line in [a.rstrip() for a in asan_input]:
617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    m = _ParseAsanLogLine(asan_log_line)
627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if m:
637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      libraries[m['library']].append(m)
647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    asan_lines.append({'raw_log': asan_log_line, 'parsed': m})
657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  all_symbols = collections.defaultdict(dict)
677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for library, items in libraries.iteritems():
687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    libname = _TranslateLibPath(library, asan_libs)
697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    lib_relative_addrs = set([i['rel_address'] for i in items])
707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    info_dict = symbol.SymbolInformationForSet(libname,
717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               lib_relative_addrs,
727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                               True)
737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if info_dict:
747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      all_symbols[library]['symbols'] = info_dict
757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
767dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for asan_log_line in asan_lines:
777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    m = asan_log_line['parsed']
787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if not m:
797dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      print asan_log_line['raw_log']
807dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      continue
817dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (m['library'] in all_symbols and
827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        m['rel_address'] in all_symbols[m['library']]['symbols']):
837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      s = all_symbols[m['library']]['symbols'][m['rel_address']][0]
84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      print '%s%s %s %s' % (m['prefix'], m['pos'], s[0], s[1])
857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    else:
867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      print asan_log_line['raw_log']
877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochdef main():
907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  parser = optparse.OptionParser()
917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  parser.add_option('-l', '--logcat',
927dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                    help='File containing adb logcat output with ASan stacks. '
937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                         'Use stdin if not specified.')
94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  options, _ = parser.parse_args()
957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  if options.logcat:
96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    asan_input = file(options.logcat, 'r')
977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  else:
98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    asan_input = sys.stdin
99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  _Symbolize(asan_input.readlines())
1007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
1027dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochif __name__ == "__main__":
1037dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  sys.exit(main())
104