//===-- NativeProcessDarwin.cpp ---------------------------------*- C++ -*-===//
//
// 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
//
//===----------------------------------------------------------------------===//

#include "NativeProcessDarwin.h"

// C includes
#include <mach/mach_init.h>
#include <mach/mach_traps.h>
#include <sys/ptrace.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <sys/types.h>

// C++ includes
// LLDB includes
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Target/ProcessLaunchInfo.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/State.h"
#include "lldb/Utility/StreamString.h"

#include "CFBundle.h"
#include "CFString.h"
#include "DarwinProcessLauncher.h"

#include "MachException.h"

#include "llvm/Support/FileSystem.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_darwin;
using namespace lldb_private::darwin_process_launcher;

// Hidden Impl

namespace {
struct hack_task_dyld_info {
  mach_vm_address_t all_image_info_addr;
  mach_vm_size_t all_image_info_size;
};
}

// Public Static Methods

Status NativeProcessProtocol::Launch(
    ProcessLaunchInfo &launch_info,
    NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
    NativeProcessProtocolSP &native_process_sp) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  Status error;

  // Verify the working directory is valid if one was specified.
  FileSpec working_dir(launch_info.GetWorkingDirectory());
  if (working_dir) {
    FileInstance::Instance().Resolve(working_dir);
    if (!FileSystem::Instance().IsDirectory(working_dir)) {
      error.SetErrorStringWithFormat("No such file or directory: %s",
                                   working_dir.GetCString());
      return error;
    }
  }

  // Launch the inferior.
  int pty_master_fd = -1;
  LaunchFlavor launch_flavor = LaunchFlavor::Default;

  error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor);

  // Handle launch failure.
  if (!error.Success()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s() failed to launch process: "
              "%s",
              __FUNCTION__, error.AsCString());
    return error;
  }

  // Handle failure to return a pid.
  if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s() launch succeeded but no "
              "pid was returned!  Aborting.",
              __FUNCTION__);
    return error;
  }

  // Create the Darwin native process impl.
  std::shared_ptr<NativeProcessDarwin> np_darwin_sp(
      new NativeProcessDarwin(launch_info.GetProcessID(), pty_master_fd));
  if (!np_darwin_sp->RegisterNativeDelegate(native_delegate)) {
    native_process_sp.reset();
    error.SetErrorStringWithFormat("failed to register the native delegate");
    return error;
  }

  // Finalize the processing needed to debug the launched process with a
  // NativeProcessDarwin instance.
  error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop);
  if (!error.Success()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s() aborting, failed to finalize"
              " the launching of the process: %s",
              __FUNCTION__, error.AsCString());
    return error;
  }

  // Return the process and process id to the caller through the launch args.
  native_process_sp = np_darwin_sp;
  return error;
}

Status NativeProcessProtocol::Attach(
    lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
    MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  LLDB_LOGF(log, "NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__,
            pid);

  // Retrieve the architecture for the running process.
  ArchSpec process_arch;
  Status error = ResolveProcessArchitecture(pid, process_arch);
  if (!error.Success())
    return error;

  // TODO get attach to return this value.
  const int pty_master_fd = -1;
  std::shared_ptr<NativeProcessDarwin> native_process_darwin_sp(
      new NativeProcessDarwin(pid, pty_master_fd));

  if (!native_process_darwin_sp->RegisterNativeDelegate(native_delegate)) {
    error.SetErrorStringWithFormat("failed to register the native "
                                   "delegate");
    return error;
  }

  native_process_darwin_sp->AttachToInferior(mainloop, pid, error);
  if (!error.Success())
    return error;

  native_process_sp = native_process_darwin_sp;
  return error;
}

// ctor/dtor

NativeProcessDarwin::NativeProcessDarwin(lldb::pid_t pid, int pty_master_fd)
    : NativeProcessProtocol(pid), m_task(TASK_NULL), m_did_exec(false),
      m_cpu_type(0), m_exception_port(MACH_PORT_NULL), m_exc_port_info(),
      m_exception_thread(nullptr), m_exception_messages_mutex(),
      m_sent_interrupt_signo(0), m_auto_resume_signo(0), m_thread_list(),
      m_thread_actions(), m_waitpid_pipe(), m_waitpid_thread(nullptr),
      m_waitpid_reader_handle() {
  // TODO add this to the NativeProcessProtocol constructor.
  m_terminal_fd = pty_master_fd;
}

NativeProcessDarwin::~NativeProcessDarwin() {}

// Instance methods

Status NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
                                           MainLoop &main_loop) {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  error = StartExceptionThread();
  if (!error.Success()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): failure starting the "
              "mach exception port monitor thread: %s",
              __FUNCTION__, error.AsCString());

    // Terminate the inferior process.  There's nothing meaningful we can do if
    // we can't receive signals and exceptions.  Since we launched the process,
    // it's fair game for us to kill it.
    ::ptrace(PT_KILL, m_pid, 0, 0);
    SetState(eStateExited);

    return error;
  }

  StartSTDIOThread();

  if (launch_flavor == LaunchFlavor::PosixSpawn) {
    SetState(eStateAttaching);
    errno = 0;
    int err = ::ptrace(PT_ATTACHEXC, m_pid, 0, 0);
    if (err == 0) {
      // m_flags |= eMachProcessFlagsAttached;
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): successfully spawned "
                "process with pid %" PRIu64,
                __FUNCTION__, m_pid);
    } else {
      error.SetErrorToErrno();
      SetState(eStateExited);
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): error: failed to "
                "attach to spawned pid %" PRIu64 " (error=%d (%s))",
                __FUNCTION__, m_pid, (int)error.GetError(), error.AsCString());
      return error;
    }
  }

  LLDB_LOGF(log, "NativeProcessDarwin::%s(): new pid is %" PRIu64 "...",
            __FUNCTION__, m_pid);

  // Spawn a thread to reap our child inferior process...
  error = StartWaitpidThread(main_loop);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): failed to start waitpid() "
              "thread: %s",
              __FUNCTION__, error.AsCString());
    kill(SIGKILL, static_cast<::pid_t>(m_pid));
    return error;
  }

  if (TaskPortForProcessID(error) == TASK_NULL) {
    // We failed to get the task for our process ID which is bad. Kill our
    // process; otherwise, it will be stopped at the entry point and get
    // reparented to someone else and never go away.
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): could not get task port "
              "for process, sending SIGKILL and exiting: %s",
              __FUNCTION__, error.AsCString());
    kill(SIGKILL, static_cast<::pid_t>(m_pid));
    return error;
  }

  // Indicate that we're stopped, as we always launch suspended.
  SetState(eStateStopped);

  // Success.
  return error;
}

