OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright 2016 The Chromium Authors. All rights reserved. | 2 # Copyright 2016 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 import argparse | 6 import argparse |
7 import bisect | 7 import bisect |
8 import collections | 8 import collections |
9 import gzip | 9 import gzip |
10 import json | 10 import json |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
89 | 89 |
90 symbolizer.Join() | 90 symbolizer.Join() |
91 | 91 |
92 def _SymbolizeMac(self, symfile): | 92 def _SymbolizeMac(self, symfile): |
93 chars_max = int(subprocess.check_output("getconf ARG_MAX", shell=True)) | 93 chars_max = int(subprocess.check_output("getconf ARG_MAX", shell=True)) |
94 | 94 |
95 # 16 for the address, 2 for "0x", 1 for the space | 95 # 16 for the address, 2 for "0x", 1 for the space |
96 chars_per_address = 19 | 96 chars_per_address = 19 |
97 | 97 |
98 cmd_base = [self.symbolizer_path, '-arch', 'x86_64', '-l', | 98 cmd_base = [self.symbolizer_path, '-arch', 'x86_64', '-l', |
99 '0x0', '-o' , symfile.symbolizable_path] | 99 '0x%x' % symfile.region_start_address, '-o', |
100 symfile.symbolizable_path] | |
100 chars_for_other_arguments = len(' '.join(cmd_base)) + 1 | 101 chars_for_other_arguments = len(' '.join(cmd_base)) + 1 |
101 | 102 |
102 # The maximum number of inputs that can be processed at once is limited by | 103 # The maximum number of inputs that can be processed at once is limited by |
103 # ARG_MAX. This currently evalutes to ~13000 on macOS. | 104 # ARG_MAX. This currently evalutes to ~13000 on macOS. |
104 max_inputs = (chars_max - chars_for_other_arguments) / chars_per_address | 105 max_inputs = (chars_max - chars_for_other_arguments) / chars_per_address |
105 | 106 |
106 all_keys = symfile.frames_by_address.keys() | 107 all_keys = symfile.frames_by_address.keys() |
107 processed_keys_count = 0 | 108 processed_keys_count = 0 |
108 while len(all_keys): | 109 while len(all_keys): |
109 input_count = min(len(all_keys), max_inputs) | 110 input_count = min(len(all_keys), max_inputs) |
110 keys_to_process = all_keys[0:input_count] | 111 keys_to_process = all_keys[0:input_count] |
111 | 112 |
112 cmd = list(cmd_base) | 113 cmd = list(cmd_base) |
113 cmd.extend([hex(int(x)) for x in keys_to_process]) | 114 cmd.extend([hex(int(x) + symfile.region_start_address) |
115 for x in keys_to_process]) | |
114 output_array = subprocess.check_output(cmd).split('\n') | 116 output_array = subprocess.check_output(cmd).split('\n') |
115 for i in range(len(keys_to_process)): | 117 for i in range(len(keys_to_process)): |
116 for frame in symfile.frames_by_address.values()[i + processed_keys_count ]: | 118 for frame in symfile.frames_by_address.values()[i + processed_keys_count ]: |
117 frame.name = self._matcher.Match(output_array[i]) | 119 frame.name = self._matcher.Match(output_array[i]) |
118 processed_keys_count += len(keys_to_process) | 120 processed_keys_count += len(keys_to_process) |
119 all_keys = all_keys[input_count:] | 121 all_keys = all_keys[input_count:] |
120 | 122 |
121 def Symbolize(self, symfile): | 123 def Symbolize(self, symfile): |
122 if self.is_mac: | 124 if self.is_mac: |
123 self._SymbolizeMac(symfile) | 125 self._SymbolizeMac(symfile) |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
311 """Holds file path, addresses to symbolize and stack frames to update. | 313 """Holds file path, addresses to symbolize and stack frames to update. |
312 | 314 |
313 This class is a link between ELFSymbolizer and a trace file: it specifies | 315 This class is a link between ELFSymbolizer and a trace file: it specifies |
314 what to symbolize (addresses) and what to update with the symbolization | 316 what to symbolize (addresses) and what to update with the symbolization |
315 result (frames). | 317 result (frames). |
316 """ | 318 """ |
317 def __init__(self, file_path): | 319 def __init__(self, file_path): |
318 self.path = file_path | 320 self.path = file_path |
319 self.symbolizable_path = file_path # path to use for symbolization | 321 self.symbolizable_path = file_path # path to use for symbolization |
320 self.frames_by_address = collections.defaultdict(list) | 322 self.frames_by_address = collections.defaultdict(list) |
323 self.region_start_address = 0 | |
321 | 324 |
322 | 325 |
323 def ResolveSymbolizableFiles(processes): | 326 def ResolveSymbolizableFiles(processes): |
324 """Resolves and groups PCs into list of SymbolizableFiles. | 327 """Resolves and groups PCs into list of SymbolizableFiles. |
325 | 328 |
326 As part of the grouping process, this function resolves PC from each stack | 329 As part of the grouping process, this function resolves PC from each stack |
327 frame to the corresponding mmap region. Stack frames that failed to resolve | 330 frame to the corresponding mmap region. Stack frames that failed to resolve |
328 are symbolized with '<unresolved>'. | 331 are symbolized with '<unresolved>'. |
329 """ | 332 """ |
330 symfile_by_path = {} | 333 symfile_by_path = {} |
331 for process in processes: | 334 for process in processes: |
332 for frame in process.stack_frames.pc_frames: | 335 for frame in process.stack_frames.pc_frames: |
333 region = process.mmaps.FindRegion(frame.pc) | 336 region = process.mmaps.FindRegion(frame.pc) |
334 if region is None: | 337 if region is None: |
335 frame.name = '<unresolved>' | 338 frame.name = '<unresolved>' |
336 continue | 339 continue |
337 | 340 |
338 symfile = symfile_by_path.get(region.file_path) | 341 symfile = symfile_by_path.get(region.file_path) |
339 if symfile is None: | 342 if symfile is None: |
340 symfile = SymbolizableFile(region.file_path) | 343 symfile = SymbolizableFile(region.file_path) |
341 symfile_by_path[symfile.path] = symfile | 344 symfile_by_path[symfile.path] = symfile |
342 | 345 |
343 relative_pc = frame.pc - region.start_address | 346 relative_pc = frame.pc - region.start_address |
347 symfile.region_start_address = region.start_address | |
DmitrySkiba
2017/02/15 22:40:38
Hmm, this overwrites the whatever value region_sta
| |
344 symfile.frames_by_address[relative_pc].append(frame) | 348 symfile.frames_by_address[relative_pc].append(frame) |
345 return symfile_by_path.values() | 349 return symfile_by_path.values() |
346 | 350 |
347 | 351 |
348 def SymbolizeFiles(symfiles, symbolizer): | 352 def SymbolizeFiles(symfiles, symbolizer): |
349 """Symbolizes each file in the given list of SymbolizableFiles | 353 """Symbolizes each file in the given list of SymbolizableFiles |
350 and updates stack frames with symbolization results.""" | 354 and updates stack frames with symbolization results.""" |
351 print 'Symbolizing...' | 355 print 'Symbolizing...' |
352 | 356 |
353 def _SubPrintf(message, *args): | 357 def _SubPrintf(message, *args): |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
453 | 457 |
454 print 'Updating trace file...' | 458 print 'Updating trace file...' |
455 with _OpenTraceFile('w') as trace_file: | 459 with _OpenTraceFile('w') as trace_file: |
456 json.dump(trace, trace_file) | 460 json.dump(trace, trace_file) |
457 else: | 461 else: |
458 print 'No PCs symbolized - not updating trace file.' | 462 print 'No PCs symbolized - not updating trace file.' |
459 | 463 |
460 | 464 |
461 if __name__ == '__main__': | 465 if __name__ == '__main__': |
462 main() | 466 main() |
OLD | NEW |