2012-04-03 21:35:43 +00:00
#!/usr/bin/python
#----------------------------------------------------------------------
# Be sure to add the python path that points to the LLDB shared library.
#
# To use this in the embedded python interpreter using "lldb":
#
# cd /path/containing/crashlog.py
# lldb
# (lldb) script import crashlog
# "crashlog" command installed, type "crashlog --help" for detailed help
# (lldb) crashlog ~/Library/Logs/DiagnosticReports/a.crash
#
# The benefit of running the crashlog command inside lldb in the
# embedded python interpreter is when the command completes, there
# will be a target with all of the files loaded at the locations
# described in the crash log. Only the files that have stack frames
# in the backtrace will be loaded unless the "--load-all" option
# has been specified. This allows users to explore the program in the
# state it was in right at crash time.
#
# On MacOSX csh, tcsh:
# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash )
#
# On MacOSX sh, bash:
# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash
#----------------------------------------------------------------------
2019-03-06 23:50:36 +00:00
from __future__ import print_function
2012-04-03 21:35:43 +00:00
import lldb
import optparse
import os
import plistlib
import re
import shlex
import sys
import time
import uuid
2016-09-06 20:57:50 +00:00
2019-03-05 01:34:47 +00:00
class Address :
2012-04-03 21:35:43 +00:00
""" Class that represents an address that will be symbolicated """
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def __init__ ( self , target , load_addr ) :
self . target = target
self . load_addr = load_addr # The load address that this object represents
# the resolved lldb.SBAddress (if any), named so_addr for
# section/offset address
self . so_addr = None
self . sym_ctx = None # The cached symbol context for this address
# Any original textual description of this address to be used as a
# backup in case symbolication fails
self . description = None
self . symbolication = None # The cached symbolicated string that describes this address
self . inlined = False
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def __str__ ( self ) :
s = " %#16.16x " % ( self . load_addr )
if self . symbolication :
s + = " %s " % ( self . symbolication )
elif self . description :
s + = " %s " % ( self . description )
elif self . so_addr :
s + = " %s " % ( self . so_addr )
return s
def resolve_addr ( self ) :
if self . so_addr is None :
self . so_addr = self . target . ResolveLoadAddress ( self . load_addr )
return self . so_addr
def is_inlined ( self ) :
return self . inlined
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def get_symbol_context ( self ) :
if self . sym_ctx is None :
sb_addr = self . resolve_addr ( )
if sb_addr :
self . sym_ctx = self . target . ResolveSymbolContextForAddress (
sb_addr , lldb . eSymbolContextEverything )
else :
self . sym_ctx = lldb . SBSymbolContext ( )
return self . sym_ctx
def get_instructions ( self ) :
sym_ctx = self . get_symbol_context ( )
if sym_ctx :
function = sym_ctx . GetFunction ( )
if function :
return function . GetInstructions ( self . target )
return sym_ctx . GetSymbol ( ) . GetInstructions ( self . target )
return None
2016-09-06 20:57:50 +00:00
2012-06-28 18:10:14 +00:00
def symbolicate ( self , verbose = False ) :
2012-04-03 21:35:43 +00:00
if self . symbolication is None :
self . symbolication = ' '
self . inlined = False
sym_ctx = self . get_symbol_context ( )
if sym_ctx :
module = sym_ctx . GetModule ( )
if module :
2012-06-28 18:10:14 +00:00
# Print full source file path in verbose mode
if verbose :
self . symbolication + = str ( module . GetFileSpec ( ) ) + ' ` '
else :
self . symbolication + = module . GetFileSpec ( ) . GetFilename ( ) + ' ` '
2012-04-03 21:35:43 +00:00
function_start_load_addr = - 1
function = sym_ctx . GetFunction ( )
block = sym_ctx . GetBlock ( )
line_entry = sym_ctx . GetLineEntry ( )
symbol = sym_ctx . GetSymbol ( )
inlined_block = block . GetContainingInlinedBlock ( )
if function :
self . symbolication + = function . GetName ( )
if inlined_block :
self . inlined = True
self . symbolication + = ' [inlined] ' + \
inlined_block . GetInlinedName ( )
block_range_idx = inlined_block . GetRangeIndexForBlockAddress (
self . so_addr )
if block_range_idx < lldb . UINT32_MAX :
block_range_start_addr = inlined_block . GetRangeStartAddress (
block_range_idx )
function_start_load_addr = block_range_start_addr . GetLoadAddress (
self . target )
if function_start_load_addr == - 1 :
function_start_load_addr = function . GetStartAddress ( ) . GetLoadAddress ( self . target )
elif symbol :
self . symbolication + = symbol . GetName ( )
function_start_load_addr = symbol . GetStartAddress ( ) . GetLoadAddress ( self . target )
else :
self . symbolication = ' '
return False
# Dump the offset from the current function or symbol if it
# is non zero
function_offset = self . load_addr - function_start_load_addr
if function_offset > 0 :
self . symbolication + = " + %u " % ( function_offset )
elif function_offset < 0 :
self . symbolication + = " %i (invalid negative offset, file a bug) " % function_offset
# Print out any line information if any is available
if line_entry . GetFileSpec ( ) :
2012-06-28 18:10:14 +00:00
# Print full source file path in verbose mode
if verbose :
self . symbolication + = ' at %s ' % line_entry . GetFileSpec ( )
else :
2012-04-03 21:35:43 +00:00
self . symbolication + = ' at %s ' % line_entry . GetFileSpec ( ) . GetFilename ( )
2012-06-28 18:10:14 +00:00
self . symbolication + = ' : %u ' % line_entry . GetLine ( )
column = line_entry . GetColumn ( )
if column > 0 :
self . symbolication + = ' : %u ' % column
2012-04-03 21:35:43 +00:00
return True
return False
2016-09-06 20:57:50 +00:00
2019-03-05 01:34:47 +00:00
class Section :
2012-04-03 21:35:43 +00:00
""" Class that represents an load address range """
sect_info_regex = re . compile ( ' (?P<name>[^=]+)=(?P<range>.*) ' )
addr_regex = re . compile ( ' ^ \ s*(?P<start>0x[0-9A-Fa-f]+) \ s*$ ' )
range_regex = re . compile (
' ^ \ s*(?P<start>0x[0-9A-Fa-f]+) \ s*(?P<op>[-+]) \ s*(?P<end>0x[0-9A-Fa-f]+) \ s*$ ' )
def __init__ ( self , start_addr = None , end_addr = None , name = None ) :
self . start_addr = start_addr
self . end_addr = end_addr
self . name = name
2016-09-06 20:57:50 +00:00
2014-05-28 00:21:15 +00:00
@classmethod
def InitWithSBTargetAndSBSection ( cls , target , section ) :
sect_load_addr = section . GetLoadAddress ( target )
if sect_load_addr != lldb . LLDB_INVALID_ADDRESS :
obj = cls (
sect_load_addr ,
sect_load_addr +
section . size ,
section . name )
return obj
else :
return None
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def contains ( self , addr ) :
return self . start_addr < = addr and addr < self . end_addr
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def set_from_string ( self , s ) :
match = self . sect_info_regex . match ( s )
if match :
self . name = match . group ( ' name ' )
range_str = match . group ( ' range ' )
addr_match = self . addr_regex . match ( range_str )
if addr_match :
self . start_addr = int ( addr_match . group ( ' start ' ) , 16 )
self . end_addr = None
return True
range_match = self . range_regex . match ( range_str )
if range_match :
self . start_addr = int ( range_match . group ( ' start ' ) , 16 )
self . end_addr = int ( range_match . group ( ' end ' ) , 16 )
op = range_match . group ( ' op ' )
if op == ' + ' :
self . end_addr + = self . start_addr
return True
2019-03-06 22:54:11 +00:00
print ( ' error: invalid section info string " %s " ' % s )
print ( ' Valid section info formats are: ' )
print ( ' Format Example Description ' )
print ( ' --------------------- ----------------------------------------------- ' )
print ( ' <name>=<base> __TEXT=0x123000 Section from base address only ' )
print ( ' <name>=<base>-<end> __TEXT=0x123000-0x124000 Section from base address and end address ' )
print ( ' <name>=<base>+<size> __TEXT=0x123000+0x1000 Section from base address and size ' )
2012-04-03 21:35:43 +00:00
return False
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def __str__ ( self ) :
if self . name :
if self . end_addr is not None :
if self . start_addr is not None :
return " %s =[0x %16.16x - 0x %16.16x ) " % (
self . name , self . start_addr , self . end_addr )
else :
if self . start_addr is not None :
return " %s =0x %16.16x " % ( self . name , self . start_addr )
return self . name
return " <invalid> "
2016-09-06 20:57:50 +00:00
2019-03-05 01:34:47 +00:00
class Image :
2012-04-03 21:35:43 +00:00
""" A class that represents an executable image and any associated data """
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def __init__ ( self , path , uuid = None ) :
self . path = path
self . resolved_path = None
2012-06-04 23:22:17 +00:00
self . resolved = False
self . unavailable = False
2012-04-03 21:35:43 +00:00
self . uuid = uuid
self . section_infos = list ( )
self . identifier = None
self . version = None
self . arch = None
self . module = None
self . symfile = None
self . slide = None
2016-09-06 20:57:50 +00:00
2014-05-28 00:21:15 +00:00
@classmethod
def InitWithSBTargetAndSBModule ( cls , target , module ) :
2015-09-22 05:07:56 +00:00
''' Initialize this Image object with a module from a target. '''
2014-05-28 00:21:15 +00:00
obj = cls ( module . file . fullpath , module . uuid )
obj . resolved_path = module . platform_file . fullpath
obj . resolved = True
for section in module . sections :
symb_section = Section . InitWithSBTargetAndSBSection (
target , section )
if symb_section :
obj . section_infos . append ( symb_section )
obj . arch = module . triple
obj . module = module
obj . symfile = None
obj . slide = None
return obj
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def dump ( self , prefix ) :
2019-03-06 22:54:11 +00:00
print ( " %s %s " % ( prefix , self ) )
2012-08-29 21:13:06 +00:00
def debug_dump ( self ) :
2019-03-06 22:54:11 +00:00
print ( ' path = " %s " ' % ( self . path ) )
print ( ' resolved_path = " %s " ' % ( self . resolved_path ) )
print ( ' resolved = %i ' % ( self . resolved ) )
print ( ' unavailable = %i ' % ( self . unavailable ) )
print ( ' uuid = %s ' % ( self . uuid ) )
print ( ' section_infos = %s ' % ( self . section_infos ) )
print ( ' identifier = " %s " ' % ( self . identifier ) )
print ( ' version = %s ' % ( self . version ) )
print ( ' arch = %s ' % ( self . arch ) )
print ( ' module = %s ' % ( self . module ) )
print ( ' symfile = " %s " ' % ( self . symfile ) )
print ( ' slide = %i (0x %x ) ' % ( self . slide , self . slide ) )
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def __str__ ( self ) :
2014-05-28 00:21:15 +00:00
s = ' '
if self . uuid :
s + = " %s " % ( self . get_uuid ( ) )
if self . arch :
s + = " %s " % ( self . arch )
if self . version :
s + = " %s " % ( self . version )
resolved_path = self . get_resolved_path ( )
if resolved_path :
s + = " %s " % ( resolved_path )
2012-04-03 21:35:43 +00:00
for section_info in self . section_infos :
s + = " , %s " % ( section_info )
if self . slide is not None :
s + = ' , slide = 0x %16.16x ' % self . slide
return s
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def add_section ( self , section ) :
# print "added '%s' to '%s'" % (section, self.path)
self . section_infos . append ( section )
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def get_section_containing_load_addr ( self , load_addr ) :
for section_info in self . section_infos :
if section_info . contains ( load_addr ) :
return section_info
return None
def get_resolved_path ( self ) :
if self . resolved_path :
return self . resolved_path
elif self . path :
return self . path
return None
def get_resolved_path_basename ( self ) :
path = self . get_resolved_path ( )
if path :
return os . path . basename ( path )
return None
def symfile_basename ( self ) :
if self . symfile :
return os . path . basename ( self . symfile )
return None
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def has_section_load_info ( self ) :
return self . section_infos or self . slide is not None
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def load_module ( self , target ) :
2012-06-04 23:22:17 +00:00
if self . unavailable :
return None # We already warned that we couldn't find this module, so don't return an error string
2012-04-03 21:35:43 +00:00
# Load this module into "target" using the section infos to
# set the section load addresses
if self . has_section_load_info ( ) :
if target :
if self . module :
if self . section_infos :
num_sections_loaded = 0
for section_info in self . section_infos :
if section_info . name :
section = self . module . FindSection (
section_info . name )
if section :
error = target . SetSectionLoadAddress (
section , section_info . start_addr )
if error . Success ( ) :
num_sections_loaded + = 1
else :
return ' error: %s ' % error . GetCString ( )
else :
return ' error: unable to find the section named " %s " ' % section_info . name
else :
return ' error: unable to find " %s " section in " %s " ' % (
range . name , self . get_resolved_path ( ) )
if num_sections_loaded == 0 :
return ' error: no sections were successfully loaded '
else :
err = target . SetModuleLoadAddress (
self . module , self . slide )
if err . Fail ( ) :
return err . GetCString ( )
return None
else :
return ' error: invalid module '
else :
return ' error: invalid target '
else :
return ' error: no section infos '
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def add_module ( self , target ) :
''' Add the Image described in this object to " target " and load the sections if " load " is True. '''
if target :
# Try and find using UUID only first so that paths need not match
# up
2012-05-11 00:30:14 +00:00
uuid_str = self . get_normalized_uuid_string ( )
if uuid_str :
self . module = target . AddModule ( None , None , uuid_str )
2012-04-03 21:35:43 +00:00
if not self . module :
2012-04-20 23:31:27 +00:00
self . locate_module_and_debug_symbols ( )
2012-06-04 23:22:17 +00:00
if self . unavailable :
return None
2012-04-20 23:31:27 +00:00
resolved_path = self . get_resolved_path ( )
2012-05-11 00:30:14 +00:00
self . module = target . AddModule (
2019-07-29 21:25:37 +00:00
resolved_path , str ( self . arch ) , uuid_str , self . symfile )
2012-04-03 21:35:43 +00:00
if not self . module :
2012-04-20 23:31:27 +00:00
return ' error: unable to get module for ( %s ) " %s " ' % (
self . arch , self . get_resolved_path ( ) )
2012-04-03 21:35:43 +00:00
if self . has_section_load_info ( ) :
return self . load_module ( target )
else :
return None # No sections, the module was added to the target, so success
else :
return ' error: invalid target '
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def locate_module_and_debug_symbols ( self ) :
# By default, just use the paths that were supplied in:
# self.path
# self.resolved_path
# self.module
# self.symfile
# Subclasses can inherit from this class and override this function
2012-06-04 23:22:17 +00:00
self . resolved = True
2012-04-03 21:35:43 +00:00
return True
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def get_uuid ( self ) :
2012-05-11 00:30:14 +00:00
if not self . uuid and self . module :
2012-04-03 21:35:43 +00:00
self . uuid = uuid . UUID ( self . module . GetUUIDString ( ) )
return self . uuid
2012-05-11 00:30:14 +00:00
def get_normalized_uuid_string ( self ) :
if self . uuid :
return str ( self . uuid ) . upper ( )
return None
2012-04-03 21:35:43 +00:00
def create_target ( self ) :
''' Create a target using the information in this Image object. '''
2012-06-04 23:22:17 +00:00
if self . unavailable :
return None
2012-04-03 21:35:43 +00:00
if self . locate_module_and_debug_symbols ( ) :
resolved_path = self . get_resolved_path ( )
path_spec = lldb . SBFileSpec ( resolved_path )
error = lldb . SBError ( )
target = lldb . debugger . CreateTarget (
resolved_path , self . arch , None , False , error )
if target :
self . module = target . FindModule ( path_spec )
if self . has_section_load_info ( ) :
err = self . load_module ( target )
if err :
2019-03-06 22:54:11 +00:00
print ( ' ERROR: ' , err )
2012-04-03 21:35:43 +00:00
return target
else :
2019-03-06 22:54:11 +00:00
print ( ' error: unable to create a valid target for ( %s ) " %s " ' % ( self . arch , self . path ) )
2012-04-03 21:35:43 +00:00
else :
2019-03-06 22:54:11 +00:00
print ( ' error: unable to locate main executable ( %s ) " %s " ' % ( self . arch , self . path ) )
2012-04-03 21:35:43 +00:00
return None
2016-09-06 20:57:50 +00:00
2019-03-05 01:34:47 +00:00
class Symbolicator :
2012-04-03 21:35:43 +00:00
def __init__ ( self ) :
""" A class the represents the information needed to symbolicate addresses in a program """
self . target = None
self . images = list ( ) # a list of images to be used when symbolicating
2013-04-04 23:36:51 +00:00
self . addr_mask = 0xffffffffffffffff
2016-09-06 20:57:50 +00:00
2014-05-28 00:21:15 +00:00
@classmethod
def InitWithSBTarget ( cls , target ) :
obj = cls ( )
obj . target = target
obj . images = list ( )
triple = target . triple
if triple :
arch = triple . split ( ' - ' ) [ 0 ]
if " arm " in arch :
obj . addr_mask = 0xfffffffffffffffe
for module in target . modules :
image = Image . InitWithSBTargetAndSBModule ( target , module )
obj . images . append ( image )
return obj
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def __str__ ( self ) :
s = " Symbolicator: \n "
if self . target :
s + = " Target = ' %s ' \n " % ( self . target )
2014-05-28 00:21:15 +00:00
s + = " Target modules: \n "
2012-04-03 21:35:43 +00:00
for m in self . target . modules :
2014-05-28 00:21:15 +00:00
s + = str ( m ) + " \n "
2012-04-03 21:35:43 +00:00
s + = " Images: \n "
for image in self . images :
s + = ' %s \n ' % ( image )
return s
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def find_images_with_identifier ( self , identifier ) :
images = list ( )
for image in self . images :
if image . identifier == identifier :
images . append ( image )
2015-03-05 22:53:06 +00:00
if len ( images ) == 0 :
2016-06-10 20:09:33 +00:00
regex_text = ' ^.* \ . %s $ ' % ( re . escape ( identifier ) )
2015-03-05 22:53:06 +00:00
regex = re . compile ( regex_text )
for image in self . images :
if regex . match ( image . identifier ) :
images . append ( image )
2012-04-03 21:35:43 +00:00
return images
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def find_image_containing_load_addr ( self , load_addr ) :
for image in self . images :
2012-06-04 23:22:17 +00:00
if image . get_section_containing_load_addr ( load_addr ) :
2012-04-03 21:35:43 +00:00
return image
return None
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def create_target ( self ) :
if self . target :
return self . target
if self . images :
for image in self . images :
self . target = image . create_target ( )
if self . target :
2013-04-04 23:36:51 +00:00
if self . target . GetAddressByteSize ( ) == 4 :
triple = self . target . triple
if triple :
arch = triple . split ( ' - ' ) [ 0 ]
if " arm " in arch :
self . addr_mask = 0xfffffffffffffffe
2012-04-03 21:35:43 +00:00
return self . target
return None
2016-09-06 20:57:50 +00:00
2012-06-28 18:10:14 +00:00
def symbolicate ( self , load_addr , verbose = False ) :
2012-06-04 23:22:17 +00:00
if not self . target :
self . create_target ( )
2012-04-03 21:35:43 +00:00
if self . target :
2013-02-25 19:34:57 +00:00
live_process = False
process = self . target . process
if process :
state = process . state
2013-02-25 21:20:59 +00:00
if state > lldb . eStateUnloaded and state < lldb . eStateDetached :
2013-02-25 19:34:57 +00:00
live_process = True
# If we don't have a live process, we can attempt to find the image
# that a load address belongs to and lazily load its module in the
# target, but we shouldn't do any of this if we have a live process
if not live_process :
image = self . find_image_containing_load_addr ( load_addr )
if image :
image . add_module ( self . target )
2012-07-07 01:22:45 +00:00
symbolicated_address = Address ( self . target , load_addr )
if symbolicated_address . symbolicate ( verbose ) :
if symbolicated_address . so_addr :
symbolicated_addresses = list ( )
symbolicated_addresses . append ( symbolicated_address )
# See if we were able to reconstruct anything?
while True :
inlined_parent_so_addr = lldb . SBAddress ( )
inlined_parent_sym_ctx = symbolicated_address . sym_ctx . GetParentOfInlinedScope (
symbolicated_address . so_addr , inlined_parent_so_addr )
if not inlined_parent_sym_ctx :
break
if not inlined_parent_so_addr :
break
2012-04-03 21:35:43 +00:00
2012-07-07 01:22:45 +00:00
symbolicated_address = Address (
self . target , inlined_parent_so_addr . GetLoadAddress (
self . target ) )
symbolicated_address . sym_ctx = inlined_parent_sym_ctx
symbolicated_address . so_addr = inlined_parent_so_addr
symbolicated_address . symbolicate ( verbose )
2016-09-06 20:57:50 +00:00
2012-07-07 01:22:45 +00:00
# push the new frame onto the new frame stack
symbolicated_addresses . append ( symbolicated_address )
2016-09-06 20:57:50 +00:00
2012-07-07 01:22:45 +00:00
if symbolicated_addresses :
return symbolicated_addresses
2012-06-04 23:22:17 +00:00
else :
2019-03-06 22:54:11 +00:00
print ( ' error: no target in Symbolicator ' )
2012-04-03 21:35:43 +00:00
return None
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def disassemble_instructions (
target ,
instructions ,
pc ,
insts_before_pc ,
insts_after_pc ,
non_zeroeth_frame ) :
lines = list ( )
pc_index = - 1
comment_column = 50
for inst_idx , inst in enumerate ( instructions ) :
inst_pc = inst . GetAddress ( ) . GetLoadAddress ( target )
if pc == inst_pc :
pc_index = inst_idx
mnemonic = inst . GetMnemonic ( target )
operands = inst . GetOperands ( target )
comment = inst . GetComment ( target )
lines . append ( " %#16.16x : %8s %s " % ( inst_pc , mnemonic , operands ) )
if comment :
line_len = len ( lines [ - 1 ] )
if line_len < comment_column :
lines [ - 1 ] + = ' ' * ( comment_column - line_len )
lines [ - 1 ] + = " ; %s " % comment
if pc_index > = 0 :
# If we are disassembling the non-zeroeth frame, we need to backup the
# PC by 1
if non_zeroeth_frame and pc_index > 0 :
pc_index = pc_index - 1
if insts_before_pc == - 1 :
start_idx = 0
else :
start_idx = pc_index - insts_before_pc
if start_idx < 0 :
start_idx = 0
if insts_before_pc == - 1 :
end_idx = inst_idx
else :
end_idx = pc_index + insts_after_pc
if end_idx > inst_idx :
end_idx = inst_idx
for i in range ( start_idx , end_idx + 1 ) :
if i == pc_index :
2019-03-06 22:54:11 +00:00
print ( ' -> ' , lines [ i ] )
2012-04-03 21:35:43 +00:00
else :
2019-03-06 22:54:11 +00:00
print ( ' ' , lines [ i ] )
2012-04-03 21:35:43 +00:00
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def print_module_section_data ( section ) :
2019-03-06 22:54:11 +00:00
print ( section )
2012-04-03 21:35:43 +00:00
section_data = section . GetSectionData ( )
if section_data :
ostream = lldb . SBStream ( )
section_data . GetDescription ( ostream , section . GetFileAddress ( ) )
2019-03-06 22:54:11 +00:00
print ( ostream . GetData ( ) )
2012-04-03 21:35:43 +00:00
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def print_module_section ( section , depth ) :
2019-03-06 22:54:11 +00:00
print ( section )
2012-04-03 21:35:43 +00:00
if depth > 0 :
num_sub_sections = section . GetNumSubSections ( )
for sect_idx in range ( num_sub_sections ) :
print_module_section (
section . GetSubSectionAtIndex ( sect_idx ) , depth - 1 )
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def print_module_sections ( module , depth ) :
for sect in module . section_iter ( ) :
print_module_section ( sect , depth )
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def print_module_symbols ( module ) :
for sym in module :
2019-03-06 22:54:11 +00:00
print ( sym )
2012-04-03 21:35:43 +00:00
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
def Symbolicate ( command_args ) :
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
usage = " usage: % prog [options] <addr1> [addr2 ...] "
description = ''' Symbolicate one or more addresses using LLDB ' s python scripting API.. '''
parser = optparse . OptionParser (
description = description ,
prog = ' crashlog.py ' ,
usage = usage )
parser . add_option (
' -v ' ,
' --verbose ' ,
action = ' store_true ' ,
dest = ' verbose ' ,
help = ' display verbose debug info ' ,
default = False )
2013-06-26 22:24:05 +00:00
parser . add_option (
' -p ' ,
' --platform ' ,
type = ' string ' ,
metavar = ' platform ' ,
dest = ' platform ' ,
help = ' Specify the platform to use when creating the debug target. Valid values include " localhost " , " darwin-kernel " , " ios-simulator " , " remote-freebsd " , " remote-macosx " , " remote-ios " , " remote-linux " . ' )
2012-04-03 21:35:43 +00:00
parser . add_option (
' -f ' ,
' --file ' ,
type = ' string ' ,
metavar = ' file ' ,
dest = ' file ' ,
help = ' Specify a file to use when symbolicating ' )
parser . add_option (
' -a ' ,
' --arch ' ,
type = ' string ' ,
metavar = ' arch ' ,
dest = ' arch ' ,
help = ' Specify a architecture to use when symbolicating ' )
parser . add_option (
' -s ' ,
' --slide ' ,
type = ' int ' ,
metavar = ' slide ' ,
dest = ' slide ' ,
help = ' Specify the slide to use on the file specified with the --file option ' ,
default = None )
parser . add_option (
' --section ' ,
type = ' string ' ,
action = ' append ' ,
dest = ' section_strings ' ,
help = ' specify <sect-name>=<start-addr> or <sect-name>=<start-addr>-<end-addr> ' )
try :
( options , args ) = parser . parse_args ( command_args )
except :
return
symbolicator = Symbolicator ( )
images = list ( )
if options . file :
image = Image ( options . file )
image . arch = options . arch
# Add any sections that were specified with one or more --section
# options
if options . section_strings :
for section_str in options . section_strings :
section = Section ( )
if section . set_from_string ( section_str ) :
image . add_section ( section )
else :
sys . exit ( 1 )
if options . slide is not None :
image . slide = options . slide
symbolicator . images . append ( image )
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
target = symbolicator . create_target ( )
if options . verbose :
2019-03-06 22:54:11 +00:00
print ( symbolicator )
2012-04-03 21:35:43 +00:00
if target :
for addr_str in args :
addr = int ( addr_str , 0 )
2012-06-28 18:10:14 +00:00
symbolicated_addrs = symbolicator . symbolicate (
addr , options . verbose )
2012-04-03 21:35:43 +00:00
for symbolicated_addr in symbolicated_addrs :
2019-03-06 22:54:11 +00:00
print ( symbolicated_addr )
print ( )
2012-04-03 21:35:43 +00:00
else :
2019-03-06 22:54:11 +00:00
print ( ' error: no target for %s ' % ( symbolicator ) )
2016-09-06 20:57:50 +00:00
2012-04-03 21:35:43 +00:00
if __name__ == ' __main__ ' :
# Create a new debugger instance
lldb . debugger = lldb . SBDebugger . Create ( )
Symbolicate ( sys . argv [ 1 : ] )