#!/usr/bin/env python
#===- lib/asan/scripts/asan_symbolize.py -----------------------------------===#
#
# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
#===------------------------------------------------------------------------===#
"""
Example of use:
  asan_symbolize.py -c "$HOME/opt/cross/bin/arm-linux-gnueabi-" -s "$HOME/SymbolFiles" < asan.log

PLUGINS

This script provides a way for external plug-ins to hook into the behaviour of
various parts of this script (see `--plugins`). This is useful for situations
where it is necessary to handle site-specific quirks (e.g. binaries with debug
symbols only accessible via a remote service) without having to modify the
script itself.

"""
import argparse
import bisect
import errno
import getopt
import logging
import os
import re
import subprocess
import sys
from distutils.spawn import find_executable

symbolizers = {}
demangle = False
binutils_prefix = None
fix_filename_patterns = None
logfile = sys.stdin
allow_system_symbolizer = True
force_system_symbolizer = False

# FIXME: merge the code that calls fix_filename().
def fix_filename(file_name):
  if fix_filename_patterns:
    for path_to_cut in fix_filename_patterns:
      file_name = re.sub('.*' + path_to_cut, '', file_name)
  file_name = re.sub('.*asan_[a-z_]*.(cc|cpp):[0-9]*', '_asan_rtl_', file_name)
  file_name = re.sub('.*crtstuff.c:0', '???:0', file_name)
  return file_name

def is_valid_arch(s):
  return s in ["i386", "x86_64", "x86_64h", "arm", "armv6", "armv7", "armv7s",
               "armv7k", "arm64", "powerpc64", "powerpc64le", "s390x", "s390",
               "riscv64"]

def guess_arch(addr):
  # Guess which arch we're running. 10 = len('0x') + 8 hex digits.
  if len(addr) > 10:
    return 'x86_64'
  else:
    return 'i386'

class Symbolizer(object):
  def __init__(self):
    pass

  def symbolize(self, addr, binary, offset):
    """Symbolize the given address (pair of binary and offset).

    Overriden in subclasses.
    Args:
        addr: virtual address of an instruction.
        binary: path to executable/shared object containing this instruction.
        offset: instruction offset in the @binary.
    Returns:
        list of strings (one string for each inlined frame) describing
        the code locations for this instruction (that is, function name, file
        name, line and column numbers).
    """
    return None


class LLVMSymbolizer(Symbolizer):
  def __init__(self, symbolizer_path, default_arch, system, dsym_hints=[]):
    super(LLVMSymbolizer, self).__init__()
    self.symbolizer_path = symbolizer_path
    self.default_arch = default_arch
    self.system = system
    self.dsym_hints = dsym_hints
    self.pipe = self.open_llvm_symbolizer()

  def open_llvm_symbolizer(self):
    cmd = [self.symbolizer_path,
           ('--demangle' if demangle else '--no-demangle'),
           '--functions=linkage',
           '--inlines',
           '--default-arch=%s' % self.default_arch]
    if self.system == 'Darwin':
      for hint in self.dsym_hints:
        cmd.append('--dsym-hint=%s' % hint)
    logging.debug(' '.join(cmd))
    try:
      result = subprocess.Popen(cmd, stdin=subprocess.PIPE,
                                stdout=subprocess.PIPE,
                                bufsize=0,
                                universal_newlines=True)
    except OSError:
      result = None
    return result

  def symbolize(self, addr, binary, offset):
    """Overrides Symbolizer.symbolize."""
    if not self.pipe:
      return None
    result = []
    try:
      symbolizer_input = '"%s" %s' % (binary, offset)
      logging.debug(symbolizer_input)
      self.pipe.stdin.write("%s\n" % symbolizer_input)
      while True:
        function_name = self.pipe.stdout.readline().rstrip()
        if not function_name:
          break
        file_name = self.pipe.stdout.readline().rstrip()
        file_name = fix_filename(file_name)
        if (not function_name.startswith('??') or
            not file_name.startswith('??')):
          # Append only non-trivial frames.
          result.append('%s in %s %s' % (addr, function_name,
                                         file_name))
    except Exception:
      result = []
    if not result:
      result = None
    return result


def LLVMSymbolizerFactory(system, default_arch, dsym_hints=[]):
  symbolizer_path = os.getenv('LLVM_SYMBOLIZER_PATH')
  if not symbolizer_path:
    symbolizer_path = os.getenv('ASAN_SYMBOLIZER_PATH')
    if not symbolizer_path:
      # Assume llvm-symbolizer is in PATH.
      symbolizer_path = 'llvm-symbolizer'
  return LLVMSymbolizer(symbolizer_path, default_arch, system, dsym_hints)


