diff options
Diffstat (limited to 'lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp')
| -rw-r--r-- | lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp | 1535 | 
1 files changed, 0 insertions, 1535 deletions
diff --git a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp deleted file mode 100644 index 18dbdda9a33b2..0000000000000 --- a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp +++ /dev/null @@ -1,1535 +0,0 @@ -//===-- 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; -}  | 
