Chromium Code Reviews| 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 |