diff options
| author | Matt Kopec <Matt.Kopec@intel.com> | 2013-01-08 16:30:18 +0000 |
|---|---|---|
| committer | Matt Kopec <Matt.Kopec@intel.com> | 2013-01-08 16:30:18 +0000 |
| commit | 650648fa57368241964a576a696bf38851771f21 (patch) | |
| tree | 80cf404e5f547f3a1b933ca56ea7e642baa7770c | |
| parent | 08e2394dfd5a258cd3b4bcec12c82799f4b6e8b4 (diff) | |
| download | bcm5719-llvm-650648fa57368241964a576a696bf38851771f21.tar.gz bcm5719-llvm-650648fa57368241964a576a696bf38851771f21.zip | |
Add initial support to trace spawned threads in a process on Linux.
llvm-svn: 171864
| -rw-r--r-- | lldb/source/Host/common/Host.cpp | 19 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/ProcessLinux.cpp | 17 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp | 19 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp | 29 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h | 28 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/POSIXThread.cpp | 10 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/POSIXThread.h | 1 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp | 3 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessMessage.h | 25 | ||||
| -rw-r--r-- | lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp | 23 |
10 files changed, 146 insertions, 28 deletions
diff --git a/lldb/source/Host/common/Host.cpp b/lldb/source/Host/common/Host.cpp index 0763cee9395..738a4adcdd8 100644 --- a/lldb/source/Host/common/Host.cpp +++ b/lldb/source/Host/common/Host.cpp @@ -147,7 +147,8 @@ MonitorChildProcessThreadFunction (void *arg) delete info; int status = -1; - const int options = 0; + const int options = __WALL; + while (1) { log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS); @@ -156,7 +157,8 @@ MonitorChildProcessThreadFunction (void *arg) // Wait for all child processes ::pthread_testcancel (); - const lldb::pid_t wait_pid = ::waitpid (pid, &status, options); + // Get signals from all children with same process group of pid + const lldb::pid_t wait_pid = ::waitpid (-1*pid, &status, options); ::pthread_testcancel (); if (wait_pid == -1) @@ -166,7 +168,7 @@ MonitorChildProcessThreadFunction (void *arg) else break; } - else if (wait_pid == pid) + else if (wait_pid > 0) { bool exited = false; int signal = 0; @@ -181,14 +183,17 @@ MonitorChildProcessThreadFunction (void *arg) { exit_status = WEXITSTATUS(status); status_cstr = "EXITED"; - exited = true; + if (wait_pid == pid) + exited = true; } else if (WIFSIGNALED(status)) { signal = WTERMSIG(status); status_cstr = "SIGNALED"; - exited = true; - exit_status = -1; + if (wait_pid == pid) { + exited = true; + exit_status = -1; + } } else { @@ -215,7 +220,7 @@ MonitorChildProcessThreadFunction (void *arg) { bool callback_return = false; if (callback) - callback_return = callback (callback_baton, pid, exited, signal, exit_status); + callback_return = callback (callback_baton, wait_pid, exited, signal, exit_status); // If our process exited, then this thread should exit if (exited) diff --git a/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp index 6a766d7ceb1..6118a0976f7 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/ProcessLinux.cpp @@ -97,22 +97,7 @@ ProcessLinux::GetPluginDescriptionStatic() bool ProcessLinux::UpdateThreadList(ThreadList &old_thread_list, ThreadList &new_thread_list) { - LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_THREAD)); - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s() (pid = %" PRIu64 ")", __FUNCTION__, 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 (GetID(), false)); - if (!thread_sp) { - thread_sp.reset(new POSIXThread(*this, GetID())); - } - - if (log && log->GetMask().Test(POSIX_LOG_VERBOSE)) - log->Printf ("ProcessLinux::%s() updated pid = %" PRIu64, __FUNCTION__, GetID()); - new_thread_list.AddThread(thread_sp); - + new_thread_list = old_thread_list; return new_thread_list.GetSize(false) > 0; } diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp index b71f0f94469..f36a9eef732 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp +++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp @@ -985,6 +985,7 @@ ProcessMonitor::Launch(LaunchArgs *args) const size_t err_len = 1024; char err_str[err_len]; lldb::pid_t pid; + long ptrace_opts = 0; lldb::ThreadSP inferior; LogSP log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); @@ -1102,7 +1103,12 @@ ProcessMonitor::Launch(LaunchArgs *args) // Have the child raise an event on exit. This is used to keep the child in // limbo until it is destroyed. - if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)PTRACE_O_TRACEEXIT) < 0) + ptrace_opts |= PTRACE_O_TRACEEXIT; + + // Have the tracer trace threads which spawn in the inferior process. + ptrace_opts |= PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACECLONE; + + if (PTRACE(PTRACE_SETOPTIONS, pid, NULL, (void*)ptrace_opts) < 0) { args->m_error.SetErrorToErrno(); goto FINISH; @@ -1282,6 +1288,17 @@ ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, assert(false && "Unexpected SIGTRAP code!"); break; + case (SIGTRAP | (PTRACE_EVENT_FORK << 8)): + case (SIGTRAP | (PTRACE_EVENT_VFORK << 8)): + case (SIGTRAP | (PTRACE_EVENT_CLONE << 8)): + { + unsigned long tid = 0; + if (!monitor->GetEventMessage(pid, &tid)) + tid = -1; + message = ProcessMessage::NewThread(pid, tid); + break; + } + case (SIGTRAP | (PTRACE_EVENT_EXIT << 8)): { // The inferior process is about to exit. Maintain the process in a diff --git a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp index 3dd3c869884..b9765b6997c 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp +++ b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.cpp @@ -58,3 +58,32 @@ POSIXCrashStopInfo::GetDescription() { return ProcessMessage::GetCrashReasonString(m_crash_reason); } + +//===----------------------------------------------------------------------===// +// POSIXNewThreadStopInfo + +POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() { } + +lldb::StopReason +POSIXNewThreadStopInfo::GetStopReason() const +{ + return lldb::eStopReasonNone; +} + +const char * +POSIXNewThreadStopInfo::GetDescription() +{ + return "thread spawned"; +} + +bool +POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr) +{ + return false; +} + +bool +POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr) +{ + return false; +} diff --git a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h index c510377f462..7c5be3dc615 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h +++ b/lldb/source/Plugins/Process/POSIX/POSIXStopInfo.h @@ -89,4 +89,32 @@ private: ProcessMessage::CrashReason m_crash_reason; }; +//===----------------------------------------------------------------------===// +/// @class POSIXNewThreadStopInfo +/// @brief Represents the stop state of process when a new thread is spawned. +/// + +class POSIXNewThreadStopInfo + : public POSIXStopInfo +{ +public: + POSIXNewThreadStopInfo (POSIXThread &thread) + : POSIXStopInfo (thread, 0) + { } + + ~POSIXNewThreadStopInfo(); + + lldb::StopReason + GetStopReason() const; + + const char * + GetDescription(); + + bool + ShouldStop(lldb_private::Event *event_ptr); + + bool + ShouldNotify(lldb_private::Event *event_ptr); +}; + #endif diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp index e7848c0c2a3..ce439131fb5 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp @@ -226,6 +226,10 @@ POSIXThread::Notify(const ProcessMessage &message) case ProcessMessage::eCrashMessage: CrashNotify(message); break; + + case ProcessMessage::eNewThreadMessage: + ThreadNotify(message); + break; } } @@ -301,6 +305,12 @@ POSIXThread::CrashNotify(const ProcessMessage &message) SetResumeSignal(signo); } +void +POSIXThread::ThreadNotify(const ProcessMessage &message) +{ + m_stop_info = lldb::StopInfoSP(new POSIXNewThreadStopInfo(*this)); +} + unsigned POSIXThread::GetRegisterIndexFromOffset(unsigned offset) { diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.h b/lldb/source/Plugins/Process/POSIX/POSIXThread.h index 95280d46bc5..7aad6719385 100644 --- a/lldb/source/Plugins/Process/POSIX/POSIXThread.h +++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.h @@ -98,6 +98,7 @@ private: void SignalNotify(const ProcessMessage &message); void SignalDeliveredNotify(const ProcessMessage &message); void CrashNotify(const ProcessMessage &message); + void ThreadNotify(const ProcessMessage &message); lldb_private::Unwind * GetUnwinder(); diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp index a8b8e959387..cefacc3ef8f 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.cpp @@ -224,6 +224,9 @@ ProcessMessage::PrintKind(Kind kind) case eCrashMessage: str = "eCrashMessage"; break; + case eNewThreadMessage: + str = "eNewThreadMessage"; + break; } #endif diff --git a/lldb/source/Plugins/Process/POSIX/ProcessMessage.h b/lldb/source/Plugins/Process/POSIX/ProcessMessage.h index 826567e582b..7eca5c845a7 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessMessage.h +++ b/lldb/source/Plugins/Process/POSIX/ProcessMessage.h @@ -29,7 +29,8 @@ public: eSignalDeliveredMessage, eTraceMessage, eBreakpointMessage, - eCrashMessage + eCrashMessage, + eNewThreadMessage }; enum CrashReason @@ -111,6 +112,11 @@ public: return message; } + /// Indicates that the thread @p tid was spawned. + static ProcessMessage NewThread(lldb::tid_t parent_tid, lldb::tid_t child_tid) { + return ProcessMessage(parent_tid, eNewThreadMessage, child_tid); + } + int GetExitStatus() const { assert(GetKind() == eExitMessage || GetKind() == eLimboMessage); return m_status; @@ -137,6 +143,11 @@ public: return m_addr; } + lldb::tid_t GetChildTID() const { + assert(GetKind() == eNewThreadMessage); + return m_child_tid; + } + static const char * GetCrashReasonString(CrashReason reason); @@ -159,13 +170,23 @@ private: m_kind(kind), m_crash_reason(eInvalidCrashReason), m_status(status), - m_addr(addr) { } + m_addr(addr), + m_child_tid(0) { } + + ProcessMessage(lldb::tid_t tid, Kind kind, lldb::tid_t child_tid) + : m_tid(tid), + m_kind(kind), + m_crash_reason(eInvalidCrashReason), + m_status(0), + m_addr(0), + m_child_tid(child_tid) { } lldb::tid_t m_tid; Kind m_kind : 8; CrashReason m_crash_reason : 8; int m_status; lldb::addr_t m_addr; + lldb::tid_t m_child_tid; }; #endif // #ifndef liblldb_ProcessMessage_H_ diff --git a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp index a69486559b8..980778f0eec 100644 --- a/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp +++ b/lldb/source/Plugins/Process/POSIX/ProcessPOSIX.cpp @@ -361,13 +361,26 @@ ProcessPOSIX::SendMessage(const ProcessMessage &message) case ProcessMessage::eSignalMessage: case ProcessMessage::eSignalDeliveredMessage: - SetPrivateState(eStateStopped); - break; + { + lldb::tid_t tid = message.GetTID(); + lldb::tid_t pid = GetID(); + if (tid == pid) { + SetPrivateState(eStateStopped); + break; + } else { + // FIXME: Ignore any signals generated by children. + return; + } + } case ProcessMessage::eCrashMessage: // FIXME: Update stop reason as per bugzilla 14598 SetPrivateState(eStateStopped); break; + + case ProcessMessage::eNewThreadMessage: + SetPrivateState(eStateStopped); + break; } m_message_queue.push(message); @@ -395,6 +408,12 @@ ProcessPOSIX::RefreshStateAfterStop() POSIXThread *thread = static_cast<POSIXThread*>( GetThreadList().FindThreadByID(tid, false).get()); + if (message.GetKind() == ProcessMessage::eNewThreadMessage) { + ThreadSP thread_sp; + thread_sp.reset(new POSIXThread(*this, message.GetChildTID())); + m_thread_list.AddThread(thread_sp); + } + assert(thread); thread->Notify(message); |

