Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / build / android / asan_symbolize.py
1 #!/usr/bin/env python
2 #
3 # Copyright 2013 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file.
6
7
8 import collections
9 import optparse
10 import os
11 import re
12 import sys
13
14 from pylib import constants
15
16 # Uses symbol.py from third_party/android_platform, not python's.
17 sys.path.insert(0,
18                 os.path.join(constants.DIR_SOURCE_ROOT,
19                             'third_party/android_platform/development/scripts'))
20 import symbol
21
22
23 _RE_ASAN = re.compile(r'(.*?)(#\S*?) (\S*?) \((.*?)\+(.*?)\)')
24
25 def _ParseAsanLogLine(line):
26   m = re.match(_RE_ASAN, line)
27   if not m:
28     return None
29   return {
30       'prefix': m.group(1),
31       'library': m.group(4),
32       'pos': m.group(2),
33       'rel_address': '%08x' % int(m.group(5), 16),
34   }
35
36
37 def _FindASanLibraries():
38   asan_lib_dir = os.path.join(constants.DIR_SOURCE_ROOT,
39                               'third_party', 'llvm-build',
40                               'Release+Asserts', 'lib')
41   asan_libs = []
42   for src_dir, _, files in os.walk(asan_lib_dir):
43     asan_libs += [os.path.relpath(os.path.join(src_dir, f))
44                   for f in files
45                   if f.endswith('.so')]
46   return asan_libs
47
48
49 def _TranslateLibPath(library, asan_libs):
50   for asan_lib in asan_libs:
51     if os.path.basename(library) == os.path.basename(asan_lib):
52       return '/' + asan_lib
53   return symbol.TranslateLibPath(library)
54
55
56 def _Symbolize(input):
57   asan_libs = _FindASanLibraries()
58   libraries = collections.defaultdict(list)
59   asan_lines = []
60   for asan_log_line in [a.rstrip() for a in input]:
61     m = _ParseAsanLogLine(asan_log_line)
62     if m:
63       libraries[m['library']].append(m)
64     asan_lines.append({'raw_log': asan_log_line, 'parsed': m})
65
66   all_symbols = collections.defaultdict(dict)
67   original_symbols_dir = symbol.SYMBOLS_DIR
68   for library, items in libraries.iteritems():
69     libname = _TranslateLibPath(library, asan_libs)
70     lib_relative_addrs = set([i['rel_address'] for i in items])
71     info_dict = symbol.SymbolInformationForSet(libname,
72                                                lib_relative_addrs,
73                                                True)
74     if info_dict:
75       all_symbols[library]['symbols'] = info_dict
76
77   for asan_log_line in asan_lines:
78     m = asan_log_line['parsed']
79     if not m:
80       print asan_log_line['raw_log']
81       continue
82     if (m['library'] in all_symbols and
83         m['rel_address'] in all_symbols[m['library']]['symbols']):
84       s = all_symbols[m['library']]['symbols'][m['rel_address']][0]
85       print '%s%s %s %s' %(m['prefix'], m['pos'], s[0], s[1])
86     else:
87       print asan_log_line['raw_log']
88
89
90 def main():
91   parser = optparse.OptionParser()
92   parser.add_option('-l', '--logcat',
93                     help='File containing adb logcat output with ASan stacks. '
94                          'Use stdin if not specified.')
95   options, args = parser.parse_args()
96   if options.logcat:
97     input = file(options.logcat, 'r')
98   else:
99     input = sys.stdin
100   _Symbolize(input.readlines())
101
102
103 if __name__ == "__main__":
104   sys.exit(main())