class Addr2LineSymbolizer(Symbolizer):
  def __init__(self, binary):
    super(Addr2LineSymbolizer, self).__init__()
    self.binary = binary
    self.pipe = self.open_addr2line()
    self.output_terminator = -1

  def open_addr2line(self):
    addr2line_tool = 'addr2line'
    if binutils_prefix:
      addr2line_tool = binutils_prefix + addr2line_tool
    logging.debug('addr2line binary is %s' % find_executable(addr2line_tool))
    cmd = [addr2line_tool, '-fi']
    if demangle:
      cmd += ['--demangle']
    cmd += ['-e', self.binary]
    logging.debug(' '.join(cmd))
    return subprocess.Popen(cmd,
                            stdin=subprocess.PIPE, stdout=subprocess.PIPE,
                            bufsize=0,
                            universal_newlines=True)

  def symbolize(self, addr, binary, offset):
    """Overrides Symbolizer.symbolize."""
    if self.binary != binary:
      return None
    lines = []
    try:
      self.pipe.stdin.write("%s\n" % offset)
      self.pipe.stdin.write("%s\n" % self.output_terminator)
      is_first_frame = True
      while True:
        function_name = self.pipe.stdout.readline().rstrip()
        logging.debug("read function_name='%s' from addr2line" % function_name)
        # If llvm-symbolizer is installed as addr2line, older versions of
        # llvm-symbolizer will print -1 when presented with -1 and not print
        # a second line. In that case we will block for ever trying to read the
        # file name. This also happens for non-existent files, in which case GNU
        # addr2line exits immediate, but llvm-symbolizer does not (see
        # https://llvm.org/PR42754).
        if function_name == '-1':
          logging.debug("got function '-1' -> no more input")
          break
        file_name = self.pipe.stdout.readline().rstrip()
        logging.debug("read file_name='%s' from addr2line" % file_name)
        if is_first_frame:
          is_first_frame = False
        elif function_name == '??':
          assert file_name == '??:0', file_name
          logging.debug("got function '??' -> no more input")
          break
        elif not function_name:
          assert not file_name, file_name
          logging.debug("got empty function name -> no more input")
          break
        if not function_name and not file_name:
          logging.debug("got empty function and file name -> unknown function")
          function_name = '??'
          file_name = '??:0'
        lines.append((function_name, file_name))
    except IOError as e:
      # EPIPE happens if addr2line exits early (which some implementations do
      # if an invalid file is passed).
      if e.errno == errno.EPIPE:
        logging.debug(f"addr2line exited early (broken pipe) returncode={self.pipe.poll()}")
      else:
        logging.debug("unexpected I/O exception communicating with addr2line", exc_info=e)
      lines.append(('??', '??:0'))
    except Exception as e:
      logging.debug("got unknown exception communicating with addr2line", exc_info=e)
      lines.append(('??', '??:0'))
    return ['%s in %s %s' % (addr, function, fix_filename(file)) for (function, file) in lines]

class UnbufferedLineConverter(object):
  """
  Wrap a child process that responds to each line of input with one line of
  output.  Uses pty to trick the child into providing unbuffered output.
  """
  def __init__(self, args, close_stderr=False):
    # Local imports so that the script can start on Windows.
    import pty
    import termios
    pid, fd = pty.fork()
    if pid == 0:
      # We're the child. Transfer control to command.
      if close_stderr:
        dev_null = os.open('/dev/null', 0)
        os.dup2(dev_null, 2)
      os.execvp(args[0], args)
    else:
      # Disable echoing.
      attr = termios.tcgetattr(fd)
      attr[3] = attr[3] & ~termios.ECHO
      termios.tcsetattr(fd, termios.TCSANOW, attr)
      # Set up a file()-like interface to the child process
      self.r = os.fdopen(fd, "r", 1)
      self.w = os.fdopen(os.dup(fd), "w", 1)

  def convert(self, line):
    self.w.write(line + "\n")
    return self.readline()

  def readline(self):
    return self.r.readline().rstrip()


class DarwinSymbolizer(Symbolizer):
  def __init__(self, addr, binary, arch):
    super(DarwinSymbolizer, self).__init__()
    self.binary = binary
    self.arch = arch
    self.open_atos()

  def open_atos(self):
    logging.debug('atos -o %s -arch %s', self.binary, self.arch)
    cmdline = ['atos', '-o', self.binary, '-arch', self.arch]
    self.atos = UnbufferedLineConverter(cmdline, close_stderr=True)

  def symbolize(self, addr, binary, offset):
    """Overrides Symbolizer.symbolize."""
    if self.binary != binary:
      return None
    if not os.path.exists(binary):
      # If the binary doesn't exist atos will exit which will lead to IOError
      # exceptions being raised later on so just don't try to symbolize.
      return ['{} ({}:{}+{})'.format(addr, binary, self.arch, offset)]
    atos_line = self.atos.convert('0x%x' % int(offset, 16))
    while "got symbolicator for" in atos_line:
      atos_line = self.atos.readline()
    # A well-formed atos response looks like this:
    #   foo(type1, type2) (in object.name) (filename.cc:80)
    # NOTE:
    #   * For C functions atos omits parentheses and argument types.
    #   * For C++ functions the function name (i.e., `foo` above) may contain
    #     templates which may contain parentheses.
    match = re.match('^(.*) \(in (.*)\) \((.*:\d*)\)$', atos_line)
    logging.debug('atos_line: %s', atos_line)
    if match:
      function_name = match.group(1)
      file_name = fix_filename(match.group(3))
      return ['%s in %s %s' % (addr, function_name, file_name)]
    else:
      return ['%s in %s' % (addr, atos_line)]


