diff options
author | Ed Maste <emaste@FreeBSD.org> | 2014-02-18 16:23:10 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2014-02-18 16:23:10 +0000 |
commit | 866dcdacfe59f5f448e008fe2c4cb9dfcf72b2ec (patch) | |
tree | 95cb16075f0af1b3a05b9b84eb18dda8e6c903e9 /source/Plugins/Process/FreeBSD | |
parent | de889deb2c386f2a7831befaf226e5c86685fa53 (diff) |
Notes
Diffstat (limited to 'source/Plugins/Process/FreeBSD')
-rw-r--r-- | source/Plugins/Process/FreeBSD/FreeBSDThread.cpp | 69 | ||||
-rw-r--r-- | source/Plugins/Process/FreeBSD/FreeBSDThread.h | 39 | ||||
-rw-r--r-- | source/Plugins/Process/FreeBSD/ProcessFreeBSD.cpp | 145 | ||||
-rw-r--r-- | source/Plugins/Process/FreeBSD/ProcessFreeBSD.h | 21 | ||||
-rw-r--r-- | source/Plugins/Process/FreeBSD/ProcessMonitor.cpp | 102 | ||||
-rw-r--r-- | source/Plugins/Process/FreeBSD/ProcessMonitor.h | 24 |
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. |