Status NativeProcessDarwin::SaveExceptionPortInfo() {
  return m_exc_port_info.Save(m_task);
}

bool NativeProcessDarwin::ProcessUsingSpringBoard() const {
  // TODO implement flags
  // return (m_flags & eMachProcessFlagsUsingSBS) != 0;
  return false;
}

bool NativeProcessDarwin::ProcessUsingBackBoard() const {
  // TODO implement flags
  // return (m_flags & eMachProcessFlagsUsingBKS) != 0;
  return false;
}

// Called by the exception thread when an exception has been received from our
// process. The exception message is completely filled and the exception data
// has already been copied.
void NativeProcessDarwin::ExceptionMessageReceived(
    const MachException::Message &message) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));

  std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
  if (m_exception_messages.empty()) {
    // Suspend the task the moment we receive our first exception message.
    SuspendTask();
  }

  // Use a locker to automatically unlock our mutex in case of exceptions Add
  // the exception to our internal exception stack
  m_exception_messages.push_back(message);

  LLDB_LOGF(log, "NativeProcessDarwin::%s(): new queued message count: %lu",
            __FUNCTION__, m_exception_messages.size());
}

void *NativeProcessDarwin::ExceptionThread(void *arg) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
  if (!arg) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): cannot run mach exception "
              "thread, mandatory process arg was null",
              __FUNCTION__);
    return nullptr;
  }

  return reinterpret_cast<NativeProcessDarwin *>(arg)->DoExceptionThread();
}

void *NativeProcessDarwin::DoExceptionThread() {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));

  LLDB_LOGF(log, "NativeProcessDarwin::%s(arg=%p) starting thread...",
            __FUNCTION__, this);

  pthread_setname_np("exception monitoring thread");

  // Ensure we don't get CPU starved.
  MaybeRaiseThreadPriority();

  // We keep a count of the number of consecutive exceptions received so we
  // know to grab all exceptions without a timeout. We do this to get a bunch
  // of related exceptions on our exception port so we can process then
  // together. When we have multiple threads, we can get an exception per
  // thread and they will come in consecutively. The main loop in this thread
  // can stop periodically if needed to service things related to this process.
  //
  // [did we lose some words here?]
  //
  // flag set in the options, so we will wait forever for an exception on
  // 0 our exception port. After we get one exception, we then will use the
  // MACH_RCV_TIMEOUT option with a zero timeout to grab all other current
  // exceptions for our process. After we have received the last pending
  // exception, we will get a timeout which enables us to then notify our main
  // thread that we have an exception bundle available. We then wait for the
  // main thread to tell this exception thread to start trying to get
  // exceptions messages again and we start again with a mach_msg read with
  // infinite timeout.
  //
  // We choose to park a thread on this, rather than polling, because the
  // polling is expensive.  On devices, we need to minimize overhead caused by
  // the process monitor.
  uint32_t num_exceptions_received = 0;
  Status error;
  task_t task = m_task;
  mach_msg_timeout_t periodic_timeout = 0;

#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
  mach_msg_timeout_t watchdog_elapsed = 0;
  mach_msg_timeout_t watchdog_timeout = 60 * 1000;
  ::pid_t pid = (::pid_t)process->GetID();
  CFReleaser<SBSWatchdogAssertionRef> watchdog;

  if (process->ProcessUsingSpringBoard()) {
    // Request a renewal for every 60 seconds if we attached using SpringBoard.
    watchdog.reset(::SBSWatchdogAssertionCreateForPID(nullptr, pid, 60));
    LLDB_LOGF(log,
              "::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
              "=> %p",
              pid, watchdog.get());

    if (watchdog.get()) {
      ::SBSWatchdogAssertionRenew(watchdog.get());

      CFTimeInterval watchdogRenewalInterval =
          ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get());
      LLDB_LOGF(log,
                "::SBSWatchdogAssertionGetRenewalInterval(%p) => "
                "%g seconds",
                watchdog.get(), watchdogRenewalInterval);
      if (watchdogRenewalInterval > 0.0) {
        watchdog_timeout = (mach_msg_timeout_t)watchdogRenewalInterval * 1000;
        if (watchdog_timeout > 3000) {
          // Give us a second to renew our timeout.
          watchdog_timeout -= 1000;
        } else if (watchdog_timeout > 1000) {
          // Give us a quarter of a second to renew our timeout.
          watchdog_timeout -= 250;
        }
      }
    }
    if (periodic_timeout == 0 || periodic_timeout > watchdog_timeout)
      periodic_timeout = watchdog_timeout;
  }
#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)

#ifdef WITH_BKS
  CFReleaser<BKSWatchdogAssertionRef> watchdog;
  if (process->ProcessUsingBackBoard()) {
    ::pid_t pid = process->GetID();
    CFAllocatorRef alloc = kCFAllocatorDefault;
    watchdog.reset(::BKSWatchdogAssertionCreateForPID(alloc, pid));
  }
