#!/usr/bin/env 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
#----------------------------------------------------------------------

import lldb
import optparse
import os
import plistlib
import re
import shlex
import sys
import time
import uuid
import json
import tempfile


class Address:
    """Class that represents an address that will be symbolicated"""

    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

    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

    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

    def symbolicate(self, verbose=False):
        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:
                    # Print full source file path in verbose mode
                    if verbose:
                        self.symbolication += str(module.GetFileSpec()) + '`'
                    else:
                        self.symbolication += module.GetFileSpec().GetFilename() + '`'
                    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():
                        # Print full source file path in verbose mode
                        if verbose:
                            self.symbolication += ' at %s' % line_entry.GetFileSpec()
                        else:
                            self.symbolication += ' at %s' % line_entry.GetFileSpec().GetFilename()
                        self.symbolication += ':%u' % line_entry.GetLine()
                        column = line_entry.GetColumn()
                        if column > 0:
                            self.symbolication += ':%u' % column
                    return True
        return False


class Section:
    """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

    @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

    def contains(self, addr):
        return self.start_addr <= addr and addr < self.end_addr

    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
        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')
        return False

    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>"


class Image:
    """A class that represents an executable image and any associated data"""

    def __init__(self, path, uuid=None):
        self.path = path
        self.resolved_path = None
        self.resolve = False
        self.resolved = False
        self.unavailable = False
        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
        self.symbols = dict()

    @classmethod
    def InitWithSBTargetAndSBModule(cls, target, module):
        '''Initialize this Image object with a module from a target.'''
        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

    def dump(self, prefix):
        print("%s%s" % (prefix, self))

    def debug_dump(self):
        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))

    def __str__(self):
        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)
        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

    def add_section(self, section):
        # print "added '%s' to '%s'" % (section, self.path)
        self.section_infos.append(section)

    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

    def has_section_load_info(self):
        return self.section_infos or self.slide is not None

    def load_module(self, target):
        if self.unavailable:
            return None  # We already warned that we couldn't find this module, so don't return an error string
        # 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'

    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
            uuid_str = self.get_normalized_uuid_string()
            if uuid_str:
                self.module = target.AddModule(None, None, uuid_str)
            if not self.module and self.resolve:
                self.locate_module_and_debug_symbols()
                if not self.unavailable:
                    resolved_path = self.get_resolved_path()
                    self.module = target.AddModule(
                        resolved_path, None, uuid_str, self.symfile)
            if not self.module and self.section_infos:
                name = os.path.basename(self.path)
                with tempfile.NamedTemporaryFile(suffix='.' + name) as tf:
                    data = {
                        'triple': target.triple,
                        'uuid': uuid_str,
                        'type': 'sharedlibrary',
                        'sections': list(),
                        'symbols': list()
                    }
                    for section in self.section_infos:
                        data['sections'].append({
                            'name' : section.name,
                            'size': section.end_addr - section.start_addr
                            })
                    data['symbols'] = list(self.symbols.values())
                    with open(tf.name, 'w') as f:
                        f.write(json.dumps(data, indent=4))
                    self.module = target.AddModule(tf.name, None, uuid_str)
            if not self.module and not self.unavailable:
                return 'error: unable to get module for (%s) "%s"' % (
                    self.arch, self.get_resolved_path())
            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'

    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
        self.resolved = True
        return True

    def get_uuid(self):
        if not self.uuid and self.module:
            self.uuid = uuid.UUID(self.module.GetUUIDString())
        return self.uuid

    def get_normalized_uuid_string(self):
        if self.uuid:
            return str(self.uuid).upper()
        return None

    def create_target(self, debugger):
        '''Create a target using the information in this Image object.'''
        if self.unavailable:
            return None

        if self.locate_module_and_debug_symbols():
            resolved_path = self.get_resolved_path()
            path_spec = lldb.SBFileSpec(resolved_path)
            error = lldb.SBError()
            target = 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:
                        print('ERROR: ', err)
                return target
            else:
                print('error: unable to create a valid target for (%s) "%s"' % (self.arch, self.path))
        else:
            print('error: unable to locate main executable (%s) "%s"' % (self.arch, self.path))
        return None


class Symbolicator:

    def __init__(self, debugger=None, target=None, images=list()):
        """A class the represents the information needed to symbolicate
        addresses in a program.

        Do not call this initializer directly, but rather use the factory
        methods.
        """
        self.debugger = debugger
        self.target = target
        self.images = images  # a list of images to be used when symbolicating
        self.addr_mask = 0xffffffffffffffff

    @classmethod
    def InitWithSBTarget(cls, target):
        """Initialize a new Symbolicator with an existing SBTarget."""
        obj = cls(target=target)
        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

    @classmethod
    def InitWithSBDebugger(cls, debugger, images):
        """Initialize a new Symbolicator with an existing debugger and list of
        images. The Symbolicator will create the target."""
        obj = cls(debugger=debugger, images=images)
        return obj

    def __str__(self):
        s = "Symbolicator:\n"
        if self.target:
            s += "Target = '%s'\n" % (self.target)
            s += "Target modules:\n"
            for m in self.target.modules:
                s += str(m) + "\n"
        s += "Images:\n"
        for image in self.images:
            s += '    %s\n' % (image)
        return s

    def find_images_with_identifier(self, identifier):
        images = list()
        for image in self.images:
            if image.identifier == identifier:
                images.append(image)
        if len(images) == 0:
            regex_text = '^.*\.%s$' % (re.escape(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):
        for image in self.images:
            if image.get_section_containing_load_addr(load_addr):
                return image
        return None

    def create_target(self):
        if self.target:
            return self.target

        if self.images:
            for image in self.images:
                self.target = image.create_target(self.debugger)
                if self.target:
                    if self.target.GetAddressByteSize() == 4:
                        triple = self.target.triple
                        if triple:
                            arch = triple.split('-')[0]
                            if "arm" in arch:
                                self.addr_mask = 0xfffffffffffffffe
                    return self.target
        return None

    def symbolicate(self, load_addr, verbose=False):
        if not self.target:
            self.create_target()
        if self.target:
            live_process = False
            process = self.target.process
            if process:
                state = process.state
                if state > lldb.eStateUnloaded and state < lldb.eStateDetached:
                    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)
            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

                        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)

                        # push the new frame onto the new frame stack
                        symbolicated_addresses.append(symbolicated_address)

                    if symbolicated_addresses:
                        return symbolicated_addresses
        else:
            print('error: no target in Symbolicator')
        return None


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:
                print(' -> ', lines[i])
            else:
                print('    ', lines[i])


def print_module_section_data(section):
    print(section)
    section_data = section.GetSectionData()
    if section_data:
        ostream = lldb.SBStream()
        section_data.GetDescription(ostream, section.GetFileAddress())
        print(ostream.GetData())


def print_module_section(section, depth):
    print(section)
    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)


def print_module_sections(module, depth):
    for sect in module.section_iter():
        print_module_section(sect, depth)


def print_module_symbols(module):
    for sym in module:
        print(sym)


def Symbolicate(debugger, command_args):

    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)
    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".')
    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(debugger)
    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)

    target = symbolicator.create_target()
    if options.verbose:
        print(symbolicator)
    if target:
        for addr_str in args:
            addr = int(addr_str, 0)
            symbolicated_addrs = symbolicator.symbolicate(
                addr, options.verbose)
            for symbolicated_addr in symbolicated_addrs:
                print(symbolicated_addr)
            print()
    else:
        print('error: no target for %s' % (symbolicator))

if __name__ == '__main__':
    # Create a new debugger instance
    debugger = lldb.SBDebugger.Create()
    Symbolicate(debugger, sys.argv[1:])
    SBDebugger.Destroy(debugger)