# Chain several symbolizers so that if one symbolizer fails, we fall back
# to the next symbolizer in chain.
class ChainSymbolizer(Symbolizer):
  def __init__(self, symbolizer_list):
    super(ChainSymbolizer, self).__init__()
    self.symbolizer_list = symbolizer_list

  def symbolize(self, addr, binary, offset):
    """Overrides Symbolizer.symbolize."""
    for symbolizer in self.symbolizer_list:
      if symbolizer:
        result = symbolizer.symbolize(addr, binary, offset)
        if result:
          return result
    return None

  def append_symbolizer(self, symbolizer):
    self.symbolizer_list.append(symbolizer)


def BreakpadSymbolizerFactory(binary):
  suffix = os.getenv('BREAKPAD_SUFFIX')
  if suffix:
    filename = binary + suffix
    if os.access(filename, os.F_OK):
      return BreakpadSymbolizer(filename)
  return None


def SystemSymbolizerFactory(system, addr, binary, arch):
  if system == 'Darwin':
    return DarwinSymbolizer(addr, binary, arch)
  elif system in ['Linux', 'FreeBSD', 'NetBSD', 'SunOS']:
    return Addr2LineSymbolizer(binary)


class BreakpadSymbolizer(Symbolizer):
  def __init__(self, filename):
    super(BreakpadSymbolizer, self).__init__()
    self.filename = filename
    lines = file(filename).readlines()
    self.files = []
    self.symbols = {}
    self.address_list = []
    self.addresses = {}
    # MODULE mac x86_64 A7001116478B33F18FF9BEDE9F615F190 t
    fragments = lines[0].rstrip().split()
    self.arch = fragments[2]
    self.debug_id = fragments[3]
    self.binary = ' '.join(fragments[4:])
    self.parse_lines(lines[1:])

  def parse_lines(self, lines):
    cur_function_addr = ''
    for line in lines:
      fragments = line.split()
      if fragments[0] == 'FILE':
        assert int(fragments[1]) == len(self.files)
        self.files.append(' '.join(fragments[2:]))
      elif fragments[0] == 'PUBLIC':
        self.symbols[int(fragments[1], 16)] = ' '.join(fragments[3:])
      elif fragments[0] in ['CFI', 'STACK']:
        pass
      elif fragments[0] == 'FUNC':
        cur_function_addr = int(fragments[1], 16)
        if not cur_function_addr in self.symbols.keys():
          self.symbols[cur_function_addr] = ' '.join(fragments[4:])
      else:
        # Line starting with an address.
        addr = int(fragments[0], 16)
        self.address_list.append(addr)
        # Tuple of symbol address, size, line, file number.
        self.addresses[addr] = (cur_function_addr,
                                int(fragments[1], 16),
                                int(fragments[2]),
                                int(fragments[3]))
    self.address_list.sort()

  def get_sym_file_line(self, addr):
    key = None
    if addr in self.addresses.keys():
      key = addr
    else:
      index = bisect.bisect_left(self.address_list, addr)
      if index == 0:
        return None
      else:
        key = self.address_list[index - 1]
    sym_id, size, line_no, file_no = self.addresses[key]
    symbol = self.symbols[sym_id]
    filename = self.files[file_no]
    if addr < key + size:
      return symbol, filename, line_no
    else:
      return None

  def symbolize(self, addr, binary, offset):
    if self.binary != binary:
      return None
    res = self.get_sym_file_line(int(offset, 16))
    if res:
      function_name, file_name, line_no = res
      result = ['%s in %s %s:%d' % (
          addr, function_name, file_name, line_no)]
      print(result)
      return result
    else:
      return None


