# Copyright 2015 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.

"""
Manages a debugging session with GDB.

This module is meant to be imported from inside GDB. Once loaded, the
|DebugSession| attaches GDB to a running Mojo Shell process on an Android
device using a remote gdbserver.

At startup and each time the execution stops, |DebugSession| associates
debugging symbols for every frame. For more information, see |DebugSession|
documentation.
"""

import gdb
import glob
import itertools
import logging
import os
import os.path
import shutil
import subprocess
import sys
import tempfile
import traceback
import urllib2

sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import android_gdb.config as config
from android_gdb.remote_file_connection import RemoteFileConnection
from android_gdb.signatures import get_signature


logging.getLogger().setLevel(logging.INFO)


def _gdb_execute(command):
  """Executes a GDB command."""
  return gdb.execute(command, to_string=True)


class Mapping(object):
  """Represents a mapped memory region."""
  def __init__(self, line):
    self.start = int(line[0], 16)
    self.end = int(line[1], 16)
    self.size = int(line[2], 16)
    self.offset = int(line[3], 16)
    self.filename = line[4]


def _get_mapped_files():
  """Retrieves all the files mapped into the debugged process memory.

  Returns:
    List of mapped memory regions grouped by files.
  """
  # info proc map returns a space-separated table with the following fields:
  # start address, end address, size, offset, file path.
  mappings = [Mapping(x) for x in
              [x.split() for x in
               _gdb_execute("info proc map").split('\n')]
              if len(x) == 5 and x[4][0] == '/']
  res = {}
  for m in mappings:
    libname = m.filename[m.filename.rfind('/') + 1:]
    res[libname] = res.get(libname, []) + [m]
  return res.values()


