1515bc8c1Sserge-sans-paille#!/usr/bin/env python 23c2c4bb2SGreg Clayton 33c2c4bb2SGreg Clayton#---------------------------------------------------------------------- 43c2c4bb2SGreg Clayton# Be sure to add the python path that points to the LLDB shared library. 53c2c4bb2SGreg Clayton# 63c2c4bb2SGreg Clayton# To use this in the embedded python interpreter using "lldb": 73c2c4bb2SGreg Clayton# 83c2c4bb2SGreg Clayton# cd /path/containing/crashlog.py 93c2c4bb2SGreg Clayton# lldb 103c2c4bb2SGreg Clayton# (lldb) script import crashlog 113c2c4bb2SGreg Clayton# "crashlog" command installed, type "crashlog --help" for detailed help 123c2c4bb2SGreg Clayton# (lldb) crashlog ~/Library/Logs/DiagnosticReports/a.crash 133c2c4bb2SGreg Clayton# 143c2c4bb2SGreg Clayton# The benefit of running the crashlog command inside lldb in the 153c2c4bb2SGreg Clayton# embedded python interpreter is when the command completes, there 163c2c4bb2SGreg Clayton# will be a target with all of the files loaded at the locations 173c2c4bb2SGreg Clayton# described in the crash log. Only the files that have stack frames 183c2c4bb2SGreg Clayton# in the backtrace will be loaded unless the "--load-all" option 193c2c4bb2SGreg Clayton# has been specified. This allows users to explore the program in the 203c2c4bb2SGreg Clayton# state it was in right at crash time. 213c2c4bb2SGreg Clayton# 223c2c4bb2SGreg Clayton# On MacOSX csh, tcsh: 233c2c4bb2SGreg Clayton# ( setenv PYTHONPATH /path/to/LLDB.framework/Resources/Python ; ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash ) 243c2c4bb2SGreg Clayton# 253c2c4bb2SGreg Clayton# On MacOSX sh, bash: 263c2c4bb2SGreg Clayton# PYTHONPATH=/path/to/LLDB.framework/Resources/Python ./crashlog.py ~/Library/Logs/DiagnosticReports/a.crash 273c2c4bb2SGreg Clayton#---------------------------------------------------------------------- 283c2c4bb2SGreg Clayton 299a8e777fSDavide Italianofrom __future__ import print_function 303c2c4bb2SGreg Claytonimport lldb 313c2c4bb2SGreg Claytonimport optparse 323c2c4bb2SGreg Claytonimport os 333c2c4bb2SGreg Claytonimport plistlib 343c2c4bb2SGreg Claytonimport re 353c2c4bb2SGreg Claytonimport shlex 363c2c4bb2SGreg Claytonimport sys 373c2c4bb2SGreg Claytonimport time 383c2c4bb2SGreg Claytonimport uuid 393c2c4bb2SGreg Clayton 40b9c1b51eSKate Stone 41814ad734SDavide Italianoclass Address: 423c2c4bb2SGreg Clayton """Class that represents an address that will be symbolicated""" 43b9c1b51eSKate Stone 443c2c4bb2SGreg Clayton def __init__(self, target, load_addr): 453c2c4bb2SGreg Clayton self.target = target 463c2c4bb2SGreg Clayton self.load_addr = load_addr # The load address that this object represents 47b9c1b51eSKate Stone # the resolved lldb.SBAddress (if any), named so_addr for 48b9c1b51eSKate Stone # section/offset address 49b9c1b51eSKate Stone self.so_addr = None 503c2c4bb2SGreg Clayton self.sym_ctx = None # The cached symbol context for this address 51b9c1b51eSKate Stone # Any original textual description of this address to be used as a 52b9c1b51eSKate Stone # backup in case symbolication fails 53b9c1b51eSKate Stone self.description = None 543c2c4bb2SGreg Clayton self.symbolication = None # The cached symbolicated string that describes this address 553c2c4bb2SGreg Clayton self.inlined = False 56b9c1b51eSKate Stone 573c2c4bb2SGreg Clayton def __str__(self): 583c2c4bb2SGreg Clayton s = "%#16.16x" % (self.load_addr) 593c2c4bb2SGreg Clayton if self.symbolication: 603c2c4bb2SGreg Clayton s += " %s" % (self.symbolication) 613c2c4bb2SGreg Clayton elif self.description: 623c2c4bb2SGreg Clayton s += " %s" % (self.description) 633c2c4bb2SGreg Clayton elif self.so_addr: 643c2c4bb2SGreg Clayton s += " %s" % (self.so_addr) 653c2c4bb2SGreg Clayton return s 663c2c4bb2SGreg Clayton 673c2c4bb2SGreg Clayton def resolve_addr(self): 68b9c1b51eSKate Stone if self.so_addr is None: 693c2c4bb2SGreg Clayton self.so_addr = self.target.ResolveLoadAddress(self.load_addr) 703c2c4bb2SGreg Clayton return self.so_addr 713c2c4bb2SGreg Clayton 723c2c4bb2SGreg Clayton def is_inlined(self): 733c2c4bb2SGreg Clayton return self.inlined 743c2c4bb2SGreg Clayton 753c2c4bb2SGreg Clayton def get_symbol_context(self): 76b9c1b51eSKate Stone if self.sym_ctx is None: 773c2c4bb2SGreg Clayton sb_addr = self.resolve_addr() 783c2c4bb2SGreg Clayton if sb_addr: 79b9c1b51eSKate Stone self.sym_ctx = self.target.ResolveSymbolContextForAddress( 80b9c1b51eSKate Stone sb_addr, lldb.eSymbolContextEverything) 813c2c4bb2SGreg Clayton else: 823c2c4bb2SGreg Clayton self.sym_ctx = lldb.SBSymbolContext() 833c2c4bb2SGreg Clayton return self.sym_ctx 843c2c4bb2SGreg Clayton 853c2c4bb2SGreg Clayton def get_instructions(self): 863c2c4bb2SGreg Clayton sym_ctx = self.get_symbol_context() 873c2c4bb2SGreg Clayton if sym_ctx: 883c2c4bb2SGreg Clayton function = sym_ctx.GetFunction() 893c2c4bb2SGreg Clayton if function: 903c2c4bb2SGreg Clayton return function.GetInstructions(self.target) 913c2c4bb2SGreg Clayton return sym_ctx.GetSymbol().GetInstructions(self.target) 923c2c4bb2SGreg Clayton return None 933c2c4bb2SGreg Clayton 94a7fb1dcdSGreg Clayton def symbolicate(self, verbose=False): 95b9c1b51eSKate Stone if self.symbolication is None: 963c2c4bb2SGreg Clayton self.symbolication = '' 973c2c4bb2SGreg Clayton self.inlined = False 983c2c4bb2SGreg Clayton sym_ctx = self.get_symbol_context() 993c2c4bb2SGreg Clayton if sym_ctx: 1003c2c4bb2SGreg Clayton module = sym_ctx.GetModule() 1013c2c4bb2SGreg Clayton if module: 102a7fb1dcdSGreg Clayton # Print full source file path in verbose mode 103a7fb1dcdSGreg Clayton if verbose: 104a7fb1dcdSGreg Clayton self.symbolication += str(module.GetFileSpec()) + '`' 105a7fb1dcdSGreg Clayton else: 1063c2c4bb2SGreg Clayton self.symbolication += module.GetFileSpec().GetFilename() + '`' 1073c2c4bb2SGreg Clayton function_start_load_addr = -1 1083c2c4bb2SGreg Clayton function = sym_ctx.GetFunction() 1093c2c4bb2SGreg Clayton block = sym_ctx.GetBlock() 1103c2c4bb2SGreg Clayton line_entry = sym_ctx.GetLineEntry() 1113c2c4bb2SGreg Clayton symbol = sym_ctx.GetSymbol() 112b9c1b51eSKate Stone inlined_block = block.GetContainingInlinedBlock() 1133c2c4bb2SGreg Clayton if function: 1143c2c4bb2SGreg Clayton self.symbolication += function.GetName() 1153c2c4bb2SGreg Clayton 1163c2c4bb2SGreg Clayton if inlined_block: 1173c2c4bb2SGreg Clayton self.inlined = True 118b9c1b51eSKate Stone self.symbolication += ' [inlined] ' + \ 119b9c1b51eSKate Stone inlined_block.GetInlinedName() 120b9c1b51eSKate Stone block_range_idx = inlined_block.GetRangeIndexForBlockAddress( 121b9c1b51eSKate Stone self.so_addr) 1223c2c4bb2SGreg Clayton if block_range_idx < lldb.UINT32_MAX: 123b9c1b51eSKate Stone block_range_start_addr = inlined_block.GetRangeStartAddress( 124b9c1b51eSKate Stone block_range_idx) 125b9c1b51eSKate Stone function_start_load_addr = block_range_start_addr.GetLoadAddress( 126b9c1b51eSKate Stone self.target) 1273c2c4bb2SGreg Clayton if function_start_load_addr == -1: 1283c2c4bb2SGreg Clayton function_start_load_addr = function.GetStartAddress().GetLoadAddress(self.target) 1293c2c4bb2SGreg Clayton elif symbol: 1303c2c4bb2SGreg Clayton self.symbolication += symbol.GetName() 1313c2c4bb2SGreg Clayton function_start_load_addr = symbol.GetStartAddress().GetLoadAddress(self.target) 1323c2c4bb2SGreg Clayton else: 1333c2c4bb2SGreg Clayton self.symbolication = '' 1343c2c4bb2SGreg Clayton return False 1353c2c4bb2SGreg Clayton 136b9c1b51eSKate Stone # Dump the offset from the current function or symbol if it 137b9c1b51eSKate Stone # is non zero 1383c2c4bb2SGreg Clayton function_offset = self.load_addr - function_start_load_addr 1393c2c4bb2SGreg Clayton if function_offset > 0: 1403c2c4bb2SGreg Clayton self.symbolication += " + %u" % (function_offset) 1413c2c4bb2SGreg Clayton elif function_offset < 0: 1423c2c4bb2SGreg Clayton self.symbolication += " %i (invalid negative offset, file a bug) " % function_offset 1433c2c4bb2SGreg Clayton 1443c2c4bb2SGreg Clayton # Print out any line information if any is available 1453c2c4bb2SGreg Clayton if line_entry.GetFileSpec(): 146a7fb1dcdSGreg Clayton # Print full source file path in verbose mode 147a7fb1dcdSGreg Clayton if verbose: 148a7fb1dcdSGreg Clayton self.symbolication += ' at %s' % line_entry.GetFileSpec() 149a7fb1dcdSGreg Clayton else: 1503c2c4bb2SGreg Clayton self.symbolication += ' at %s' % line_entry.GetFileSpec().GetFilename() 1513c2c4bb2SGreg Clayton self.symbolication += ':%u' % line_entry.GetLine() 1523c2c4bb2SGreg Clayton column = line_entry.GetColumn() 1533c2c4bb2SGreg Clayton if column > 0: 1543c2c4bb2SGreg Clayton self.symbolication += ':%u' % column 1553c2c4bb2SGreg Clayton return True 1563c2c4bb2SGreg Clayton return False 1573c2c4bb2SGreg Clayton 158b9c1b51eSKate Stone 159814ad734SDavide Italianoclass Section: 1603c2c4bb2SGreg Clayton """Class that represents an load address range""" 1613c2c4bb2SGreg Clayton sect_info_regex = re.compile('(?P<name>[^=]+)=(?P<range>.*)') 1623c2c4bb2SGreg Clayton addr_regex = re.compile('^\s*(?P<start>0x[0-9A-Fa-f]+)\s*$') 163b9c1b51eSKate Stone range_regex = re.compile( 164b9c1b51eSKate Stone '^\s*(?P<start>0x[0-9A-Fa-f]+)\s*(?P<op>[-+])\s*(?P<end>0x[0-9A-Fa-f]+)\s*$') 1653c2c4bb2SGreg Clayton 1663c2c4bb2SGreg Clayton def __init__(self, start_addr=None, end_addr=None, name=None): 1673c2c4bb2SGreg Clayton self.start_addr = start_addr 1683c2c4bb2SGreg Clayton self.end_addr = end_addr 1693c2c4bb2SGreg Clayton self.name = name 1703c2c4bb2SGreg Clayton 171641c23f3SGreg Clayton @classmethod 172641c23f3SGreg Clayton def InitWithSBTargetAndSBSection(cls, target, section): 173641c23f3SGreg Clayton sect_load_addr = section.GetLoadAddress(target) 174641c23f3SGreg Clayton if sect_load_addr != lldb.LLDB_INVALID_ADDRESS: 175b9c1b51eSKate Stone obj = cls( 176b9c1b51eSKate Stone sect_load_addr, 177b9c1b51eSKate Stone sect_load_addr + 178b9c1b51eSKate Stone section.size, 179b9c1b51eSKate Stone section.name) 180641c23f3SGreg Clayton return obj 181641c23f3SGreg Clayton else: 182641c23f3SGreg Clayton return None 183641c23f3SGreg Clayton 1843c2c4bb2SGreg Clayton def contains(self, addr): 185b9c1b51eSKate Stone return self.start_addr <= addr and addr < self.end_addr 1863c2c4bb2SGreg Clayton 1873c2c4bb2SGreg Clayton def set_from_string(self, s): 1883c2c4bb2SGreg Clayton match = self.sect_info_regex.match(s) 1893c2c4bb2SGreg Clayton if match: 1903c2c4bb2SGreg Clayton self.name = match.group('name') 1913c2c4bb2SGreg Clayton range_str = match.group('range') 1923c2c4bb2SGreg Clayton addr_match = self.addr_regex.match(range_str) 1933c2c4bb2SGreg Clayton if addr_match: 1943c2c4bb2SGreg Clayton self.start_addr = int(addr_match.group('start'), 16) 1953c2c4bb2SGreg Clayton self.end_addr = None 1963c2c4bb2SGreg Clayton return True 1973c2c4bb2SGreg Clayton 1983c2c4bb2SGreg Clayton range_match = self.range_regex.match(range_str) 1993c2c4bb2SGreg Clayton if range_match: 2003c2c4bb2SGreg Clayton self.start_addr = int(range_match.group('start'), 16) 2013c2c4bb2SGreg Clayton self.end_addr = int(range_match.group('end'), 16) 2023c2c4bb2SGreg Clayton op = range_match.group('op') 2033c2c4bb2SGreg Clayton if op == '+': 2043c2c4bb2SGreg Clayton self.end_addr += self.start_addr 2053c2c4bb2SGreg Clayton return True 206a658ab9fSDavide Italiano print('error: invalid section info string "%s"' % s) 207a658ab9fSDavide Italiano print('Valid section info formats are:') 208a658ab9fSDavide Italiano print('Format Example Description') 209a658ab9fSDavide Italiano print('--------------------- -----------------------------------------------') 210a658ab9fSDavide Italiano print('<name>=<base> __TEXT=0x123000 Section from base address only') 211a658ab9fSDavide Italiano print('<name>=<base>-<end> __TEXT=0x123000-0x124000 Section from base address and end address') 212a658ab9fSDavide Italiano print('<name>=<base>+<size> __TEXT=0x123000+0x1000 Section from base address and size') 2133c2c4bb2SGreg Clayton return False 2143c2c4bb2SGreg Clayton 2153c2c4bb2SGreg Clayton def __str__(self): 2163c2c4bb2SGreg Clayton if self.name: 217b9c1b51eSKate Stone if self.end_addr is not None: 218b9c1b51eSKate Stone if self.start_addr is not None: 219b9c1b51eSKate Stone return "%s=[0x%16.16x - 0x%16.16x)" % ( 220b9c1b51eSKate Stone self.name, self.start_addr, self.end_addr) 2213c2c4bb2SGreg Clayton else: 222b9c1b51eSKate Stone if self.start_addr is not None: 2233c2c4bb2SGreg Clayton return "%s=0x%16.16x" % (self.name, self.start_addr) 2243c2c4bb2SGreg Clayton return self.name 2253c2c4bb2SGreg Clayton return "<invalid>" 2263c2c4bb2SGreg Clayton 227b9c1b51eSKate Stone 228814ad734SDavide Italianoclass Image: 2293c2c4bb2SGreg Clayton """A class that represents an executable image and any associated data""" 2303c2c4bb2SGreg Clayton 2313c2c4bb2SGreg Clayton def __init__(self, path, uuid=None): 2323c2c4bb2SGreg Clayton self.path = path 2333c2c4bb2SGreg Clayton self.resolved_path = None 234f51a23fbSGreg Clayton self.resolved = False 235f51a23fbSGreg Clayton self.unavailable = False 2363c2c4bb2SGreg Clayton self.uuid = uuid 2373c2c4bb2SGreg Clayton self.section_infos = list() 2383c2c4bb2SGreg Clayton self.identifier = None 2393c2c4bb2SGreg Clayton self.version = None 2403c2c4bb2SGreg Clayton self.arch = None 2413c2c4bb2SGreg Clayton self.module = None 2423c2c4bb2SGreg Clayton self.symfile = None 2433c2c4bb2SGreg Clayton self.slide = None 2443c2c4bb2SGreg Clayton 245641c23f3SGreg Clayton @classmethod 246641c23f3SGreg Clayton def InitWithSBTargetAndSBModule(cls, target, module): 247adb99821SBruce Mitchener '''Initialize this Image object with a module from a target.''' 248641c23f3SGreg Clayton obj = cls(module.file.fullpath, module.uuid) 249641c23f3SGreg Clayton obj.resolved_path = module.platform_file.fullpath 250641c23f3SGreg Clayton obj.resolved = True 251641c23f3SGreg Clayton for section in module.sections: 252b9c1b51eSKate Stone symb_section = Section.InitWithSBTargetAndSBSection( 253b9c1b51eSKate Stone target, section) 254641c23f3SGreg Clayton if symb_section: 255641c23f3SGreg Clayton obj.section_infos.append(symb_section) 256641c23f3SGreg Clayton obj.arch = module.triple 257641c23f3SGreg Clayton obj.module = module 258641c23f3SGreg Clayton obj.symfile = None 259641c23f3SGreg Clayton obj.slide = None 260641c23f3SGreg Clayton return obj 261a16cb16aSGreg Clayton 2623c2c4bb2SGreg Clayton def dump(self, prefix): 263a658ab9fSDavide Italiano print("%s%s" % (prefix, self)) 2643c2c4bb2SGreg Clayton 2651f746071SGreg Clayton def debug_dump(self): 266a658ab9fSDavide Italiano print('path = "%s"' % (self.path)) 267a658ab9fSDavide Italiano print('resolved_path = "%s"' % (self.resolved_path)) 268a658ab9fSDavide Italiano print('resolved = %i' % (self.resolved)) 269a658ab9fSDavide Italiano print('unavailable = %i' % (self.unavailable)) 270a658ab9fSDavide Italiano print('uuid = %s' % (self.uuid)) 271a658ab9fSDavide Italiano print('section_infos = %s' % (self.section_infos)) 272a658ab9fSDavide Italiano print('identifier = "%s"' % (self.identifier)) 273a658ab9fSDavide Italiano print('version = %s' % (self.version)) 274a658ab9fSDavide Italiano print('arch = %s' % (self.arch)) 275a658ab9fSDavide Italiano print('module = %s' % (self.module)) 276a658ab9fSDavide Italiano print('symfile = "%s"' % (self.symfile)) 277a658ab9fSDavide Italiano print('slide = %i (0x%x)' % (self.slide, self.slide)) 2781f746071SGreg Clayton 2793c2c4bb2SGreg Clayton def __str__(self): 280641c23f3SGreg Clayton s = '' 281641c23f3SGreg Clayton if self.uuid: 282641c23f3SGreg Clayton s += "%s " % (self.get_uuid()) 283641c23f3SGreg Clayton if self.arch: 284641c23f3SGreg Clayton s += "%s " % (self.arch) 285641c23f3SGreg Clayton if self.version: 286641c23f3SGreg Clayton s += "%s " % (self.version) 287641c23f3SGreg Clayton resolved_path = self.get_resolved_path() 288641c23f3SGreg Clayton if resolved_path: 289641c23f3SGreg Clayton s += "%s " % (resolved_path) 2903c2c4bb2SGreg Clayton for section_info in self.section_infos: 2913c2c4bb2SGreg Clayton s += ", %s" % (section_info) 292b9c1b51eSKate Stone if self.slide is not None: 2933c2c4bb2SGreg Clayton s += ', slide = 0x%16.16x' % self.slide 2943c2c4bb2SGreg Clayton return s 2953c2c4bb2SGreg Clayton 2963c2c4bb2SGreg Clayton def add_section(self, section): 2973c2c4bb2SGreg Clayton # print "added '%s' to '%s'" % (section, self.path) 2983c2c4bb2SGreg Clayton self.section_infos.append(section) 2993c2c4bb2SGreg Clayton 3003c2c4bb2SGreg Clayton def get_section_containing_load_addr(self, load_addr): 3013c2c4bb2SGreg Clayton for section_info in self.section_infos: 3023c2c4bb2SGreg Clayton if section_info.contains(load_addr): 3033c2c4bb2SGreg Clayton return section_info 3043c2c4bb2SGreg Clayton return None 3053c2c4bb2SGreg Clayton 3063c2c4bb2SGreg Clayton def get_resolved_path(self): 3073c2c4bb2SGreg Clayton if self.resolved_path: 3083c2c4bb2SGreg Clayton return self.resolved_path 3093c2c4bb2SGreg Clayton elif self.path: 3103c2c4bb2SGreg Clayton return self.path 3113c2c4bb2SGreg Clayton return None 3123c2c4bb2SGreg Clayton 3133c2c4bb2SGreg Clayton def get_resolved_path_basename(self): 3143c2c4bb2SGreg Clayton path = self.get_resolved_path() 3153c2c4bb2SGreg Clayton if path: 3163c2c4bb2SGreg Clayton return os.path.basename(path) 3173c2c4bb2SGreg Clayton return None 3183c2c4bb2SGreg Clayton 3193c2c4bb2SGreg Clayton def symfile_basename(self): 3203c2c4bb2SGreg Clayton if self.symfile: 3213c2c4bb2SGreg Clayton return os.path.basename(self.symfile) 3223c2c4bb2SGreg Clayton return None 3233c2c4bb2SGreg Clayton 3243c2c4bb2SGreg Clayton def has_section_load_info(self): 325b9c1b51eSKate Stone return self.section_infos or self.slide is not None 3263c2c4bb2SGreg Clayton 3273c2c4bb2SGreg Clayton def load_module(self, target): 328f51a23fbSGreg Clayton if self.unavailable: 329f51a23fbSGreg Clayton return None # We already warned that we couldn't find this module, so don't return an error string 3303c2c4bb2SGreg Clayton # Load this module into "target" using the section infos to 3313c2c4bb2SGreg Clayton # set the section load addresses 3323c2c4bb2SGreg Clayton if self.has_section_load_info(): 3333c2c4bb2SGreg Clayton if target: 3343c2c4bb2SGreg Clayton if self.module: 3353c2c4bb2SGreg Clayton if self.section_infos: 3363c2c4bb2SGreg Clayton num_sections_loaded = 0 3373c2c4bb2SGreg Clayton for section_info in self.section_infos: 3383c2c4bb2SGreg Clayton if section_info.name: 339b9c1b51eSKate Stone section = self.module.FindSection( 340b9c1b51eSKate Stone section_info.name) 3413c2c4bb2SGreg Clayton if section: 342b9c1b51eSKate Stone error = target.SetSectionLoadAddress( 343b9c1b51eSKate Stone section, section_info.start_addr) 3443c2c4bb2SGreg Clayton if error.Success(): 3453c2c4bb2SGreg Clayton num_sections_loaded += 1 3463c2c4bb2SGreg Clayton else: 3473c2c4bb2SGreg Clayton return 'error: %s' % error.GetCString() 3483c2c4bb2SGreg Clayton else: 3493c2c4bb2SGreg Clayton return 'error: unable to find the section named "%s"' % section_info.name 3503c2c4bb2SGreg Clayton else: 351b9c1b51eSKate Stone return 'error: unable to find "%s" section in "%s"' % ( 352b9c1b51eSKate Stone range.name, self.get_resolved_path()) 3533c2c4bb2SGreg Clayton if num_sections_loaded == 0: 3543c2c4bb2SGreg Clayton return 'error: no sections were successfully loaded' 3553c2c4bb2SGreg Clayton else: 356b9c1b51eSKate Stone err = target.SetModuleLoadAddress( 357b9c1b51eSKate Stone self.module, self.slide) 3583c2c4bb2SGreg Clayton if err.Fail(): 3593c2c4bb2SGreg Clayton return err.GetCString() 3603c2c4bb2SGreg Clayton return None 3613c2c4bb2SGreg Clayton else: 3623c2c4bb2SGreg Clayton return 'error: invalid module' 3633c2c4bb2SGreg Clayton else: 3643c2c4bb2SGreg Clayton return 'error: invalid target' 3653c2c4bb2SGreg Clayton else: 3663c2c4bb2SGreg Clayton return 'error: no section infos' 3673c2c4bb2SGreg Clayton 3683c2c4bb2SGreg Clayton def add_module(self, target): 3693c2c4bb2SGreg Clayton '''Add the Image described in this object to "target" and load the sections if "load" is True.''' 3703c2c4bb2SGreg Clayton if target: 371b9c1b51eSKate Stone # Try and find using UUID only first so that paths need not match 372b9c1b51eSKate Stone # up 37360bb58f6SGreg Clayton uuid_str = self.get_normalized_uuid_string() 37460bb58f6SGreg Clayton if uuid_str: 37560bb58f6SGreg Clayton self.module = target.AddModule(None, None, uuid_str) 3763c2c4bb2SGreg Clayton if not self.module: 377f99295c3SGreg Clayton self.locate_module_and_debug_symbols() 378f51a23fbSGreg Clayton if self.unavailable: 379f51a23fbSGreg Clayton return None 380f99295c3SGreg Clayton resolved_path = self.get_resolved_path() 381b9c1b51eSKate Stone self.module = target.AddModule( 382*e31b2d7dSVedant Kumar resolved_path, None, uuid_str, self.symfile) 3833c2c4bb2SGreg Clayton if not self.module: 384b9c1b51eSKate Stone return 'error: unable to get module for (%s) "%s"' % ( 385b9c1b51eSKate Stone self.arch, self.get_resolved_path()) 3863c2c4bb2SGreg Clayton if self.has_section_load_info(): 3873c2c4bb2SGreg Clayton return self.load_module(target) 3883c2c4bb2SGreg Clayton else: 3893c2c4bb2SGreg Clayton return None # No sections, the module was added to the target, so success 3903c2c4bb2SGreg Clayton else: 3913c2c4bb2SGreg Clayton return 'error: invalid target' 3923c2c4bb2SGreg Clayton 3933c2c4bb2SGreg Clayton def locate_module_and_debug_symbols(self): 3943c2c4bb2SGreg Clayton # By default, just use the paths that were supplied in: 3953c2c4bb2SGreg Clayton # self.path 3963c2c4bb2SGreg Clayton # self.resolved_path 3973c2c4bb2SGreg Clayton # self.module 3983c2c4bb2SGreg Clayton # self.symfile 3993c2c4bb2SGreg Clayton # Subclasses can inherit from this class and override this function 400f51a23fbSGreg Clayton self.resolved = True 4013c2c4bb2SGreg Clayton return True 4023c2c4bb2SGreg Clayton 4033c2c4bb2SGreg Clayton def get_uuid(self): 40460bb58f6SGreg Clayton if not self.uuid and self.module: 4053c2c4bb2SGreg Clayton self.uuid = uuid.UUID(self.module.GetUUIDString()) 4063c2c4bb2SGreg Clayton return self.uuid 4073c2c4bb2SGreg Clayton 40860bb58f6SGreg Clayton def get_normalized_uuid_string(self): 40960bb58f6SGreg Clayton if self.uuid: 41060bb58f6SGreg Clayton return str(self.uuid).upper() 41160bb58f6SGreg Clayton return None 41260bb58f6SGreg Clayton 413c29c24beSJonas Devlieghere def create_target(self, debugger): 4143c2c4bb2SGreg Clayton '''Create a target using the information in this Image object.''' 415f51a23fbSGreg Clayton if self.unavailable: 416f51a23fbSGreg Clayton return None 417f51a23fbSGreg Clayton 4183c2c4bb2SGreg Clayton if self.locate_module_and_debug_symbols(): 419b9c1b51eSKate Stone resolved_path = self.get_resolved_path() 4203c2c4bb2SGreg Clayton path_spec = lldb.SBFileSpec(resolved_path) 4213c2c4bb2SGreg Clayton error = lldb.SBError() 422c29c24beSJonas Devlieghere target = debugger.CreateTarget( 423b9c1b51eSKate Stone resolved_path, self.arch, None, False, error) 4243c2c4bb2SGreg Clayton if target: 4253c2c4bb2SGreg Clayton self.module = target.FindModule(path_spec) 4263c2c4bb2SGreg Clayton if self.has_section_load_info(): 4273c2c4bb2SGreg Clayton err = self.load_module(target) 4283c2c4bb2SGreg Clayton if err: 429a658ab9fSDavide Italiano print('ERROR: ', err) 4303c2c4bb2SGreg Clayton return target 4313c2c4bb2SGreg Clayton else: 432a658ab9fSDavide Italiano print('error: unable to create a valid target for (%s) "%s"' % (self.arch, self.path)) 4333c2c4bb2SGreg Clayton else: 434a658ab9fSDavide Italiano print('error: unable to locate main executable (%s) "%s"' % (self.arch, self.path)) 4353c2c4bb2SGreg Clayton return None 4363c2c4bb2SGreg Clayton 437b9c1b51eSKate Stone 438814ad734SDavide Italianoclass Symbolicator: 4393c2c4bb2SGreg Clayton 44099ea2c46SJonas Devlieghere def __init__(self, debugger=None, target=None, images=list()): 44199ea2c46SJonas Devlieghere """A class the represents the information needed to symbolicate 44299ea2c46SJonas Devlieghere addresses in a program. 44399ea2c46SJonas Devlieghere 44499ea2c46SJonas Devlieghere Do not call this initializer directly, but rather use the factory 44599ea2c46SJonas Devlieghere methods. 44699ea2c46SJonas Devlieghere """ 447c29c24beSJonas Devlieghere self.debugger = debugger 44899ea2c46SJonas Devlieghere self.target = target 44999ea2c46SJonas Devlieghere self.images = images # a list of images to be used when symbolicating 450a16cb16aSGreg Clayton self.addr_mask = 0xffffffffffffffff 4513c2c4bb2SGreg Clayton 452641c23f3SGreg Clayton @classmethod 453641c23f3SGreg Clayton def InitWithSBTarget(cls, target): 45499ea2c46SJonas Devlieghere """Initialize a new Symbolicator with an existing SBTarget.""" 45599ea2c46SJonas Devlieghere obj = cls(target=target) 456641c23f3SGreg Clayton triple = target.triple 457641c23f3SGreg Clayton if triple: 458641c23f3SGreg Clayton arch = triple.split('-')[0] 459641c23f3SGreg Clayton if "arm" in arch: 460641c23f3SGreg Clayton obj.addr_mask = 0xfffffffffffffffe 461641c23f3SGreg Clayton 462641c23f3SGreg Clayton for module in target.modules: 463641c23f3SGreg Clayton image = Image.InitWithSBTargetAndSBModule(target, module) 464641c23f3SGreg Clayton obj.images.append(image) 465641c23f3SGreg Clayton return obj 466641c23f3SGreg Clayton 46799ea2c46SJonas Devlieghere @classmethod 46899ea2c46SJonas Devlieghere def InitWithSBDebugger(cls, debugger, images): 46999ea2c46SJonas Devlieghere """Initialize a new Symbolicator with an existing debugger and list of 47099ea2c46SJonas Devlieghere images. The Symbolicator will create the target.""" 47199ea2c46SJonas Devlieghere obj = cls(debugger=debugger, images=images) 47299ea2c46SJonas Devlieghere return obj 47399ea2c46SJonas Devlieghere 4743c2c4bb2SGreg Clayton def __str__(self): 4753c2c4bb2SGreg Clayton s = "Symbolicator:\n" 4763c2c4bb2SGreg Clayton if self.target: 4773c2c4bb2SGreg Clayton s += "Target = '%s'\n" % (self.target) 478641c23f3SGreg Clayton s += "Target modules:\n" 4793c2c4bb2SGreg Clayton for m in self.target.modules: 480641c23f3SGreg Clayton s += str(m) + "\n" 4813c2c4bb2SGreg Clayton s += "Images:\n" 4823c2c4bb2SGreg Clayton for image in self.images: 4833c2c4bb2SGreg Clayton s += ' %s\n' % (image) 4843c2c4bb2SGreg Clayton return s 4853c2c4bb2SGreg Clayton 4863c2c4bb2SGreg Clayton def find_images_with_identifier(self, identifier): 4873c2c4bb2SGreg Clayton images = list() 4883c2c4bb2SGreg Clayton for image in self.images: 4893c2c4bb2SGreg Clayton if image.identifier == identifier: 4903c2c4bb2SGreg Clayton images.append(image) 49148d157ddSGreg Clayton if len(images) == 0: 4926c42aa77SGreg Clayton regex_text = '^.*\.%s$' % (re.escape(identifier)) 49348d157ddSGreg Clayton regex = re.compile(regex_text) 49448d157ddSGreg Clayton for image in self.images: 49548d157ddSGreg Clayton if regex.match(image.identifier): 49648d157ddSGreg Clayton images.append(image) 4973c2c4bb2SGreg Clayton return images 4983c2c4bb2SGreg Clayton 4993c2c4bb2SGreg Clayton def find_image_containing_load_addr(self, load_addr): 5003c2c4bb2SGreg Clayton for image in self.images: 501f51a23fbSGreg Clayton if image.get_section_containing_load_addr(load_addr): 5023c2c4bb2SGreg Clayton return image 5033c2c4bb2SGreg Clayton return None 5043c2c4bb2SGreg Clayton 5053c2c4bb2SGreg Clayton def create_target(self): 5063c2c4bb2SGreg Clayton if self.target: 5073c2c4bb2SGreg Clayton return self.target 5083c2c4bb2SGreg Clayton 5093c2c4bb2SGreg Clayton if self.images: 5103c2c4bb2SGreg Clayton for image in self.images: 511c29c24beSJonas Devlieghere self.target = image.create_target(self.debugger) 5123c2c4bb2SGreg Clayton if self.target: 513a16cb16aSGreg Clayton if self.target.GetAddressByteSize() == 4: 514a16cb16aSGreg Clayton triple = self.target.triple 515a16cb16aSGreg Clayton if triple: 516a16cb16aSGreg Clayton arch = triple.split('-')[0] 517a16cb16aSGreg Clayton if "arm" in arch: 518a16cb16aSGreg Clayton self.addr_mask = 0xfffffffffffffffe 5193c2c4bb2SGreg Clayton return self.target 5203c2c4bb2SGreg Clayton return None 5213c2c4bb2SGreg Clayton 522a7fb1dcdSGreg Clayton def symbolicate(self, load_addr, verbose=False): 523f51a23fbSGreg Clayton if not self.target: 524f51a23fbSGreg Clayton self.create_target() 5253c2c4bb2SGreg Clayton if self.target: 52659c40ff3SGreg Clayton live_process = False 52759c40ff3SGreg Clayton process = self.target.process 52859c40ff3SGreg Clayton if process: 52959c40ff3SGreg Clayton state = process.state 530fdc2515cSGreg Clayton if state > lldb.eStateUnloaded and state < lldb.eStateDetached: 53159c40ff3SGreg Clayton live_process = True 53259c40ff3SGreg Clayton # If we don't have a live process, we can attempt to find the image 53359c40ff3SGreg Clayton # that a load address belongs to and lazily load its module in the 53459c40ff3SGreg Clayton # target, but we shouldn't do any of this if we have a live process 53559c40ff3SGreg Clayton if not live_process: 536f51a23fbSGreg Clayton image = self.find_image_containing_load_addr(load_addr) 537f51a23fbSGreg Clayton if image: 538f51a23fbSGreg Clayton image.add_module(self.target) 5393c2c4bb2SGreg Clayton symbolicated_address = Address(self.target, load_addr) 540a7fb1dcdSGreg Clayton if symbolicated_address.symbolicate(verbose): 5413c2c4bb2SGreg Clayton if symbolicated_address.so_addr: 5423c2c4bb2SGreg Clayton symbolicated_addresses = list() 5433c2c4bb2SGreg Clayton symbolicated_addresses.append(symbolicated_address) 5443c2c4bb2SGreg Clayton # See if we were able to reconstruct anything? 545b9c1b51eSKate Stone while True: 5463c2c4bb2SGreg Clayton inlined_parent_so_addr = lldb.SBAddress() 547b9c1b51eSKate Stone inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope( 548b9c1b51eSKate Stone symbolicated_address.so_addr, inlined_parent_so_addr) 5493c2c4bb2SGreg Clayton if not inlined_parent_sym_ctx: 5503c2c4bb2SGreg Clayton break 5513c2c4bb2SGreg Clayton if not inlined_parent_so_addr: 5523c2c4bb2SGreg Clayton break 5533c2c4bb2SGreg Clayton 554b9c1b51eSKate Stone symbolicated_address = Address( 555b9c1b51eSKate Stone self.target, inlined_parent_so_addr.GetLoadAddress( 556b9c1b51eSKate Stone self.target)) 5573c2c4bb2SGreg Clayton symbolicated_address.sym_ctx = inlined_parent_sym_ctx 5583c2c4bb2SGreg Clayton symbolicated_address.so_addr = inlined_parent_so_addr 559a7fb1dcdSGreg Clayton symbolicated_address.symbolicate(verbose) 5603c2c4bb2SGreg Clayton 5613c2c4bb2SGreg Clayton # push the new frame onto the new frame stack 5623c2c4bb2SGreg Clayton symbolicated_addresses.append(symbolicated_address) 5633c2c4bb2SGreg Clayton 5643c2c4bb2SGreg Clayton if symbolicated_addresses: 5653c2c4bb2SGreg Clayton return symbolicated_addresses 566f51a23fbSGreg Clayton else: 567a658ab9fSDavide Italiano print('error: no target in Symbolicator') 5683c2c4bb2SGreg Clayton return None 5693c2c4bb2SGreg Clayton 5703c2c4bb2SGreg Clayton 571b9c1b51eSKate Stonedef disassemble_instructions( 572b9c1b51eSKate Stone target, 573b9c1b51eSKate Stone instructions, 574b9c1b51eSKate Stone pc, 575b9c1b51eSKate Stone insts_before_pc, 576b9c1b51eSKate Stone insts_after_pc, 577b9c1b51eSKate Stone non_zeroeth_frame): 5783c2c4bb2SGreg Clayton lines = list() 5793c2c4bb2SGreg Clayton pc_index = -1 5803c2c4bb2SGreg Clayton comment_column = 50 5813c2c4bb2SGreg Clayton for inst_idx, inst in enumerate(instructions): 582b9c1b51eSKate Stone inst_pc = inst.GetAddress().GetLoadAddress(target) 5833c2c4bb2SGreg Clayton if pc == inst_pc: 5843c2c4bb2SGreg Clayton pc_index = inst_idx 5853c2c4bb2SGreg Clayton mnemonic = inst.GetMnemonic(target) 5863c2c4bb2SGreg Clayton operands = inst.GetOperands(target) 5873c2c4bb2SGreg Clayton comment = inst.GetComment(target) 5883c2c4bb2SGreg Clayton lines.append("%#16.16x: %8s %s" % (inst_pc, mnemonic, operands)) 5893c2c4bb2SGreg Clayton if comment: 5903c2c4bb2SGreg Clayton line_len = len(lines[-1]) 5913c2c4bb2SGreg Clayton if line_len < comment_column: 5923c2c4bb2SGreg Clayton lines[-1] += ' ' * (comment_column - line_len) 5933c2c4bb2SGreg Clayton lines[-1] += "; %s" % comment 5943c2c4bb2SGreg Clayton 5953c2c4bb2SGreg Clayton if pc_index >= 0: 596b9c1b51eSKate Stone # If we are disassembling the non-zeroeth frame, we need to backup the 597b9c1b51eSKate Stone # PC by 1 5983c2c4bb2SGreg Clayton if non_zeroeth_frame and pc_index > 0: 5993c2c4bb2SGreg Clayton pc_index = pc_index - 1 6003c2c4bb2SGreg Clayton if insts_before_pc == -1: 6013c2c4bb2SGreg Clayton start_idx = 0 6023c2c4bb2SGreg Clayton else: 6033c2c4bb2SGreg Clayton start_idx = pc_index - insts_before_pc 6043c2c4bb2SGreg Clayton if start_idx < 0: 6053c2c4bb2SGreg Clayton start_idx = 0 6063c2c4bb2SGreg Clayton if insts_before_pc == -1: 6073c2c4bb2SGreg Clayton end_idx = inst_idx 6083c2c4bb2SGreg Clayton else: 6093c2c4bb2SGreg Clayton end_idx = pc_index + insts_after_pc 6103c2c4bb2SGreg Clayton if end_idx > inst_idx: 6113c2c4bb2SGreg Clayton end_idx = inst_idx 6123c2c4bb2SGreg Clayton for i in range(start_idx, end_idx + 1): 6133c2c4bb2SGreg Clayton if i == pc_index: 614a658ab9fSDavide Italiano print(' -> ', lines[i]) 6153c2c4bb2SGreg Clayton else: 616a658ab9fSDavide Italiano print(' ', lines[i]) 6173c2c4bb2SGreg Clayton 618b9c1b51eSKate Stone 6193c2c4bb2SGreg Claytondef print_module_section_data(section): 620a658ab9fSDavide Italiano print(section) 6213c2c4bb2SGreg Clayton section_data = section.GetSectionData() 6223c2c4bb2SGreg Clayton if section_data: 6233c2c4bb2SGreg Clayton ostream = lldb.SBStream() 6243c2c4bb2SGreg Clayton section_data.GetDescription(ostream, section.GetFileAddress()) 625a658ab9fSDavide Italiano print(ostream.GetData()) 6263c2c4bb2SGreg Clayton 627b9c1b51eSKate Stone 6283c2c4bb2SGreg Claytondef print_module_section(section, depth): 629a658ab9fSDavide Italiano print(section) 6303c2c4bb2SGreg Clayton if depth > 0: 6313c2c4bb2SGreg Clayton num_sub_sections = section.GetNumSubSections() 6323c2c4bb2SGreg Clayton for sect_idx in range(num_sub_sections): 633b9c1b51eSKate Stone print_module_section( 634b9c1b51eSKate Stone section.GetSubSectionAtIndex(sect_idx), depth - 1) 635b9c1b51eSKate Stone 6363c2c4bb2SGreg Clayton 6373c2c4bb2SGreg Claytondef print_module_sections(module, depth): 6383c2c4bb2SGreg Clayton for sect in module.section_iter(): 6393c2c4bb2SGreg Clayton print_module_section(sect, depth) 6403c2c4bb2SGreg Clayton 641b9c1b51eSKate Stone 6423c2c4bb2SGreg Claytondef print_module_symbols(module): 6433c2c4bb2SGreg Clayton for sym in module: 644a658ab9fSDavide Italiano print(sym) 6453c2c4bb2SGreg Clayton 646b9c1b51eSKate Stone 647c29c24beSJonas Devliegheredef Symbolicate(debugger, command_args): 6483c2c4bb2SGreg Clayton 6493c2c4bb2SGreg Clayton usage = "usage: %prog [options] <addr1> [addr2 ...]" 6503c2c4bb2SGreg Clayton description = '''Symbolicate one or more addresses using LLDB's python scripting API..''' 651b9c1b51eSKate Stone parser = optparse.OptionParser( 652b9c1b51eSKate Stone description=description, 653b9c1b51eSKate Stone prog='crashlog.py', 654b9c1b51eSKate Stone usage=usage) 655b9c1b51eSKate Stone parser.add_option( 656b9c1b51eSKate Stone '-v', 657b9c1b51eSKate Stone '--verbose', 658b9c1b51eSKate Stone action='store_true', 659b9c1b51eSKate Stone dest='verbose', 660b9c1b51eSKate Stone help='display verbose debug info', 661b9c1b51eSKate Stone default=False) 662b9c1b51eSKate Stone parser.add_option( 663b9c1b51eSKate Stone '-p', 664b9c1b51eSKate Stone '--platform', 665b9c1b51eSKate Stone type='string', 666b9c1b51eSKate Stone metavar='platform', 667b9c1b51eSKate Stone dest='platform', 668b9c1b51eSKate Stone 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".') 669b9c1b51eSKate Stone parser.add_option( 670b9c1b51eSKate Stone '-f', 671b9c1b51eSKate Stone '--file', 672b9c1b51eSKate Stone type='string', 673b9c1b51eSKate Stone metavar='file', 674b9c1b51eSKate Stone dest='file', 675b9c1b51eSKate Stone help='Specify a file to use when symbolicating') 676b9c1b51eSKate Stone parser.add_option( 677b9c1b51eSKate Stone '-a', 678b9c1b51eSKate Stone '--arch', 679b9c1b51eSKate Stone type='string', 680b9c1b51eSKate Stone metavar='arch', 681b9c1b51eSKate Stone dest='arch', 682b9c1b51eSKate Stone help='Specify a architecture to use when symbolicating') 683b9c1b51eSKate Stone parser.add_option( 684b9c1b51eSKate Stone '-s', 685b9c1b51eSKate Stone '--slide', 686b9c1b51eSKate Stone type='int', 687b9c1b51eSKate Stone metavar='slide', 688b9c1b51eSKate Stone dest='slide', 689b9c1b51eSKate Stone help='Specify the slide to use on the file specified with the --file option', 690b9c1b51eSKate Stone default=None) 691b9c1b51eSKate Stone parser.add_option( 692b9c1b51eSKate Stone '--section', 693b9c1b51eSKate Stone type='string', 694b9c1b51eSKate Stone action='append', 695b9c1b51eSKate Stone dest='section_strings', 696b9c1b51eSKate Stone help='specify <sect-name>=<start-addr> or <sect-name>=<start-addr>-<end-addr>') 6973c2c4bb2SGreg Clayton try: 6983c2c4bb2SGreg Clayton (options, args) = parser.parse_args(command_args) 6993c2c4bb2SGreg Clayton except: 7003c2c4bb2SGreg Clayton return 701c29c24beSJonas Devlieghere symbolicator = Symbolicator(debugger) 702b9c1b51eSKate Stone images = list() 7033c2c4bb2SGreg Clayton if options.file: 704b9c1b51eSKate Stone image = Image(options.file) 7053c2c4bb2SGreg Clayton image.arch = options.arch 706b9c1b51eSKate Stone # Add any sections that were specified with one or more --section 707b9c1b51eSKate Stone # options 7083c2c4bb2SGreg Clayton if options.section_strings: 7093c2c4bb2SGreg Clayton for section_str in options.section_strings: 7103c2c4bb2SGreg Clayton section = Section() 7113c2c4bb2SGreg Clayton if section.set_from_string(section_str): 7123c2c4bb2SGreg Clayton image.add_section(section) 7133c2c4bb2SGreg Clayton else: 7143c2c4bb2SGreg Clayton sys.exit(1) 715b9c1b51eSKate Stone if options.slide is not None: 7163c2c4bb2SGreg Clayton image.slide = options.slide 7173c2c4bb2SGreg Clayton symbolicator.images.append(image) 7183c2c4bb2SGreg Clayton 7193c2c4bb2SGreg Clayton target = symbolicator.create_target() 7203c2c4bb2SGreg Clayton if options.verbose: 721a658ab9fSDavide Italiano print(symbolicator) 7223c2c4bb2SGreg Clayton if target: 7233c2c4bb2SGreg Clayton for addr_str in args: 7243c2c4bb2SGreg Clayton addr = int(addr_str, 0) 725b9c1b51eSKate Stone symbolicated_addrs = symbolicator.symbolicate( 726b9c1b51eSKate Stone addr, options.verbose) 7273c2c4bb2SGreg Clayton for symbolicated_addr in symbolicated_addrs: 728a658ab9fSDavide Italiano print(symbolicated_addr) 729a658ab9fSDavide Italiano print() 7303c2c4bb2SGreg Clayton else: 731a658ab9fSDavide Italiano print('error: no target for %s' % (symbolicator)) 7323c2c4bb2SGreg Clayton 7333c2c4bb2SGreg Claytonif __name__ == '__main__': 7343c2c4bb2SGreg Clayton # Create a new debugger instance 735c29c24beSJonas Devlieghere debugger = lldb.SBDebugger.Create() 736c29c24beSJonas Devlieghere Symbolicate(debugger, sys.argv[1:]) 737c29c24beSJonas Devlieghere SBDebugger.Destroy(debugger) 738