class SymbolizationLoop(object):
  def __init__(self, plugin_proxy=None, dsym_hint_producer=None):
    self.plugin_proxy = plugin_proxy
    if sys.platform == 'win32':
      # ASan on Windows uses dbghelp.dll to symbolize in-process, which works
      # even in sandboxed processes.  Nothing needs to be done here.
      self.process_line = self.process_line_echo
    else:
      # Used by clients who may want to supply a different binary name.
      # E.g. in Chrome several binaries may share a single .dSYM.
      self.dsym_hint_producer = dsym_hint_producer
      self.system = os.uname()[0]
      if self.system not in ['Linux', 'Darwin', 'FreeBSD', 'NetBSD','SunOS']:
        raise Exception('Unknown system')
      self.llvm_symbolizers = {}
      self.last_llvm_symbolizer = None
      self.dsym_hints = set([])
      self.frame_no = 0
      self.process_line = self.process_line_posix
      self.using_module_map = plugin_proxy.has_plugin(ModuleMapPlugIn.get_name())

  def symbolize_address(self, addr, binary, offset, arch):
    # On non-Darwin (i.e. on platforms without .dSYM debug info) always use
    # a single symbolizer binary.
    # On Darwin, if the dsym hint producer is present:
    #  1. check whether we've seen this binary already; if so,
    #     use |llvm_symbolizers[binary]|, which has already loaded the debug
    #     info for this binary (might not be the case for
    #     |last_llvm_symbolizer|);
    #  2. otherwise check if we've seen all the hints for this binary already;
    #     if so, reuse |last_llvm_symbolizer| which has the full set of hints;
    #  3. otherwise create a new symbolizer and pass all currently known
    #     .dSYM hints to it.
    result = None
    if not force_system_symbolizer:
      if not binary in self.llvm_symbolizers:
        use_new_symbolizer = True
        if self.system == 'Darwin' and self.dsym_hint_producer:
          dsym_hints_for_binary = set(self.dsym_hint_producer(binary))
          use_new_symbolizer = bool(dsym_hints_for_binary - self.dsym_hints)
          self.dsym_hints |= dsym_hints_for_binary
        if self.last_llvm_symbolizer and not use_new_symbolizer:
            self.llvm_symbolizers[binary] = self.last_llvm_symbolizer
        else:
          self.last_llvm_symbolizer = LLVMSymbolizerFactory(
              self.system, arch, self.dsym_hints)
          self.llvm_symbolizers[binary] = self.last_llvm_symbolizer
      # Use the chain of symbolizers:
      # Breakpad symbolizer -> LLVM symbolizer -> addr2line/atos
      # (fall back to next symbolizer if the previous one fails).
      if not binary in symbolizers:
        symbolizers[binary] = ChainSymbolizer(
            [BreakpadSymbolizerFactory(binary), self.llvm_symbolizers[binary]])
      result = symbolizers[binary].symbolize(addr, binary, offset)
    else:
      symbolizers[binary] = ChainSymbolizer([])
    if result is None:
      if not allow_system_symbolizer:
        raise Exception('Failed to launch or use llvm-symbolizer.')
      # Initialize system symbolizer only if other symbolizers failed.
      symbolizers[binary].append_symbolizer(
          SystemSymbolizerFactory(self.system, addr, binary, arch))
      result = symbolizers[binary].symbolize(addr, binary, offset)
    # The system symbolizer must produce some result.
    assert result
    return result

  def get_symbolized_lines(self, symbolized_lines, inc_frame_counter=True):
    if not symbolized_lines:
      if inc_frame_counter:
        self.frame_no += 1
      return [self.current_line]
    else:
      assert inc_frame_counter
      result = []
      for symbolized_frame in symbolized_lines:
        result.append('    #%s %s' % (str(self.frame_no), symbolized_frame.rstrip()))
        self.frame_no += 1
      return result

  def process_logfile(self):
    self.frame_no = 0
    for line in logfile:
      processed = self.process_line(line)
      print('\n'.join(processed))

  def process_line_echo(self, line):
    return [line.rstrip()]

  def process_line_posix(self, line):
    self.current_line = line.rstrip()
    # Unsymbolicated:
    # #0 0x7f6e35cf2e45  (/blah/foo.so+0x11fe45)
    # Partially symbolicated:
    # #0 0x7f6e35cf2e45 in foo (foo.so+0x11fe45)
    # NOTE: We have to very liberal with symbol
    # names in the regex because it could be an
    # Objective-C or C++ demangled name.
    stack_trace_line_format = (
        '^( *#([0-9]+) *)(0x[0-9a-f]+) *(?:in *.+)? *\((.*)\+(0x[0-9a-f]+)\)')
    match = re.match(stack_trace_line_format, line)
    if not match:
      logging.debug('Line "{}" does not match regex'.format(line))
      # Not a frame line so don't increment the frame counter.
      return self.get_symbolized_lines(None, inc_frame_counter=False)
    logging.debug(line)
    _, frameno_str, addr, binary, offset = match.groups()

    if not self.using_module_map and not os.path.isabs(binary):
      # Do not try to symbolicate if the binary is just the module file name
      # and a module map is unavailable.
      # FIXME(dliew): This is currently necessary for reports on Darwin that are
      # partially symbolicated by `atos`.
      return self.get_symbolized_lines(None)
    arch = ""
    # Arch can be embedded in the filename, e.g.: "libabc.dylib:x86_64h"
    colon_pos = binary.rfind(":")
    if colon_pos != -1:
      maybe_arch = binary[colon_pos+1:]
      if is_valid_arch(maybe_arch):
        arch = maybe_arch
        binary = binary[0:colon_pos]
    if arch == "":
      arch = guess_arch(addr)
    if frameno_str == '0':
      # Assume that frame #0 is the first frame of new stack trace.
      self.frame_no = 0
    original_binary = binary
    binary = self.plugin_proxy.filter_binary_path(binary)
    if binary is None:
      # The binary filter has told us this binary can't be symbolized.
      logging.debug('Skipping symbolication of binary "%s"', original_binary)
      return self.get_symbolized_lines(None)
    symbolized_line = self.symbolize_address(addr, binary, offset, arch)
    if not symbolized_line:
      if original_binary != binary:
        symbolized_line = self.symbolize_address(addr, original_binary, offset, arch)
    return self.get_symbolized_lines(symbolized_line)