#endif // #ifdef WITH_BKS

  // Do we want to use a weak pointer to the NativeProcessDarwin here, in which
  // case we can guarantee we don't whack the process monitor if we race
  // between this thread and the main one on shutdown?
  while (IsExceptionPortValid()) {
    ::pthread_testcancel();

    MachException::Message exception_message;

    if (num_exceptions_received > 0) {
      // We don't want a timeout here, just receive as many exceptions as we
      // can since we already have one.  We want to get all currently available
      // exceptions for this task at once.
      error = exception_message.Receive(
          GetExceptionPort(),
          MACH_RCV_MSG | MACH_RCV_INTERRUPT | MACH_RCV_TIMEOUT, 0);
    } else if (periodic_timeout > 0) {
      // We need to stop periodically in this loop, so try and get a mach
      // message with a valid timeout (ms).
      error = exception_message.Receive(GetExceptionPort(),
                                        MACH_RCV_MSG | MACH_RCV_INTERRUPT |
                                            MACH_RCV_TIMEOUT,
                                        periodic_timeout);
    } else {
      // We don't need to parse all current exceptions or stop periodically,
      // just wait for an exception forever.
      error = exception_message.Receive(GetExceptionPort(),
                                        MACH_RCV_MSG | MACH_RCV_INTERRUPT, 0);
    }

    if (error.Success()) {
      // We successfully received an exception.
      if (exception_message.CatchExceptionRaise(task)) {
        ++num_exceptions_received;
        ExceptionMessageReceived(exception_message);
      }
    } else {
      if (error.GetError() == MACH_RCV_INTERRUPTED) {
        // We were interrupted.

        // If we have no task port we should exit this thread, as it implies
        // the inferior went down.
        if (!IsExceptionPortValid()) {
          LLDB_LOGF(log,
                    "NativeProcessDarwin::%s(): the inferior "
                    "exception port is no longer valid, "
                    "canceling exception thread...",
                    __FUNCTION__);
          // Should we be setting a process state here?
          break;
        }

        // Make sure the inferior task is still valid.
        if (IsTaskValid()) {
          // Task is still ok.
          LLDB_LOGF(log,
                    "NativeProcessDarwin::%s(): interrupted, but "
                    "the inferior task iss till valid, "
                    "continuing...",
                    __FUNCTION__);
          continue;
        } else {
          // The inferior task is no longer valid.  Time to exit as the process
          // has gone away.
          LLDB_LOGF(log,
                    "NativeProcessDarwin::%s(): the inferior task "
                    "has exited, and so will we...",
                    __FUNCTION__);
          // Does this race at all with our waitpid()?
          SetState(eStateExited);
          break;
        }
      } else if (error.GetError() == MACH_RCV_TIMED_OUT) {
        // We timed out when waiting for exceptions.

        if (num_exceptions_received > 0) {
          // We were receiving all current exceptions with a timeout of zero.
          // It is time to go back to our normal looping mode.
          num_exceptions_received = 0;

          // Notify our main thread we have a complete exception message bundle
          // available.  Get the possibly updated task port back from the
          // process in case we exec'ed and our task port changed.
          task = ExceptionMessageBundleComplete();

          // In case we use a timeout value when getting exceptions, make sure
          // our task is still valid.
          if (IsTaskValid(task)) {
            // Task is still ok.
            LLDB_LOGF(log,
                      "NativeProcessDarwin::%s(): got a timeout, "
                      "continuing...",
                      __FUNCTION__);
            continue;
          } else {
            // The inferior task is no longer valid.  Time to exit as the
            // process has gone away.
            LLDB_LOGF(log,
                      "NativeProcessDarwin::%s(): the inferior "
                      "task has exited, and so will we...",
                      __FUNCTION__);
            // Does this race at all with our waitpid()?
            SetState(eStateExited);
            break;
          }
        }

#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
        if (watchdog.get()) {
          watchdog_elapsed += periodic_timeout;
          if (watchdog_elapsed >= watchdog_timeout) {
            LLDB_LOGF(log, "SBSWatchdogAssertionRenew(%p)", watchdog.get());
            ::SBSWatchdogAssertionRenew(watchdog.get());
            watchdog_elapsed = 0;
          }
        }
#endif
      } else {
        LLDB_LOGF(log,
                  "NativeProcessDarwin::%s(): continuing after "
                  "receiving an unexpected error: %u (%s)",
                  __FUNCTION__, error.GetError(), error.AsCString());
        // TODO: notify of error?
      }
    }
  }

#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
  if (watchdog.get()) {
    // TODO: change SBSWatchdogAssertionRelease to SBSWatchdogAssertionCancel
    // when we
    // all are up and running on systems that support it. The SBS framework has
    // a #define that will forward SBSWatchdogAssertionRelease to
    // SBSWatchdogAssertionCancel for now so it should still build either way.
    DNBLogThreadedIf(LOG_TASK, "::SBSWatchdogAssertionRelease(%p)",
                     watchdog.get());
    ::SBSWatchdogAssertionRelease(watchdog.get());
  }
#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)

  LLDB_LOGF(log, "NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__,
            this);
  return nullptr;
}

