| 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 itertools | 10 import itertools |
| 11 import json | 11 import json |
| 12 import os | 12 import os |
| 13 import re | 13 import re |
| 14 import subprocess | 14 import subprocess |
| 15 import sys | 15 import sys |
| 16 import tempfile |
| 16 | 17 |
| 17 sys.path.append(os.path.abspath(os.path.join( | 18 sys.path.append(os.path.abspath(os.path.join( |
| 18 os.path.dirname(os.path.realpath(__file__)), | 19 os.path.dirname(os.path.realpath(__file__)), |
| 19 '..', '..', '..', 'tracing', 'bin'))) | 20 '..', '..', '..', 'tracing', 'bin'))) |
| 20 sys.path.append(os.path.abspath(os.path.join( | 21 sys.path.append(os.path.abspath(os.path.join( |
| 21 os.path.dirname(os.path.realpath(__file__)), | 22 os.path.dirname(os.path.realpath(__file__)), |
| 22 '..', '..', '..', 'tracing', 'third_party', 'symbols'))) | 23 '..', '..', '..', 'tracing', 'third_party', 'symbols'))) |
| 23 # pylint: disable=import-error | 24 # pylint: disable=import-error |
| 24 import symbols.elf_symbolizer as elf_symbolizer | 25 import symbols.elf_symbolizer as elf_symbolizer |
| 25 | 26 |
| (...skipping 892 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 918 # SymbolizeAsync() asserts that the type of address is int. We operate | 919 # SymbolizeAsync() asserts that the type of address is int. We operate |
| 919 # on longs (since they are raw pointers possibly from 64-bit processes). | 920 # on longs (since they are raw pointers possibly from 64-bit processes). |
| 920 # It's OK to cast here because we're passing relative PC, which should | 921 # It's OK to cast here because we're passing relative PC, which should |
| 921 # always fit into int. | 922 # always fit into int. |
| 922 symbolizer.SymbolizeAsync(int(address), frames) | 923 symbolizer.SymbolizeAsync(int(address), frames) |
| 923 | 924 |
| 924 symbolizer.Join() | 925 symbolizer.Join() |
| 925 | 926 |
| 926 | 927 |
| 927 def _SymbolizeMac(self, symfile): | 928 def _SymbolizeMac(self, symfile): |
| 928 chars_max = int(subprocess.check_output("getconf ARG_MAX", shell=True)) | |
| 929 | |
| 930 # 16 for the address, 2 for "0x", 1 for the space | |
| 931 chars_per_address = 19 | |
| 932 | |
| 933 load_address = (symbolize_trace_macho_reader. | 929 load_address = (symbolize_trace_macho_reader. |
| 934 ReadMachOTextLoadAddress(symfile.symbolizable_path)) | 930 ReadMachOTextLoadAddress(symfile.symbolizable_path)) |
| 935 assert load_address is not None | 931 assert load_address is not None |
| 936 | 932 |
| 937 cmd_base = [self.symbolizer_path, '-arch', 'x86_64', '-l', | 933 address_os_file, address_file_path = tempfile.mkstemp() |
| 938 '0x%x' % load_address, '-o', | 934 try: |
| 939 symfile.symbolizable_path] | 935 with os.fdopen(address_os_file, 'w') as address_file: |
| 940 chars_for_other_arguments = len(' '.join(cmd_base)) + 1 | 936 for address in symfile.frames_by_address.iterkeys(): |
| 937 address_file.write('{:x} '.format(address + load_address)) |
| 941 | 938 |
| 942 # The maximum number of inputs that can be processed at once is limited by | 939 cmd = [self.symbolizer_path, '-arch', 'x86_64', '-l', |
| 943 # ARG_MAX. This currently evalutes to ~13000 on macOS. | 940 '0x%x' % load_address, '-o', symfile.symbolizable_path, |
| 944 max_inputs = (chars_max - chars_for_other_arguments) / chars_per_address | 941 '-f', address_file_path] |
| 942 output_array = subprocess.check_output(cmd).split('\n') |
| 945 | 943 |
| 946 all_keys = symfile.frames_by_address.keys() | 944 for i, frames in enumerate(symfile.frames_by_address.itervalues()): |
| 947 processed_keys_count = 0 | 945 symbolized_name = self._matcher.Match(output_array[i]) |
| 948 while len(all_keys): | 946 for frame in frames: |
| 949 input_count = min(len(all_keys), max_inputs) | 947 frame.name = symbolized_name |
| 950 keys_to_process = all_keys[0:input_count] | 948 finally: |
| 951 cmd = list(cmd_base) | 949 os.remove(address_file_path) |
| 952 cmd.extend([hex(int(x) + load_address) | |
| 953 for x in keys_to_process]) | |
| 954 output_array = subprocess.check_output(cmd).split('\n') | |
| 955 for i in range(len(keys_to_process)): | |
| 956 for frame in (symfile.frames_by_address.values() | |
| 957 [i + processed_keys_count]): | |
| 958 frame.name = self._matcher.Match(output_array[i]) | |
| 959 processed_keys_count += len(keys_to_process) | |
| 960 all_keys = all_keys[input_count:] | |
| 961 | 950 |
| 962 def _SymbolizeWin(self, symfile): | 951 def _SymbolizeWin(self, symfile): |
| 963 """Invoke symbolizer binary on windows and write all input in one go. | 952 """Invoke symbolizer binary on windows and write all input in one go. |
| 964 | 953 |
| 965 Unlike linux, on windows, symbolization talks through a shared system | 954 Unlike linux, on windows, symbolization talks through a shared system |
| 966 service that handles communication with the NT symbol servers. This | 955 service that handles communication with the NT symbol servers. This |
| 967 creates an explicit serialization (and therefor lock contention) of | 956 creates an explicit serialization (and therefor lock contention) of |
| 968 any process using the symbol API for files do not have a local PDB. | 957 any process using the symbol API for files do not have a local PDB. |
| 969 | 958 |
| 970 Thus, even though the windows symbolizer binary can be make command line | 959 Thus, even though the windows symbolizer binary can be make command line |
| (...skipping 596 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1567 | 1556 |
| 1568 print 'Updating the trace file...' | 1557 print 'Updating the trace file...' |
| 1569 with OpenTraceFile(trace_file_path, 'w') as trace_file: | 1558 with OpenTraceFile(trace_file_path, 'w') as trace_file: |
| 1570 json.dump(trace.Serialize(), trace_file) | 1559 json.dump(trace.Serialize(), trace_file) |
| 1571 else: | 1560 else: |
| 1572 print 'No modifications were made - not updating the trace file.' | 1561 print 'No modifications were made - not updating the trace file.' |
| 1573 | 1562 |
| 1574 | 1563 |
| 1575 if __name__ == '__main__': | 1564 if __name__ == '__main__': |
| 1576 main() | 1565 main() |
| OLD | NEW |