class AsanSymbolizerPlugInProxy(object):
  """
    Serves several purposes:
    - Manages the lifetime of plugins (must be used a `with` statement).
    - Provides interface for calling into plugins from within this script.
  """
  def __init__(self):
    self._plugins = [ ]
    self._plugin_names = set()

  def _load_plugin_from_file_impl_py_gt_2(self, file_path, globals_space):
      with open(file_path, 'r') as f:
        exec(f.read(), globals_space, None)

  def load_plugin_from_file(self, file_path):
    logging.info('Loading plugins from "{}"'.format(file_path))
    globals_space = dict(globals())
    # Provide function to register plugins
    def register_plugin(plugin):
      logging.info('Registering plugin %s', plugin.get_name())
      self.add_plugin(plugin)
    globals_space['register_plugin'] = register_plugin
    if sys.version_info.major < 3:
      execfile(file_path, globals_space, None)
    else:
      # Indirection here is to avoid a bug in older Python 2 versions:
      # `SyntaxError: unqualified exec is not allowed in function ...`
      self._load_plugin_from_file_impl_py_gt_2(file_path, globals_space)

  def add_plugin(self, plugin):
    assert isinstance(plugin, AsanSymbolizerPlugIn)
    self._plugins.append(plugin)
    self._plugin_names.add(plugin.get_name())
    plugin._receive_proxy(self)

  def remove_plugin(self, plugin):
    assert isinstance(plugin, AsanSymbolizerPlugIn)
    self._plugins.remove(plugin)
    self._plugin_names.remove(plugin.get_name())
    logging.debug('Removing plugin %s', plugin.get_name())
    plugin.destroy()

  def has_plugin(self, name):
    """
      Returns true iff the plugin name is currently
      being managed by AsanSymbolizerPlugInProxy.
    """
    return name in self._plugin_names

  def register_cmdline_args(self, parser):
    plugins = list(self._plugins)
    for plugin in plugins:
      plugin.register_cmdline_args(parser)

  def process_cmdline_args(self, pargs):
    # Use copy so we can remove items as we iterate.
    plugins = list(self._plugins)
    for plugin in plugins:
      keep = plugin.process_cmdline_args(pargs)
      assert isinstance(keep, bool)
      if not keep:
        self.remove_plugin(plugin)

  def __enter__(self):
    return self

  def __exit__(self, exc_type, exc_val, exc_tb):
    for plugin in self._plugins:
      plugin.destroy()
    # Don't suppress raised exceptions
    return False

  def _filter_single_value(self, function_name, input_value):
    """
      Helper for filter style plugin functions.
    """
    new_value = input_value
    for plugin in self._plugins:
      result = getattr(plugin, function_name)(new_value)
      if result is None:
        return None
      new_value = result
    return new_value

  def filter_binary_path(self, binary_path):
    """
      Consult available plugins to filter the path to a binary
      to make it suitable for symbolication.

      Returns `None` if symbolication should not be attempted for this
      binary.
    """
    return self._filter_single_value('filter_binary_path', binary_path)

  def filter_module_desc(self, module_desc):
    """
      Consult available plugins to determine the module
      description suitable for symbolication.

      Returns `None` if symbolication should not be attempted for this module.
    """
    assert isinstance(module_desc, ModuleDesc)
    return self._filter_single_value('filter_module_desc', module_desc)