Status NativeProcessDarwin::StartExceptionThread() {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__);

  // Make sure we've looked up the inferior port.
  TaskPortForProcessID(error);

  // Ensure the inferior task is valid.
  if (!IsTaskValid()) {
    error.SetErrorStringWithFormat("cannot start exception thread: "
                                   "task 0x%4.4x is not valid",
                                   m_task);
    return error;
  }

  // Get the mach port for the process monitor.
  mach_port_t task_self = mach_task_self();

  // Allocate an exception port that we will use to track our child process
  auto mach_err = ::mach_port_allocate(task_self, MACH_PORT_RIGHT_RECEIVE,
                                       &m_exception_port);
  error.SetError(mach_err, eErrorTypeMachKernel);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): mach_port_allocate("
              "task_self=0x%4.4x, MACH_PORT_RIGHT_RECEIVE, "
              "&m_exception_port) failed: %u (%s)",
              __FUNCTION__, task_self, error.GetError(), error.AsCString());
    return error;
  }

  // Add the ability to send messages on the new exception port
  mach_err = ::mach_port_insert_right(
      task_self, m_exception_port, m_exception_port, MACH_MSG_TYPE_MAKE_SEND);
  error.SetError(mach_err, eErrorTypeMachKernel);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): mach_port_insert_right("
              "task_self=0x%4.4x, m_exception_port=0x%4.4x, "
              "m_exception_port=0x%4.4x, MACH_MSG_TYPE_MAKE_SEND) "
              "failed: %u (%s)",
              __FUNCTION__, task_self, m_exception_port, m_exception_port,
              error.GetError(), error.AsCString());
    return error;
  }

  // Save the original state of the exception ports for our child process.
  error = SaveExceptionPortInfo();
  if (error.Fail() || (m_exc_port_info.mask == 0)) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): SaveExceptionPortInfo() "
              "failed, cannot install exception handler: %s",
              __FUNCTION__, error.AsCString());
    return error;
  }

  // Set the ability to get all exceptions on this port.
  mach_err = ::task_set_exception_ports(
      m_task, m_exc_port_info.mask, m_exception_port,
      EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES, THREAD_STATE_NONE);
  error.SetError(mach_err, eErrorTypeMachKernel);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "::task_set_exception_ports (task = 0x%4.4x, "
              "exception_mask = 0x%8.8x, new_port = 0x%4.4x, "
              "behavior = 0x%8.8x, new_flavor = 0x%8.8x) failed: "
              "%u (%s)",
              m_task, m_exc_port_info.mask, m_exception_port,
              (EXCEPTION_DEFAULT | MACH_EXCEPTION_CODES), THREAD_STATE_NONE,
              error.GetError(), error.AsCString());
    return error;
  }

  // Create the exception thread.
  auto pthread_err =
      ::pthread_create(&m_exception_thread, nullptr, ExceptionThread, this);
  error.SetError(pthread_err, eErrorTypePOSIX);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): failed to create Mach "
              "exception-handling thread: %u (%s)",
              __FUNCTION__, error.GetError(), error.AsCString());
  }

  return error;
}

lldb::addr_t
NativeProcessDarwin::GetDYLDAllImageInfosAddress(Status &error) const {
  error.Clear();

  struct hack_task_dyld_info dyld_info;
  mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT;
  // Make sure that COUNT isn't bigger than our hacked up struct
  // hack_task_dyld_info.  If it is, then make COUNT smaller to match.
  if (count > (sizeof(struct hack_task_dyld_info) / sizeof(natural_t))) {
    count = (sizeof(struct hack_task_dyld_info) / sizeof(natural_t));
  }

  TaskPortForProcessID(error);
  if (error.Fail())
    return LLDB_INVALID_ADDRESS;

  auto mach_err =
      ::task_info(m_task, TASK_DYLD_INFO, (task_info_t)&dyld_info, &count);
  error.SetError(mach_err, eErrorTypeMachKernel);
  if (error.Success()) {
    // We now have the address of the all image infos structure.
    return dyld_info.all_image_info_addr;
  }

  // We don't have it.
  return LLDB_INVALID_ADDRESS;
}

uint32_t NativeProcessDarwin::GetCPUTypeForLocalProcess(::pid_t pid) {
  int mib[CTL_MAXNAME] = {
      0,
  };
  size_t len = CTL_MAXNAME;

  if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
    return 0;

  mib[len] = pid;
  len++;

  cpu_type_t cpu;
  size_t cpu_len = sizeof(cpu);
  if (::sysctl(mib, static_cast<u_int>(len), &cpu, &cpu_len, 0, 0))
    cpu = 0;
  return cpu;
}

uint32_t NativeProcessDarwin::GetCPUType() const {
  if (m_cpu_type == 0 && m_pid != 0)
    m_cpu_type = GetCPUTypeForLocalProcess(m_pid);
  return m_cpu_type;
}

