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 |
11 import os | 11 import os |
12 import re | 12 import re |
13 import subprocess | 13 import subprocess |
14 import sys | 14 import sys |
15 | 15 |
16 _SYMBOLS_PATH = os.path.abspath(os.path.join( | 16 _SYMBOLS_PATH = os.path.abspath(os.path.join( |
17 os.path.dirname(os.path.realpath(__file__)), | 17 os.path.dirname(os.path.realpath(__file__)), |
18 '..', | 18 '..', |
19 'third_party', | 19 'third_party', |
20 'symbols')) | 20 'symbols')) |
21 sys.path.append(_SYMBOLS_PATH) | 21 sys.path.append(_SYMBOLS_PATH) |
22 # pylint: disable=import-error | 22 # pylint: disable=import-error |
23 import symbols.elf_symbolizer as elf_symbolizer | 23 import symbols.elf_symbolizer as elf_symbolizer |
24 | 24 |
25 import symbolize_trace_atos_regex | 25 import symbolize_trace_atos_regex |
| 26 import symbolize_trace_macho_reader |
26 | 27 |
27 | 28 |
28 # Relevant trace event phases from Chromium's | 29 # Relevant trace event phases from Chromium's |
29 # src/base/trace_event/common/trace_event_common.h. | 30 # src/base/trace_event/common/trace_event_common.h. |
30 TRACE_EVENT_PHASE_METADATA = 'M' | 31 TRACE_EVENT_PHASE_METADATA = 'M' |
31 TRACE_EVENT_PHASE_MEMORY_DUMP = 'v' | 32 TRACE_EVENT_PHASE_MEMORY_DUMP = 'v' |
32 | 33 |
33 | 34 |
34 # Matches Android library paths, supports both K (/data/app-lib/<>/lib.so) | 35 # Matches Android library paths, supports both K (/data/app-lib/<>/lib.so) |
35 # as well as L+ (/data/app/<>/lib/<>/lib.so). Library name is available | 36 # as well as L+ (/data/app/<>/lib/<>/lib.so). Library name is available |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 symbolizer.SymbolizeAsync(int(address), frames) | 89 symbolizer.SymbolizeAsync(int(address), frames) |
89 | 90 |
90 symbolizer.Join() | 91 symbolizer.Join() |
91 | 92 |
92 def _SymbolizeMac(self, symfile): | 93 def _SymbolizeMac(self, symfile): |
93 chars_max = int(subprocess.check_output("getconf ARG_MAX", shell=True)) | 94 chars_max = int(subprocess.check_output("getconf ARG_MAX", shell=True)) |
94 | 95 |
95 # 16 for the address, 2 for "0x", 1 for the space | 96 # 16 for the address, 2 for "0x", 1 for the space |
96 chars_per_address = 19 | 97 chars_per_address = 19 |
97 | 98 |
| 99 load_address = (symbolize_trace_macho_reader. |
| 100 ReadMachOTextLoadAddress(symfile.symbolizable_path)) |
| 101 assert load_address is not None |
| 102 |
98 cmd_base = [self.symbolizer_path, '-arch', 'x86_64', '-l', | 103 cmd_base = [self.symbolizer_path, '-arch', 'x86_64', '-l', |
99 '0x0', '-o' , symfile.symbolizable_path] | 104 '0x%x' % load_address, '-o', |
| 105 symfile.symbolizable_path] |
100 chars_for_other_arguments = len(' '.join(cmd_base)) + 1 | 106 chars_for_other_arguments = len(' '.join(cmd_base)) + 1 |
101 | 107 |
102 # The maximum number of inputs that can be processed at once is limited by | 108 # The maximum number of inputs that can be processed at once is limited by |
103 # ARG_MAX. This currently evalutes to ~13000 on macOS. | 109 # ARG_MAX. This currently evalutes to ~13000 on macOS. |
104 max_inputs = (chars_max - chars_for_other_arguments) / chars_per_address | 110 max_inputs = (chars_max - chars_for_other_arguments) / chars_per_address |
105 | 111 |
106 all_keys = symfile.frames_by_address.keys() | 112 all_keys = symfile.frames_by_address.keys() |
107 processed_keys_count = 0 | 113 processed_keys_count = 0 |
108 while len(all_keys): | 114 while len(all_keys): |
109 input_count = min(len(all_keys), max_inputs) | 115 input_count = min(len(all_keys), max_inputs) |
110 keys_to_process = all_keys[0:input_count] | 116 keys_to_process = all_keys[0:input_count] |
111 | 117 |
112 cmd = list(cmd_base) | 118 cmd = list(cmd_base) |
113 cmd.extend([hex(int(x)) for x in keys_to_process]) | 119 cmd.extend([hex(int(x) + load_address) |
| 120 for x in keys_to_process]) |
114 output_array = subprocess.check_output(cmd).split('\n') | 121 output_array = subprocess.check_output(cmd).split('\n') |
115 for i in range(len(keys_to_process)): | 122 for i in range(len(keys_to_process)): |
116 for frame in symfile.frames_by_address.values()[i + processed_keys_count
]: | 123 for frame in (symfile.frames_by_address.values() |
| 124 [i + processed_keys_count]): |
117 frame.name = self._matcher.Match(output_array[i]) | 125 frame.name = self._matcher.Match(output_array[i]) |
118 processed_keys_count += len(keys_to_process) | 126 processed_keys_count += len(keys_to_process) |
119 all_keys = all_keys[input_count:] | 127 all_keys = all_keys[input_count:] |
120 | 128 |
121 def Symbolize(self, symfile): | 129 def Symbolize(self, symfile): |
122 if self.is_mac: | 130 if self.is_mac: |
123 self._SymbolizeMac(symfile) | 131 self._SymbolizeMac(symfile) |
124 else: | 132 else: |
125 self._SymbolizeLinuxAndAndroid(symfile) | 133 self._SymbolizeLinuxAndAndroid(symfile) |
126 | 134 |
(...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 | 461 |
454 print 'Updating trace file...' | 462 print 'Updating trace file...' |
455 with _OpenTraceFile('w') as trace_file: | 463 with _OpenTraceFile('w') as trace_file: |
456 json.dump(trace, trace_file) | 464 json.dump(trace, trace_file) |
457 else: | 465 else: |
458 print 'No PCs symbolized - not updating trace file.' | 466 print 'No PCs symbolized - not updating trace file.' |
459 | 467 |
460 | 468 |
461 if __name__ == '__main__': | 469 if __name__ == '__main__': |
462 main() | 470 main() |
OLD | NEW |