#!/usr/bin/env python

# Copyright 2016 The Fuchsia Authors
#
# Use of this source code is governed by a MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT

"""

This tool will symbolize a crash from Zircon's crash logger, adding
function names and, if available, source code locations (filenames and
line numbers from debug info).

Example usage #1:
  ./scripts/run-zircon -a x64 | ./scripts/symbolize devmgr.elf --build-dir=build-x64

Example usage #2:
  ./scripts/symbolize devmgr.elf --build-dir=build-x64
  <copy and paste output from Zircon>

Example usage #3 (for zircon kernel output):
  ./scripts/symbolize --build-dir=build-x64
  <copy and paste output from Zircon>

"""

import argparse
import errno
import os
import re
import subprocess
import sys

SCRIPT_DIR = os.path.abspath(os.path.dirname(__file__))
PREBUILTS_BASE_DIR = os.path.abspath(os.path.join(os.path.dirname(SCRIPT_DIR), "prebuilt",
                                                  "downloads"))
GCC_VERSION = '6.3.0'
name_to_full_path = {}
debug_mode = False

# Paths to various external tools can be provided on the command line.
# If these are None then use the prebuilt location.
addr2line_tool_path = None
gdb_tool_path = None


def find_func(find_args, dirname, names):
    if find_args["path"] != "":  # found something!
        return
    if dirname.find("sysroot") != -1:
        return
    for name in names:
        if name == find_args["name"]:
            find_args["path"] = dirname
            return


def find_file_in_build_dir(name, build_dirs):
    find_args = {"name": name, "path": ""}
    for location in build_dirs:
        os.path.walk(location, find_func, find_args)
        if find_args["path"] != "":
            return os.path.abspath(os.path.join(find_args["path"], name))
    return None


def buildid_to_full_path(buildid, build_dirs):
    for build_dir in build_dirs:
        id_file_path = os.path.join(build_dir, "ids.txt")
        if os.path.exists(id_file_path):
            with open(id_file_path) as id_file:
                for line in id_file:
                    id, path = line.split()
                    if id == buildid:
                        return path
    return None


def find_file_in_boot_manifest(boot_app_name, build_dirs):
    manifest_path = find_file_in_build_dir("bootfs.manifest", build_dirs)
    if manifest_path:
        with open(manifest_path) as manifest_file:
            for line in manifest_file:
                out_path, in_path = line.rstrip().split("=")
                if out_path == boot_app_name:
                    if in_path.endswith(".strip"):
                        in_path = in_path[:-len(".strip")]
                    return in_path
    return None


def find_dso_full_path_uncached(dso, exe_name, name_to_buildid, build_dirs):
    if dso in name_to_buildid:
        found_path = buildid_to_full_path(name_to_buildid[dso], build_dirs)
        if found_path:
            return found_path
        # This can be a bug in the generation of the ids.txt file, report it.
        # It's not necessarily a bug though, so for now only report in debug mode.
        if debug_mode:
            print "WARNING: Unable to find %s in any ids.txt file." % dso

    # The name 'app' indicates the real app name is unknown.
    # If the process has a name property that will be printed, but
    # it has a max of 32 characters so it may be insufficient.
    # Crashlogger prefixes such names with "app:" for our benefit.
    if dso == "app" or dso.startswith("app:"):
        # If an executable was passed on the command-line, try using that
        if exe_name:
            found_path = find_file_in_build_dir(exe_name, build_dirs)
            if found_path:
                return found_path

        # If this looks like a program in boot fs, consult the manifest
        if dso.startswith("app:/boot/"):
            boot_app_name = dso[len("app:/boot/"):]
            found_path = find_file_in_boot_manifest(boot_app_name, build_dirs)
            if found_path:
                return found_path
        return None

    # First, try an exact match for the filename
    found_path = find_file_in_build_dir(dso, build_dirs)
    if not found_path:
        # If that fails, and this file doesn't end with .so, try the executable
        # name
        if not dso.endswith(".so"):
            found_path = find_file_in_build_dir(exe_name, build_dirs)
    if not found_path:
        # If that still fails and this looks like an absolute path, try the
        # last path component
        if dso.startswith("/"):
            short_name = dso[dso.rfind("/"):]
            found_path = find_file_in_build_dir(short_name, build_dirs)
    return found_path