task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
  // We have a complete bundle of exceptions for our child process.
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));

  std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
  LLDB_LOGF(log,
            "NativeProcessDarwin::%s(): processing %lu exception "
            "messages.",
            __FUNCTION__, m_exception_messages.size());

  if (m_exception_messages.empty()) {
    // Not particularly useful...
    return m_task;
  }

  bool auto_resume = false;
  m_did_exec = false;

  // First check for any SIGTRAP and make sure we didn't exec
  const task_t task = m_task;
  size_t i;
  if (m_pid != 0) {
    bool received_interrupt = false;
    uint32_t num_task_exceptions = 0;
    for (i = 0; i < m_exception_messages.size(); ++i) {
      if (m_exception_messages[i].state.task_port != task) {
        // This is an exception that is not for our inferior, ignore.
        continue;
      }

      // This is an exception for the inferior.
      ++num_task_exceptions;
      const int signo = m_exception_messages[i].state.SoftSignal();
      if (signo == SIGTRAP) {
        // SIGTRAP could mean that we exec'ed. We need to check the
        // dyld all_image_infos.infoArray to see if it is NULL and if so, say
        // that we exec'ed.
        const addr_t aii_addr = GetDYLDAllImageInfosAddress(error);
        if (aii_addr == LLDB_INVALID_ADDRESS)
          break;

        const addr_t info_array_count_addr = aii_addr + 4;
        uint32_t info_array_count = 0;
        size_t bytes_read = 0;
        Status read_error;
        read_error = ReadMemory(info_array_count_addr, // source addr
                                &info_array_count,     // dest addr
                                4,                     // byte count
                                bytes_read);           // #bytes read
        if (read_error.Success() && (bytes_read == 4)) {
          if (info_array_count == 0) {
            // We got the all infos address, and there are zero entries.  We
            // think we exec'd.
            m_did_exec = true;

            // Force the task port to update itself in case the task port
            // changed after exec
            const task_t old_task = m_task;
            const bool force_update = true;
            const task_t new_task = TaskPortForProcessID(error, force_update);
            if (old_task != new_task) {
              LLDB_LOGF(log,
                        "exec: inferior task port changed "
                        "from 0x%4.4x to 0x%4.4x",
                        old_task, new_task);
            }
          }
        } else {
          LLDB_LOGF(log,
                    "NativeProcessDarwin::%s() warning: "
                    "failed to read all_image_infos."
                    "infoArrayCount from 0x%8.8llx",
                    __FUNCTION__, info_array_count_addr);
        }
      } else if ((m_sent_interrupt_signo != 0) &&
                 (signo == m_sent_interrupt_signo)) {
        // We just received the interrupt that we sent to ourselves.
        received_interrupt = true;
      }
    }

    if (m_did_exec) {
      cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_pid);
      if (m_cpu_type != process_cpu_type) {
        LLDB_LOGF(log,
                  "NativeProcessDarwin::%s(): arch changed from "
                  "0x%8.8x to 0x%8.8x",
                  __FUNCTION__, m_cpu_type, process_cpu_type);
        m_cpu_type = process_cpu_type;
        // TODO figure out if we need to do something here.
        // DNBArchProtocol::SetArchitecture (process_cpu_type);
      }
      m_thread_list.Clear();

      // TODO hook up breakpoints.
      // m_breakpoints.DisableAll();
    }

    if (m_sent_interrupt_signo != 0) {
      if (received_interrupt) {
        LLDB_LOGF(log,
                  "NativeProcessDarwin::%s(): process "
                  "successfully interrupted with signal %i",
                  __FUNCTION__, m_sent_interrupt_signo);

        // Mark that we received the interrupt signal
        m_sent_interrupt_signo = 0;
        // Now check if we had a case where:
        // 1 - We called NativeProcessDarwin::Interrupt() but we stopped
        //     for another reason.
        // 2 - We called NativeProcessDarwin::Resume() (but still
        //     haven't gotten the interrupt signal).
        // 3 - We are now incorrectly stopped because we are handling
        //     the interrupt signal we missed.
        // 4 - We might need to resume if we stopped only with the
        //     interrupt signal that we never handled.
        if (m_auto_resume_signo != 0) {
          // Only auto_resume if we stopped with _only_ the interrupt signal.
          if (num_task_exceptions == 1) {
            auto_resume = true;
            LLDB_LOGF(log,
                      "NativeProcessDarwin::%s(): auto "
                      "resuming due to unhandled interrupt "
                      "signal %i",
                      __FUNCTION__, m_auto_resume_signo);
          }
          m_auto_resume_signo = 0;
        }
      } else {
        LLDB_LOGF(log,
                  "NativeProcessDarwin::%s(): didn't get signal "
                  "%i after MachProcess::Interrupt()",
                  __FUNCTION__, m_sent_interrupt_signo);
      }
    }
  }

  // Let all threads recover from stopping and do any clean up based on the
  // previous thread state (if any).
  m_thread_list.ProcessDidStop(*this);

  // Let each thread know of any exceptions
  for (i = 0; i < m_exception_messages.size(); ++i) {
    // Let the thread list forward all exceptions on down to each thread.
    if (m_exception_messages[i].state.task_port == task) {
      // This exception is for our inferior.
      m_thread_list.NotifyException(m_exception_messages[i].state);
    }

    if (log) {
      StreamString stream;
      m_exception_messages[i].Dump(stream);
      stream.Flush();
      log->PutCString(stream.GetString().c_str());
    }
  }

  if (log) {
    StreamString stream;
    m_thread_list.Dump(stream);
    stream.Flush();
    log->PutCString(stream.GetString().c_str());
  }

  bool step_more = false;
  if (m_thread_list.ShouldStop(step_more) && (auto_resume == false)) {
// TODO - need to hook up event system here. !!!!
#if 0
        // Wait for the eEventProcessRunningStateChanged event to be reset
        // before changing state to stopped to avoid race condition with very
        // fast start/stops.
        struct timespec timeout;

        //DNBTimer::OffsetTimeOfDay(&timeout, 0, 250 * 1000);   // Wait for 250 ms
        DNBTimer::OffsetTimeOfDay(&timeout, 1, 0);  // Wait for 250 ms
        m_events.WaitForEventsToReset(eEventProcessRunningStateChanged,
                                      &timeout);
#endif
    SetState(eStateStopped);
  } else {
    // Resume without checking our current state.
    PrivateResume();
  }

  return m_task;
}

void NativeProcessDarwin::StartSTDIOThread() {
  // TODO implement
}

Status NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Strategy: create a thread that sits on waitpid(), waiting for the inferior
  // process to die, reaping it in the process.  Arrange for the thread to have
  // a pipe file descriptor that it can send a byte over when the waitpid
  // completes.  Have the main loop have a read object for the other side of
  // the pipe, and have the callback for the read do the process termination
  // message sending.

  // Create a single-direction communication channel.
  const bool child_inherits = false;
  error = m_waitpid_pipe.CreateNew(child_inherits);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): failed to create waitpid "
              "communication pipe: %s",
              __FUNCTION__, error.AsCString());
    return error;
  }

  // Hook up the waitpid reader callback.

  // TODO make PipePOSIX derive from IOObject.  This is goofy here.
  const bool transfer_ownership = false;
  auto io_sp = IOObjectSP(new NativeFile(m_waitpid_pipe.GetReadFileDescriptor(),
                                         transfer_ownership));
  m_waitpid_reader_handle = main_loop.RegisterReadObject(
      io_sp, [this](MainLoopBase &) { HandleWaitpidResult(); }, error);

  // Create the thread.
  auto pthread_err =
      ::pthread_create(&m_waitpid_thread, nullptr, WaitpidThread, this);
  error.SetError(pthread_err, eErrorTypePOSIX);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): failed to create waitpid "
              "handling thread: %u (%s)",
              __FUNCTION__, error.GetError(), error.AsCString());
    return error;
  }

  return error;
}

