[Lldb-commits] [lldb] r231415 - symbolicate the application specific backtraces that are in MacOSX crash log files.
Greg Clayton
gclayton at apple.com
Thu Mar 5 14:53:06 PST 2015
Author: gclayton
Date: Thu Mar 5 16:53:06 2015
New Revision: 231415
URL: http://llvm.org/viewvc/llvm-project?rev=231415&view=rev
Log:
symbolicate the application specific backtraces that are in MacOSX crash log files.
<rdar://problem/20039160>
Modified:
lldb/trunk/examples/python/crashlog.py
lldb/trunk/examples/python/symbolication.py
Modified: lldb/trunk/examples/python/crashlog.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/crashlog.py?rev=231415&r1=231414&r2=231415&view=diff
==============================================================================
--- lldb/trunk/examples/python/crashlog.py (original)
+++ lldb/trunk/examples/python/crashlog.py Thu Mar 5 16:53:06 2015
@@ -86,23 +86,28 @@ class CrashLog(symbolication.Symbolicato
parent_process_regex = re.compile('^Parent Process:\s*(.*)\[(\d+)\]');
thread_state_regex = re.compile('^Thread ([0-9]+) crashed with')
thread_regex = re.compile('^Thread ([0-9]+)([^:]*):(.*)')
- frame_regex = re.compile('^([0-9]+) +([^ ]+) *\t?(0x[0-9a-fA-F]+) +(.*)')
+ app_backtrace_regex = re.compile('^Application Specific Backtrace ([0-9]+)([^:]*):(.*)')
+ frame_regex = re.compile('^([0-9]+)\s+([^ ]+)\s+(0x[0-9a-fA-F]+) +(.*)')
image_regex_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^<]+)<([-0-9a-fA-F]+)> (.*)');
image_regex_no_uuid = re.compile('(0x[0-9a-fA-F]+)[- ]+(0x[0-9a-fA-F]+) +[+]?([^ ]+) +([^/]+)/(.*)');
empty_line_regex = re.compile('^$')
class Thread:
"""Class that represents a thread in a darwin crash log"""
- def __init__(self, index):
+ def __init__(self, index, app_specific_backtrace):
self.index = index
self.frames = list()
self.idents = list()
self.registers = dict()
self.reason = None
self.queue = None
+ self.app_specific_backtrace = app_specific_backtrace
def dump(self, prefix):
- print "%sThread[%u] %s" % (prefix, self.index, self.reason)
+ if self.app_specific_backtrace:
+ print "%Application Specific Backtrace[%u] %s" % (prefix, self.index, self.reason)
+ else:
+ print "%sThread[%u] %s" % (prefix, self.index, self.reason)
if self.frames:
print "%s Frames:" % (prefix)
for frame in self.frames:
@@ -112,6 +117,57 @@ class CrashLog(symbolication.Symbolicato
for reg in self.registers.keys():
print "%s %-5s = %#16.16x" % (prefix, reg, self.registers[reg])
+ def dump_symbolicated (self, crash_log, options):
+ this_thread_crashed = self.app_specific_backtrace
+ if not this_thread_crashed:
+ this_thread_crashed = self.did_crash()
+ if options.crashed_only and this_thread_crashed == False:
+ return
+
+ print "%s" % self
+ #prev_frame_index = -1
+ display_frame_idx = -1
+ for frame_idx, frame in enumerate(self.frames):
+ disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
+ if frame_idx == 0:
+ symbolicated_frame_addresses = crash_log.symbolicate (frame.pc & crash_log.addr_mask, options.verbose)
+ else:
+ # Any frame above frame zero and we have to subtract one to get the previous line entry
+ symbolicated_frame_addresses = crash_log.symbolicate ((frame.pc & crash_log.addr_mask) - 1, options.verbose)
+
+ if symbolicated_frame_addresses:
+ symbolicated_frame_address_idx = 0
+ for symbolicated_frame_address in symbolicated_frame_addresses:
+ display_frame_idx += 1
+ print '[%3u] %s' % (frame_idx, symbolicated_frame_address)
+ if (options.source_all or self.did_crash()) and display_frame_idx < options.source_frames and options.source_context:
+ source_context = options.source_context
+ line_entry = symbolicated_frame_address.get_symbol_context().line_entry
+ if line_entry.IsValid():
+ strm = lldb.SBStream()
+ if line_entry:
+ lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(line_entry.file, line_entry.line, source_context, source_context, "->", strm)
+ source_text = strm.GetData()
+ if source_text:
+ # Indent the source a bit
+ indent_str = ' '
+ join_str = '\n' + indent_str
+ print '%s%s' % (indent_str, join_str.join(source_text.split('\n')))
+ if symbolicated_frame_address_idx == 0:
+ if disassemble:
+ instructions = symbolicated_frame_address.get_instructions()
+ if instructions:
+ print
+ symbolication.disassemble_instructions (crash_log.get_target(),
+ instructions,
+ frame.pc,
+ options.disassemble_before,
+ options.disassemble_after, frame.index > 0)
+ print
+ symbolicated_frame_address_idx += 1
+ else:
+ print frame
+
def add_ident(self, ident):
if not ident in self.idents:
self.idents.append(ident)
@@ -120,7 +176,10 @@ class CrashLog(symbolication.Symbolicato
return self.reason != None
def __str__(self):
- s = "Thread[%u]" % self.index
+ if self.app_specific_backtrace:
+ s = "Application Specific Backtrace[%u]" % self.index
+ else:
+ s = "Thread[%u]" % self.index
if self.reason:
s += ' %s' % self.reason
return s
@@ -215,10 +274,12 @@ class CrashLog(symbolication.Symbolicato
self.info_lines = list()
self.system_profile = list()
self.threads = list()
+ self.backtraces = list() # For application specific backtraces
self.idents = list() # A list of the required identifiers for doing all stack backtraces
self.crashed_thread_idx = -1
self.version = -1
self.error = None
+ self.target = None
# With possible initial component of ~ or ~user replaced by that user's home directory.
try:
f = open(self.path)
@@ -229,6 +290,7 @@ class CrashLog(symbolication.Symbolicato
self.file_lines = f.read().splitlines()
parse_mode = PARSE_MODE_NORMAL
thread = None
+ app_specific_backtrace = False
for line in self.file_lines:
# print line
line_len = len(line)
@@ -240,8 +302,11 @@ class CrashLog(symbolication.Symbolicato
if self.thread_exception:
thread.reason += self.thread_exception
if self.thread_exception_data:
- thread.reason += " (%s)" % self.thread_exception_data
- self.threads.append(thread)
+ thread.reason += " (%s)" % self.thread_exception_data
+ if app_specific_backtrace:
+ self.backtraces.append(thread)
+ else:
+ self.threads.append(thread)
thread = None
else:
# only append an extra empty line if the previous line
@@ -297,6 +362,7 @@ class CrashLog(symbolication.Symbolicato
elif line.startswith ('Thread'):
thread_state_match = self.thread_state_regex.search (line)
if thread_state_match:
+ app_specific_backtrace = False
thread_state_match = self.thread_regex.search (line)
thread_idx = int(thread_state_match.group(1))
parse_mode = PARSE_MODE_THREGS
@@ -304,14 +370,21 @@ class CrashLog(symbolication.Symbolicato
else:
thread_match = self.thread_regex.search (line)
if thread_match:
- # print 'PARSE_MODE_THREAD'
+ app_specific_backtrace = False
parse_mode = PARSE_MODE_THREAD
thread_idx = int(thread_match.group(1))
- thread = CrashLog.Thread(thread_idx)
+ thread = CrashLog.Thread(thread_idx, False)
continue
elif line.startswith ('Binary Images:'):
parse_mode = PARSE_MODE_IMAGES
continue
+ elif line.startswith ('Application Specific Backtrace'):
+ app_backtrace_match = self.app_backtrace_regex.search (line)
+ if app_backtrace_match:
+ parse_mode = PARSE_MODE_THREAD
+ app_specific_backtrace = True
+ idx = int(app_backtrace_match.group(1))
+ thread = CrashLog.Thread(idx, True)
self.info_lines.append(line.strip())
elif parse_mode == PARSE_MODE_THREAD:
if line.startswith ('Thread'):
@@ -364,6 +437,10 @@ class CrashLog(symbolication.Symbolicato
def dump(self):
print "Crash Log File: %s" % (self.path)
+ if self.backtraces:
+ print "\nApplication Specific Backtraces:"
+ for thread in self.backtraces:
+ thread.dump(' ')
print "\nThreads:"
for thread in self.threads:
thread.dump(' ')
@@ -374,32 +451,40 @@ class CrashLog(symbolication.Symbolicato
def find_image_with_identifier(self, identifier):
for image in self.images:
if image.identifier == identifier:
+ return image
+ regex_text = '^.*\.%s$' % (identifier)
+ regex = re.compile(regex_text)
+ for image in self.images:
+ if regex.match(image.identifier):
return image
return None
def create_target(self):
#print 'crashlog.create_target()...'
- target = symbolication.Symbolicator.create_target(self)
- if target:
- return target
- # We weren't able to open the main executable as, but we can still symbolicate
- print 'crashlog.create_target()...2'
- if self.idents:
- for ident in self.idents:
- image = self.find_image_with_identifier (ident)
- if image:
- target = image.create_target ()
- if target:
- return target # success
- print 'crashlog.create_target()...3'
- for image in self.images:
- target = image.create_target ()
- if target:
- return target # success
- print 'crashlog.create_target()...4'
- print 'error: unable to locate any executables from the crash log'
- return None
+ if self.target is None:
+ self.target = symbolication.Symbolicator.create_target(self)
+ if self.target:
+ return self.target
+ # We weren't able to open the main executable as, but we can still symbolicate
+ print 'crashlog.create_target()...2'
+ if self.idents:
+ for ident in self.idents:
+ image = self.find_image_with_identifier (ident)
+ if image:
+ self.target = image.create_target ()
+ if self.target:
+ return self.target # success
+ print 'crashlog.create_target()...3'
+ for image in self.images:
+ self.target = image.create_target ()
+ if self.target:
+ return self.target # success
+ print 'crashlog.create_target()...4'
+ print 'error: unable to locate any executables from the crash log'
+ return self.target
+ def get_target(self):
+ return self.target
def usage():
print "Usage: lldb-symbolicate.py [-n name] executable-image"
@@ -661,9 +746,7 @@ def SymbolicateCrashLog(crash_log, optio
print 'error: can\'t find image for identifier "%s"' % ident
for image in images_to_load:
- if image in loaded_images:
- print "warning: skipping %s loaded at %#16.16x duplicate entry (probably commpage)" % (image.path, image.text_addr_lo)
- else:
+ if not image in loaded_images:
err = image.add_module (target)
if err:
print err
@@ -671,55 +754,16 @@ def SymbolicateCrashLog(crash_log, optio
#print 'loaded %s' % image
loaded_images.append(image)
+ if crash_log.backtraces:
+ for thread in crash_log.backtraces:
+ thread.dump_symbolicated (crash_log, options)
+ print
+
for thread in crash_log.threads:
- this_thread_crashed = thread.did_crash()
- if options.crashed_only and this_thread_crashed == False:
- continue
- print "%s" % thread
- #prev_frame_index = -1
- display_frame_idx = -1
- for frame_idx, frame in enumerate(thread.frames):
- disassemble = (this_thread_crashed or options.disassemble_all_threads) and frame_idx < options.disassemble_depth;
- if frame_idx == 0:
- symbolicated_frame_addresses = crash_log.symbolicate (frame.pc & crash_log.addr_mask, options.verbose)
- else:
- # Any frame above frame zero and we have to subtract one to get the previous line entry
- symbolicated_frame_addresses = crash_log.symbolicate ((frame.pc & crash_log.addr_mask) - 1, options.verbose)
-
- if symbolicated_frame_addresses:
- symbolicated_frame_address_idx = 0
- for symbolicated_frame_address in symbolicated_frame_addresses:
- display_frame_idx += 1
- print '[%3u] %s' % (frame_idx, symbolicated_frame_address)
- if (options.source_all or thread.did_crash()) and display_frame_idx < options.source_frames and options.source_context:
- source_context = options.source_context
- line_entry = symbolicated_frame_address.get_symbol_context().line_entry
- if line_entry.IsValid():
- strm = lldb.SBStream()
- if line_entry:
- lldb.debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers(line_entry.file, line_entry.line, source_context, source_context, "->", strm)
- source_text = strm.GetData()
- if source_text:
- # Indent the source a bit
- indent_str = ' '
- join_str = '\n' + indent_str
- print '%s%s' % (indent_str, join_str.join(source_text.split('\n')))
- if symbolicated_frame_address_idx == 0:
- if disassemble:
- instructions = symbolicated_frame_address.get_instructions()
- if instructions:
- print
- symbolication.disassemble_instructions (target,
- instructions,
- frame.pc,
- options.disassemble_before,
- options.disassemble_after, frame.index > 0)
- print
- symbolicated_frame_address_idx += 1
- else:
- print frame
+ thread.dump_symbolicated (crash_log, options)
print
+
def CreateSymbolicateCrashLogOptions(command_name, description, add_interactive_options):
usage = "usage: %prog [options] <FILE> [FILE ...]"
option_parser = optparse.OptionParser(description=description, prog='crashlog',usage=usage)
Modified: lldb/trunk/examples/python/symbolication.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/python/symbolication.py?rev=231415&r1=231414&r2=231415&view=diff
==============================================================================
--- lldb/trunk/examples/python/symbolication.py (original)
+++ lldb/trunk/examples/python/symbolication.py Thu Mar 5 16:53:06 2015
@@ -447,6 +447,12 @@ class Symbolicator:
for image in self.images:
if image.identifier == identifier:
images.append(image)
+ if len(images) == 0:
+ regex_text = '^.*\.%s$' % (identifier)
+ regex = re.compile(regex_text)
+ for image in self.images:
+ if regex.match(image.identifier):
+ images.append(image)
return images
def find_image_containing_load_addr(self, load_addr):
More information about the lldb-commits
mailing list