class AsanSymbolizerPlugIn(object):
  """
    This is the interface the `asan_symbolize.py` code uses to talk
    to plugins.
  """
  @classmethod
  def get_name(cls):
    """
      Returns the name of the plugin.
    """
    return cls.__name__

  def _receive_proxy(self, proxy):
    assert isinstance(proxy, AsanSymbolizerPlugInProxy)
    self.proxy = proxy

  def register_cmdline_args(self, parser):
    """
      Hook for registering command line arguments to be
      consumed in `process_cmdline_args()`.

      `parser` - Instance of `argparse.ArgumentParser`.
    """
    pass

  def process_cmdline_args(self, pargs):
    """
      Hook for handling parsed arguments. Implementations
      should not modify `pargs`.

      `pargs` - Instance of `argparse.Namespace` containing
      parsed command line arguments.

      Return `True` if plug-in should be used, otherwise
      return `False`.
    """
    return True

  def destroy(self):
    """
      Hook called when a plugin is about to be destroyed.
      Implementations should free any allocated resources here.
    """
    pass

  # Symbolization hooks
  def filter_binary_path(self, binary_path):
    """
      Given a binary path return a binary path suitable for symbolication.

      Implementations should return `None` if symbolication of this binary
      should be skipped.
    """
    return binary_path

  def filter_module_desc(self, module_desc):
    """
      Given a ModuleDesc object (`module_desc`) return
      a ModuleDesc suitable for symbolication.

      Implementations should return `None` if symbolication of this binary
      should be skipped.
    """
    return module_desc

class ModuleDesc(object):
  def __init__(self, name, arch, start_addr, end_addr, module_path, uuid):
    self.name = name
    self.arch = arch
    self.start_addr = start_addr
    self.end_addr = end_addr
    # Module path from an ASan report.
    self.module_path = module_path
    # Module for performing symbolization, by default same as above.
    self.module_path_for_symbolization = module_path
    self.uuid = uuid
    assert self.is_valid()

  def __str__(self):
    assert self.is_valid()
    return "{name} {arch} {start_addr:#016x}-{end_addr:#016x} {module_path} {uuid}".format(
      name=self.name,
      arch=self.arch,
      start_addr=self.start_addr,
      end_addr=self.end_addr,
      module_path=self.module_path if self.module_path == self.module_path_for_symbolization else '{} ({})'.format(self.module_path_for_symbolization, self.module_path),
      uuid=self.uuid
    )

  def is_valid(self):
    if not isinstance(self.name, str):
      return False
    if not isinstance(self.arch, str):
      return False
    if not isinstance(self.start_addr, int):
      return False
    if self.start_addr < 0:
      return False
    if not isinstance(self.end_addr, int):
      return False
    if self.end_addr <= self.start_addr:
      return False
    if not isinstance(self.module_path, str):
      return False
    if not os.path.isabs(self.module_path):
      return False
    if not isinstance(self.module_path_for_symbolization, str):
      return False
    if not os.path.isabs(self.module_path_for_symbolization):
      return False
    if not isinstance(self.uuid, str):
      return False
    return True

class GetUUIDFromBinaryException(Exception):
  def __init__(self, msg):
    super(GetUUIDFromBinaryException, self).__init__(msg)

_get_uuid_from_binary_cache = dict()

def get_uuid_from_binary(path_to_binary, arch=None):
  cache_key = (path_to_binary, arch)
  cached_value = _get_uuid_from_binary_cache.get(cache_key)
  if cached_value:
    return cached_value
  if not os.path.exists(path_to_binary):
    raise GetUUIDFromBinaryException('Binary "{}" does not exist'.format(path_to_binary))
  cmd = [ '/usr/bin/otool', '-l']
  if arch:
    cmd.extend(['-arch', arch])
  cmd.append(path_to_binary)
  output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
  # Look for this output:
  # cmd LC_UUID
  # cmdsize 24
  # uuid 4CA778FE-5BF9-3C45-AE59-7DF01B2BE83F
  if isinstance(output, str):
    output_str = output
  else:
    assert isinstance(output, bytes)
    output_str = output.decode()
  assert isinstance(output_str, str)
  lines = output_str.split('\n')
  uuid = None
  for index, line in enumerate(lines):
    stripped_line = line.strip()
    if not stripped_line.startswith('cmd LC_UUID'):
      continue
    uuid_line = lines[index+2].strip()
    if not uuid_line.startswith('uuid'):
      raise GetUUIDFromBinaryException('Malformed output: "{}"'.format(uuid_line))
    split_uuid_line = uuid_line.split()
    uuid = split_uuid_line[1]
    break
  if uuid is None:
    logging.error('Failed to retrieve UUID from binary {}'.format(path_to_binary))
    logging.error('otool output was:\n{}'.format(output_str))
    raise GetUUIDFromBinaryException('Failed to retrieve UUID from binary "{}"'.format(path_to_binary))
  else:
    # Update cache
    _get_uuid_from_binary_cache[cache_key] = uuid
  return uuid