void *NativeProcessDarwin::WaitpidThread(void *arg) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
  if (!arg) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): cannot run waitpid "
              "thread, mandatory process arg was null",
              __FUNCTION__);
    return nullptr;
  }

  return reinterpret_cast<NativeProcessDarwin *>(arg)->DoWaitpidThread();
}

void NativeProcessDarwin::MaybeRaiseThreadPriority() {
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
  struct sched_param thread_param;
  int thread_sched_policy;
  if (pthread_getschedparam(pthread_self(), &thread_sched_policy,
                            &thread_param) == 0) {
    thread_param.sched_priority = 47;
    pthread_setschedparam(pthread_self(), thread_sched_policy, &thread_param);
  }
#endif
}

void *NativeProcessDarwin::DoWaitpidThread() {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  if (m_pid == LLDB_INVALID_PROCESS_ID) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): inferior process ID is "
              "not set, cannot waitpid on it",
              __FUNCTION__);
    return nullptr;
  }

  // Name the thread.
  pthread_setname_np("waitpid thread");

  // Ensure we don't get CPU starved.
  MaybeRaiseThreadPriority();

  Status error;
  int status = -1;

  while (1) {
    // Do a waitpid.
    ::pid_t child_pid = ::waitpid(m_pid, &status, 0);
    if (child_pid < 0)
      error.SetErrorToErrno();
    if (error.Fail()) {
      if (error.GetError() == EINTR) {
        // This is okay, we can keep going.
        LLDB_LOGF(log,
                  "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
                  ", &status, 0) interrupted, continuing",
                  __FUNCTION__, m_pid);
        continue;
      }

      // This error is not okay, abort.
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
                ", &status, 0) aborting due to error: %u (%s)",
                __FUNCTION__, m_pid, error.GetError(), error.AsCString());
      break;
    }

    // Log the successful result.
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
              ", &status, 0) => %i, status = %i",
              __FUNCTION__, m_pid, child_pid, status);

    // Handle the result.
    if (WIFSTOPPED(status)) {
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
                ") received a stop, continuing waitpid() loop",
                __FUNCTION__, m_pid);
      continue;
    } else // if (WIFEXITED(status) || WIFSIGNALED(status))
    {
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(pid = %" PRIu64 "): "
                "waitpid thread is setting exit status for pid = "
                "%i to %i",
                __FUNCTION__, m_pid, child_pid, status);

      error = SendInferiorExitStatusToMainLoop(child_pid, status);
      return nullptr;
    }
  }

  // We should never exit as long as our child process is alive.  If we get
  // here, something completely unexpected went wrong and we should exit.
  LLDB_LOGF(log,
            "NativeProcessDarwin::%s(): internal error: waitpid thread "
            "exited out of its main loop in an unexpected way. pid = %" PRIu64
            ". Sending exit status of -1.",
            __FUNCTION__, m_pid);

  error = SendInferiorExitStatusToMainLoop((::pid_t)m_pid, -1);
  return nullptr;
}

Status NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid,
                                                             int status) {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  size_t bytes_written = 0;

  // Send the pid.
  error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written);
  if (error.Fail() || (bytes_written < sizeof(pid))) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s() - failed to write "
              "waitpid exiting pid to the pipe.  Client will not "
              "hear about inferior exit status!",
              __FUNCTION__);
    return error;
  }

  // Send the status.
  bytes_written = 0;
  error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written);
  if (error.Fail() || (bytes_written < sizeof(status))) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s() - failed to write "
              "waitpid exit result to the pipe.  Client will not "
              "hear about inferior exit status!",
              __FUNCTION__);
  }
  return error;
}

Status NativeProcessDarwin::HandleWaitpidResult() {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Read the pid.
  const bool notify_status = true;

  ::pid_t pid = -1;
  size_t bytes_read = 0;
  error = m_waitpid_pipe.Read(&pid, sizeof(pid), bytes_read);
  if (error.Fail() || (bytes_read < sizeof(pid))) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s() - failed to read "
              "waitpid exiting pid from the pipe.  Will notify "
              "as if parent process died with exit status -1.",
              __FUNCTION__);
    SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status);
    return error;
  }

  // Read the status.
  int status = -1;
  error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read);
  if (error.Fail() || (bytes_read < sizeof(status))) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s() - failed to read "
              "waitpid exit status from the pipe.  Will notify "
              "as if parent process died with exit status -1.",
              __FUNCTION__);
    SetExitStatus(WaitStatus(WaitStatus::Exit, -1), notify_status);
    return error;
  }

  // Notify the monitor that our state has changed.
  LLDB_LOGF(log,
            "NativeProcessDarwin::%s(): main loop received waitpid "
            "exit status info: pid=%i (%s), status=%i",
            __FUNCTION__, pid,
            (pid == m_pid) ? "the inferior" : "not the inferior", status);

  SetExitStatus(WaitStatus::Decode(status), notify_status);
  return error;
}

