linux: initial support for 'real' signal handling

This patch upgrades the Linux process plugin to handle a larger range of signal
events.  For example, we can detect when the inferior has "crashed" and why,
interrupt a running process, deliver an arbitrary signal, and so on.



git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@128547 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/source/Plugins/Process/Linux/LinuxThread.cpp b/source/Plugins/Process/Linux/LinuxThread.cpp
index ebda0d8..bac9d48 100644
--- a/source/Plugins/Process/Linux/LinuxThread.cpp
+++ b/source/Plugins/Process/Linux/LinuxThread.cpp
@@ -12,11 +12,13 @@
 
 // C++ Includes
 // Other libraries and framework includes
+// Project includes
 #include "lldb/Host/Host.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/StopInfo.h"
 #include "lldb/Target/Target.h"
 
+#include "LinuxStopInfo.h"
 #include "LinuxThread.h"
 #include "ProcessLinux.h"
 #include "ProcessMonitor.h"
@@ -26,11 +28,10 @@
 
 using namespace lldb_private;
 
+
 LinuxThread::LinuxThread(Process &process, lldb::tid_t tid)
     : Thread(process, tid),
-      m_frame_ap(0),
-      m_stop_info_id(0),
-      m_note(eNone)
+      m_frame_ap(0)
 {
 }
 
@@ -49,7 +50,6 @@
 void
 LinuxThread::RefreshStateAfterStop()
 {
-    RefreshPrivateStopReason();
 }
 
 const char *
@@ -117,10 +117,6 @@
 lldb::StopInfoSP
 LinuxThread::GetPrivateStopReason()
 {
-    const uint32_t process_stop_id = GetProcess().GetStopID();
-
-    if (m_stop_info_id != process_stop_id || !m_stop_info || !m_stop_info->IsValid())
-        RefreshPrivateStopReason();
     return m_stop_info;
 }
 
@@ -152,34 +148,64 @@
     ProcessMonitor &monitor = GetMonitor();
     bool status;
 
-    switch (GetResumeState())
+    switch (resume_state)
     {
     default:
         assert(false && "Unexpected state for resume!");
         status = false;
         break;
 
-    case lldb::eStateSuspended:
-        // FIXME: Implement process suspension.
-        status = false;
-
     case lldb::eStateRunning:
         SetState(resume_state);
-        status = monitor.Resume(GetID());
+        status = monitor.Resume(GetID(), GetResumeSignal());
         break;
 
     case lldb::eStateStepping:
         SetState(resume_state);
-        status = monitor.SingleStep(GetID());
+        status = monitor.SingleStep(GetID(), GetResumeSignal());
         break;
     }
 
-    m_note = eNone;
     return status;
 }
 
 void
-LinuxThread::BreakNotify()
+LinuxThread::Notify(const ProcessMessage &message)
+{
+    switch (message.GetKind())
+    {
+    default:
+        assert(false && "Unexpected message kind!");
+        break;
+
+    case ProcessMessage::eLimboMessage:
+        LimboNotify(message);
+        break;
+        
+    case ProcessMessage::eSignalMessage:
+        SignalNotify(message);
+        break;
+
+    case ProcessMessage::eSignalDeliveredMessage:
+        SignalDeliveredNotify(message);
+        break;
+
+    case ProcessMessage::eTraceMessage:
+        TraceNotify(message);
+        break;
+
+    case ProcessMessage::eBreakpointMessage:
+        BreakNotify(message);
+        break;
+
+    case ProcessMessage::eCrashMessage:
+        CrashNotify(message);
+        break;
+    }
+}
+
+void
+LinuxThread::BreakNotify(const ProcessMessage &message)
 {
     bool status;
 
@@ -190,47 +216,53 @@
     // corresponding to our current PC.
     lldb::addr_t pc = GetRegisterContext()->GetPC();
     lldb::BreakpointSiteSP bp_site(GetProcess().GetBreakpointSiteList().FindByAddress(pc));
+    lldb::break_id_t bp_id = bp_site->GetID();
     assert(bp_site && bp_site->ValidForThisThread(this));
 
-    m_note = eBreak;
+    
     m_breakpoint = bp_site;
+    m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(*this, bp_id);
 }
 
 void
-LinuxThread::TraceNotify()
+LinuxThread::TraceNotify(const ProcessMessage &message)
 {
-    m_note = eTrace;
+    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
 }
 
 void
-LinuxThread::ExitNotify()
+LinuxThread::LimboNotify(const ProcessMessage &message)
 {
-    m_note = eExit;
+    m_stop_info = lldb::StopInfoSP(new LinuxLimboStopInfo(*this));
 }
 
 void
-LinuxThread::RefreshPrivateStopReason()
+LinuxThread::SignalNotify(const ProcessMessage &message)
 {
-    m_stop_info_id = GetProcess().GetStopID();
+    int signo = message.GetSignal();
 
-    switch (m_note) {
+    m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, signo);
+    SetResumeSignal(signo);
+}
 
-    default:
-    case eNone:
-        m_stop_info.reset();
-        break;
+void
+LinuxThread::SignalDeliveredNotify(const ProcessMessage &message)
+{
+    int signo = message.GetSignal();
 
-    case eBreak:
-        m_stop_info = StopInfo::CreateStopReasonWithBreakpointSiteID(
-            *this, m_breakpoint->GetID());
-        break;
+    // Just treat debugger generated signal events like breakpoints for now.
+    m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
+    SetResumeSignal(signo);
+}
 
-    case eTrace:
-        m_stop_info = StopInfo::CreateStopReasonToTrace(*this);
-        break;
+void
+LinuxThread::CrashNotify(const ProcessMessage &message)
+{
+    int signo = message.GetSignal();
 
-    case eExit:
-        m_stop_info = StopInfo::CreateStopReasonWithSignal(*this, SIGCHLD);
-        break;
-    }
+    assert(message.GetKind() == ProcessMessage::eCrashMessage);
+
+    m_stop_info = lldb::StopInfoSP(new LinuxCrashStopInfo(
+                                       *this, signo, message.GetCrashReason()));
+    SetResumeSignal(signo);
 }