# Copyright 2022 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import os
import re
import subprocess

_CHROME_SRC = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
_LLVM_OBJDUMP_PATH = os.path.join(_CHROME_SRC, 'third_party', 'llvm-build',
                                  'Release+Asserts', 'bin', 'llvm-objdump')

# Function lines look like:
#   000177b0 <android::IBinder::~IBinder()+0x2c>:
# We pull out the address and function first. Then we check for an optional
# offset. This is tricky due to functions that look like "operator+(..)+0x2c"
_FUNC = re.compile(r"(^[a-f0-9]*) <(.*)>:$")
_OFFSET = re.compile(r"(.*)\+0x([a-f0-9]*)")

# A disassembly line looks like:
#   177b2:  b510        push  {r4, lr}
_ASM = re.compile(r"(^[ a-f0-9]*):[ a-f0-0]*.*$")


def _StripPC(addr, cpu_arch):
  """Strips the Thumb bit from a program counter address when appropriate.

  Args:
    addr: the program counter address
    cpu_arch: Target CPU architecture.

  Returns:
    The stripped program counter address.
  """
  if cpu_arch == "arm":
    return addr & ~1
  return addr


class ObjdumpInformation(object):
  def __init__(self, address, library, symbol, offset):
    self.address = address
    self.library = library
    self.symbol = symbol
    self.offset = offset


class LLVMObjdumper(object):
  def __init__(self):
    """Creates an instance of LLVMObjdumper that interacts with llvm-objdump.
    """
    self._llvm_objdump_parameters = [
        '--disassemble',
        '--demangle',
        '--section=.text',
    ]

  def __enter__(self):
    return self

  def __exit__(self, exc_type, exc_val, exc_tb):
    pass

  @staticmethod
  def GetSymbolDataFromObjdumpOutput(objdump_out, address, cpu_arch):
    stripped_target_address = _StripPC(address, cpu_arch)
    for line in objdump_out.split(os.linesep):
      components = _FUNC.match(line)
      if components:
        # This is a new function, so record the current function and its
        # address.
        current_symbol_addr = int(components.group(1), 16)
        current_symbol = components.group(2)

        # Does it have an optional offset like: "foo(..)+0x2c"?
        components = _OFFSET.match(current_symbol)
        if components:
          current_symbol = components.group(1)
          offset = components.group(2)
          if offset:
            current_symbol_addr -= int(offset, 16)

      # Is it a disassembly line like: "177b2:  b510        push  {r4, lr}"?
      components = _ASM.match(line)
      if components:
        addr = components.group(1)
        i_addr = int(addr, 16)
        if i_addr == stripped_target_address:
          return (current_symbol, stripped_target_address - current_symbol_addr)

    return (None, None)

  def GetSymbolInformation(self, lib, address, cpu_arch):
    """Returns the corresponding function names and line numbers.

    Args:
      lib: library to search for info.
      address: address to look for info.
      cpu_arch: architecture where the dump was taken

    Returns:
      An ObjdumpInformation object
    """
    if not os.path.isfile(_LLVM_OBJDUMP_PATH):
      logging.error('Cannot find llvm-objdump. path=%s', _LLVM_OBJDUMP_PATH)
      return None

    stripped_address = _StripPC(address, cpu_arch)

    full_arguments = [_LLVM_OBJDUMP_PATH] + self._llvm_objdump_parameters
    full_arguments.append('--start-address=' + str(stripped_address))
    full_arguments.append('--stop-address=' + str(stripped_address + 8))
    full_arguments.append(lib)

    objdump_process = subprocess.Popen(full_arguments,
                                       stdout=subprocess.PIPE,
                                       stdin=subprocess.PIPE,
                                       universal_newlines=True)

    stdout, stderr = objdump_process.communicate()
    objdump_process_return_code = objdump_process.poll()

    if objdump_process_return_code != 0:
      logging.error(
          'Invocation of llvm-objdump failed!' +
          ' tool-command-line=\'{}\', return-code={}, std-error=\'{}\''.format(
              ' '.join(full_arguments), objdump_process_return_code, stderr))
      return None

    symbol, offset = LLVMObjdumper.GetSymbolDataFromObjdumpOutput(
        stdout, address, cpu_arch)

    return ObjdumpInformation(address=address,
                              library=lib,
                              symbol=symbol,
                              offset=offset)
