summaryrefslogtreecommitdiff
path: root/source/Plugins/Process/FreeBSD
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/Process/FreeBSD')
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.cpp69
-rw-r--r--source/Plugins/Process/FreeBSD/FreeBSDThread.h39
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp145
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessFreeBSD.h21
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.cpp102
-rw-r--r--source/Plugins/Process/FreeBSD/ProcessMonitor.h24
6 files changed, 344 insertions, 56 deletions
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
new file mode 100644
index 0000000000000..493f36ca8b48e
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.cpp
@@ -0,0 +1,69 @@
+//===-- FreeBSDThread.cpp ---------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+#include "lldb/Core/State.h"
+
+// Project includes
+#include "FreeBSDThread.h"
+#include "ProcessFreeBSD.h"
+#include "ProcessPOSIXLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+//------------------------------------------------------------------------------
+// Constructors and destructors.
+
+FreeBSDThread::FreeBSDThread(Process &process, lldb::tid_t tid)
+ : POSIXThread(process, tid)
+{
+}
+
+FreeBSDThread::~FreeBSDThread()
+{
+}
+
+//------------------------------------------------------------------------------
+// ProcessInterface protocol.
+
+void
+FreeBSDThread::WillResume(lldb::StateType resume_state)
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
+ if (log)
+ log->Printf("tid %lu resume_state = %s", GetID(),
+ lldb_private::StateAsCString(resume_state));
+ ProcessSP process_sp(GetProcess());
+ ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(process_sp.get());
+ int signo = GetResumeSignal();
+ bool signo_valid = process->GetUnixSignals().SignalIsValid(signo);
+
+ switch (resume_state)
+ {
+ case eStateSuspended:
+ case eStateStopped:
+ process->m_suspend_tids.push_back(GetID());
+ break;
+ case eStateRunning:
+ process->m_run_tids.push_back(GetID());
+ if (signo_valid)
+ process->m_resume_signo = signo;
+ break;
+ case eStateStepping:
+ process->m_step_tids.push_back(GetID());
+ if (signo_valid)
+ process->m_resume_signo = signo;
+ break;
+ default:
+ break;
+ }
+}
diff --git a/source/Plugins/Process/FreeBSD/FreeBSDThread.h b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
new file mode 100644
index 0000000000000..8741075cb60be
--- /dev/null
+++ b/source/Plugins/Process/FreeBSD/FreeBSDThread.h
@@ -0,0 +1,39 @@
+//===-- FreeBSDThread.h -----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_FreeBSDThread_H_
+#define liblldb_FreeBSDThread_H_
+
+// Other libraries and framework includes
+#include "POSIXThread.h"
+
+//------------------------------------------------------------------------------
+// @class FreeBSDThread
+// @brief Abstraction of a FreeBSD thread.
+class FreeBSDThread
+ : public POSIXThread
+{
+public:
+
+ //------------------------------------------------------------------
+ // Constructors and destructors
+ //------------------------------------------------------------------
+ FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);
+
+ virtual ~FreeBSDThread();
+
+ //--------------------------------------------------------------------------
+ // FreeBSDThread internal API.
+
+ // POSIXThread override
+ virtual void
+ WillResume(lldb::StateType resume_state);
+};
+
+#endif // #ifndef liblldb_FreeBSDThread_H_
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
index 952ec95f5873e..083f08ebba842 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp
@@ -23,7 +23,7 @@
#include "ProcessPOSIXLog.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "ProcessMonitor.h"
-#include "POSIXThread.h"
+#include "FreeBSDThread.h"
using namespace lldb;
using namespace lldb_private;
@@ -140,29 +140,136 @@ ProcessFreeBSD::DoDetach(bool keep_stopped)
return error;
}
+Error
+ProcessFreeBSD::DoResume()
+{
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+
+ // FreeBSD's ptrace() uses 0 to indicate "no signal is to be sent."
+ int resume_signal = 0;
+
+ SetPrivateState(eStateRunning);
+
+ Mutex::Locker lock(m_thread_list.GetMutex());
+ bool do_step = false;
+
+ for (tid_collection::const_iterator t_pos = m_run_tids.begin(), t_end = m_run_tids.end(); t_pos != t_end; ++t_pos)
+ {
+ m_monitor->ThreadSuspend(*t_pos, false);
+ }
+ for (tid_collection::const_iterator t_pos = m_step_tids.begin(), t_end = m_step_tids.end(); t_pos != t_end; ++t_pos)
+ {
+ m_monitor->ThreadSuspend(*t_pos, false);
+ do_step = true;
+ }
+ for (tid_collection::const_iterator t_pos = m_suspend_tids.begin(), t_end = m_suspend_tids.end(); t_pos != t_end; ++t_pos)
+ {
+ m_monitor->ThreadSuspend(*t_pos, true);
+ // XXX Cannot PT_CONTINUE properly with suspended threads.
+ do_step = true;
+ }
+
+ if (log)
+ log->Printf("process %lu resuming (%s)", GetID(), do_step ? "step" : "continue");
+ if (do_step)
+ m_monitor->SingleStep(GetID(), resume_signal);
+ else
+ m_monitor->Resume(GetID(), resume_signal);
+
+ return Error();
+}
+
bool
ProcessFreeBSD::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list)
{
- Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD));
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessFreeBSD::%s() (pid = %" PRIu64 ")", __FUNCTION__, GetID());
-
- bool has_updated = false;
- const lldb::pid_t pid = GetID();
- // Update the process thread list with this new thread.
- // FIXME: We should be using tid, not pid.
- assert(m_monitor);
- ThreadSP thread_sp (old_thread_list.FindThreadByID (pid, false));
- if (!thread_sp) {
- ProcessSP me = this->shared_from_this();
- thread_sp.reset(new POSIXThread(*me, pid));
- has_updated = true;
+ Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessFreeBSD::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
+
+ std::vector<lldb::pid_t> tds;
+ if (!GetMonitor().GetCurrentThreadIDs(tds))
+ {
+ return false;
}
- if (log && log->GetMask().Test(POSIX_LOG_VERBOSE))
- log->Printf ("ProcessFreeBSD::%s() updated tid = %" PRIu64, __FUNCTION__, pid);
+ ThreadList old_thread_list_copy(old_thread_list);
+ for (size_t i = 0; i < tds.size(); ++i)
+ {
+ tid_t tid = tds[i];
+ ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByID(tid, false));
+ if (!thread_sp)
+ {
+ thread_sp.reset(new FreeBSDThread(*this, tid));
+ if (log)
+ log->Printf("ProcessFreeBSD::%s new tid = %" PRIu64, __FUNCTION__, tid);
+ }
+ else
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::%s existing tid = %" PRIu64, __FUNCTION__, tid);
+ }
+ new_thread_list.AddThread(thread_sp);
+ }
+ for (size_t i = 0; i < old_thread_list_copy.GetSize(false); ++i)
+ {
+ ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
+ if (old_thread_sp)
+ {
+ if (log)
+ log->Printf("ProcessFreeBSD::%s remove tid", __FUNCTION__);
+ }
+ }
- new_thread_list.AddThread(thread_sp);
+ return true;
+}
- return has_updated; // the list has been updated
+Error
+ProcessFreeBSD::WillResume()
+{
+ m_suspend_tids.clear();
+ m_run_tids.clear();
+ m_step_tids.clear();
+ return ProcessPOSIX::WillResume();
}
+
+void
+ProcessFreeBSD::SendMessage(const ProcessMessage &message)
+{
+ Mutex::Locker lock(m_message_mutex);
+
+ switch (message.GetKind())
+ {
+ case ProcessMessage::eInvalidMessage:
+ return;
+
+ case ProcessMessage::eAttachMessage:
+ SetPrivateState(eStateStopped);
+ return;
+
+ case ProcessMessage::eLimboMessage:
+ case ProcessMessage::eExitMessage:
+ m_exit_status = message.GetExitStatus();
+ SetExitStatus(m_exit_status, NULL);
+ break;
+
+ case ProcessMessage::eSignalMessage:
+ case ProcessMessage::eSignalDeliveredMessage:
+ case ProcessMessage::eBreakpointMessage:
+ case ProcessMessage::eTraceMessage:
+ case ProcessMessage::eWatchpointMessage:
+ case ProcessMessage::eCrashMessage:
+ SetPrivateState(eStateStopped);
+ break;
+
+ case ProcessMessage::eNewThreadMessage:
+ assert(0 && "eNewThreadMessage unexpected on FreeBSD");
+ break;
+
+ case ProcessMessage::eExecMessage:
+ SetPrivateState(eStateStopped);
+ break;
+ }
+
+ m_message_queue.push(message);
+}
+
diff --git a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
index fb549745b80c6..d6ae3462c73b1 100644
--- a/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
+++ b/source/Plugins/Process/FreeBSD/ProcessFreeBSD.h
@@ -60,6 +60,15 @@ public:
virtual bool
UpdateThreadList(lldb_private::ThreadList &old_thread_list, lldb_private::ThreadList &new_thread_list);
+ virtual lldb_private::Error
+ DoResume();
+
+ virtual lldb_private::Error
+ WillResume();
+
+ virtual void
+ SendMessage(const ProcessMessage &message);
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
@@ -80,6 +89,16 @@ public:
EnablePluginLogging(lldb_private::Stream *strm,
lldb_private::Args &command);
+protected:
+ friend class FreeBSDThread;
+
+ typedef std::vector<lldb::tid_t> tid_collection;
+ tid_collection m_suspend_tids;
+ tid_collection m_run_tids;
+ tid_collection m_step_tids;
+
+ int m_resume_signo;
+
};
-#endif // liblldb_MacOSXProcess_H_
+#endif // liblldb_ProcessFreeBSD_H_
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index ac5357916501e..3b260538b1907 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -560,6 +560,31 @@ LwpInfoOperation::Execute(ProcessMonitor *monitor)
}
//------------------------------------------------------------------------------
+/// @class ThreadSuspendOperation
+/// @brief Implements ProcessMonitor::ThreadSuspend.
+class ThreadSuspendOperation : public Operation
+{
+public:
+ ThreadSuspendOperation(lldb::tid_t tid, bool suspend, bool &result)
+ : m_tid(tid), m_suspend(suspend), m_result(result) { }
+
+ void Execute(ProcessMonitor *monitor);
+
+private:
+ lldb::tid_t m_tid;
+ bool m_suspend;
+ bool &m_result;
+} ;
+
+void
+ThreadSuspendOperation::Execute(ProcessMonitor *monitor)
+{
+ m_result = !PTRACE(m_suspend ? PT_SUSPEND : PT_RESUME, m_tid, NULL, 0);
+}
+
+
+
+//------------------------------------------------------------------------------
/// @class EventMessageOperation
/// @brief Implements ProcessMonitor::GetEventMessage.
class EventMessageOperation : public Operation
@@ -871,7 +896,8 @@ ProcessMonitor::Launch(LaunchArgs *args)
eDupStdoutFailed,
eDupStderrFailed,
eChdirFailed,
- eExecFailed
+ eExecFailed,
+ eSetGidFailed
};
// Child process.
@@ -882,7 +908,8 @@ ProcessMonitor::Launch(LaunchArgs *args)
exit(ePtraceFailed);
// Do not inherit setgid powers.
- setgid(getgid());
+ if (setgid(getgid()) != 0)
+ exit(eSetGidFailed);
// Let us have our own process group.
setpgid(0, 0);
@@ -947,6 +974,9 @@ ProcessMonitor::Launch(LaunchArgs *args)
case eExecFailed:
args->m_error.SetErrorString("Child exec failed.");
break;
+ case eSetGidFailed:
+ args->m_error.SetErrorString("Child setgid failed.");
+ break;
default:
args->m_error.SetErrorString("Child returned unknown exit status.");
break;
@@ -1041,6 +1071,29 @@ FINISH:
return args->m_error.Success();
}
+size_t
+ProcessMonitor::GetCurrentThreadIDs(std::vector<lldb::tid_t>&thread_ids)
+{
+ lwpid_t *tids;
+ int tdcnt;
+
+ thread_ids.clear();
+
+ tdcnt = PTRACE(PT_GETNUMLWPS, m_pid, NULL, 0);
+ if (tdcnt <= 0)
+ return 0;
+ tids = (lwpid_t *)malloc(tdcnt * sizeof(*tids));
+ if (tids == NULL)
+ return 0;
+ if (PTRACE(PT_GETLWPLIST, m_pid, (void *)tids, tdcnt) < 0) {
+ free(tids);
+ return 0;
+ }
+ thread_ids = std::vector<lldb::tid_t>(tids, tids + tdcnt);
+ free(tids);
+ return thread_ids.size();
+}
+
bool
ProcessMonitor::MonitorCallback(void *callback_baton,
lldb::pid_t pid,
@@ -1073,11 +1126,11 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
switch (plwp.pl_siginfo.si_signo)
{
case SIGTRAP:
- message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, pid);
+ message = MonitorSIGTRAP(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
break;
default:
- message = MonitorSignal(monitor, &plwp.pl_siginfo, pid);
+ message = MonitorSignal(monitor, &plwp.pl_siginfo, plwp.pl_lwpid);
break;
}
@@ -1090,7 +1143,7 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
ProcessMessage
ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid)
+ const siginfo_t *info, lldb::tid_t tid)
{
ProcessMessage message;
@@ -1111,26 +1164,26 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
// state of "limbo" until we are explicitly commanded to detach,
// destroy, resume, etc.
unsigned long data = 0;
- if (!monitor->GetEventMessage(pid, &data))
+ if (!monitor->GetEventMessage(tid, &data))
data = -1;
if (log)
- log->Printf ("ProcessMonitor::%s() received exit? event, data = %lx, pid = %" PRIu64, __FUNCTION__, data, pid);
- message = ProcessMessage::Limbo(pid, (data >> 8));
+ log->Printf ("ProcessMonitor::%s() received exit? event, data = %lx, tid = %" PRIu64, __FUNCTION__, data, tid);
+ message = ProcessMessage::Limbo(tid, (data >> 8));
break;
}
case 0:
case TRAP_TRACE:
if (log)
- log->Printf ("ProcessMonitor::%s() received trace event, pid = %" PRIu64, __FUNCTION__, pid);
- message = ProcessMessage::Trace(pid);
+ log->Printf ("ProcessMonitor::%s() received trace event, tid = %" PRIu64, __FUNCTION__, tid);
+ message = ProcessMessage::Trace(tid);
break;
case SI_KERNEL:
case TRAP_BRKPT:
if (log)
- log->Printf ("ProcessMonitor::%s() received breakpoint event, pid = %" PRIu64, __FUNCTION__, pid);
- message = ProcessMessage::Break(pid);
+ log->Printf ("ProcessMonitor::%s() received breakpoint event, tid = %" PRIu64, __FUNCTION__, tid);
+ message = ProcessMessage::Break(tid);
break;
}
@@ -1139,7 +1192,7 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
ProcessMessage
ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
- const siginfo_t *info, lldb::pid_t pid)
+ const siginfo_t *info, lldb::tid_t tid)
{
ProcessMessage message;
int signo = info->si_signo;
@@ -1163,9 +1216,9 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
"SI_USER",
info->si_pid);
if (info->si_pid == getpid())
- return ProcessMessage::SignalDelivered(pid, signo);
+ return ProcessMessage::SignalDelivered(tid, signo);
else
- return ProcessMessage::Signal(pid, signo);
+ return ProcessMessage::Signal(tid, signo);
}
if (log)
@@ -1174,30 +1227,30 @@ ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
if (signo == SIGSEGV) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGSEGV(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
if (signo == SIGILL) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGILL(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
if (signo == SIGFPE) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGFPE(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
if (signo == SIGBUS) {
lldb::addr_t fault_addr = reinterpret_cast<lldb::addr_t>(info->si_addr);
ProcessMessage::CrashReason reason = GetCrashReasonForSIGBUS(info);
- return ProcessMessage::Crash(pid, reason, signo, fault_addr);
+ return ProcessMessage::Crash(tid, reason, signo, fault_addr);
}
// Everything else is "normal" and does not require any special action on
// our part.
- return ProcessMessage::Signal(pid, signo);
+ return ProcessMessage::Signal(tid, signo);
}
ProcessMessage::CrashReason
@@ -1508,6 +1561,15 @@ ProcessMonitor::GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &ptrace_err)
}
bool
+ProcessMonitor::ThreadSuspend(lldb::tid_t tid, bool suspend)
+{
+ bool result;
+ ThreadSuspendOperation op(tid, suspend, result);
+ DoOperation(&op);
+ return result;
+}
+
+bool
ProcessMonitor::GetEventMessage(lldb::tid_t tid, unsigned long *message)
{
bool result;
diff --git a/source/Plugins/Process/FreeBSD/ProcessMonitor.h b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
index 44219c4eb9e3e..84bbac16e5e5b 100644
--- a/source/Plugins/Process/FreeBSD/ProcessMonitor.h
+++ b/source/Plugins/Process/FreeBSD/ProcessMonitor.h
@@ -104,8 +104,6 @@ public:
/// dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
unsigned size, lldb_private::RegisterValue &value);
@@ -114,49 +112,35 @@ public:
/// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
const lldb_private::RegisterValue &value);
/// Reads all general purpose registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Reads all floating point registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Reads the specified register set into the specified buffer.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
/// Writes all general purpose registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Writes all floating point registers into the specified buffer.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Writes the specified register set into the specified buffer.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
- /// FIXME: The FreeBSD implementation of this function should use tid in order
- /// to enable support for debugging threaded programs.
bool
WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
@@ -164,11 +148,19 @@ public:
bool
ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
+ /// Returns current thread IDs in process
+ size_t
+ GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids);
+
/// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
/// to the memory region pointed to by @p lwpinfo.
bool
GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no);
+ /// Suspends or unsuspends a thread prior to process resume or step.
+ bool
+ ThreadSuspend(lldb::tid_t tid, bool suspend);
+
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
/// corresponding to the given thread IDto the memory pointed to by @p
/// message.