OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 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 | 5 |
6 """Symbolize log file produced by cypgofile instrumentation. | 6 """Symbolize log file produced by cypgofile instrumentation. |
7 | 7 |
8 Given a log file and the binary being profiled (e.g. executable, shared | 8 Given a log file and the binary being profiled (e.g. executable, shared |
9 library), the script can produce three different outputs: 1) symbols for the | 9 library), the script can produce three different outputs: 1) symbols for the |
10 addresses, 2) function and line numbers for the addresses, or 3) an order file. | 10 addresses, 2) function and line numbers for the addresses, or 3) an order file. |
(...skipping 21 matching lines...) Expand all Loading... |
32 1314897086 795874 3587:1074648168 0x509e0eb4 | 32 1314897086 795874 3587:1074648168 0x509e0eb4 |
33 1314897086 796326 3587:1074648168 0x509e0e3c | 33 1314897086 796326 3587:1074648168 0x509e0e3c |
34 1314897086 796552 3587:1074648168 0x509e07bc | 34 1314897086 796552 3587:1074648168 0x509e07bc |
35 END | 35 END |
36 | 36 |
37 Returns: | 37 Returns: |
38 call_info list with list of tuples of the format (sec, usec, call id, | 38 call_info list with list of tuples of the format (sec, usec, call id, |
39 function address called) | 39 function address called) |
40 """ | 40 """ |
41 call_lines = [] | 41 call_lines = [] |
42 has_started = False | |
43 vm_start = 0 | 42 vm_start = 0 |
44 line = log_file_lines[0] | 43 line = log_file_lines[0] |
45 assert("r-xp" in line) | 44 assert("r-xp" in line) |
46 end_index = line.find('-') | 45 end_index = line.find('-') |
47 vm_start = int(line[:end_index], 16) | 46 vm_start = int(line[:end_index], 16) |
48 for line in log_file_lines[2:]: | 47 for line in log_file_lines[2:]: |
49 # print hex(vm_start) | 48 # print hex(vm_start) |
50 fields = line.split() | 49 fields = line.split() |
51 if len(fields) == 4: | 50 if len(fields) == 4: |
52 call_lines.append(fields) | 51 call_lines.append(fields) |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
106 nm_index += 1 | 105 nm_index += 1 |
107 address_map[addr] = fnames | 106 address_map[addr] = fnames |
108 unique_addrs.append((addr, size)) | 107 unique_addrs.append((addr, size)) |
109 else: | 108 else: |
110 nm_index += 1 | 109 nm_index += 1 |
111 | 110 |
112 return (unique_addrs, address_map) | 111 return (unique_addrs, address_map) |
113 | 112 |
114 class SymbolNotFoundException(Exception): | 113 class SymbolNotFoundException(Exception): |
115 def __init__(self,value): | 114 def __init__(self,value): |
| 115 super(SymbolNotFoundException,self).__init__(value) |
116 self.value = value | 116 self.value = value |
117 def __str__(self): | 117 def __str__(self): |
118 return repr(self.value) | 118 return repr(self.value) |
119 | 119 |
120 def BinarySearchAddresses(addr, start, end, arr): | 120 def BinarySearchAddresses(addr, start, end, arr): |
121 """Find starting address of a symbol at a particular address. | 121 """Find starting address of a symbol at a particular address. |
122 | 122 |
123 The reason we can not directly use the address provided by the log file is | 123 The reason we can not directly use the address provided by the log file is |
124 that the log file may give an address after the start of the symbol. The | 124 that the log file may give an address after the start of the symbol. The |
125 logged address is often one byte after the start. By using this search | 125 logged address is often one byte after the start. By using this search |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
194 | 194 |
195 # Option for output type. The log file and lib file arguments are required | 195 # Option for output type. The log file and lib file arguments are required |
196 # by the script and therefore are not options. | 196 # by the script and therefore are not options. |
197 (options, args) = parser.parse_args() | 197 (options, args) = parser.parse_args() |
198 if len(args) != 2: | 198 if len(args) != 2: |
199 parser.error('expected 2 args: log_file lib_file') | 199 parser.error('expected 2 args: log_file lib_file') |
200 | 200 |
201 (log_file, lib_file) = args | 201 (log_file, lib_file) = args |
202 output_type = options.output_type | 202 output_type = options.output_type |
203 | 203 |
204 lib_name = lib_file.split('/')[-1].strip() | |
205 log_file_lines = map(string.rstrip, open(log_file).readlines()) | 204 log_file_lines = map(string.rstrip, open(log_file).readlines()) |
206 call_info = ParseLogLines(log_file_lines) | 205 call_info = ParseLogLines(log_file_lines) |
207 (unique_addrs, address_map) = ParseLibSymbols(lib_file) | 206 (unique_addrs, address_map) = ParseLibSymbols(lib_file) |
208 | 207 |
209 # Check for duplicate addresses in the log file, and print a warning if | 208 # Check for duplicate addresses in the log file, and print a warning if |
210 # duplicates are found. The instrumentation that produces the log file | 209 # duplicates are found. The instrumentation that produces the log file |
211 # should only print the first time a function is entered. | 210 # should only print the first time a function is entered. |
212 addr_list = [] | 211 addr_list = [] |
213 for call in call_info: | 212 for call in call_info: |
214 addr = call[3] | 213 addr = call[3] |
215 if addr not in addr_list: | 214 if addr not in addr_list: |
216 addr_list.append(addr) | 215 addr_list.append(addr) |
217 else: | 216 else: |
218 print('WARNING: Address ' + hex(addr) + ' (line= ' + | 217 print('WARNING: Address ' + hex(addr) + ' (line= ' + |
219 AddrToLine(addr, lib_file) + ') already profiled.') | 218 AddrToLine(addr, lib_file) + ') already profiled.') |
220 | 219 |
221 for call in call_info: | 220 for call in call_info: |
222 if output_type == 'lineize': | 221 if output_type == 'lineize': |
223 symbol = AddrToLine(call[3], lib_file) | 222 symbol = AddrToLine(call[3], lib_file) |
224 print(str(call[0]) + ' ' + str(call[1]) + '\t' + str(call[2]) + '\t' | 223 print(str(call[0]) + ' ' + str(call[1]) + '\t' + str(call[2]) + '\t' |
225 + symbol) | 224 + symbol) |
226 elif output_type == 'orderfile': | 225 elif output_type == 'orderfile': |
227 try: | 226 try: |
228 symbols = FindFunctions(call[3], unique_addrs, address_map) | 227 symbols = FindFunctions(call[3], unique_addrs, address_map) |
229 for symbol in symbols: | 228 for symbol in symbols: |
230 print '.text.' + symbol | 229 print '.text.' + symbol |
231 print '' | 230 print '' |
232 except SymbolNotFoundException as e: | 231 except SymbolNotFoundException: |
233 sys.stderr.write('WARNING: Did not find function in binary. addr: ' | 232 sys.stderr.write('WARNING: Did not find function in binary. addr: ' |
234 + hex(addr) + '\n') | 233 + hex(addr) + '\n') |
235 else: | 234 else: |
236 try: | 235 try: |
237 symbols = FindFunctions(call[3], unique_addrs, address_map) | 236 symbols = FindFunctions(call[3], unique_addrs, address_map) |
238 print(str(call[0]) + ' ' + str(call[1]) + '\t' + str(call[2]) + '\t' | 237 print(str(call[0]) + ' ' + str(call[1]) + '\t' + str(call[2]) + '\t' |
239 + symbols[0]) | 238 + symbols[0]) |
240 first_symbol = True | 239 first_symbol = True |
241 for symbol in symbols: | 240 for symbol in symbols: |
242 if not first_symbol: | 241 if not first_symbol: |
243 print '\t\t\t\t\t' + symbol | 242 print '\t\t\t\t\t' + symbol |
244 else: | 243 else: |
245 first_symbol = False | 244 first_symbol = False |
246 except SymbolNotFoundException as e: | 245 except SymbolNotFoundException: |
247 sys.stderr.write('WARNING: Did not find function in binary. addr: ' | 246 sys.stderr.write('WARNING: Did not find function in binary. addr: ' |
248 + hex(addr) + '\n') | 247 + hex(addr) + '\n') |
249 | 248 |
250 if __name__ == '__main__': | 249 if __name__ == '__main__': |
251 main() | 250 main() |
OLD | NEW |