def find_dso_full_path(dso, exe_name, name_to_buildid, build_dirs):
    if dso in name_to_full_path:
        return name_to_full_path[dso]
    found_path = find_dso_full_path_uncached(dso, exe_name, name_to_buildid, build_dirs)
    if found_path:
        name_to_full_path[dso] = found_path
    return found_path


def tool_path(arch, tool, user_provided_path):
    if user_provided_path is not None:
        return user_provided_path
    return ("%s/gcc/bin/%s-elf-%s" %
            (PREBUILTS_BASE_DIR, arch, tool))


def run_tool(path, *args):
    cmd = [path] + list(args)
    if debug_mode:
        print "Running: %s" % " ".join(cmd)
    try:
        output = subprocess.check_output(cmd)
    except Exception as e:
        tool = os.path.basename(path)
        print "Calling %s failed: command %s error %s" % (tool, cmd, e)
        return False
    return output.rstrip()


# Note: addr2line requires hex addresses.
# |addr_as_hex_string| must already be PIE-adjusted.
def run_addr2line(arch, elf_path, addr_as_hex_string):
    path = tool_path(arch, "addr2line", addr2line_tool_path)
    return run_tool(path, "-Cipfe", elf_path, addr_as_hex_string)


# The caller passes in a list of arguments, this is not a varargs function.
def run_gdb(arch, arguments):
    path = tool_path(arch, "gdb", gdb_tool_path)
    return run_tool(path, *arguments)


GDB_ARCH_LUT = { "x86_64": "i386:x86-64",
                 "aarch64": "aarch64" }
def get_gdb_set_arch_cmd(arch):
    gdb_arch = GDB_ARCH_LUT[arch]
    return "set arch %s" % gdb_arch


def get_call_location(arch, elf_path, addr_as_hex_string):
    # Subtract 1 to convert from a return address to a call site
    # address.  (To be more exact, this converts to an address that
    # is within the call site instruction.)  This adjustment gives
    # more correct results in the presence of inlining and
    # 'noreturn' functions.  (See ZX-842.)
    call_addr = "0x%x" % (int(addr_as_hex_string, 16) - 1)
    return run_addr2line(arch, elf_path, call_addr)


# On BSD platforms there are cases where writing to stdout can return EAGAIN.
# In that event, retry the line again. This only manifests itself when piping
# qemu's stdout directly to this script.
def writelines(lines):
    for line in lines:
        writeline(line)


def writeline(line):
    while True:
        try:
            sys.stdout.write(line + "\n")
        except IOError as e:
            if e.errno == errno.EAGAIN:
                continue
        break


# Offset the address based on binary code start and bias
# Return same type than input
def kaslr_offset(addr, code_start, bias):
    if not code_start or not bias:
        return addr
    is_string = isinstance(addr, str)
    if is_string:
        addr = int(addr, 16)
    addr -= bias - code_start
    if is_string:
        return '%x' % addr
    return addr

ARCH_REMAP_LUT = { 'x86_64' : 'x64',
                   'aarch64' : 'arm64'
                 }
def choose_build_dirs(cli_args, arch):
    arch = ARCH_REMAP_LUT.get(arch, arch)
    zircon_build_dir = os.path.join(
        os.path.dirname(SCRIPT_DIR), "build-%s" % (arch, ))
    if not os.path.exists(zircon_build_dir):
        zircon_build_dir = os.path.join(
            os.path.dirname(SCRIPT_DIR), os.pardir, "out", "build-zircon", "build-%s" % (arch, ))
    build_dirs = [zircon_build_dir]
    if cli_args.build_dir:
        build_dirs = cli_args.build_dir + build_dirs
    else:
        # Put the unstripped path ahead of the stripped one, we want the
        # former searched first. This does mean the unstripped directory
        # will get searched twice, but relative to the entire search time,
        # the addition is small.
        # Plus once a file is found its location is cached.
        # Plus this is only used as a fallback in case the file isn't found
        # in ids.txt.
        fuchsia_build_dir = os.path.abspath(os.path.join(
            os.path.dirname(SCRIPT_DIR), os.pardir, "out", arch))
        fuchsia_unstripped_dir = os.path.join(fuchsia_build_dir, "exe.unstripped")
        build_dirs = [fuchsia_unstripped_dir, fuchsia_build_dir] + build_dirs
    return build_dirs

def get_zircon_source_dir():
    zircon_source_dir = os.path.join(
        os.path.dirname(SCRIPT_DIR), os.pardir, "zircon")
    return zircon_source_dir

