# -*- coding: utf-8 -*-
# Copyright 2014 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Wrapper for running gdb.

This handles the fun details like running against the right sysroot, via
qemu, bind mounts, etc...
"""

from __future__ import print_function

import argparse
import contextlib
import errno
import os
import sys
import tempfile

from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import namespaces
from chromite.lib import osutils
from chromite.lib import path_util
from chromite.lib import qemu
from chromite.lib import remote_access
from chromite.lib import retry_util
from chromite.lib import toolchain

class GdbException(Exception):
  """Base exception for this module."""


class GdbBadRemoteDeviceError(GdbException):
  """Raised when remote device does not exist or is not responding."""


class GdbMissingSysrootError(GdbException):
  """Raised when path to sysroot cannot be found in chroot."""


class GdbMissingInferiorError(GdbException):
  """Raised when the binary to be debugged cannot be found."""


class GdbMissingDebuggerError(GdbException):
  """Raised when cannot find correct version of debugger."""


class GdbCannotFindRemoteProcessError(GdbException):
  """Raised when cannot find requested executing process on remote device."""


class GdbUnableToStartGdbserverError(GdbException):
  """Raised when error occurs trying to start gdbserver on remote device."""


class GdbTooManyPidsError(GdbException):
  """Raised when more than one matching pid is found running on device."""


class GdbEarlyExitError(GdbException):
  """Raised when user requests to exit early."""


class GdbCannotDetectBoardError(GdbException):
  """Raised when board isn't specified and can't be automatically determined."""

class GdbSimpleChromeBinaryError(GdbException):
  """Raised when none or multiple chrome binaries are under out_${board} dir."""

class BoardSpecificGdb(object):
  """Framework for running gdb."""

  _BIND_MOUNT_PATHS = ('dev', 'dev/pts', 'proc', 'mnt/host/source', 'sys')
  _GDB = '/usr/bin/gdb'
  _EXTRA_SSH_SETTINGS = {
      'CheckHostIP': 'no',
      'BatchMode': 'yes',
      'LogLevel': 'QUIET'
  }
  _MISSING_DEBUG_INFO_MSG = """
%(inf_cmd)s is stripped and %(debug_file)s does not exist on your local machine.
  The debug symbols for that package may not be installed.  To install the debug
 symbols for %(package)s only, run:

   cros_install_debug_syms --board=%(board)s %(package)s