class DebugSession(object):
  def __init__(self, build_directory, package_name, pyelftools_dir, adb):
    self._build_directory = build_directory
    if not os.path.exists(self._build_directory):
      logging.fatal("Please pass a valid build directory")
      sys.exit(1)
    self._package_name = package_name
    self._adb = adb
    self._remote_file_cache = os.path.join(os.getenv('HOME'), '.mojosymbols')

    if pyelftools_dir != None:
      sys.path.append(pyelftools_dir)
    try:
      import elftools.elf.elffile as elffile
    except ImportError:
      logging.fatal("Unable to find elftools module; please install pyelftools "
                    "and specify its path on the command line using "
                    "--pyelftools-dir.")
      sys.exit(1)

    self._elffile_module = elffile

    self._libraries = self._find_libraries(build_directory)
    self._rfc = RemoteFileConnection('localhost', 10000)
    self._remote_file_reader_process = None
    if not os.path.exists(self._remote_file_cache):
      os.makedirs(self._remote_file_cache)
    self._done_mapping = set()
    self._downloaded_files = []

  def __del__(self):
    # Note that, per python interpreter documentation, __del__ is not
    # guaranteed to be called when the interpreter (GDB, in our case) quits.
    # Also, most (all?) globals are no longer available at this time (launching
    # a subprocess does not work).
    self.stop()

  def stop(self, _unused_return_value=None):
    if self._remote_file_reader_process != None:
      self._remote_file_reader_process.kill()

  def _find_libraries(self, lib_dir):
    """Finds all libraries in |lib_dir| and key them by their signatures.
    """
    res = {}
    for fn in glob.glob('%s/*.so' % lib_dir):
      with open(fn, 'r') as f:
        s = get_signature(f, self._elffile_module)
        if s is not None:
          res[s] = fn
    return res

  def _associate_symbols(self, mapping, local_file):
    with open(local_file, "r") as f:
      elf = self._elffile_module.ELFFile(f)
      s = elf.get_section_by_name(".text")
      text_address = mapping[0].start + s['sh_offset']
      _gdb_execute("add-symbol-file %s 0x%x" % (local_file, text_address))

  def _download_file(self, signature, remote):
    """Downloads a remote file either from the cloud or through GDB connection.

    Returns:
      The filename of the downloaded file
    """
    temp_file = tempfile.NamedTemporaryFile()
    logging.info("Trying to download symbols from the cloud.")
    symbols_url = "http://storage.googleapis.com/mojo/symbols/%s" % signature
    try:
      symbol_file = urllib2.urlopen(symbols_url)
      try:
        with open(temp_file.name, "w") as dst:
          shutil.copyfileobj(symbol_file, dst)
          logging.info("Getting symbols for %s at %s." % (remote, symbols_url))
          # This allows the deletion of temporary files on disk when the
          # debugging session terminates.
          self._downloaded_files.append(temp_file)
          return temp_file.name
      finally:
        symbol_file.close()
    except urllib2.HTTPError:
      pass
    logging.info("Downloading file %s" % remote)
    _gdb_execute("remote get %s %s" % (remote, temp_file.name))
    # This allows the deletion of temporary files on disk when the debugging
    # session terminates.
    self._downloaded_files.append(temp_file)
    return temp_file.name

  def _find_mapping_for_address(self, mappings, address):
    """Returns the list of all mappings of the file occupying the |address|
    memory address.
    """
    for file_mappings in mappings:
      for mapping in file_mappings:
        if address >= mapping.start and address <= mapping.end:
          return file_mappings
    return None

  def _try_to_map(self, mapping):
    remote_file = mapping[0].filename
    if remote_file in self._done_mapping:
      return False
    self._done_mapping.add(remote_file)
    self._rfc.open(remote_file)
    signature = get_signature(self._rfc, self._elffile_module)
    if signature is not None:
      if signature in self._libraries:
        self._associate_symbols(mapping, self._libraries[signature])
      else:
        # This library file is not known locally. Download it from the device or
        # the cloud and put it in cache so, if it got symbols, we can see them.
        local_file = os.path.join(self._remote_file_cache, signature)
        if not os.path.exists(local_file):
          tmp_output = self._download_file(signature, remote_file)
          shutil.move(tmp_output, local_file)
        self._associate_symbols(mapping, local_file)
      return True
    return False

  def _map_symbols_on_current_thread(self, mapped_files):
    """Updates the symbols for the current thread using files from mapped_files.
    """
    frame = gdb.newest_frame()
    while frame and frame.is_valid():
      if frame.name() is None:
        m = self._find_mapping_for_address(mapped_files, frame.pc())
        if m is not None and self._try_to_map(m):
          # Force gdb to recompute its frames.
          _gdb_execute("info threads")
          frame = gdb.newest_frame()
          assert frame.is_valid()
      if (frame.older() is not None and
          frame.older().is_valid() and
          frame.older().pc() != frame.pc()):
        frame = frame.older()
      else:
        frame = None

  def update_symbols(self, current_thread_only):
    """Updates the mapping between symbols as seen from GDB and local library
    files.

    If current_thread_only is True, only update symbols for the current thread.
    """
    logging.info("Updating symbols")
    mapped_files = _get_mapped_files()
    # Map all symbols from native libraries packages with the APK.
    for file_mappings in mapped_files:
      filename = file_mappings[0].filename
      if ((filename.startswith('/data/data/') or
           filename.startswith('/data/app')) and
          not filename.endswith('.apk') and
          not filename.endswith('.dex')):
        logging.info('Pre-mapping: %s' % file_mappings[0].filename)
        self._try_to_map(file_mappings)

    if current_thread_only:
      self._map_symbols_on_current_thread(mapped_files)
    else:
      logging.info('Updating all threads\' symbols')
      current_thread = gdb.selected_thread()
      nb_threads = len(_gdb_execute("info threads").split("\n")) - 2
      for i in xrange(nb_threads):
        try:
          _gdb_execute("thread %d" % (i + 1))
          self._map_symbols_on_current_thread(mapped_files)
        except gdb.error:
          traceback.print_exc()
      current_thread.switch()

  def _get_device_application_pid(self, application):
    """Gets the PID of an application running on a device."""
    output = subprocess.check_output([self._adb, 'shell', 'ps'])
    for line in output.split('\n'):
      elements = line.split()
      if len(elements) > 0 and elements[-1] == application:
        return elements[1]
    return None

  def start(self):
    """Starts a debugging session."""
    gdbserver_pid = self._get_device_application_pid('gdbserver')
    if gdbserver_pid is not None:
      subprocess.check_call([self._adb, 'shell', 'kill', gdbserver_pid])
    shell_pid = self._get_device_application_pid(self._package_name)
    if shell_pid is None:
      raise Exception('Unable to find a running mojo shell.')
    subprocess.check_call([self._adb, 'forward', 'tcp:9999', 'tcp:9999'])
    subprocess.Popen(
        [self._adb, 'shell', 'gdbserver', '--attach', ':9999', shell_pid],
        # os.setpgrp ensures signals passed to this file (such as SIGINT) are
        # not propagated to child processes.
        preexec_fn = os.setpgrp)

    # Kill stray remote reader processes. See __del__ comment for more info.
    remote_file_reader_pid = self._get_device_application_pid(
        config.REMOTE_FILE_READER_DEVICE_PATH)
    if remote_file_reader_pid is not None:
      subprocess.check_call([self._adb, 'shell', 'kill',
                             remote_file_reader_pid])
    self._remote_file_reader_process = subprocess.Popen(
        [self._adb, 'shell', config.REMOTE_FILE_READER_DEVICE_PATH],
        stdout=subprocess.PIPE, preexec_fn = os.setpgrp)
    port = int(self._remote_file_reader_process.stdout.readline())
    subprocess.check_call([self._adb, 'forward', 'tcp:10000', 'tcp:%d' % port])
    self._rfc.connect()

    _gdb_execute('target remote localhost:9999')

    self.update_symbols(current_thread_only=False)
    def on_stop(_):
      self.update_symbols(current_thread_only=True)
    gdb.events.stop.connect(on_stop)
    gdb.events.exited.connect(self.stop)

    # Register the update-symbols command.
    UpdateSymbols(self)

class UpdateSymbols(gdb.Command):
  """Command to update symbols loaded into GDB.

  GDB usage: update-symbols [all|current]
  """
  _UPDATE_COMMAND = "update-symbols"

  def __init__(self, session):
    super(UpdateSymbols, self).__init__(self._UPDATE_COMMAND, gdb.COMMAND_STACK)
    self._session = session

  def invoke(self, arg, _unused_from_tty):
    if arg == 'current':
      self._session.update_symbols(current_thread_only=True)
    else:
      self._session.update_symbols(current_thread_only=False)

  def complete(self, text, _unused_word):
    if text == self._UPDATE_COMMAND:
      return ('all', 'current')
    elif text in self._UPDATE_COMMAND + ' all':
      return ['all']
    elif text in self._UPDATE_COMMAND + ' current':
      return ['current']
    else:
      return []