def parse_args():
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument("--file", "-f", nargs="?", type=argparse.FileType("r"),
                        default=sys.stdin,
                        help="File to read from, stdin by default")
    parser.add_argument("--build-dir", "-b", nargs="*",
                        help="List of build directories to search instead of the default (out/x64)")
    parser.add_argument("--disassemble", "-d", action="store_true",
                        help="Show disassembly of each function")
    parser.add_argument("--source", "-S", action="store_true",
                        help="Include source in the disassembly (requires -d)")
    parser.add_argument("--stack_size", "-s", type=int,
                        default=256*1024,
                        help="Change the assumed size of the stack (e.g. use 1048576 for ftl or "
                             "mtl default thread size")
    parser.add_argument("--echo", dest="echo", action="store_true",
                        help="Echo lines of input (on by default)")
    parser.add_argument("--no-echo", dest="echo", action="store_false",
                        help="Don't echo lines of input")
    parser.add_argument("--debug", "-D", action="store_true",
                        help="Print messages for debugging symbolize")
    parser.add_argument("--addr2line", default=None,
                        help="Path of addr2line program to use")
    parser.add_argument("--gdb", default=None,
                        help="Path of gdb program to use")
    parser.add_argument("app", nargs="?", help="Name of primary application")
    parser.set_defaults(echo=True)
    return parser.parse_args()