task_t NativeProcessDarwin::TaskPortForProcessID(Status &error,
                                                 bool force) const {
  if ((m_task == TASK_NULL) || force) {
    Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
    if (m_pid == LLDB_INVALID_PROCESS_ID) {
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): cannot get task due "
                "to invalid pid",
                __FUNCTION__);
      return TASK_NULL;
    }

    const uint32_t num_retries = 10;
    const uint32_t usec_interval = 10000;

    mach_port_t task_self = mach_task_self();
    task_t task = TASK_NULL;

    for (uint32_t i = 0; i < num_retries; i++) {
      kern_return_t err = ::task_for_pid(task_self, m_pid, &task);
      if (err == 0) {
        // Succeeded.  Save and return it.
        error.Clear();
        m_task = task;
        LLDB_LOGF(log,
                  "NativeProcessDarwin::%s(): ::task_for_pid("
                  "stub_port = 0x%4.4x, pid = %llu, &task) "
                  "succeeded: inferior task port = 0x%4.4x",
                  __FUNCTION__, task_self, m_pid, m_task);
        return m_task;
      } else {
        // Failed to get the task for the inferior process.
        error.SetError(err, eErrorTypeMachKernel);
        if (log) {
          LLDB_LOGF(log,
                    "NativeProcessDarwin::%s(): ::task_for_pid("
                    "stub_port = 0x%4.4x, pid = %llu, &task) "
                    "failed, err = 0x%8.8x (%s)",
                    __FUNCTION__, task_self, m_pid, err, error.AsCString());
        }
      }

      // Sleep a bit and try again
      ::usleep(usec_interval);
    }

    // We failed to get the task for the inferior process. Ensure that it is
    // cleared out.
    m_task = TASK_NULL;
  }
  return m_task;
}

void NativeProcessDarwin::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
                                           Status &error) {
  error.SetErrorString("TODO: implement");
}

Status NativeProcessDarwin::PrivateResume() {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
  m_auto_resume_signo = m_sent_interrupt_signo;

  if (log) {
    if (m_auto_resume_signo)
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): task 0x%x resuming (with "
                "unhandled interrupt signal %i)...",
                __FUNCTION__, m_task, m_auto_resume_signo);
    else
      LLDB_LOGF(log, "NativeProcessDarwin::%s(): task 0x%x resuming...",
                __FUNCTION__, m_task);
  }

  error = ReplyToAllExceptions();
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): aborting, failed to "
              "reply to exceptions: %s",
              __FUNCTION__, error.AsCString());
    return error;
  }
  //    bool stepOverBreakInstruction = step;

  // Let the thread prepare to resume and see if any threads want us to step
  // over a breakpoint instruction (ProcessWillResume will modify the value of
  // stepOverBreakInstruction).
  m_thread_list.ProcessWillResume(*this, m_thread_actions);

  // Set our state accordingly
  if (m_thread_actions.NumActionsWithState(eStateStepping))
    SetState(eStateStepping);
  else
    SetState(eStateRunning);

  // Now resume our task.
  error = ResumeTask();
  return error;
}

Status NativeProcessDarwin::ReplyToAllExceptions() {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));

  TaskPortForProcessID(error);
  if (error.Fail()) {
    LLDB_LOGF(log, "NativeProcessDarwin::%s(): no task port, aborting",
              __FUNCTION__);
    return error;
  }

  std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
  if (m_exception_messages.empty()) {
    // We're done.
    return error;
  }

  size_t index = 0;
  for (auto &message : m_exception_messages) {
    if (log) {
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): replying to exception "
                "%zu...",
                __FUNCTION__, index++);
    }

    int thread_reply_signal = 0;

    const tid_t tid =
        m_thread_list.GetThreadIDByMachPortNumber(message.state.thread_port);
    const ResumeAction *action = nullptr;
    if (tid != LLDB_INVALID_THREAD_ID)
      action = m_thread_actions.GetActionForThread(tid, false);

    if (action) {
      thread_reply_signal = action->signal;
      if (thread_reply_signal)
        m_thread_actions.SetSignalHandledForThread(tid);
    }

    error = message.Reply(m_pid, m_task, thread_reply_signal);
    if (error.Fail() && log) {
      // We log any error here, but we don't stop the exception response
      // handling.
      LLDB_LOGF(log,
                "NativeProcessDarwin::%s(): failed to reply to "
                "exception: %s",
                __FUNCTION__, error.AsCString());
      error.Clear();
    }
  }

  // Erase all exception message as we should have used and replied to them all
  // already.
  m_exception_messages.clear();
  return error;
}

Status NativeProcessDarwin::ResumeTask() {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  TaskPortForProcessID(error);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): failed to get task port "
              "for process when attempting to resume: %s",
              __FUNCTION__, error.AsCString());
    return error;
  }
  if (m_task == TASK_NULL) {
    error.SetErrorString("task port retrieval succeeded but task port is "
                         "null when attempting to resume the task");
    return error;
  }

  LLDB_LOGF(log,
            "NativeProcessDarwin::%s(): requesting resume of task "
            "0x%4.4x",
            __FUNCTION__, m_task);

  // Get the BasicInfo struct to verify that we're suspended before we try to
  // resume the task.
  struct task_basic_info task_info;
  error = GetTaskBasicInfo(m_task, &task_info);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): failed to get task "
              "BasicInfo when attempting to resume: %s",
              __FUNCTION__, error.AsCString());
    return error;
  }

  // task_resume isn't counted like task_suspend calls are, so if the task is
  // not suspended, don't try and resume it since it is already running
  if (task_info.suspend_count > 0) {
    auto mach_err = ::task_resume(m_task);
    error.SetError(mach_err, eErrorTypeMachKernel);
    if (log) {
      if (error.Success())
        LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x): success", m_task);
      else
        LLDB_LOGF(log, "::task_resume(target_task = 0x%4.4x) error: %s", m_task,
                  error.AsCString());
    }
  } else {
    LLDB_LOGF(log,
              "::task_resume(target_task = 0x%4.4x): ignored, "
              "already running",
              m_task);
  }

  return error;
}

