Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(90)

Side by Side Diff: tools/find_runtime_symbols/find_runtime_symbols.py

Issue 13514003: Breakdown memory usage by source file names in dmprof. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 """Find symbols in a binary corresponding to given runtime virtual addresses.
6
7 Note that source file names are treated as symbols in this script while they
8 are actually not.
9 """
5 10
6 import json 11 import json
7 import logging 12 import logging
8 import os 13 import os
9 import sys 14 import sys
10 15
11 from static_symbols import StaticSymbolsInFile 16 from static_symbols import StaticSymbolsInFile
12 from proc_maps import ProcMaps 17 from proc_maps import ProcMaps
13 18
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
26
27
28 FUNCTION_SYMBOLS = 0
29 SOURCEFILE_SYMBOLS = 1
30 TYPEINFO_SYMBOLS = 2
14 31
15 _MAPS_FILENAME = 'maps' 32 _MAPS_FILENAME = 'maps'
16 _FILES_FILENAME = 'files.json' 33 _FILES_FILENAME = 'files.json'
17 34
18 35
19 class _ListOutput(object):
20 def __init__(self, result):
21 self.result = result
22
23 def output(self, address, symbol): # pylint: disable=W0613
24 self.result.append(symbol)
25
26
27 class _DictOutput(object):
28 def __init__(self, result):
29 self.result = result
30
31 def output(self, address, symbol):
32 self.result[address] = symbol
33
34
35 class _FileOutput(object):
36 def __init__(self, result, with_address):
37 self.result = result
38 self.with_address = with_address
39
40 def output(self, address, symbol):
41 if self.with_address:
42 self.result.write('%016x %s\n' % (address, symbol))
43 else:
44 self.result.write('%s\n' % symbol)
45
46
47 class RuntimeSymbolsInProcess(object): 36 class RuntimeSymbolsInProcess(object):
48 def __init__(self): 37 def __init__(self):
49 self._maps = None 38 self._maps = None
50 self._static_symbols_in_filse = {} 39 self._static_symbols_in_filse = {}
51 40
52 def find_procedure(self, runtime_address): 41 def find_procedure(self, runtime_address):
53 for vma in self._maps.iter(ProcMaps.executable): 42 for vma in self._maps.iter(ProcMaps.executable):
54 if vma.begin <= runtime_address < vma.end: 43 if vma.begin <= runtime_address < vma.end:
55 static_symbols = self._static_symbols_in_filse.get(vma.name) 44 static_symbols = self._static_symbols_in_filse.get(vma.name)
56 if static_symbols: 45 if static_symbols:
57 return static_symbols.find_procedure_by_runtime_address( 46 return static_symbols.find_procedure_by_runtime_address(
58 runtime_address, vma) 47 runtime_address, vma)
59 else: 48 else:
60 return None 49 return None
61 return None 50 return None
62 51
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
62
63 def find_typeinfo(self, runtime_address): 63 def find_typeinfo(self, runtime_address):
64 for vma in self._maps.iter(ProcMaps.constants): 64 for vma in self._maps.iter(ProcMaps.constants):
65 if vma.begin <= runtime_address < vma.end: 65 if vma.begin <= runtime_address < vma.end:
66 static_symbols = self._static_symbols_in_filse.get(vma.name) 66 static_symbols = self._static_symbols_in_filse.get(vma.name)
67 if static_symbols: 67 if static_symbols:
68 return static_symbols.find_typeinfo_by_runtime_address( 68 return static_symbols.find_typeinfo_by_runtime_address(
69 runtime_address, vma) 69 runtime_address, vma)
70 else: 70 else:
71 return None 71 return None
72 return None 72 return None
(...skipping 19 matching lines...) Expand all
92 if nm_entry and nm_entry['format'] == 'bsd': 92 if nm_entry and nm_entry['format'] == 'bsd':
93 with open(os.path.join(prepared_data_dir, nm_entry['file']), 'r') as f: 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']) 94 static_symbols.load_nm_bsd(f, nm_entry['mangled'])
95 95
96 readelf_entry = file_entry.get('readelf-e') 96 readelf_entry = file_entry.get('readelf-e')
97 if readelf_entry: 97 if readelf_entry:
98 with open(os.path.join(prepared_data_dir, readelf_entry['file']), 98 with open(os.path.join(prepared_data_dir, readelf_entry['file']),
99 'r') as f: 99 'r') as f:
100 static_symbols.load_readelf_ew(f) 100 static_symbols.load_readelf_ew(f)
101 101
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)
107
102 symbols_in_process._static_symbols_in_filse[vma.name] = static_symbols 108 symbols_in_process._static_symbols_in_filse[vma.name] = static_symbols
103 109
104 return symbols_in_process 110 return symbols_in_process
105 111
106 112
107 def _find_runtime_symbols(symbols_in_process, addresses, outputter): 113 def _find_runtime_function_symbols(symbols_in_process, addresses):
114 result = OrderedDict()
108 for address in addresses: 115 for address in addresses:
109 if isinstance(address, basestring): 116 if isinstance(address, basestring):
110 address = int(address, 16) 117 address = int(address, 16)
111 found = symbols_in_process.find_procedure(address) 118 found = symbols_in_process.find_procedure(address)
112 if found: 119 if found:
113 outputter.output(address, found.name) 120 result[address] = found.name
114 else: 121 else:
115 outputter.output(address, '0x%016x' % address) 122 result[address] = '0x%016x' % address
123 return result
116 124
117 125
118 def _find_runtime_typeinfo_symbols(symbols_in_process, addresses, outputter): 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
137
138
139 def _find_runtime_typeinfo_symbols(symbols_in_process, addresses):
140 result = OrderedDict()
119 for address in addresses: 141 for address in addresses:
120 if isinstance(address, basestring): 142 if isinstance(address, basestring):
121 address = int(address, 16) 143 address = int(address, 16)
122 if address == 0: 144 if address == 0:
123 outputter.output(address, 'no typeinfo') 145 result[address] = 'no typeinfo'
124 else: 146 else:
125 found = symbols_in_process.find_typeinfo(address) 147 found = symbols_in_process.find_typeinfo(address)
126 if found: 148 if found:
127 if found.startswith('typeinfo for '): 149 if found.startswith('typeinfo for '):
128 outputter.output(address, found[13:]) 150 result[address] = found[13:]
129 else: 151 else:
130 outputter.output(address, found) 152 result[address] = found
131 else: 153 else:
132 outputter.output(address, '0x%016x' % address) 154 result[address] = '0x%016x' % address
133
134
135 def find_runtime_typeinfo_symbols_list(symbols_in_process, addresses):
136 result = []
137 _find_runtime_typeinfo_symbols(
138 symbols_in_process, addresses, _ListOutput(result))
139 return result 155 return result
140 156
141 157
142 def find_runtime_typeinfo_symbols_dict(symbols_in_process, addresses): 158 _INTERNAL_FINDERS = {
143 result = {} 159 FUNCTION_SYMBOLS: _find_runtime_function_symbols,
144 _find_runtime_typeinfo_symbols( 160 SOURCEFILE_SYMBOLS: _find_runtime_sourcefile_symbols,
145 symbols_in_process, addresses, _DictOutput(result)) 161 TYPEINFO_SYMBOLS: _find_runtime_typeinfo_symbols,
146 return result 162 }
147 163
148 164
149 def find_runtime_typeinfo_symbols_file(symbols_in_process, addresses, f): 165 def find_runtime_symbols(symbol_type, symbols_in_process, addresses):
150 _find_runtime_typeinfo_symbols( 166 return _INTERNAL_FINDERS[symbol_type](symbols_in_process, addresses)
151 symbols_in_process, addresses, _FileOutput(f, False))
152
153
154 def find_runtime_symbols_list(symbols_in_process, addresses):
155 result = []
156 _find_runtime_symbols(symbols_in_process, addresses, _ListOutput(result))
157 return result
158
159
160 def find_runtime_symbols_dict(symbols_in_process, addresses):
161 result = {}
162 _find_runtime_symbols(symbols_in_process, addresses, _DictOutput(result))
163 return result
164
165
166 def find_runtime_symbols_file(symbols_in_process, addresses, f):
167 _find_runtime_symbols(
168 symbols_in_process, addresses, _FileOutput(f, False))
169 167
170 168
171 def main(): 169 def main():
172 # FIX: Accept only .pre data 170 # FIX: Accept only .pre data
173 if len(sys.argv) < 2: 171 if len(sys.argv) < 2:
174 sys.stderr.write("""Usage: 172 sys.stderr.write("""Usage:
175 %s /path/to/prepared_data_dir/ < addresses.txt 173 %s /path/to/prepared_data_dir/ < addresses.txt
176 """ % sys.argv[0]) 174 """ % sys.argv[0])
177 return 1 175 return 1
178 176
179 log = logging.getLogger('find_runtime_symbols') 177 log = logging.getLogger('find_runtime_symbols')
180 log.setLevel(logging.WARN) 178 log.setLevel(logging.WARN)
181 handler = logging.StreamHandler() 179 handler = logging.StreamHandler()
182 handler.setLevel(logging.WARN) 180 handler.setLevel(logging.WARN)
183 formatter = logging.Formatter('%(message)s') 181 formatter = logging.Formatter('%(message)s')
184 handler.setFormatter(formatter) 182 handler.setFormatter(formatter)
185 log.addHandler(handler) 183 log.addHandler(handler)
186 184
187 prepared_data_dir = sys.argv[1] 185 prepared_data_dir = sys.argv[1]
188 if not os.path.exists(prepared_data_dir): 186 if not os.path.exists(prepared_data_dir):
189 log.warn("Nothing found: %s" % prepared_data_dir) 187 log.warn("Nothing found: %s" % prepared_data_dir)
190 return 1 188 return 1
191 if not os.path.isdir(prepared_data_dir): 189 if not os.path.isdir(prepared_data_dir):
192 log.warn("Not a directory: %s" % prepared_data_dir) 190 log.warn("Not a directory: %s" % prepared_data_dir)
193 return 1 191 return 1
194 192
195 symbols_in_process = RuntimeSymbolsInProcess.load(prepared_data_dir) 193 symbols_in_process = RuntimeSymbolsInProcess.load(prepared_data_dir)
196 return find_runtime_symbols_file(symbols_in_process, sys.stdin, sys.stdout) 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
202
203 return 0
197 204
198 205
199 if __name__ == '__main__': 206 if __name__ == '__main__':
200 sys.exit(main()) 207 sys.exit(main())
OLDNEW
« no previous file with comments | « tools/deep_memory_profiler/tests/dmprof_test.py ('k') | tools/find_runtime_symbols/static_symbols.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698