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; -} |