Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(264)

Unified Diff: tracing/bin/symbolize_trace

Issue 2605183002: Update symbolize_trace to work on macOS. (Closed)
Patch Set: Comments from dskiba. Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tracing/bin/symbolize_trace_atos_regex.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tracing/bin/symbolize_trace
diff --git a/tracing/bin/symbolize_trace b/tracing/bin/symbolize_trace
index ecfbb673bf0c46bbbcb4dce0f414a68388f237fe..adb26739cce3c75165c50ab153e0cb2cde19d0c3 100755
--- a/tracing/bin/symbolize_trace
+++ b/tracing/bin/symbolize_trace
@@ -22,6 +22,8 @@ sys.path.append(_SYMBOLS_PATH)
# pylint: disable=import-error
import symbols.elf_symbolizer as elf_symbolizer
+import symbolize_trace_atos_regex
+
# Relevant trace event phases from Chromium's
# src/base/trace_event/common/trace_event_common.h.
@@ -52,10 +54,82 @@ def FindInSystemPath(binary_name):
return None
+class Symbolizer(object):
+ # Encapsulates platform-specific symbolization logic.
+ def __init__(self):
+ self.is_mac = sys.platform == 'darwin'
+ if self.is_mac:
+ self.binary = 'atos'
+ self._matcher = symbolize_trace_atos_regex.AtosRegexMatcher()
+ else:
+ self.binary = 'addr2line'
+ self.symbolizer_path = FindInSystemPath(self.binary)
+
+ def _SymbolizeLinuxAndAndroid(self, symfile):
+ def _SymbolizerCallback(sym_info, frames):
+ # Unwind inline chain to the top.
+ while sym_info.inlined_by:
+ sym_info = sym_info.inlined_by
+
+ symbolized_name = sym_info.name if sym_info.name else unsymbolized_name
+ for frame in frames:
+ frame.name = symbolized_name
+
+ symbolizer = elf_symbolizer.ELFSymbolizer(symfile.symbolizable_path,
+ self.symbolizer_path,
+ _SymbolizerCallback,
+ inlines=True)
+
+ for address, frames in symfile.frames_by_address.iteritems():
+ # SymbolizeAsync() asserts that the type of address is int. We operate
+ # on longs (since they are raw pointers possibly from 64-bit processes).
+ # It's OK to cast here because we're passing relative PC, which should
+ # always fit into int.
+ symbolizer.SymbolizeAsync(int(address), frames)
+
+ symbolizer.Join()
+
+ def _SymbolizeMac(self, symfile):
+ chars_max = int(subprocess.check_output("getconf ARG_MAX", shell=True))
+
+ # 16 for the address, 2 for "0x", 1 for the space
+ chars_per_address = 19
+
+ cmd_base = [self.symbolizer_path, '-arch', 'x86_64', '-l',
+ '0x0', '-o' , symfile.symbolizable_path]
+ chars_for_other_arguments = len(' '.join(cmd_base)) + 1
+
+ # The maximum number of inputs that can be processed at once is limited by
+ # ARG_MAX. This currently evalutes to ~13000 on macOS.
+ max_inputs = (chars_max - chars_for_other_arguments) / chars_per_address
+
+ all_keys = symfile.frames_by_address.keys()
+ processed_keys_count = 0
+ while len(all_keys):
+ input_count = min(len(all_keys), max_inputs)
+ keys_to_process = all_keys[0:input_count]
+
+ cmd = list(cmd_base)
+ cmd.extend([hex(int(x)) for x in keys_to_process])
+ output_array = subprocess.check_output(cmd).split('\n')
+ for i in range(len(keys_to_process)):
+ for frame in symfile.frames_by_address.values()[i + processed_keys_count]:
+ frame.name = self._matcher.Match(output_array[i])
+ processed_keys_count += len(keys_to_process)
+ all_keys = all_keys[input_count:]
+
+ def Symbolize(self, symfile):
+ if self.is_mac:
+ self._SymbolizeMac(symfile)
+ else:
+ self._SymbolizeLinuxAndAndroid(symfile)
+
+
def IsSymbolizableFile(file_path):
result = subprocess.check_output(['file', '-0', file_path])
type_string = result[result.find('\0') + 1:]
- return bool(re.match(r'\: (ELF|Mach-O) (32|64)-bit\b', type_string))
+ return bool(re.match(r'.*(ELF|Mach-O) (32|64)-bit\b.*',
+ type_string, re.DOTALL))
class ProcessMemoryMaps(object):
@@ -271,7 +345,7 @@ def ResolveSymbolizableFiles(processes):
return symfile_by_path.values()
-def SymbolizeFiles(symfiles, addr2line_path):
+def SymbolizeFiles(symfiles, symbolizer):
"""Symbolizes each file in the given list of SymbolizableFiles
and updates stack frames with symbolization results."""
print 'Symbolizing...'
@@ -301,32 +375,11 @@ def SymbolizeFiles(symfiles, addr2line_path):
frame.name = unsymbolized_name
continue
- def _SymbolizerCallback(sym_info, frames):
- # Unwind inline chain to the top.
- while sym_info.inlined_by:
- sym_info = sym_info.inlined_by
-
- symbolized_name = sym_info.name if sym_info.name else unsymbolized_name
- for frame in frames:
- frame.name = symbolized_name
-
- symbolizer = elf_symbolizer.ELFSymbolizer(symfile.symbolizable_path,
- addr2line_path,
- _SymbolizerCallback,
- inlines=True)
-
_SubPrintf('Symbolizing {} PCs from {}...',
len(symfile.frames_by_address),
symfile.path)
- for address, frames in symfile.frames_by_address.iteritems():
- # SymbolizeAsync() asserts that the type of address is int. We operate
- # on longs (since they are raw pointers possibly from 64-bit processes).
- # It's OK to cast here because we're passing relative PC, which should
- # always fit into int.
- symbolizer.SymbolizeAsync(int(address), frames)
-
- symbolizer.Join()
+ symbolizer.Symbolize(symfile)
symbolized = True
return symbolized
@@ -372,9 +425,9 @@ def main():
else:
return open(trace_file_path, mode + 't')
- addr2line_path = FindInSystemPath('addr2line')
- if addr2line_path is None:
- sys.exit("Can't symbolize - no addr2line in PATH.")
+ symbolizer = Symbolizer()
+ if symbolizer.symbolizer_path is None:
+ sys.exit("Can't symbolize - no %s in PATH." % symbolizer.binary)
print 'Reading trace file...'
with _OpenTraceFile('r') as trace_file:
@@ -392,7 +445,7 @@ def main():
'symbolize it.')
RemapAndroidFiles(symfiles, os.path.abspath(options.output_directory))
- if SymbolizeFiles(symfiles, addr2line_path):
+ if SymbolizeFiles(symfiles, symbolizer):
if options.backup:
backup_file_path = trace_file_path + BACKUP_FILE_TAG
print 'Backing up trace file to {}...'.format(backup_file_path)
« no previous file with comments | « no previous file | tracing/bin/symbolize_trace_atos_regex.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698