class Symbolizer:
    # Regex for parsing
    # Full prefix can be:
    #   - nothing
    #   - something like "[00007.268] 00304.00325> "  (before we started using pid:tid)
    #   - something like "[00007.268] 00304:00325> "
    #   - something like "[00041.807507][1105][1119][klog] INFO: "
    full_prefix = "^(|\[\d+\.\d+\] \d+[\.:]\d+> ?|\[\d{5}\.\d{6}\]\[\d+\]\[\d+\]\[[\w ,]+\] INFO: ?)"
    btre = re.compile(full_prefix + "bt#(\d+):")
    bt_with_offset_re = re.compile(full_prefix +
        "bt#(\d+): pc 0x[0-9a-f]+ sp (0x[0-9a-f]+) \(([^,]+),(0x[0-9a-f]+)\)$")
    bt_end_re = re.compile(full_prefix + "bt#(\d+): end")
    arch_re = re.compile(full_prefix + "arch: ([\\S]+)$")
    build_id_re = re.compile(full_prefix +
        "(?:dlsvc: debug: )?dso: id=([0-9a-z]+) base=(0x[0-9a-f]+) name=(.+)$")
    disasm_re = re.compile("^ *(0x[0-9a-f]+)( .+)$")

    # Zircon backtraces
    zircon_crash_re = re.compile(full_prefix + "ZIRCON KERNEL PANIC$")
    # TODO(cja): Add ARM to the regex
    zircon_pc_re = re.compile("RIP: (0x[0-9a-z]+)")
    zircon_bt_re = re.compile(full_prefix +
        "bt#(\d+): (\dx[0-9a-fA-F]+)$")
    zircon_nm_codestart = re.compile('^([a-f0-9]+) t __code_start$', re.M)

    # ASAN backtraces
    asan_bt_re = re.compile(full_prefix + "\{\{\{bt:(\d+):(0x[0-9a-f]+)\}\}\}")
    asan_bt_end_re = re.compile(full_prefix + "$")

    def __init__(self, args):
        self.args = args
        self.arch = "x86_64"
        self.build_dirs = choose_build_dirs(self.args, self.arch)
        self.name_to_buildid = {}
        self.bias_to_name = {}
        self.reset()

    def reset(self):
        self.bias = 0
        self.processed_lines = []
        self.prev_sp = None
        self.prev_frame_num = None
        self.frame_sizes = []
        self.total_stack_size = 0
        # If True and we see a dso line, start over collecting the list.
        self.done_dso_list = True

        self.zircon_elf_path = ''
        self.zircon_code_start = None
        self.zircon_bt = False
        self.zircon_pc = ''

        self.asan_bt = False

    def write_processed_lines(self):
        writeline("\nstart of symbolized stack:")
        writelines(self.processed_lines)
        writeline("end of symbolized stack\n")

        if self.total_stack_size > self.args.stack_size - 8*1024:
            if self.total_stack_size >= self.args.stack_size:
                message = "Overflowed stack"
            else:
                message = "Potentially overflowed stack"
            writeline("WARNING: %s (total usage: %d, stack size: %d)" %
                (message, self.total_stack_size, self.args.stack_size))
            for frame, size in self.frame_sizes:
                writeline("#%s: %d bytes" % (frame, size))
        self.reset()

    # If the architecture has changed, choose our new build dirs and
    # clear our DSO cache.  We may be symbolizing the output of
    # logserver, and it may be reasonable for the target architecture to
    # be changing as the user boots and tests on different
    # architectures.
    def update_arch(self, m):
        new_arch = m.group(2)
        if (self.arch != new_arch):
            self.arch = new_arch
            global name_to_full_path
            name_to_full_path = {}
            self.build_dirs = choose_build_dirs(self.args, self.arch)

    def update_build_id(self, m):
        if self.done_dso_list:
            self.name_to_buildid = {}
            self.bias_to_name = {}
            self.done_dso_list = False
        buildid = m.group(2)
        self.bias = int(m.group(3), 16)
        name = m.group(4)
        self.name_to_buildid[name] = buildid
        self.bias_to_name[self.bias] = name

        if self.zircon_code_start and self.zircon_code_start != self.bias:
            if self.zircon_code_start < self.bias:
                diff = self.bias - self.zircon_code_start
                c = '+'
            else:
                diff = self.zircon_code_start - self.bias
                c = '-'
            writeline('kaslr offset is %c0x%x' % (c, diff))

    def process_bt(self, m, frame_num):
        sp = int(m.group(3), 16)
        if self.prev_sp is not None:
            frame_size = sp - self.prev_sp
            self.total_stack_size += frame_size
            self.frame_sizes.append((self.prev_frame_num, frame_size))
        self.prev_sp = sp
        self.prev_frame_num = frame_num

        dso = m.group(4)
        off = m.group(5)

        # Adapt offset for KASLR move
        off = kaslr_offset(off, self.zircon_code_start, self.bias)

        dso_full_path = find_dso_full_path(
            dso, self.args.app, self.name_to_buildid, self.build_dirs)
        if not dso_full_path:
            # can't find dso_full_path
            self.processed_lines.append("#%s: unknown, can't find full path for %s" %
                (frame_num, dso))
            return

        call_loc = get_call_location(self.arch, dso_full_path, off)
        if call_loc:
            self.processed_lines.append(
                "#%s: %s" % (frame_num, call_loc))
        if self.args.disassemble:
            pc = int(off, 16)
            # GDB can get confused what the default arch should be.
            # Cope by explicitly setting it.
            gdb_set_arch_cmd = get_gdb_set_arch_cmd(self.arch)
            run_gdb_options = [ "--nx", "--batch",
                                "-ex", gdb_set_arch_cmd ]
            if self.args.source:
                gdb_source_search_dirs = self.build_dirs
                gdb_source_search_dirs.append(get_zircon_source_dir())
                run_gdb_options += [ "-ex", "dir %s" % (
                    ":".join(gdb_source_search_dirs)) ]
            disassemble_cmd = "disassemble %s %#x" % (
                "/s" if self.args.source else "", pc)
            run_gdb_options += [ "-ex", disassemble_cmd, dso_full_path ]
            disassembly = run_gdb(self.arch, run_gdb_options)
            if disassembly:
                for line in disassembly.splitlines():
                    m = Symbolizer.disasm_re.match(line)
                    if not m:
                        # If we're printing source, include these lines.
                        if self.args.source:
                            self.processed_lines.append(line)
                        continue
                    addr, rest = m.groups()
                    addr = int(addr, 16)
                    if addr == pc:
                        prefix = "=> "
                    else:
                        prefix = "   "
                    line = "%s%#.16x%s" % (prefix, self.bias + addr, rest)
                    self.processed_lines.append(line)

    def update_zircon(self):
        self.zircon_elf_path = find_file_in_build_dir("zircon.elf", self.build_dirs)
        if not self.zircon_elf_path:
            sys.stderr.write("Symbolize could not find the zircon elf binary. Perhaps you need "
                              "to build zircon or specify the build directory with -b?\n")
            return
        self.zircon_bt = True
        nm_result = run_tool(self.arch, "nm", self.zircon_elf_path)
        m = Symbolizer.zircon_nm_codestart.search(nm_result)
        if not m:
            sys.stderr.write("Failed to find __code_start from nm")
            return
        self.zircon_code_start = int(m.group(1), 16)

    # In the case of inlined methods, it is more readable if the
    # inlined lines are aligned to be to the right of "=>".
    @staticmethod
    def align_inlined(prefix, s):
        return prefix + s.replace("(inlined", (" " * len(prefix)) + "(inlined")

    def process_zircon_bt(self, m):
        frame_num = m.group(2)
        addr = m.group(3)
        # If we saw the instruction pointer for the fault/panic then use it once
        if self.zircon_pc:
            prefix = "   pc: %s => " % self.zircon_pc
            a2l_out = run_addr2line(self.arch, self.zircon_elf_path, self.zircon_pc)
            self.processed_lines.append(prefix +
                    a2l_out.replace("(inlined", (" " * len(prefix)) + "(inlined"))
            self.zircon_pc = None

        # Adapt offset for KASLR move
        addr = kaslr_offset(addr, self.zircon_code_start, self.bias)

        prefix = "bt#%s: %s => " % (frame_num, addr)
        call_loc = get_call_location(self.arch, self.zircon_elf_path, addr)
        self.processed_lines.append(Symbolizer.align_inlined(prefix, call_loc))

    def process_asan_bt(self, m):
        self.asan_bt = True
        frame_num = m.group(2)
        addr = int(m.group(3), 16)
        offset = None
        dso = None
        for bias, candidate_dso in self.bias_to_name.items():
            if addr >= bias:
                candidate_offset = addr - bias
                if offset is None or candidate_offset < offset:
                    offset = candidate_offset
                    dso = candidate_dso
        if offset is None:
            self.processed_lines.append("#%s: unknown, can't find DSO for addr 0x%x" %
                (frame_num, addr))
            return
        dso_full_path = find_dso_full_path(dso, self.args.app, self.name_to_buildid, self.build_dirs)
        if not dso_full_path:
            self.processed_lines.append("#%s: unknown, can't find full path for %s" %
                (frame_num, dso))
            return

        # Adapt offset for KASLR move
        offset = kaslr_offset(offset, self.zircon_code_start, self.bias)

        prefix = "bt#%s: 0x%x => " % (frame_num, addr)
        call_loc = run_addr2line(self.arch, dso_full_path, "0x%x" % offset)
        if call_loc:
            self.processed_lines.append(Symbolizer.align_inlined(prefix, call_loc))

    def run(self):
        while True:
            line = self.args.file.readline()
            end_of_file = (line == '')
            line = line.rstrip()
            if self.args.echo and not self.args.file.isatty():
                writeline(line)

            bt_end = Symbolizer.bt_end_re.match(line)
            self.asan_bt_end = self.asan_bt and Symbolizer.asan_bt_end_re.match(line)
            if bt_end or self.asan_bt_end or end_of_file:
                if len(self.processed_lines) != 0:
                    self.write_processed_lines()
                if end_of_file:
                    break
                else:
                    continue

            m = Symbolizer.arch_re.match(line)
            if m:
                self.update_arch(m)
                continue

            m = Symbolizer.build_id_re.match(line)
            if m:
                self.update_build_id(m)
                continue

            # We didn't see a dso line, so we're done with this list.
            # The next time we see one means we're starting a new list.
            self.done_dso_list = True

            m = Symbolizer.btre.match(line)
            if m and not self.zircon_bt:
                frame_num = m.group(2)
                m = Symbolizer.bt_with_offset_re.match(line)
                if not m:
                    self.processed_lines.append("#%s: unknown, can't find pc, sp or app/library in line" %
                        frame_num)
                    continue
                self.process_bt(m, frame_num)
                continue

            # Zircon Specific Handling
            if Symbolizer.zircon_crash_re.search(line):
                self.update_zircon()
                continue

            m = Symbolizer.zircon_pc_re.search(line)
            if m:
                self.zircon_pc = kaslr_offset(m.group(1), self.zircon_code_start, self.bias)
                continue

            m = Symbolizer.zircon_bt_re.match(line)
            if m and self.zircon_bt:
                self.process_zircon_bt(m)
                continue

            # ASAN Specific Handling
            m = Symbolizer.asan_bt_re.match(line)
            if m and not self.zircon_bt:
                self.process_asan_bt(m)
                continue


def main():
    args = parse_args()
    global debug_mode
    debug_mode = args.debug
    global addr2line_tool_path
    addr2line_tool_path = args.addr2line
    global gdb_tool_path
    gdb_tool_path = args.gdb

    symbolizer = Symbolizer(args)
    symbolizer.run()


if __name__ == '__main__':
    sys.exit(main())