bool NativeProcessDarwin::IsTaskValid() const {
  if (m_task == TASK_NULL)
    return false;

  struct task_basic_info task_info;
  return GetTaskBasicInfo(m_task, &task_info).Success();
}

bool NativeProcessDarwin::IsTaskValid(task_t task) const {
  if (task == TASK_NULL)
    return false;

  struct task_basic_info task_info;
  return GetTaskBasicInfo(task, &task_info).Success();
}

mach_port_t NativeProcessDarwin::GetExceptionPort() const {
  return m_exception_port;
}

bool NativeProcessDarwin::IsExceptionPortValid() const {
  return MACH_PORT_VALID(m_exception_port);
}

Status
NativeProcessDarwin::GetTaskBasicInfo(task_t task,
                                      struct task_basic_info *info) const {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  // Validate args.
  if (info == NULL) {
    error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): mandatory "
                                   "info arg is null",
                                   __FUNCTION__);
    return error;
  }

  // Grab the task if we don't already have it.
  if (task == TASK_NULL) {
    error.SetErrorStringWithFormat("NativeProcessDarwin::%s(): given task "
                                   "is invalid",
                                   __FUNCTION__);
  }

  mach_msg_type_number_t count = TASK_BASIC_INFO_COUNT;
  auto err = ::task_info(m_task, TASK_BASIC_INFO, (task_info_t)info, &count);
  error.SetError(err, eErrorTypeMachKernel);
  if (error.Fail()) {
    LLDB_LOGF(log,
              "::task_info(target_task = 0x%4.4x, "
              "flavor = TASK_BASIC_INFO, task_info_out => %p, "
              "task_info_outCnt => %u) failed: %u (%s)",
              m_task, info, count, error.GetError(), error.AsCString());
    return error;
  }

  Log *verbose_log(
      GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
  if (verbose_log) {
    float user = (float)info->user_time.seconds +
                 (float)info->user_time.microseconds / 1000000.0f;
    float system = (float)info->user_time.seconds +
                   (float)info->user_time.microseconds / 1000000.0f;
    verbose_LLDB_LOGF(log,
                      "task_basic_info = { suspend_count = %i, "
                      "virtual_size = 0x%8.8llx, resident_size = "
                      "0x%8.8llx, user_time = %f, system_time = %f }",
                      info->suspend_count, (uint64_t)info->virtual_size,
                      (uint64_t)info->resident_size, user, system);
  }
  return error;
}

Status NativeProcessDarwin::SuspendTask() {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  if (m_task == TASK_NULL) {
    error.SetErrorString("task port is null, cannot suspend task");
    LLDB_LOGF(log, "NativeProcessDarwin::%s() failed: %s", __FUNCTION__,
              error.AsCString());
    return error;
  }

  auto mach_err = ::task_suspend(m_task);
  error.SetError(mach_err, eErrorTypeMachKernel);
  if (error.Fail() && log)
    LLDB_LOGF(log, "::task_suspend(target_task = 0x%4.4x)", m_task);

  return error;
}

Status NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) {
  Status error;
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));

  LLDB_LOGF(log, "NativeProcessDarwin::%s() called", __FUNCTION__);

  if (CanResume()) {
    m_thread_actions = resume_actions;
    error = PrivateResume();
    return error;
  }

  auto state = GetState();
  if (state == eStateRunning) {
    LLDB_LOGF(log,
              "NativeProcessDarwin::%s(): task 0x%x is already "
              "running, ignoring...",
              __FUNCTION__, TaskPortForProcessID(error));
    return error;
  }

  // We can't resume from this state.
  error.SetErrorStringWithFormat("task 0x%x has state %s, can't resume",
                                 TaskPortForProcessID(error),
                                 StateAsCString(state));
  return error;
}

Status NativeProcessDarwin::Halt() {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::Detach() {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::Signal(int signo) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::Interrupt() {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::Kill() {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::GetMemoryRegionInfo(lldb::addr_t load_addr,
                                                MemoryRegionInfo &range_info) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::ReadMemory(lldb::addr_t addr, void *buf,
                                       size_t size, size_t &bytes_read) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
                                                  size_t size,
                                                  size_t &bytes_read) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::WriteMemory(lldb::addr_t addr, const void *buf,
                                        size_t size, size_t &bytes_written) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::AllocateMemory(size_t size, uint32_t permissions,
                                           lldb::addr_t &addr) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::DeallocateMemory(lldb::addr_t addr) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

lldb::addr_t NativeProcessDarwin::GetSharedLibraryInfoAddress() {
  return LLDB_INVALID_ADDRESS;
}

size_t NativeProcessDarwin::UpdateThreads() { return 0; }

bool NativeProcessDarwin::GetArchitecture(ArchSpec &arch) const {
  return false;
}

Status NativeProcessDarwin::SetBreakpoint(lldb::addr_t addr, uint32_t size,
                                          bool hardware) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

void NativeProcessDarwin::DoStopIDBumped(uint32_t newBumpId) {}

Status NativeProcessDarwin::GetLoadedModuleFileSpec(const char *module_path,
                                                    FileSpec &file_spec) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

Status NativeProcessDarwin::GetFileLoadAddress(const llvm::StringRef &file_name,
                                               lldb::addr_t &load_addr) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}

// NativeProcessProtocol protected interface
Status NativeProcessDarwin::GetSoftwareBreakpointTrapOpcode(
    size_t trap_opcode_size_hint, size_t &actual_opcode_size,
    const uint8_t *&trap_opcode_bytes) {
  Status error;
  error.SetErrorString("TODO: implement");
  return error;
}
