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

"""cros debug: Debug the applications on the target device."""

from __future__ import print_function

import os

from chromite.cli import command
from chromite.lib import commandline
from chromite.lib import cros_build_lib
from chromite.lib import cros_logging as logging
from chromite.lib import remote_access


@command.CommandDecorator('debug')
class DebugCommand(command.CliCommand):
  """Use GDB to debug a process running on the target device.

  This command starts a GDB session to debug a remote process running on the
  target device. The remote process can either be an existing process or newly
  started by calling this command.

  This command can also be used to find out information about all running
  processes of an executable on the target device.
  """

  EPILOG = """
To list all running processes of an executable:
  cros debug device --list --exe=/path/to/executable

To debug an executable:
  cros debug device --exe=/path/to/executable

To debug a process by its pid:
  cros debug device --pid=1234
"""

  # Override base class property to enable stats upload.
  upload_stats = True

  def __init__(self, options):
    """Initialize DebugCommand."""
    super(DebugCommand, self).__init__(options)
    # SSH connection settings.
    self.ssh_hostname = None
    self.ssh_port = None
    self.ssh_username = None
    self.ssh_private_key = None
    # The board name of the target device.
    self.board = None
    # Settings of the process to debug.
    self.list = False
    self.exe = None
    self.pid = None
    # The command for starting gdb.
    self.gdb_cmd = None

  @classmethod
  def AddParser(cls, parser):
    """Add parser arguments."""
    super(cls, DebugCommand).AddParser(parser)
    cls.AddDeviceArgument(parser)
    parser.add_argument(
        '--board', default=None, help='The board to use. By default it is '
        'automatically detected. You can override the detected board with '
        'this option.')
    parser.add_argument(
        '--private-key', type='path', default=None,
        help='SSH identity file (private key).')
    parser.add_argument(
        '-l', '--list', action='store_true', default=False,
        help='List running processes of the executable on the target device.')
    parser.add_argument(
        '--exe', help='Full path of the executable on the target device.')
    parser.add_argument(
        '-p', '--pid', type=int,
        help='The pid of the process on the target device.')

  def _ListProcesses(self, device, pids):
    """Provided with a list of pids, print out information of the processes."""
    if not pids:
      logging.info(
          'No running process of %s on device %s', self.exe, self.ssh_hostname)
      return

    try:
      result = device.BaseRunCommand(['ps', 'aux'])
      lines = result.output.splitlines()
      try:
        header, procs = lines[0], lines[1:]
        info = os.linesep.join([p for p in procs if int(p.split()[1]) in pids])
      except ValueError:
        cros_build_lib.Die('Parsing output failed:\n%s', result.output)

      print('\nList running processes of %s on device %s:\n%s\n%s' %
            (self.exe, self.ssh_hostname, header, info))
    except cros_build_lib.RunCommandError:
      cros_build_lib.Die(
          'Failed to find any running process on device %s', self.ssh_hostname)

  def _DebugNewProcess(self):
    """Start a new process on the target device and attach gdb to it."""
    logging.info(
        'Ready to start and debug %s on device %s', self.exe, self.ssh_hostname)
    cros_build_lib.RunCommand(self.gdb_cmd + ['--remote_file', self.exe])

  def _DebugRunningProcess(self, pid):
    """Start gdb and attach it to the remote running process with |pid|."""
    logging.info(
        'Ready to debug process %d on device %s', pid, self.ssh_hostname)
    cros_build_lib.RunCommand(self.gdb_cmd + ['--remote_pid', str(pid)])

  def _ReadOptions(self):
    """Process options and set variables."""
    if self.options.device:
      self.ssh_hostname = self.options.device.hostname
      self.ssh_username = self.options.device.username
      self.ssh_port = self.options.device.port
    self.ssh_private_key = self.options.private_key
    self.list = self.options.list
    self.exe = self.options.exe
    self.pid = self.options.pid

  def Run(self):
    """Run cros debug."""
    commandline.RunInsideChroot(self)
    self.options.Freeze()
    self._ReadOptions()
    with remote_access.ChromiumOSDeviceHandler(
        self.ssh_hostname, port=self.ssh_port, username=self.ssh_username,
        private_key=self.ssh_private_key) as device:
      self.board = cros_build_lib.GetBoard(device_board=device.board,
                                           override_board=self.options.board)
      logging.info('Board is %s', self.board)

      self.gdb_cmd = [
          'gdb_remote', '--ssh',
          '--board', self.board,
          '--remote', self.ssh_hostname,
      ]
      if self.ssh_port:
        self.gdb_cmd.extend(['--ssh_port', str(self.ssh_port)])

      if not (self.pid or self.exe):
        cros_build_lib.Die(
            'Must use --exe or --pid to specify the process to debug.')

      if self.pid:
        if self.list or self.exe:
          cros_build_lib.Die(
              '--list and --exe are disallowed when --pid is used.')
        self._DebugRunningProcess(self.pid)
        return

      if not self.exe.startswith('/'):
        cros_build_lib.Die('--exe must have a full pathname.')
      logging.debug('Executable path is %s', self.exe)
      if not device.IsFileExecutable(self.exe):
        cros_build_lib.Die(
            'File path "%s" does not exist or is not executable on device %s',
            self.exe, self.ssh_hostname)

      pids = device.GetRunningPids(self.exe)
      self._ListProcesses(device, pids)

      if self.list:
        # If '--list' flag is on, do not launch GDB.
        return

      if pids:
        choices = ['Start a new process under GDB']
        choices.extend(pids)
        idx = cros_build_lib.GetChoice(
            'Please select the process pid to debug (select [0] to start a '
            'new process):', choices)
        if idx == 0:
          self._DebugNewProcess()
        else:
          self._DebugRunningProcess(pids[idx - 1])
      else:
        self._DebugNewProcess()
