#!/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(r"^\s*(?P<start>0x[0-9A-Fa-f]+)\s*$")
    range_regex = re.compile(
        r"^\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, obj_dir=None):
        """Add the Image described in this object to "target" and load the sections if "load" is True."""
        if not self.path and self.uuid == uuid.UUID(int=0):
            return "error: invalid image"

        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)
                if obj_dir and os.path.isdir(obj_dir):
                    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())
                    obj_file = os.path.join(obj_dir, name)
                    with open(obj_file, "w") as f:
                        f.write(json.dumps(data, indent=4))
                    self.module = target.AddModule(obj_file, None, uuid_str)
                    if self.module:
                        # If we were able to add the module with inlined
                        # symbols, we should mark it as available so load_module
                        # does not exit early.
                        self.unavailable = False
            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=None):
        """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
        # a list of images to be used when symbolicating
        self.images = images if images else list()
        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 = r"^.*\.%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)