class ModuleMap(object):
  def __init__(self):
    self._module_name_to_description_map = dict()

  def add_module(self, desc):
    assert isinstance(desc, ModuleDesc)
    assert desc.name not in self._module_name_to_description_map
    self._module_name_to_description_map[desc.name] = desc

  def find_module_by_name(self, name):
    return self._module_name_to_description_map.get(name, None)

  def __str__(self):
    s = '{} modules:\n'.format(self.num_modules)
    for module_desc in sorted(self._module_name_to_description_map.values(), key=lambda v: v.start_addr):
      s += str(module_desc) + '\n'
    return s

  @property
  def num_modules(self):
    return len(self._module_name_to_description_map)

  @property
  def modules(self):
    return set(self._module_name_to_description_map.values())

  def get_module_path_for_symbolication(self, module_name, proxy, validate_uuid):
    module_desc = self.find_module_by_name(module_name)
    if module_desc is None:
      return None
    # Allow a plug-in to change the module description to make it
    # suitable for symbolication or avoid symbolication altogether.
    module_desc = proxy.filter_module_desc(module_desc)
    if module_desc is None:
      return None
    if validate_uuid:
      logging.debug('Validating UUID of {}'.format(module_desc.module_path_for_symbolization))
      try:
        uuid = get_uuid_from_binary(module_desc.module_path_for_symbolization, arch = module_desc.arch)
        if uuid != module_desc.uuid:
          logging.warning("Detected UUID mismatch {} != {}".format(uuid, module_desc.uuid))
          # UUIDs don't match. Tell client to not symbolize this.
          return None
      except GetUUIDFromBinaryException as e:
        logging.error('Failed to get binary from UUID: %s', str(e))
        return None
    else:
      logging.warning('Skipping validation of UUID of {}'.format(module_desc.module_path_for_symbolization))
    return module_desc.module_path_for_symbolization

  @staticmethod
  def parse_from_file(module_map_path):
    if not os.path.exists(module_map_path):
      raise Exception('module map "{}" does not exist'.format(module_map_path))
    with open(module_map_path, 'r') as f:
      mm = None
      # E.g.
      # 0x2db4000-0x102ddc000 /path/to (arm64) <0D6BBDE0-FF90-3680-899D-8E6F9528E04C>
      hex_regex = lambda name: r'0x(?P<' + name + r'>[0-9a-f]+)'
      module_path_regex = r'(?P<path>.+)'
      arch_regex = r'\((?P<arch>.+)\)'
      uuid_regex = r'<(?P<uuid>[0-9A-Z-]+)>'
      line_regex = r'^{}-{}\s+{}\s+{}\s+{}'.format(
        hex_regex('start_addr'),
        hex_regex('end_addr'),
        module_path_regex,
        arch_regex,
        uuid_regex
      )
      matcher = re.compile(line_regex)
      line_num = 0
      line = 'dummy'
      while line != '':
        line = f.readline()
        line_num += 1
        if mm is None:
          if line.startswith('Process module map:'):
            mm = ModuleMap()
          continue
        if line.startswith('End of module map'):
          break
        m_obj = matcher.match(line)
        if not m_obj:
          raise Exception('Failed to parse line {} "{}"'.format(line_num, line))
        arch = m_obj.group('arch')
        start_addr = int(m_obj.group('start_addr'), base=16)
        end_addr = int(m_obj.group('end_addr'), base=16)
        module_path = m_obj.group('path')
        uuid = m_obj.group('uuid')
        module_desc = ModuleDesc(
          name=os.path.basename(module_path),
          arch=arch,
          start_addr=start_addr,
          end_addr=end_addr,
          module_path=module_path,
          uuid=uuid
        )
        mm.add_module(module_desc)
      if mm is not None:
        logging.debug('Loaded Module map from "{}":\n{}'.format(
          f.name,
          str(mm))
        )
      return mm

class SysRootFilterPlugIn(AsanSymbolizerPlugIn):
  """
    Simple plug-in to add sys root prefix to all binary paths
    used for symbolication.
  """
  def __init__(self):
    self.sysroot_path = ""

  def register_cmdline_args(self, parser):
    parser.add_argument('-s', dest='sys_root', metavar='SYSROOT',
                      help='set path to sysroot for sanitized binaries')

  def process_cmdline_args(self, pargs):
    if pargs.sys_root is None:
      # Not being used so remove ourselves.
      return False
    self.sysroot_path = pargs.sys_root
    return True

  def filter_binary_path(self, path):
    return self.sysroot_path + path