To install the debug symbols for all available packages, run:

   cros_install_debug_syms --board=%(board)s --all"""

  def __init__(self, board, gdb_args, inf_cmd, inf_args, remote, pid,
               remote_process_name, cgdb_flag, ping, binary):
    self.board = board
    self.sysroot = None
    self.prompt = '(gdb) '
    self.inf_cmd = inf_cmd
    self.run_as_root = False
    self.gdb_args = gdb_args
    self.inf_args = inf_args
    self.remote = remote.hostname if remote else None
    self.pid = pid
    self.remote_process_name = remote_process_name
    # Port used for sending ssh commands to DUT.
    self.remote_port = remote.port if remote else None
    # Port for communicating between gdb & gdbserver.
    self.gdbserver_port = remote_access.GetUnusedPort()
    self.ssh_settings = remote_access.CompileSSHConnectSettings(
        **self._EXTRA_SSH_SETTINGS)
    self.cgdb = cgdb_flag
    self.framework = 'auto'
    self.qemu = None
    self.device = None
    self.cross_gdb = None
    self.ping = ping
    self.binary = binary
    self.in_chroot = None
    self.chrome_path = None
    self.sdk_path = None

  def IsInChroot(self):
    """Decide whether we are in chroot or chrome-sdk."""
    return os.path.exists("/mnt/host/source/chromite/")

  def SimpleChromeGdb(self):
    """Get the name of the cross gdb based on board name."""
    bin_path = self.board + '+' + os.environ['SDK_VERSION'] + '+' + \
               'target_toolchain'
    bin_path = os.path.join(self.sdk_path, bin_path, 'bin')
    for f in os.listdir(bin_path):
      if f.endswith('gdb'):
        return os.path.join(bin_path, f)
    raise GdbMissingDebuggerError('Cannot find cros gdb for %s.'
                                  % self.board)

  def SimpleChromeSysroot(self):
    """Get the sysroot in simple chrome."""
    sysroot = self.board + '+' + os.environ['SDK_VERSION'] + \
              '+' + 'sysroot_chromeos-base_chromeos-chrome.tar.xz'
    sysroot = os.path.join(self.sdk_path, sysroot)
    if not os.path.isdir(sysroot):
      raise GdbMissingSysrootError('Cannot find sysroot for %s at.'
                                   ' %s' % self.board, sysroot)
    return sysroot

  def GetSimpleChromeBinary(self):
    """Get path to the  binary in simple chrome."""
    if self.binary:
      return self.binary

    output_dir = os.path.join(self.chrome_path, 'src',
                              'out_{}'.format(self.board))
    target_binary = None
    binary_name = os.path.basename(self.inf_cmd)
    for root, _, files in os.walk(output_dir):
      for f in files:
        if f == binary_name:
          if target_binary is None:
            target_binary = os.path.join(root, f)
          else:
            raise GdbSimpleChromeBinaryError(
                'There are multiple %s under %s. Please specify the path to '
                'the binary via --binary'% binary_name, output_dir)
    if target_binary is None:
      raise GdbSimpleChromeBinaryError('There is no %s under %s.'
                                       % binary_name, output_dir)
    return target_binary

  def VerifyAndFinishInitialization(self, device):
    """Verify files/processes exist and flags are correct."""
    if not self.board:
      if self.remote:
        self.board = cros_build_lib.GetBoard(device_board=device.board,
                                             override_board=self.board)
      else:
        raise GdbCannotDetectBoardError('Cannot determine which board to use. '
                                        'Please specify the with --board flag.')
    self.in_chroot = self.IsInChroot()
    self.prompt = '(%s-gdb) ' % self.board
    if self.in_chroot:
      self.sysroot = cros_build_lib.GetSysroot(board=self.board)
      self.inf_cmd = self.RemoveSysrootPrefix(self.inf_cmd)
      self.cross_gdb = self.GetCrossGdb()
    else:
      self.chrome_path = os.path.realpath(os.path.join(os.path.dirname(
          os.path.realpath(__file__)), "../../../.."))
      self.sdk_path = os.path.join(
          path_util.FindCacheDir(), 'chrome-sdk/tarballs/')
      self.sysroot = self.SimpleChromeSysroot()
      self.cross_gdb = self.SimpleChromeGdb()

    if self.remote:

      # If given remote process name, find pid & inf_cmd on remote device.
      if self.remote_process_name or self.pid:
        self._FindRemoteProcess(device)

      # Verify that sysroot is valid (exists).
      if not os.path.isdir(self.sysroot):
        raise GdbMissingSysrootError('Sysroot does not exist: %s' %
                                     self.sysroot)

    self.device = device
    if not self.in_chroot:
      return

    sysroot_inf_cmd = ''
    if self.inf_cmd:
      sysroot_inf_cmd = os.path.join(self.sysroot,
                                     self.inf_cmd.lstrip('/'))

    # Verify that inf_cmd, if given, exists.
    if sysroot_inf_cmd and not os.path.exists(sysroot_inf_cmd):
      raise GdbMissingInferiorError('Cannot find file %s (in sysroot).' %
                                    sysroot_inf_cmd)

    # Check to see if inf_cmd is stripped, and if so, check to see if debug file
    # exists.  If not, tell user and give them the option of quitting & getting
    # the debug info.
    if sysroot_inf_cmd:
      stripped_info = cros_build_lib.RunCommand(['file', sysroot_inf_cmd],
                                                capture_output=True).output
      if ' not stripped' not in stripped_info:
        debug_file = os.path.join(self.sysroot, 'usr/lib/debug',
                                  self.inf_cmd.lstrip('/'))
        debug_file += '.debug'
        if not os.path.exists(debug_file):
          equery = 'equery-%s' % self.board
          package = cros_build_lib.RunCommand([equery, '-q', 'b',
                                               self.inf_cmd],
                                              capture_output=True).output
          # pylint: disable=logging-not-lazy
          logging.info(self._MISSING_DEBUG_INFO_MSG % {
              'board': self.board,
              'inf_cmd': self.inf_cmd,
              'package': package,
              'debug_file': debug_file})
          answer = cros_build_lib.BooleanPrompt()
          if not answer:
            raise GdbEarlyExitError('Exiting early, at user request.')

    # Set up qemu, if appropriate.
    qemu_arch = qemu.Qemu.DetectArch(self._GDB, self.sysroot)
    if qemu_arch is None:
      self.framework = 'ldso'
    else:
      self.framework = 'qemu'
      self.qemu = qemu.Qemu(self.sysroot, arch=qemu_arch)

    if self.remote:
      # Verify cgdb flag info.
      if self.cgdb:
        if osutils.Which('cgdb') is None:
          raise GdbMissingDebuggerError('Cannot find cgdb.  Please install '
                                        'cgdb first.')

  def RemoveSysrootPrefix(self, path):
    """Returns the given path with any sysroot prefix removed."""
    # If the sysroot is /, then the paths are already normalized.
    if self.sysroot != '/' and path.startswith(self.sysroot):
      path = path.replace(self.sysroot, '', 1)
    return path

  @staticmethod
  def GetNonRootAccount():
    """Return details about the non-root account we want to use.

    Returns:
      A tuple of (username, uid, gid, home).
    """
    return (
        os.environ.get('SUDO_USER', 'nobody'),
        int(os.environ.get('SUDO_UID', '65534')),
        int(os.environ.get('SUDO_GID', '65534')),
        # Should we find a better home?
        '/tmp/portage',
    )

  @staticmethod
  @contextlib.contextmanager
  def LockDb(db):
    """Lock an account database.

    We use the same algorithm as shadow/user.eclass.  This way we don't race
    and corrupt things in parallel.
    """
    lock = '%s.lock' % db
    _, tmplock = tempfile.mkstemp(prefix='%s.platform.' % lock)

    # First try forever to grab the lock.
    retry = lambda e: e.errno == errno.EEXIST
    # Retry quickly at first, but slow down over time.
    try:
      retry_util.GenericRetry(retry, 60, os.link, tmplock, lock, sleep=0.1)
    except Exception as e:
      raise Exception('Could not grab lock %s. %s' % (lock, e))

    # Yield while holding the lock, but try to clean it no matter what.
    try:
      os.unlink(tmplock)
      yield lock
    finally:
      os.unlink(lock)

  def SetupUser(self):
    """Propogate the user name<->id mapping from outside the chroot.

    Some unittests use getpwnam($USER), as does bash.  If the account
    is not registered in the sysroot, they get back errors.
    """
    MAGIC_GECOS = 'Added by your friendly platform test helper; do not modify'
    # This is kept in sync with what sdk_lib/make_chroot.sh generates.
    SDK_GECOS = 'ChromeOS Developer'

    user, uid, gid, home = self.GetNonRootAccount()
    if user == 'nobody':
      return

    passwd_db = os.path.join(self.sysroot, 'etc', 'passwd')
    with self.LockDb(passwd_db):
      data = osutils.ReadFile(passwd_db)
      accts = data.splitlines()
      for acct in accts:
        passwd = acct.split(':')
        if passwd[0] == user:
          # Did the sdk make this account?
          if passwd[4] == SDK_GECOS:
            # Don't modify it (see below) since we didn't create it.
            return

          # Did we make this account?
          if passwd[4] != MAGIC_GECOS:
            raise RuntimeError('your passwd db (%s) has unmanaged acct %s' %
                               (passwd_db, user))

          # Maybe we should see if it needs to be updated?  Like if they
          # changed UIDs?  But we don't really check that elsewhere ...
          return

      acct = '%(name)s:x:%(uid)s:%(gid)s:%(gecos)s:%(homedir)s:%(shell)s' % {
          'name': user,
          'uid': uid,
          'gid': gid,
          'gecos': MAGIC_GECOS,
          'homedir': home,
          'shell': '/bin/bash',
      }
      with open(passwd_db, 'a') as f:
        if data[-1] != '\n':
          f.write('\n')
        f.write('%s\n' % acct)

  def _FindRemoteProcess(self, device):
    """Find a named process (or a pid) running on a remote device."""
    if not self.remote_process_name and not self.pid:
      return

    if self.remote_process_name:
      # Look for a process with the specified name on the remote device; if
      # found, get its pid.
      pname = self.remote_process_name
      if pname == 'browser':
        all_chrome_pids = set(device.GetRunningPids(
            '/opt/google/chrome/chrome'))
        non_main_chrome_pids = set(device.GetRunningPids('type='))
        pids = list(all_chrome_pids - non_main_chrome_pids)
      elif pname == 'renderer' or pname == 'gpu-process':
        pids = device.GetRunningPids('type=%s'% pname)
      else:
        pids = device.GetRunningPids(pname)

      if pids:
        if len(pids) == 1:
          self.pid = pids[0]
        else:
          raise GdbTooManyPidsError('Multiple pids found for %s process: %s. '
                                    'You must specify the correct pid.'
                                    % (pname, repr(pids)))
      else:
        raise GdbCannotFindRemoteProcessError('Cannot find pid for "%s" on %s' %
                                              (pname, self.remote))

    # Find full path for process, from pid (and verify pid).
    command = [
        'readlink',
        '-e', '/proc/%s/exe' % self.pid,
    ]
    try:
      res = device.RunCommand(command, capture_output=True)
      if res.returncode == 0:
        self.inf_cmd = res.output.rstrip('\n')
    except cros_build_lib.RunCommandError:
      raise GdbCannotFindRemoteProcessError('Unable to find name of process '
                                            'with pid %s on %s' %
                                            (self.pid, self.remote))

  def GetCrossGdb(self):
    """Find the appropriate cross-version of gdb for the board."""
    toolchains = toolchain.GetToolchainsForBoard(self.board)
    tc = toolchain.FilterToolchains(toolchains, 'default', True).keys()
    cross_gdb = tc[0] + '-gdb'
    if not osutils.Which(cross_gdb):
      raise GdbMissingDebuggerError('Cannot find %s; do you need to run '
                                    'setup_board?' % cross_gdb)
    return cross_gdb

  def GetGdbInitCommands(self, inferior_cmd, device=None):
    """Generate list of commands with which to initialize the gdb session."""
    gdb_init_commands = []

    if self.remote:
      sysroot_var = self.sysroot
    else:
      sysroot_var = '/'

    gdb_init_commands = [
        'set sysroot %s' % sysroot_var,
        'set prompt %s' % self.prompt,
    ]
    if self.in_chroot:
      gdb_init_commands += [
          'set solib-absolute-prefix %s' % sysroot_var,
          'set solib-search-path %s' % sysroot_var,
          'set debug-file-directory %s/usr/lib/debug' % sysroot_var,
      ]

    if device:
      ssh_cmd = device.GetAgent().GetSSHCommand(self.ssh_settings)

      ssh_cmd.extend(['--', 'gdbserver'])

      if self.pid:
        ssh_cmd.extend(['--attach', 'stdio', str(self.pid)])
        target_type = 'remote'
      elif inferior_cmd:
        ssh_cmd.extend(['-', inferior_cmd])
        ssh_cmd.extend(self.inf_args)
        target_type = 'remote'
      else:
        ssh_cmd.extend(['--multi', 'stdio'])
        target_type = 'extended-remote'

      ssh_cmd = cros_build_lib.CmdToStr(ssh_cmd)

      if self.in_chroot:
        if inferior_cmd:
          gdb_init_commands.append(
              'file %s' % os.path.join(sysroot_var,
                                       inferior_cmd.lstrip(os.sep)))
      else:
        binary = self.GetSimpleChromeBinary()
        gdb_init_commands += [
            'set debug-file-directory %s' % os.path.dirname(binary),
            'file %s' % binary
        ]

      gdb_init_commands.append('target %s | %s' % (target_type, ssh_cmd))
    else:
      if inferior_cmd:
        gdb_init_commands.append('file %s ' % inferior_cmd)
        gdb_init_commands.append('set args %s' % ' '.join(self.inf_args))

    return gdb_init_commands

  def RunRemote(self):
    """Handle remote debugging, via gdbserver & cross debugger."""
    with remote_access.ChromiumOSDeviceHandler(
        self.remote,
        port=self.remote_port,
        connect_settings=self.ssh_settings,
        ping=self.ping) as device:

      self.VerifyAndFinishInitialization(device)
      gdb_cmd = self.cross_gdb

      gdb_commands = self.GetGdbInitCommands(self.inf_cmd, device)
      gdb_args = ['--quiet'] + ['--eval-command=%s' % x for x in gdb_commands]
      gdb_args += self.gdb_args

      if self.cgdb:
        gdb_args = ['-d', gdb_cmd, '--'] + gdb_args
        gdb_cmd = 'cgdb'

      cros_build_lib.RunCommand(
          [gdb_cmd] + gdb_args,
          ignore_sigint=True,
          print_cmd=True,
          cwd=self.sysroot)

  def Run(self):
    """Runs the debugger in a proper environment (e.g. qemu)."""

    self.VerifyAndFinishInitialization(None)
    self.SetupUser()
    if self.framework == 'qemu':
      self.qemu.Install(self.sysroot)
      self.qemu.RegisterBinfmt()

    for mount in self._BIND_MOUNT_PATHS:
      path = os.path.join(self.sysroot, mount)
      osutils.SafeMakedirs(path)
      osutils.Mount('/' + mount, path, 'none', osutils.MS_BIND)

    gdb_cmd = self._GDB
    inferior_cmd = self.inf_cmd

    gdb_argv = self.gdb_args[:]
    if gdb_argv:
      gdb_argv[0] = self.RemoveSysrootPrefix(gdb_argv[0])
    # Some programs expect to find data files via $CWD, so doing a chroot
    # and dropping them into / would make them fail.
    cwd = self.RemoveSysrootPrefix(os.getcwd())

    os.chroot(self.sysroot)
    os.chdir(cwd)
    # The TERM the user is leveraging might not exist in the sysroot.
    # Force a sane default that supports standard color sequences.
    os.environ['TERM'] = 'ansi'
    # Some progs want this like bash else they get super confused.
    os.environ['PWD'] = cwd
    if not self.run_as_root:
      _, uid, gid, home = self.GetNonRootAccount()
      os.setgid(gid)
      os.setuid(uid)
      os.environ['HOME'] = home

    gdb_commands = self.GetGdbInitCommands(inferior_cmd)

    gdb_args = [gdb_cmd, '--quiet'] + ['--eval-command=%s' % x
                                       for x in gdb_commands]
    gdb_args += self.gdb_args

    os.execvp(gdb_cmd, gdb_args)


def _ReExecuteIfNeeded(argv, ns_net=False, ns_pid=False):
  """Re-execute gdb as root.

  We often need to do things as root, so make sure we're that.  Like chroot
  for proper library environment or do bind mounts.

  Also unshare the mount namespace so as to ensure that doing bind mounts for
  tests don't leak out to the normal chroot.  Also unshare the UTS namespace
  so changes to `hostname` do not impact the host.
  """
  if os.geteuid() != 0:
    cmd = ['sudo', '-E', '--'] + argv
    os.execvp(cmd[0], cmd)
  else:
    namespaces.SimpleUnshare(net=ns_net, pid=ns_pid)


def FindInferior(arg_list):
  """Look for the name of the inferior (to be debugged) in arg list."""

  program_name = ''
  new_list = []
  for item in arg_list:
    if item[0] == '-':
      new_list.append(item)
    elif not program_name:
      program_name = item
    else:
      raise RuntimeError('Found multiple program names: %s  %s'
                         % (program_name, item))

  return program_name, new_list


def main(argv):

  parser = commandline.ArgumentParser(description=__doc__)

  parser.add_argument('--board', default=None,
                      help='board to debug for')
  parser.add_argument('-g', '--gdb_args', action='append', default=[],
                      help='Arguments to gdb itself.  If multiple arguments are'
                      ' passed, each argument needs a separate \'-g\' flag.')
  parser.add_argument(
      '--remote', default=None,
      type=commandline.DeviceParser(commandline.DEVICE_SCHEME_SSH),
      help='Remote device on which to run the binary. Use'
      ' "--remote=localhost:9222" to debug in a ChromeOS image in an'
      ' already running local virtual machine.')
  parser.add_argument('--pid', default='',
                      help='Process ID of the (already) running process on the'
                      ' remote device to which to attach.')
  parser.add_argument('--remote_pid', dest='pid', default='',
                      help='Deprecated alias for --pid.')
  parser.add_argument('--no-ping', dest='ping', default=True,
                      action='store_false',
                      help='Do not ping remote before attempting to connect.')
  parser.add_argument('--attach', dest='attach_name', default='',
                      help='Name of existing process to which to attach, on'
                      ' remote device (remote debugging only). "--attach'
                      ' browser" will find the main chrome browser process;'
                      ' "--attach renderer" will find a chrome renderer'
                      ' process; "--attach gpu-process" will find the chrome'
                      ' gpu process.')
  parser.add_argument('--cgdb', default=False,
                      action='store_true',
                      help='Use cgdb curses interface rather than plain gdb.'
                      'This option is only valid for remote debugging.')
  parser.add_argument('inf_args', nargs=argparse.REMAINDER,
                      help='Arguments for gdb to pass to the program being'
                      ' debugged. These are positional and must come at the end'
                      ' of the command line.  This will not work if attaching'
                      ' to an already running program.')
  parser.add_argument('--binary', default='',
                      help='full path to the binary being debuged.'
                      ' This is only useful for simple chrome.'
                      ' An example is --bianry /home/out_falco/chrome.')

  options = parser.parse_args(argv)
  options.Freeze()

  gdb_args = []
  inf_args = []
  inf_cmd = ''

  if options.inf_args:
    inf_cmd = options.inf_args[0]
    inf_args = options.inf_args[1:]

  if options.gdb_args:
    gdb_args = options.gdb_args

  if inf_cmd:
    fname = os.path.join(cros_build_lib.GetSysroot(options.board),
                         inf_cmd.lstrip('/'))
    if not os.path.exists(fname):
      cros_build_lib.Die('Cannot find program %s.' % fname)
  else:
    if inf_args:
      parser.error('Cannot specify arguments without a program.')

  if inf_args and (options.pid or options.attach_name):
    parser.error('Cannot pass arguments to an already'
                 ' running process (--remote-pid or --attach).')

  if options.remote:
    if options.attach_name and options.attach_name == 'browser':
      inf_cmd = '/opt/google/chrome/chrome'
  else:
    if options.cgdb:
      parser.error('--cgdb option can only be used with remote debugging.')
    if options.pid:
      parser.error('Must specify a remote device (--remote) if you want '
                   'to attach to a remote pid.')
    if options.attach_name:
      parser.error('Must specify remote device (--remote) when using'
                   ' --attach option.')
  if options.binary:
    if not os.path.exists(options.binary):
      parser.error('%s does not exist.' % options.binary)

  # Once we've finished sanity checking args, make sure we're root.
  if not options.remote:
    _ReExecuteIfNeeded([sys.argv[0]] + argv)

  gdb = BoardSpecificGdb(options.board, gdb_args, inf_cmd, inf_args,
                         options.remote, options.pid, options.attach_name,
                         options.cgdb, options.ping, options.binary)

  try:
    if options.remote:
      gdb.RunRemote()
    else:
      gdb.Run()

  except GdbException as e:
    if options.debug:
      raise
    else:
      raise cros_build_lib.Die(str(e))
