summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp')
-rw-r--r--lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp2795
1 files changed, 1273 insertions, 1522 deletions
diff --git a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
index d0eaac3c793..e56375ebaa4 100644
--- a/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
+++ b/lldb/source/Plugins/Process/Darwin/NativeProcessDarwin.cpp
@@ -40,170 +40,142 @@ 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;
- };
+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
// -----------------------------------------------------------------------------
-Error
-NativeProcessProtocol::Launch(ProcessLaunchInfo &launch_info,
- NativeProcessProtocol::NativeDelegate
- &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &native_process_sp)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- Error error;
-
- // Verify the working directory is valid if one was specified.
- FileSpec working_dir(launch_info.GetWorkingDirectory());
- if (working_dir &&
- (!working_dir.ResolvePath() ||
- working_dir.GetFileType() != FileSpec::eFileTypeDirectory))
- {
- error.SetErrorStringWithFormat("No such file or directory: %s",
- working_dir.GetCString());
- return error;
- }
+Error NativeProcessProtocol::Launch(
+ ProcessLaunchInfo &launch_info,
+ NativeProcessProtocol::NativeDelegate &native_delegate, MainLoop &mainloop,
+ NativeProcessProtocolSP &native_process_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ Error error;
+
+ // Verify the working directory is valid if one was specified.
+ FileSpec working_dir(launch_info.GetWorkingDirectory());
+ if (working_dir &&
+ (!working_dir.ResolvePath() ||
+ working_dir.GetFileType() != FileSpec::eFileTypeDirectory)) {
+ 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;
+ // Launch the inferior.
+ int pty_master_fd = -1;
+ LaunchFlavor launch_flavor = LaunchFlavor::Default;
- error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor);
+ error = LaunchInferior(launch_info, &pty_master_fd, &launch_flavor);
- // Handle launch failure.
- if (!error.Success())
- {
- if (log)
- log->Printf("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)
- {
- if (log)
- log->Printf("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())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() aborting, failed to finalize"
- " the launching of the process: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
+ // Handle launch failure.
+ if (!error.Success()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() failed to launch 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;
+ // Handle failure to return a pid.
+ if (launch_info.GetProcessID() == LLDB_INVALID_PROCESS_ID) {
+ if (log)
+ log->Printf("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;
+ }
-Error
-NativeProcessProtocol::Attach(lldb::pid_t pid,
- NativeProcessProtocol::NativeDelegate
- &native_delegate,
- MainLoop &mainloop,
- NativeProcessProtocolSP &native_process_sp)
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Finalize the processing needed to debug the launched process with
+ // a NativeProcessDarwin instance.
+ error = np_darwin_sp->FinalizeLaunch(launch_flavor, mainloop);
+ if (!error.Success()) {
if (log)
- log->Printf ("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__,
- pid);
+ log->Printf("NativeProcessDarwin::%s() aborting, failed to finalize"
+ " the launching of the process: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
+ }
- // Retrieve the architecture for the running process.
- ArchSpec process_arch;
- Error error = ResolveProcessArchitecture(pid, process_arch);
- if (!error.Success())
- return error;
+ // Return the process and process id to the caller through the launch args.
+ native_process_sp = np_darwin_sp;
+ 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));
+Error NativeProcessProtocol::Attach(
+ lldb::pid_t pid, NativeProcessProtocol::NativeDelegate &native_delegate,
+ MainLoop &mainloop, NativeProcessProtocolSP &native_process_sp) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(pid = %" PRIi64 ")", __FUNCTION__,
+ pid);
+
+ // Retrieve the architecture for the running process.
+ ArchSpec process_arch;
+ Error error = ResolveProcessArchitecture(pid, process_arch);
+ if (!error.Success())
+ return error;
- if (!native_process_darwin_sp->RegisterNativeDelegate(native_delegate))
- {
- error.SetErrorStringWithFormat("failed to register the native "
- "delegate");
- 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));
- native_process_darwin_sp->AttachToInferior(mainloop, pid, error);
- if (!error.Success())
- return error;
+ if (!native_process_darwin_sp->RegisterNativeDelegate(native_delegate)) {
+ error.SetErrorStringWithFormat("failed to register the native "
+ "delegate");
+ return error;
+ }
- native_process_sp = native_process_darwin_sp;
+ 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(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()
-{
-}
+NativeProcessDarwin::~NativeProcessDarwin() {}
// -----------------------------------------------------------------------------
// Instance methods
// -----------------------------------------------------------------------------
-Error
-NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
- MainLoop &main_loop)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+Error NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
+ MainLoop &main_loop) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
#if 0
m_path = path;
@@ -213,772 +185,680 @@ NativeProcessDarwin::FinalizeLaunch(LaunchFlavor launch_flavor,
m_args.push_back(arg);
#endif
- error = StartExceptionThread();
- if (!error.Success())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failure starting the "
- "mach exception port monitor thread: %s",
- __FUNCTION__, error.AsCString());
+ error = StartExceptionThread();
+ if (!error.Success()) {
+ if (log)
+ log->Printf("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);
+ // 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;
+ 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;
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): successfully spawned "
+ "process with pid %" PRIu64,
+ __FUNCTION__, m_pid);
+ } else {
+ error.SetErrorToErrno();
+ SetState(eStateExited);
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): error: failed to "
+ "attach to spawned pid %" PRIu64 " (error=%d (%s))",
+ __FUNCTION__, m_pid, (int)error.GetError(),
+ error.AsCString());
+ 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;
- if (log)
- log->Printf("NativeProcessDarwin::%s(): successfully spawned "
- "process with pid %" PRIu64, __FUNCTION__, m_pid);
- }
- else
- {
- error.SetErrorToErrno();
- SetState(eStateExited);
- if (log)
- log->Printf("NativeProcessDarwin::%s(): error: failed to "
- "attach to spawned pid %" PRIu64 " (error=%d (%s))",
- __FUNCTION__, m_pid, (int)error.GetError(),
- error.AsCString());
- return error;
- }
- }
+ if (log)
+ log->Printf("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()) {
if (log)
- log->Printf("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())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to start waitpid() "
- "thread: %s", __FUNCTION__, error.AsCString());
- kill(SIGKILL, static_cast<::pid_t>(m_pid));
- return error;
- }
+ log->Printf("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.
- if (log)
- log->Printf("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;
- }
+ 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.
+ if (log)
+ log->Printf("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);
+ // Indicate that we're stopped, as we always launch suspended.
+ SetState(eStateStopped);
- // Success.
- return error;
+ // Success.
+ return error;
}
-Error
-NativeProcessDarwin::SaveExceptionPortInfo()
-{
- return m_exc_port_info.Save(m_task);
+Error 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::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;
+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);
-
- if (log)
- log->Printf("NativeProcessDarwin::%s(): new queued message count: %lu",
- __FUNCTION__, m_exception_messages.size());
+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);
+
+ if (log)
+ log->Printf("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)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): cannot run mach exception "
- "thread, mandatory process arg was null", __FUNCTION__);
- return nullptr;
- }
+void *NativeProcessDarwin::ExceptionThread(void *arg) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+ if (!arg) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): cannot run mach exception "
+ "thread, mandatory process arg was null",
+ __FUNCTION__);
+ return nullptr;
+ }
- return reinterpret_cast<NativeProcessDarwin*>(arg)->DoExceptionThread();
+ return reinterpret_cast<NativeProcessDarwin *>(arg)->DoExceptionThread();
}
-void*
-NativeProcessDarwin::DoExceptionThread()
-{
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
-
+void *NativeProcessDarwin::DoExceptionThread() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
+
+ if (log)
+ log->Printf("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;
+ Error 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));
if (log)
- log->Printf("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;
- Error 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));
- if (log)
- log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
- "=> %p", pid, watchdog.get());
-
- if (watchdog.get())
- {
- ::SBSWatchdogAssertionRenew (watchdog.get());
-
- CFTimeInterval watchdogRenewalInterval =
- ::SBSWatchdogAssertionGetRenewalInterval (watchdog.get());
- if (log)
- log->Printf("::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;
- }
- }
+ log->Printf("::SBSWatchdogAssertionCreateForPID(NULL, %4.4x, 60) "
+ "=> %p",
+ pid, watchdog.get());
+
+ if (watchdog.get()) {
+ ::SBSWatchdogAssertionRenew(watchdog.get());
+
+ CFTimeInterval watchdogRenewalInterval =
+ ::SBSWatchdogAssertionGetRenewalInterval(watchdog.get());
+ if (log)
+ log->Printf("::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)
+ 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));
- }
+ 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);
+ // 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()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): the inferior "
+ "exception port is no longer valid, "
+ "canceling exception thread...",
+ __FUNCTION__);
+ // Should we be setting a process state here?
+ break;
}
- 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);
+
+ // Make sure the inferior task is still valid.
+ if (IsTaskValid()) {
+ // Task is still ok.
+ if (log)
+ log->Printf("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.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): the inferior task "
+ "has exited, and so will we...",
+ __FUNCTION__);
+ // Does this race at all with our waitpid()?
+ SetState(eStateExited);
+ break;
}
- 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);
+ } 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.
+ if (log)
+ log->Printf("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.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): the inferior "
+ "task has exited, and so will we...",
+ __FUNCTION__);
+ // Does this race at all with our waitpid()?
+ SetState(eStateExited);
+ break;
+ }
}
- if (error.Success())
- {
- // We successfully received an exception.
- if (exception_message.CatchExceptionRaise(task))
- {
- ++num_exceptions_received;
- ExceptionMessageReceived(exception_message);
- }
+#if defined(WITH_SPRINGBOARD) && !defined(WITH_BKS)
+ if (watchdog.get()) {
+ watchdog_elapsed += periodic_timeout;
+ if (watchdog_elapsed >= watchdog_timeout) {
+ if (log)
+ log->Printf("SBSWatchdogAssertionRenew(%p)", watchdog.get());
+ ::SBSWatchdogAssertionRenew(watchdog.get());
+ watchdog_elapsed = 0;
+ }
}
- 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())
- {
- if (log)
- log->Printf("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.
- if (log)
- log->Printf("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.
- if (log)
- log->Printf("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.
- if (log)
- log->Printf("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.
- if (log)
- log->Printf("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)
- {
- if (log)
- log->Printf("SBSWatchdogAssertionRenew(%p)",
- watchdog.get());
- ::SBSWatchdogAssertionRenew (watchdog.get());
- watchdog_elapsed = 0;
- }
- }
#endif
- }
- else
- {
- if (log)
- log->Printf("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());
+ } else {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): continuing after "
+ "receiving an unexpected error: %u (%s)",
+ __FUNCTION__, error.GetError(), error.AsCString());
+ // TODO: notify of error?
+ }
}
-#endif // #if defined (WITH_SPRINGBOARD) && !defined (WITH_BKS)
-
- if (log)
- log->Printf("NativeProcessDarwin::%s(%p): thread exiting...",
- __FUNCTION__, this);
- return nullptr;
+ }
+
+#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)
+
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(%p): thread exiting...", __FUNCTION__,
+ this);
+ return nullptr;
}
-Error
-NativeProcessDarwin::StartExceptionThread()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
-
- // Make sure we've looked up the inferior port.
- TaskPortForProcessID(error);
+Error NativeProcessDarwin::StartExceptionThread() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
- // 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;
- }
+ // Make sure we've looked up the inferior port.
+ TaskPortForProcessID(error);
- // Get the mach port for the process monitor.
- mach_port_t task_self = mach_task_self();
+ // 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;
+ }
- // 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())
- {
- if (log)
- log->Printf("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;
- }
+ // Get the mach port for the process monitor.
+ mach_port_t task_self = mach_task_self();
- // 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())
- {
- if (log)
- log->Printf("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;
- }
+ // 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()) {
+ if (log)
+ log->Printf("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;
+ }
- // Save the original state of the exception ports for our child process.
- error = SaveExceptionPortInfo();
- if (error.Fail() || (m_exc_port_info.mask == 0))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): SaveExceptionPortInfo() "
- "failed, cannot install exception handler: %s",
- __FUNCTION__, 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()) {
+ if (log)
+ log->Printf("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;
+ }
- // 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())
- {
- if (log)
- log->Printf("::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;
- }
+ // Save the original state of the exception ports for our child process.
+ error = SaveExceptionPortInfo();
+ if (error.Fail() || (m_exc_port_info.mask == 0)) {
+ if (log)
+ log->Printf("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()) {
+ if (log)
+ log->Printf("::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())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to create Mach "
- "exception-handling thread: %u (%s)", __FUNCTION__,
- error.GetError(), error.AsCString());
- }
+ // Create the exception thread.
+ auto pthread_err =
+ ::pthread_create(&m_exception_thread, nullptr, ExceptionThread, this);
+ error.SetError(pthread_err, eErrorTypePOSIX);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): failed to create Mach "
+ "exception-handling thread: %u (%s)",
+ __FUNCTION__, error.GetError(), error.AsCString());
+ }
- return error;
+ return error;
}
lldb::addr_t
-NativeProcessDarwin::GetDYLDAllImageInfosAddress(Error &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;
+NativeProcessDarwin::GetDYLDAllImageInfosAddress(Error &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;
- }
+ 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;
+ // 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;
+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;
+ if (::sysctlnametomib("sysctl.proc_cputype", mib, &len))
+ return 0;
- mib[len] = pid;
- len++;
+ 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;
+ 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;
+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.
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
-
- std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
- if (log)
- log->Printf("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;
+task_t NativeProcessDarwin::ExceptionMessageBundleComplete() {
+ // We have a complete bundle of exceptions for our child process.
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
- // 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;
- Error 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)
- {
- if (log)
- log->Printf("exec: inferior task port changed "
- "from 0x%4.4x to 0x%4.4x", old_task,
- new_task);
- }
- }
- }
- else
- {
- if (log)
- log->Printf("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)
- {
- if (log)
- log->Printf("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();
+ std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): processing %lu exception "
+ "messages.",
+ __FUNCTION__, m_exception_messages.size());
- // TODO hook up breakpoints.
- // m_breakpoints.DisableAll();
- }
-
- if (m_sent_interrupt_signo != 0)
- {
- if (received_interrupt)
- {
- if (log)
- log->Printf("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;
- if (log)
- log->Printf("NativeProcessDarwin::%s(): auto "
- "resuming due to unhandled interrupt "
- "signal %i", __FUNCTION__,
- m_auto_resume_signo);
- }
- m_auto_resume_signo = 0;
- }
- }
- else
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): didn't get signal "
- "%i after MachProcess::Interrupt()",
- __FUNCTION__, m_sent_interrupt_signo);
+ 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;
+ Error 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) {
+ if (log)
+ log->Printf("exec: inferior task port changed "
+ "from 0x%4.4x to 0x%4.4x",
+ old_task, new_task);
}
+ }
+ } else {
+ if (log)
+ log->Printf("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;
+ }
}
- // 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 (m_did_exec) {
+ cpu_type_t process_cpu_type = GetCPUTypeForLocalProcess(m_pid);
+ if (m_cpu_type != process_cpu_type) {
+ if (log)
+ log->Printf("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) {
if (log)
- {
- StreamString stream;
- m_exception_messages[i].Dump(stream);
- stream.Flush();
- log->PutCString(stream.GetString().c_str());
+ log->Printf("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;
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): auto "
+ "resuming due to unhandled interrupt "
+ "signal %i",
+ __FUNCTION__, m_auto_resume_signo);
+ }
+ m_auto_resume_signo = 0;
}
+ } else {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): didn't get signal "
+ "%i after MachProcess::Interrupt()",
+ __FUNCTION__, m_sent_interrupt_signo);
+ }
}
-
- if (log)
- {
- StreamString stream;
- m_thread_list.Dump(stream);
- stream.Flush();
- log->PutCString(stream.GetString().c_str());
+ }
+
+ // 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);
}
- bool step_more = false;
- if (m_thread_list.ShouldStop(step_more) && (auto_resume == false))
- {
- // TODO - need to hook up event system here. !!!!
+ 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
@@ -990,836 +870,707 @@ NativeProcessDarwin::ExceptionMessageBundleComplete()
m_events.WaitForEventsToReset(eEventProcessRunningStateChanged,
&timeout);
#endif
- SetState(eStateStopped);
- }
- else
- {
- // Resume without checking our current state.
- PrivateResume();
- }
+ SetState(eStateStopped);
+ } else {
+ // Resume without checking our current state.
+ PrivateResume();
+ }
- return m_task;
+ return m_task;
}
-void
-NativeProcessDarwin::StartSTDIOThread()
-{
- // TODO implement
+void NativeProcessDarwin::StartSTDIOThread() {
+ // TODO implement
}
-Error
-NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop)
-{
- Error 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())
- {
- if (log)
- log->Printf("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 File(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())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to create waitpid "
- "handling thread: %u (%s)", __FUNCTION__,
- error.GetError(), error.AsCString());
- return error;
- }
-
+Error NativeProcessDarwin::StartWaitpidThread(MainLoop &main_loop) {
+ Error 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()) {
+ if (log)
+ log->Printf("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 File(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()) {
+ if (log)
+ log->Printf("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)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): cannot run waitpid "
- "thread, mandatory process arg was null", __FUNCTION__);
- return nullptr;
- }
+void *NativeProcessDarwin::WaitpidThread(void *arg) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (!arg) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): cannot run waitpid "
+ "thread, mandatory process arg was null",
+ __FUNCTION__);
+ return nullptr;
+ }
- return reinterpret_cast<NativeProcessDarwin*>(arg)->DoWaitpidThread();
+ 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);
- }
+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)
- {
- if (log)
- log->Printf("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();
-
- Error error;
- int status = -1;
+void *NativeProcessDarwin::DoWaitpidThread() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- 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.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %"
- PRIu64 ", &status, 0) interrupted, continuing",
- __FUNCTION__, m_pid);
- continue;
- }
-
- // This error is not okay, abort.
- if (log)
- log->Printf("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.
- if (log)
- log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
- ", &status, 0) => %i, status = %i", __FUNCTION__,
- m_pid, child_pid, status);
-
- // Handle the result.
- if (WIFSTOPPED(status))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
- ") received a stop, continuing waitpid() loop",
- __FUNCTION__, m_pid);
- continue;
- }
- else // if (WIFEXITED(status) || WIFSIGNALED(status))
- {
- if (log)
- log->Printf("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.
+ if (m_pid == LLDB_INVALID_PROCESS_ID) {
if (log)
- log->Printf("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);
+ log->Printf("NativeProcessDarwin::%s(): inferior process ID is "
+ "not set, cannot waitpid on it",
+ __FUNCTION__);
return nullptr;
-}
+ }
-Error
-NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid, int status)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Name the thread.
+ pthread_setname_np("waitpid thread");
- size_t bytes_written = 0;
+ // Ensure we don't get CPU starved.
+ MaybeRaiseThreadPriority();
- // Send the pid.
- error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written);
- if (error.Fail() || (bytes_written < sizeof(pid)))
- {
+ Error 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.
if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to write "
- "waitpid exiting pid to the pipe. Client will not "
- "hear about inferior exit status!",
- __FUNCTION__);
- return error;
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ", &status, 0) interrupted, continuing",
+ __FUNCTION__, m_pid);
+ continue;
+ }
+
+ // This error is not okay, abort.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ", &status, 0) aborting due to error: %u (%s)",
+ __FUNCTION__, m_pid, error.GetError(), error.AsCString());
+ break;
}
- // Send the status.
- bytes_written = 0;
- error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written);
- if (error.Fail() || (bytes_written < sizeof(status)))
+ // Log the successful result.
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ", &status, 0) => %i, status = %i",
+ __FUNCTION__, m_pid, child_pid, status);
+
+ // Handle the result.
+ if (WIFSTOPPED(status)) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): waitpid(pid = %" PRIu64
+ ") received a stop, continuing waitpid() loop",
+ __FUNCTION__, m_pid);
+ continue;
+ } else // if (WIFEXITED(status) || WIFSIGNALED(status))
{
- if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to write "
- "waitpid exit result to the pipe. Client will not "
- "hear about inferior exit status!",
- __FUNCTION__);
+ if (log)
+ log->Printf("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;
}
- return error;
+ }
+
+ // 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.
+ if (log)
+ log->Printf(
+ "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;
}
-Error
-NativeProcessDarwin::HandleWaitpidResult()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Read the pid.
- const bool notify_status = true;
+Error NativeProcessDarwin::SendInferiorExitStatusToMainLoop(::pid_t pid,
+ int status) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- ::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)))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to read "
- "waitpid exiting pid from the pipe. Will notify "
- "as if parent process died with exit status -1.",
- __FUNCTION__);
- SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
- notify_status);
- return error;
- }
+ size_t bytes_written = 0;
- // Read the status.
- int status = -1;
- error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read);
- if (error.Fail() || (bytes_read < sizeof(status)))
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s() - failed to read "
- "waitpid exit status from the pipe. Will notify "
- "as if parent process died with exit status -1.",
- __FUNCTION__);
- SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
- notify_status);
- return error;
- }
+ // Send the pid.
+ error = m_waitpid_pipe.Write(&pid, sizeof(pid), bytes_written);
+ if (error.Fail() || (bytes_written < sizeof(pid))) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() - failed to write "
+ "waitpid exiting pid to the pipe. Client will not "
+ "hear about inferior exit status!",
+ __FUNCTION__);
+ return error;
+ }
- // Notify the monitor that our state has changed.
+ // Send the status.
+ bytes_written = 0;
+ error = m_waitpid_pipe.Write(&status, sizeof(status), bytes_written);
+ if (error.Fail() || (bytes_written < sizeof(status))) {
if (log)
- log->Printf("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);
+ log->Printf("NativeProcessDarwin::%s() - failed to write "
+ "waitpid exit result to the pipe. Client will not "
+ "hear about inferior exit status!",
+ __FUNCTION__);
+ }
+ return error;
+}
- ExitType exit_type = eExitTypeInvalid;
- int exit_status = -1;
+Error NativeProcessDarwin::HandleWaitpidResult() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (WIFEXITED(status))
- {
- exit_type = eExitTypeExit;
- exit_status = WEXITSTATUS(status);
- }
- else if (WIFSIGNALED(status))
- {
- exit_type = eExitTypeSignal;
- exit_status = WTERMSIG(status);
- }
+ // 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))) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() - failed to read "
+ "waitpid exiting pid from the pipe. Will notify "
+ "as if parent process died with exit status -1.",
+ __FUNCTION__);
+ SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
+ notify_status);
+ return error;
+ }
- SetExitStatus(exit_type, exit_status, nullptr, notify_status);
+ // Read the status.
+ int status = -1;
+ error = m_waitpid_pipe.Read(&status, sizeof(status), bytes_read);
+ if (error.Fail() || (bytes_read < sizeof(status))) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() - failed to read "
+ "waitpid exit status from the pipe. Will notify "
+ "as if parent process died with exit status -1.",
+ __FUNCTION__);
+ SetExitStatus(eExitTypeInvalid, -1, "failed to receive waitpid result",
+ notify_status);
return error;
+ }
+
+ // Notify the monitor that our state has changed.
+ if (log)
+ log->Printf("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);
+
+ ExitType exit_type = eExitTypeInvalid;
+ int exit_status = -1;
+
+ if (WIFEXITED(status)) {
+ exit_type = eExitTypeExit;
+ exit_status = WEXITSTATUS(status);
+ } else if (WIFSIGNALED(status)) {
+ exit_type = eExitTypeSignal;
+ exit_status = WTERMSIG(status);
+ }
+
+ SetExitStatus(exit_type, exit_status, nullptr, notify_status);
+ return error;
}
-task_t
-NativeProcessDarwin::TaskPortForProcessID(Error &error, bool force) const
-{
- if ((m_task == TASK_NULL) || force)
- {
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (m_pid == LLDB_INVALID_PROCESS_ID)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): cannot get task due "
- "to invalid pid", __FUNCTION__);
- return TASK_NULL;
- }
+task_t NativeProcessDarwin::TaskPortForProcessID(Error &error,
+ bool force) const {
+ if ((m_task == TASK_NULL) || force) {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (m_pid == LLDB_INVALID_PROCESS_ID) {
+ if (log)
+ log->Printf("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;
- log->Printf("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)
- {
- log->Printf("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());
- }
- }
+ const uint32_t num_retries = 10;
+ const uint32_t usec_interval = 10000;
- // Sleep a bit and try again
- ::usleep (usec_interval);
+ 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;
+ log->Printf("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) {
+ log->Printf("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());
}
+ }
- // We failed to get the task for the inferior process.
- // Ensure that it is cleared out.
- m_task = TASK_NULL;
+ // Sleep a bit and try again
+ ::usleep(usec_interval);
}
- return m_task;
-}
-void
-NativeProcessDarwin::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
- Error &error)
-{
- error.SetErrorString("TODO: implement");
+ // We failed to get the task for the inferior process.
+ // Ensure that it is cleared out.
+ m_task = TASK_NULL;
+ }
+ return m_task;
}
-Error
-NativeProcessDarwin::PrivateResume()
-{
- Error 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)
- log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming (with "
- "unhandled interrupt signal %i)...", __FUNCTION__,
- m_task, m_auto_resume_signo);
- else
- log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming...",
- __FUNCTION__, m_task);
- }
+void NativeProcessDarwin::AttachToInferior(MainLoop &mainloop, lldb::pid_t pid,
+ Error &error) {
+ error.SetErrorString("TODO: implement");
+}
- error = ReplyToAllExceptions();
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): aborting, failed to "
- "reply to exceptions: %s", __FUNCTION__,
- error.AsCString());
- return error;
- }
- // bool stepOverBreakInstruction = step;
+Error NativeProcessDarwin::PrivateResume() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- // 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);
+ std::lock_guard<std::recursive_mutex> locker(m_exception_messages_mutex);
+ m_auto_resume_signo = m_sent_interrupt_signo;
- // Set our state accordingly
- if (m_thread_actions.NumActionsWithState(eStateStepping))
- SetState(eStateStepping);
+ if (log) {
+ if (m_auto_resume_signo)
+ log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming (with "
+ "unhandled interrupt signal %i)...",
+ __FUNCTION__, m_task, m_auto_resume_signo);
else
- SetState(eStateRunning);
+ log->Printf("NativeProcessDarwin::%s(): task 0x%x resuming...",
+ __FUNCTION__, m_task);
+ }
- // Now resume our task.
- error = ResumeTask();
+ error = ReplyToAllExceptions();
+ if (error.Fail()) {
+ if (log)
+ log->Printf("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;
}
-Error
-NativeProcessDarwin::ReplyToAllExceptions()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS |
- LIBLLDB_LOG_VERBOSE));
+Error NativeProcessDarwin::ReplyToAllExceptions() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE));
- TaskPortForProcessID(error);
- if (error.Fail())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): no task port, aborting",
- __FUNCTION__);
- return error;
- }
+ TaskPortForProcessID(error);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("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;
+ 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) {
+ log->Printf("NativeProcessDarwin::%s(): replying to exception "
+ "%zu...",
+ __FUNCTION__, index++);
}
- size_t index = 0;
- for (auto &message : m_exception_messages)
- {
- if (log)
- {
- log->Printf("NativeProcessDarwin::%s(): replying to exception "
- "%zu...", __FUNCTION__, index++);
- }
-
- int thread_reply_signal = 0;
+ 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);
+ 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);
- }
+ 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.
- log->Printf("NativeProcessDarwin::%s(): failed to reply to "
- "exception: %s", __FUNCTION__, error.AsCString());
- error.Clear();
- }
+ 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.
+ log->Printf("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;
+ // Erase all exception message as we should have used and replied
+ // to them all already.
+ m_exception_messages.clear();
+ return error;
}
-Error
-NativeProcessDarwin::ResumeTask()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- TaskPortForProcessID(error);
- if (error.Fail())
- {
- if (log)
- log->Printf("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;
- }
+Error NativeProcessDarwin::ResumeTask() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ TaskPortForProcessID(error);
+ if (error.Fail()) {
if (log)
- log->Printf("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())
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): failed to get task "
- "BasicInfo when attempting to resume: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
+ log->Printf("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;
+ }
+
+ if (log)
+ log->Printf("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()) {
+ if (log)
+ log->Printf("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())
- log->Printf("::task_resume(target_task = 0x%4.4x): success",
- m_task);
- else
- log->Printf("::task_resume(target_task = 0x%4.4x) error: %s",
- m_task, error.AsCString());
- }
- }
- else
- {
- if (log)
- log->Printf("::task_resume(target_task = 0x%4.4x): ignored, "
- "already running", m_task);
+ // 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())
+ log->Printf("::task_resume(target_task = 0x%4.4x): success", m_task);
+ else
+ log->Printf("::task_resume(target_task = 0x%4.4x) error: %s", m_task,
+ error.AsCString());
}
+ } else {
+ if (log)
+ log->Printf("::task_resume(target_task = 0x%4.4x): ignored, "
+ "already running",
+ m_task);
+ }
- return error;
+ return error;
}
-bool
-NativeProcessDarwin::IsTaskValid() const
-{
- if (m_task == TASK_NULL)
- return false;
+bool NativeProcessDarwin::IsTaskValid() const {
+ if (m_task == TASK_NULL)
+ return false;
- struct task_basic_info task_info;
- return GetTaskBasicInfo(m_task, &task_info).Success();
+ 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;
+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();
+ struct task_basic_info task_info;
+ return GetTaskBasicInfo(task, &task_info).Success();
}
-mach_port_t
-NativeProcessDarwin::GetExceptionPort() const
-{
- return m_exception_port;
+mach_port_t NativeProcessDarwin::GetExceptionPort() const {
+ return m_exception_port;
}
-bool
-NativeProcessDarwin::IsExceptionPortValid () const
-{
- return MACH_PORT_VALID(m_exception_port);
+bool NativeProcessDarwin::IsExceptionPortValid() const {
+ return MACH_PORT_VALID(m_exception_port);
}
-Error
-NativeProcessDarwin::GetTaskBasicInfo(task_t task,
- struct task_basic_info *info) const
-{
- Error 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())
- {
- if (log)
- log->Printf("::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;
- }
+Error NativeProcessDarwin::GetTaskBasicInfo(
+ task_t task, struct task_basic_info *info) const {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- 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_log->Printf("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);
- }
+ // 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()) {
+ if (log)
+ log->Printf("::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_log->Printf("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;
}
-Error
-NativeProcessDarwin::SuspendTask()
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (m_task == TASK_NULL)
- {
- error.SetErrorString("task port is null, cannot suspend task");
- if (log)
- log->Printf("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)
- log->Printf("::task_suspend(target_task = 0x%4.4x)", m_task);
+Error NativeProcessDarwin::SuspendTask() {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (m_task == TASK_NULL) {
+ error.SetErrorString("task port is null, cannot suspend task");
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() failed: %s", __FUNCTION__,
+ error.AsCString());
return error;
-}
+ }
-Error
-NativeProcessDarwin::Resume(const ResumeActionList &resume_actions)
-{
- Error error;
- Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
+ auto mach_err = ::task_suspend(m_task);
+ error.SetError(mach_err, eErrorTypeMachKernel);
+ if (error.Fail() && log)
+ log->Printf("::task_suspend(target_task = 0x%4.4x)", m_task);
- if (log)
- log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
+ return error;
+}
- if (CanResume())
- {
- m_thread_actions = resume_actions;
- error = PrivateResume();
- return error;
- }
+Error NativeProcessDarwin::Resume(const ResumeActionList &resume_actions) {
+ Error error;
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
- auto state = GetState();
- if (state == eStateRunning)
- {
- if (log)
- log->Printf("NativeProcessDarwin::%s(): task 0x%x is already "
- "running, ignoring...", __FUNCTION__,
- TaskPortForProcessID(error));
- return error;
- }
+ if (log)
+ log->Printf("NativeProcessDarwin::%s() called", __FUNCTION__);
- // We can't resume from this state.
- error.SetErrorStringWithFormat("task 0x%x has state %s, can't resume",
- TaskPortForProcessID(error),
- StateAsCString(state));
+ if (CanResume()) {
+ m_thread_actions = resume_actions;
+ error = PrivateResume();
return error;
-}
+ }
-Error
-NativeProcessDarwin::Halt()
-{
- Error error;
- error.SetErrorString("TODO: implement");
+ auto state = GetState();
+ if (state == eStateRunning) {
+ if (log)
+ log->Printf("NativeProcessDarwin::%s(): task 0x%x is already "
+ "running, ignoring...",
+ __FUNCTION__, TaskPortForProcessID(error));
return error;
-}
+ }
-Error
-NativeProcessDarwin::Detach()
-{
- Error error;
- error.SetErrorString("TODO: implement");
- 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;
}
-Error
-NativeProcessDarwin::Signal(int signo)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Halt() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::Interrupt()
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Detach() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::Kill()
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Signal(int signo) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::GetMemoryRegionInfo(lldb::addr_t load_addr,
- MemoryRegionInfo &range_info)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Interrupt() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
- size_t &bytes_read)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::Kill() {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
- size_t size, size_t &bytes_read)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &range_info) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::WriteMemory(lldb::addr_t addr, const void *buf,
- size_t size, size_t &bytes_written)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::ReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ size_t &bytes_read) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::AllocateMemory(size_t size, uint32_t permissions,
- lldb::addr_t &addr)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::ReadMemoryWithoutTrap(lldb::addr_t addr, void *buf,
+ size_t size,
+ size_t &bytes_read) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::DeallocateMemory(lldb::addr_t addr)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::WriteMemory(lldb::addr_t addr, const void *buf,
+ size_t size, size_t &bytes_written) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-lldb::addr_t
-NativeProcessDarwin::GetSharedLibraryInfoAddress()
-{
- return LLDB_INVALID_ADDRESS;
+Error NativeProcessDarwin::AllocateMemory(size_t size, uint32_t permissions,
+ lldb::addr_t &addr) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-size_t
-NativeProcessDarwin::UpdateThreads()
-{
- return 0;
+Error NativeProcessDarwin::DeallocateMemory(lldb::addr_t addr) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-bool
-NativeProcessDarwin::GetArchitecture(ArchSpec &arch) const
-{
- return false;
+lldb::addr_t NativeProcessDarwin::GetSharedLibraryInfoAddress() {
+ return LLDB_INVALID_ADDRESS;
}
-Error
-NativeProcessDarwin::SetBreakpoint(lldb::addr_t addr, uint32_t size,
- bool hardware)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+size_t NativeProcessDarwin::UpdateThreads() { return 0; }
+
+bool NativeProcessDarwin::GetArchitecture(ArchSpec &arch) const {
+ return false;
}
-void
-NativeProcessDarwin::DoStopIDBumped(uint32_t newBumpId)
-{
+Error NativeProcessDarwin::SetBreakpoint(lldb::addr_t addr, uint32_t size,
+ bool hardware) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::GetLoadedModuleFileSpec(const char* module_path,
- FileSpec& file_spec)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+void NativeProcessDarwin::DoStopIDBumped(uint32_t newBumpId) {}
+
+Error NativeProcessDarwin::GetLoadedModuleFileSpec(const char *module_path,
+ FileSpec &file_spec) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
-Error
-NativeProcessDarwin::GetFileLoadAddress(const llvm::StringRef& file_name,
- lldb::addr_t& load_addr)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::GetFileLoadAddress(const llvm::StringRef &file_name,
+ lldb::addr_t &load_addr) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
// -----------------------------------------------------------------
// NativeProcessProtocol protected interface
// -----------------------------------------------------------------
-Error
-NativeProcessDarwin::GetSoftwareBreakpointTrapOpcode(size_t
- trap_opcode_size_hint,
- size_t &actual_opcode_size,
- const uint8_t
- *&trap_opcode_bytes)
-{
- Error error;
- error.SetErrorString("TODO: implement");
- return error;
+Error NativeProcessDarwin::GetSoftwareBreakpointTrapOpcode(
+ size_t trap_opcode_size_hint, size_t &actual_opcode_size,
+ const uint8_t *&trap_opcode_bytes) {
+ Error error;
+ error.SetErrorString("TODO: implement");
+ return error;
}
OpenPOWER on IntegriCloud