class ModuleMapPlugIn(AsanSymbolizerPlugIn):
  def __init__(self):
    self._module_map = None
    self._uuid_validation = True
  def register_cmdline_args(self, parser):
    parser.add_argument('--module-map',
                        help='Path to text file containing module map'
                        'output. See print_module_map ASan option.')
    parser.add_argument('--skip-uuid-validation',
                        default=False,
                        action='store_true',
                        help='Skips validating UUID of modules using otool.')

  def process_cmdline_args(self, pargs):
    if not pargs.module_map:
      return False
    self._module_map = ModuleMap.parse_from_file(args.module_map)
    if self._module_map is None:
      msg = 'Failed to find module map'
      logging.error(msg)
      raise Exception(msg)
    self._uuid_validation = not pargs.skip_uuid_validation
    return True

  def filter_binary_path(self, binary_path):
    if os.path.isabs(binary_path):
      # This is a binary path so transform into
      # a module name
      module_name = os.path.basename(binary_path)
    else:
      module_name = binary_path
    return self._module_map.get_module_path_for_symbolication(
      module_name,
      self.proxy,
      self._uuid_validation
    )

def add_logging_args(parser):
  parser.add_argument('--log-dest',
    default=None,
    help='Destination path for script logging (default stderr).',
  )
  parser.add_argument('--log-level',
    choices=['debug', 'info', 'warning', 'error', 'critical'],
    default='info',
    help='Log level for script (default: %(default)s).'
  )

def setup_logging():
  # Set up a parser just for parsing the logging arguments.
  # This is necessary because logging should be configured before we
  # perform the main argument parsing.
  parser = argparse.ArgumentParser(add_help=False)
  add_logging_args(parser)
  pargs, unparsed_args = parser.parse_known_args()

  log_level = getattr(logging, pargs.log_level.upper())
  if log_level == logging.DEBUG:
    log_format = '%(levelname)s: [%(funcName)s() %(filename)s:%(lineno)d] %(message)s'
  else:
    log_format = '%(levelname)s: %(message)s'
  basic_config = {
    'level': log_level,
    'format': log_format
  }
  log_dest = pargs.log_dest
  if log_dest:
    basic_config['filename'] = log_dest
  logging.basicConfig(**basic_config)
  logging.debug('Logging level set to "{}" and directing output to "{}"'.format(
    pargs.log_level,
    'stderr' if log_dest is None else log_dest)
  )
  return unparsed_args

def add_load_plugin_args(parser):
  parser.add_argument('-p', '--plugins',
    help='Load plug-in', nargs='+', default=[])

def setup_plugins(plugin_proxy, args):
  parser = argparse.ArgumentParser(add_help=False)
  add_load_plugin_args(parser)
  pargs , unparsed_args = parser.parse_known_args()
  for plugin_path in pargs.plugins:
    plugin_proxy.load_plugin_from_file(plugin_path)
  # Add built-in plugins.
  plugin_proxy.add_plugin(ModuleMapPlugIn())
  plugin_proxy.add_plugin(SysRootFilterPlugIn())
  return unparsed_args

if __name__ == '__main__':
  remaining_args = setup_logging()
  with AsanSymbolizerPlugInProxy() as plugin_proxy:
    remaining_args = setup_plugins(plugin_proxy, remaining_args)
    parser = argparse.ArgumentParser(
        formatter_class=argparse.RawDescriptionHelpFormatter,
        description='ASan symbolization script',
        epilog=__doc__)
    parser.add_argument('path_to_cut', nargs='*',
                        help='pattern to be cut from the result file path ')
    parser.add_argument('-d','--demangle', action='store_true',
                        help='demangle function names')
    parser.add_argument('-c', metavar='CROSS_COMPILE',
                        help='set prefix for binutils')
    parser.add_argument('-l','--logfile', default=sys.stdin,
                        type=argparse.FileType('r'),
                        help='set log file name to parse, default is stdin')
    parser.add_argument('--force-system-symbolizer', action='store_true',
                        help='don\'t use llvm-symbolizer')
    # Add logging arguments so that `--help` shows them.
    add_logging_args(parser)
    # Add load plugin arguments so that `--help` shows them.
    add_load_plugin_args(parser)
    plugin_proxy.register_cmdline_args(parser)
    args = parser.parse_args(remaining_args)
    plugin_proxy.process_cmdline_args(args)
    if args.path_to_cut:
      fix_filename_patterns = args.path_to_cut
    if args.demangle:
      demangle = True
    if args.c:
      binutils_prefix = args.c
    if args.logfile:
      logfile = args.logfile
    else:
      logfile = sys.stdin
    if args.force_system_symbolizer:
      force_system_symbolizer = True
    if force_system_symbolizer:
      assert(allow_system_symbolizer)
    loop = SymbolizationLoop(plugin_proxy)
    loop.process_logfile()
