Re-enable index-basics-workers test to see if still times
[chromium-blink-merge.git] / tools / find_runtime_symbols / find_runtime_symbols.py
blobbed9e800b171268080c1974506ec3449f11d2353
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 """Find symbols in a binary corresponding to given runtime virtual addresses.
7 Note that source file names are treated as symbols in this script while they
8 are actually not.
9 """
11 import json
12 import logging
13 import os
14 import sys
16 from static_symbols import StaticSymbolsInFile
17 from proc_maps import ProcMaps
19 try:
20 from collections import OrderedDict # pylint: disable=E0611
21 except ImportError:
22 BASE_PATH = os.path.dirname(os.path.abspath(__file__))
23 SIMPLEJSON_PATH = os.path.join(BASE_PATH, os.pardir, os.pardir, 'third_party')
24 sys.path.insert(0, SIMPLEJSON_PATH)
25 from simplejson import OrderedDict
28 FUNCTION_SYMBOLS = 0
29 SOURCEFILE_SYMBOLS = 1
30 TYPEINFO_SYMBOLS = 2
32 _MAPS_FILENAME = 'maps'
33 _FILES_FILENAME = 'files.json'
36 class RuntimeSymbolsInProcess(object):
37 def __init__(self):
38 self._maps = None
39 self._static_symbols_in_filse = {}
41 def find_procedure(self, runtime_address):
42 for vma in self._maps.iter(ProcMaps.executable):
43 if vma.begin <= runtime_address < vma.end:
44 static_symbols = self._static_symbols_in_filse.get(vma.name)
45 if static_symbols:
46 return static_symbols.find_procedure_by_runtime_address(
47 runtime_address, vma)
48 else:
49 return None
50 return None
52 def find_sourcefile(self, runtime_address):
53 for vma in self._maps.iter(ProcMaps.executable):
54 if vma.begin <= runtime_address < vma.end:
55 static_symbols = self._static_symbols_in_filse.get(vma.name)
56 if static_symbols:
57 return static_symbols.find_sourcefile_by_runtime_address(
58 runtime_address, vma)
59 else:
60 return None
61 return None
63 def find_typeinfo(self, runtime_address):
64 for vma in self._maps.iter(ProcMaps.constants):
65 if vma.begin <= runtime_address < vma.end:
66 static_symbols = self._static_symbols_in_filse.get(vma.name)
67 if static_symbols:
68 return static_symbols.find_typeinfo_by_runtime_address(
69 runtime_address, vma)
70 else:
71 return None
72 return None
74 @staticmethod
75 def load(prepared_data_dir):
76 symbols_in_process = RuntimeSymbolsInProcess()
78 with open(os.path.join(prepared_data_dir, _MAPS_FILENAME), mode='r') as f:
79 symbols_in_process._maps = ProcMaps.load(f)
80 with open(os.path.join(prepared_data_dir, _FILES_FILENAME), mode='r') as f:
81 files = json.load(f)
83 # pylint: disable=W0212
84 for vma in symbols_in_process._maps.iter(ProcMaps.executable_and_constants):
85 file_entry = files.get(vma.name)
86 if not file_entry:
87 continue
89 static_symbols = StaticSymbolsInFile(vma.name)
91 nm_entry = file_entry.get('nm')
92 if nm_entry and nm_entry['format'] == 'bsd':
93 with open(os.path.join(prepared_data_dir, nm_entry['file']), 'r') as f:
94 static_symbols.load_nm_bsd(f, nm_entry['mangled'])
96 readelf_entry = file_entry.get('readelf-e')
97 if readelf_entry:
98 with open(os.path.join(prepared_data_dir, readelf_entry['file']),
99 'r') as f:
100 static_symbols.load_readelf_ew(f)
102 decodedline_file_entry = file_entry.get('readelf-debug-decodedline-file')
103 if decodedline_file_entry:
104 with open(os.path.join(prepared_data_dir,
105 decodedline_file_entry['file']), 'r') as f:
106 static_symbols.load_readelf_debug_decodedline_file(f)
108 symbols_in_process._static_symbols_in_filse[vma.name] = static_symbols
110 return symbols_in_process
113 def _find_runtime_function_symbols(symbols_in_process, addresses):
114 result = OrderedDict()
115 for address in addresses:
116 if isinstance(address, basestring):
117 address = int(address, 16)
118 found = symbols_in_process.find_procedure(address)
119 if found:
120 result[address] = found.name
121 else:
122 result[address] = '0x%016x' % address
123 return result
126 def _find_runtime_sourcefile_symbols(symbols_in_process, addresses):
127 result = OrderedDict()
128 for address in addresses:
129 if isinstance(address, basestring):
130 address = int(address, 16)
131 found = symbols_in_process.find_sourcefile(address)
132 if found:
133 result[address] = found
134 else:
135 result[address] = ''
136 return result
139 def _find_runtime_typeinfo_symbols(symbols_in_process, addresses):
140 result = OrderedDict()
141 for address in addresses:
142 if isinstance(address, basestring):
143 address = int(address, 16)
144 if address == 0:
145 result[address] = 'no typeinfo'
146 else:
147 found = symbols_in_process.find_typeinfo(address)
148 if found:
149 if found.startswith('typeinfo for '):
150 result[address] = found[13:]
151 else:
152 result[address] = found
153 else:
154 result[address] = '0x%016x' % address
155 return result
158 _INTERNAL_FINDERS = {
159 FUNCTION_SYMBOLS: _find_runtime_function_symbols,
160 SOURCEFILE_SYMBOLS: _find_runtime_sourcefile_symbols,
161 TYPEINFO_SYMBOLS: _find_runtime_typeinfo_symbols,
165 def find_runtime_symbols(symbol_type, symbols_in_process, addresses):
166 return _INTERNAL_FINDERS[symbol_type](symbols_in_process, addresses)
169 def main():
170 # FIX: Accept only .pre data
171 if len(sys.argv) < 2:
172 sys.stderr.write("""Usage:
173 %s /path/to/prepared_data_dir/ < addresses.txt
174 """ % sys.argv[0])
175 return 1
177 log = logging.getLogger('find_runtime_symbols')
178 log.setLevel(logging.WARN)
179 handler = logging.StreamHandler()
180 handler.setLevel(logging.WARN)
181 formatter = logging.Formatter('%(message)s')
182 handler.setFormatter(formatter)
183 log.addHandler(handler)
185 prepared_data_dir = sys.argv[1]
186 if not os.path.exists(prepared_data_dir):
187 log.warn("Nothing found: %s" % prepared_data_dir)
188 return 1
189 if not os.path.isdir(prepared_data_dir):
190 log.warn("Not a directory: %s" % prepared_data_dir)
191 return 1
193 symbols_in_process = RuntimeSymbolsInProcess.load(prepared_data_dir)
194 symbols_dict = find_runtime_symbols(FUNCTION_SYMBOLS,
195 symbols_in_process,
196 sys.stdin)
197 for address, symbol in symbols_dict:
198 if symbol:
199 print '%016x %s' % (address, symbol)
200 else:
201 print '%016x' % address
203 return 0
206 if __name__ == '__main__':
207 sys.exit(main())