[Lldb-commits] [lldb] r128547 - in /lldb/trunk/source/Plugins/Process/Linux: LinuxSignals.cpp LinuxSignals.h LinuxStopInfo.cpp LinuxStopInfo.h LinuxThread.cpp LinuxThread.h ProcessLinux.cpp ProcessLinux.h ProcessMessage.cpp ProcessMessage.h ProcessMonitor.cpp ProcessMonitor.h

Stephen Wilson wilsons at start.ca
Wed Mar 30 08:55:53 PDT 2011


Author: wilsons
Date: Wed Mar 30 10:55:52 2011
New Revision: 128547

URL: http://llvm.org/viewvc/llvm-project?rev=128547&view=rev
Log:

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.


Added:
    lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.cpp
    lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.h
    lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp
    lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h
    lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp
Modified:
    lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
    lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
    lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
    lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
    lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h
    lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
    lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h

Added: lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.cpp?rev=128547&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.cpp Wed Mar 30 10:55:52 2011
@@ -0,0 +1,67 @@
+//===-- LinuxSignals.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
+#include <signal.h>
+
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "LinuxSignals.h"
+
+LinuxSignals::LinuxSignals()
+    : UnixSignals()
+{
+    Reset();
+}
+
+void
+LinuxSignals::Reset()
+{
+    m_signals.clear();
+
+#define ADDSIGNAL(S, SUPPRESS, STOP, NOTIFY, DESCRIPTION) \
+    AddSignal(SIG ## S, "SIG" #S, #S, SUPPRESS, STOP, NOTIFY, DESCRIPTION)
+
+    ADDSIGNAL(HUP,    false,  true,  true, "hangup");
+    ADDSIGNAL(INT,    true,   true,  true, "interrupt");
+    ADDSIGNAL(QUIT,   false,  true,  true, "quit");
+    ADDSIGNAL(ILL,    false,  true,  true, "illegal instruction");
+    ADDSIGNAL(TRAP,   true,   true,  true, "trace trap (not reset when caught)");
+    ADDSIGNAL(ABRT,   false,  true,  true, "abort");
+    ADDSIGNAL(IOT,    false,  true,  true, "abort");
+    ADDSIGNAL(BUS,    false,  true,  true, "bus error");
+    ADDSIGNAL(FPE,    false,  true,  true, "floating point exception");
+    ADDSIGNAL(KILL,   false,  true,  true, "kill");
+    ADDSIGNAL(USR1,   false,  true,  true, "user defined signal 1");
+    ADDSIGNAL(SEGV,   false,  true,  true, "segmentation violation");
+    ADDSIGNAL(USR2,   false,  true,  true, "user defined signal 2");
+    ADDSIGNAL(PIPE,   false,  true,  true, "write to pipe with reading end closed");
+    ADDSIGNAL(ALRM,   false,  false, true, "alarm");
+    ADDSIGNAL(TERM,   false,  true,  true, "termination requested");
+    ADDSIGNAL(STKFLT, false,  true,  true, "stack fault");
+    ADDSIGNAL(CHLD,   false,  false, true, "child process exit");
+    ADDSIGNAL(CONT,   false,  true,  true, "process continue");
+    ADDSIGNAL(STOP,   false,  true,  true, "process stop");
+    ADDSIGNAL(TSTP,   false,  true,  true, "tty stop");
+    ADDSIGNAL(TTIN,   false,  true,  true, "background tty read");
+    ADDSIGNAL(TTOU,   false,  true,  true, "background tty write");
+    ADDSIGNAL(URG,    false,  true,  true, "urgent data on socket");
+    ADDSIGNAL(XCPU,   false,  true,  true, "CPU resource exceeded");
+    ADDSIGNAL(XFSZ,   false,  true,  true, "file size limit exceeded");
+    ADDSIGNAL(VTALRM, false,  true,  true, "virtual alarm");
+    ADDSIGNAL(PROF,   false,  true,  true, "profiling alarm");
+    ADDSIGNAL(WINCH,  false,  true,  true, "window size change");
+    ADDSIGNAL(POLL,   false,  true,  true, "pollable event");
+    ADDSIGNAL(IO,     false,  true,  true, "input/output ready");
+    ADDSIGNAL(PWR,    false,  true,  true, "power failure");
+    ADDSIGNAL(SYS,    false,  true,  true, "invalid system call");
+
+#undef ADDSIGNAL
+}

Added: lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.h?rev=128547&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.h (added)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxSignals.h Wed Mar 30 10:55:52 2011
@@ -0,0 +1,31 @@
+//===-- LinuxSignals.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_LinuxSignals_H_
+#define liblldb_LinuxSignals_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/UnixSignals.h"
+
+/// Linux specific set of Unix signals.
+class LinuxSignals
+    : public lldb_private::UnixSignals
+{
+public:
+    LinuxSignals();
+
+private:
+    void
+    Reset();
+};
+
+#endif

Added: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp?rev=128547&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.cpp Wed Mar 30 10:55:52 2011
@@ -0,0 +1,60 @@
+//===-- LinuxStopInfo.cpp ---------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LinuxStopInfo.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+
+//===----------------------------------------------------------------------===//
+// LinuxLimboStopInfo
+
+LinuxLimboStopInfo::~LinuxLimboStopInfo() { }
+
+lldb::StopReason
+LinuxLimboStopInfo::GetStopReason() const
+{
+    return lldb::eStopReasonTrace;
+}
+
+const char *
+LinuxLimboStopInfo::GetDescription()
+{
+    return "thread exiting";
+}
+
+bool
+LinuxLimboStopInfo::ShouldStop(Event *event_ptr)
+{
+    return true;
+}
+
+bool
+LinuxLimboStopInfo::ShouldNotify(Event *event_ptr)
+{
+    return true;
+}
+
+//===----------------------------------------------------------------------===//
+// LinuxCrashStopInfo
+
+LinuxCrashStopInfo::~LinuxCrashStopInfo() { }
+
+lldb::StopReason
+LinuxCrashStopInfo::GetStopReason() const
+{
+    return lldb::eStopReasonException;
+}
+
+const char *
+LinuxCrashStopInfo::GetDescription()
+{
+    return ProcessMessage::GetCrashReasonString(m_crash_reason);
+}

Added: lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h?rev=128547&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h (added)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxStopInfo.h Wed Mar 30 10:55:52 2011
@@ -0,0 +1,92 @@
+//===-- LinuxStopInfo.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_LinuxStopInfo_H_
+#define liblldb_LinuxStopInfo_H_
+
+// C Includes
+// C++ Includes
+// Other libraries and framework includes
+// Project includes
+#include "lldb/Target/StopInfo.h"
+
+#include "LinuxThread.h"
+#include "ProcessMessage.h"
+
+//===----------------------------------------------------------------------===//
+/// @class LinuxStopInfo
+/// @brief Simple base class for all Linux-specific StopInfo objects.
+///
+class LinuxStopInfo
+    : public lldb_private::StopInfo
+{
+public:
+    LinuxStopInfo(lldb_private::Thread &thread, uint32_t status)
+        : StopInfo(thread, status)
+        { }
+};
+
+//===----------------------------------------------------------------------===//
+/// @class LinuxLimboStopInfo
+/// @brief Represents the stop state of a process ready to exit.
+///
+class LinuxLimboStopInfo
+    : public LinuxStopInfo
+{
+public:
+    LinuxLimboStopInfo(LinuxThread &thread)
+        : LinuxStopInfo(thread, 0)
+        { }
+
+    ~LinuxLimboStopInfo();
+
+    lldb::StopReason
+    GetStopReason() const;
+
+    const char *
+    GetDescription();
+
+    bool
+    ShouldStop(lldb_private::Event *event_ptr);
+
+    bool
+    ShouldNotify(lldb_private::Event *event_ptr);
+};
+
+
+//===----------------------------------------------------------------------===//
+/// @class LinuxCrashStopInfo
+/// @brief Represents the stop state of process that is ready to crash.
+///
+class LinuxCrashStopInfo
+    : public LinuxStopInfo
+{
+public:
+    LinuxCrashStopInfo(LinuxThread &thread, uint32_t status, 
+                  ProcessMessage::CrashReason reason)
+        : LinuxStopInfo(thread, status),
+          m_crash_reason(reason)
+        { }
+
+    ~LinuxCrashStopInfo();
+
+    lldb::StopReason
+    GetStopReason() const;
+
+    const char *
+    GetDescription();
+
+    ProcessMessage::CrashReason
+    GetCrashReason() const;
+
+private:
+    ProcessMessage::CrashReason m_crash_reason;
+};    
+
+#endif

Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp?rev=128547&r1=128546&r2=128547&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.cpp Wed Mar 30 10:55:52 2011
@@ -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);
 }

Modified: lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h?rev=128547&r1=128546&r2=128547&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/LinuxThread.h Wed Mar 30 10:55:52 2011
@@ -17,6 +17,7 @@
 // Other libraries and framework includes
 #include "lldb/Target/Thread.h"
 
+class ProcessMessage;
 class ProcessMonitor;
 class RegisterContextLinux;
 
@@ -51,9 +52,7 @@
     //
     bool Resume();
 
-    void BreakNotify();
-    void TraceNotify();
-    void ExitNotify();
+    void Notify(const ProcessMessage &message);
 
 protected:
     virtual bool
@@ -63,7 +62,6 @@
     RestoreSaveFrameZero(const RegisterCheckpoint &checkpoint);
 
 private:
-    
     RegisterContextLinux *
     GetRegisterContextLinux ()
     {
@@ -77,26 +75,18 @@
     lldb::BreakpointSiteSP m_breakpoint;
     lldb::StopInfoSP m_stop_info;
 
-    // Cached process stop id.  Used to ensure we do not recalculate stop
-    // information/state needlessly.
-    uint32_t m_stop_info_id;
-
-    enum Notification {
-        eNone,
-        eBreak,
-        eTrace,
-        eExit
-    };
-
-    Notification m_note;
-
-    ProcessMonitor &GetMonitor();
+    ProcessMonitor &
+    GetMonitor();
 
     lldb::StopInfoSP
     GetPrivateStopReason();
 
-    void
-    RefreshPrivateStopReason();
+    void BreakNotify(const ProcessMessage &message);
+    void TraceNotify(const ProcessMessage &message);
+    void LimboNotify(const ProcessMessage &message);
+    void SignalNotify(const ProcessMessage &message);
+    void SignalDeliveredNotify(const ProcessMessage &message);
+    void CrashNotify(const ProcessMessage &message);
 
     lldb_private::Unwind *
     GetUnwinder();

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp?rev=128547&r1=128546&r2=128547&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.cpp Wed Mar 30 10:55:52 2011
@@ -72,7 +72,9 @@
 ProcessLinux::ProcessLinux(Target& target, Listener &listener)
     : Process(target, listener),
       m_monitor(NULL),
-      m_module(NULL)
+      m_module(NULL),
+      m_in_limbo(false),
+      m_exit_now(false)
 {
     // FIXME: Putting this code in the ctor and saving the byte order in a
     // member variable is a hack to avoid const qual issues in GetByteOrder.
@@ -147,11 +149,20 @@
 Error
 ProcessLinux::DoResume()
 {
-    assert(GetPrivateState() == eStateStopped && "Bad state for DoResume!");
+    StateType state = GetPrivateState();
 
-    // Set our state to running.  This ensures inferior threads do not post a
-    // state change first.
-    SetPrivateState(eStateRunning);
+    assert(state == eStateStopped || state == eStateCrashed);
+
+    // We are about to resume a thread that will cause the process to exit so
+    // set our exit status now.  Do not change our state if the inferior
+    // crashed.
+    if (state == eStateStopped) 
+    {
+        if (m_in_limbo)
+            SetExitStatus(m_exit_status, NULL);
+        else
+            SetPrivateState(eStateRunning);
+    }
 
     bool did_resume = false;
     uint32_t thread_count = m_thread_list.GetSize(false);
@@ -182,7 +193,23 @@
 Error
 ProcessLinux::DoHalt(bool &caused_stop)
 {
-    return Error(1, eErrorTypeGeneric);
+    Error error;
+
+    if (IsStopped())
+    {
+        caused_stop = false;
+    }
+    else if (kill(GetID(), SIGSTOP))
+    {
+        caused_stop = false;
+        error.SetErrorToErrno();
+    }
+    else
+    {
+        caused_stop = true;
+    }
+
+    return error;
 }
 
 Error
@@ -194,7 +221,12 @@
 Error
 ProcessLinux::DoSignal(int signal)
 {
-    return Error(1, eErrorTypeGeneric);
+    Error error;
+
+    if (kill(GetID(), signal))
+        error.SetErrorToErrno();
+
+    return error;
 }
 
 Error
@@ -204,42 +236,19 @@
 
     if (!HasExited())
     {
-        // Shut down the private state thread as we will synchronize with events
-        // ourselves.  Discard all current thread plans.
-        PausePrivateStateThread();
-        GetThreadList().DiscardThreadPlans();
-
-        // Bringing the inferior into limbo will be caught by our monitor
-        // thread, in turn updating the process state.
-        if (!m_monitor->BringProcessIntoLimbo())
+        // Drive the exit event to completion (do not keep the inferior in
+        // limbo).
+        m_exit_now = true;
+
+        if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
         {
-            error.SetErrorToGenericError();
-            error.SetErrorString("Process termination failed.");
+            error.SetErrorToErrno();
             return error;
         }
 
-        // Wait for the event to arrive.  This is guaranteed to be an exit event.
-        StateType state;
-        EventSP event;
-        do {
-            TimeValue timeout_time;
-            timeout_time = TimeValue::Now();
-            timeout_time.OffsetWithSeconds(2);
-            state = WaitForStateChangedEventsPrivate(&timeout_time, event);
-        } while (state != eStateExited && state != eStateInvalid);
-
-        // Check if we timed out waiting for the exit event to arrive.
-        if (state == eStateInvalid)
-            error.SetErrorString("ProcessLinux::DoDestroy timed out.");
-
-        // Restart standard event handling and send the process the final kill,
-        // driving it out of limbo.
-        ResumePrivateStateThread();
+        SetPrivateState(eStateExited);
     }
 
-    if (kill(m_monitor->GetPID(), SIGKILL) && error.Success())
-        error.SetErrorToErrno();
-
     return error;
 }
 
@@ -251,18 +260,41 @@
     switch (message.GetKind())
     {
     default:
-        SetPrivateState(eStateStopped);
+        assert(false && "Unexpected process message!");
         break;
 
     case ProcessMessage::eInvalidMessage:
         return;
 
+    case ProcessMessage::eLimboMessage:
+        m_in_limbo = true;
+        m_exit_status = message.GetExitStatus();
+        if (m_exit_now)
+        {
+            SetPrivateState(eStateExited);
+            m_monitor->Detach();
+        }
+        else
+            SetPrivateState(eStateStopped);
+        break;
+
     case ProcessMessage::eExitMessage:
-        SetExitStatus(message.GetExitStatus(), NULL);
+        m_exit_status = message.GetExitStatus();
+        SetExitStatus(m_exit_status, NULL);
+        break;
+
+    case ProcessMessage::eTraceMessage:
+    case ProcessMessage::eBreakpointMessage:
+        SetPrivateState(eStateStopped);
         break;
 
     case ProcessMessage::eSignalMessage:
-        SetExitStatus(-1, NULL);
+    case ProcessMessage::eSignalDeliveredMessage:
+        SetPrivateState(eStateStopped);
+        break;
+
+    case ProcessMessage::eCrashMessage:
+        SetPrivateState(eStateCrashed);
         break;
     }
 
@@ -278,30 +310,12 @@
 
     ProcessMessage &message = m_message_queue.front();
 
-    // Resolve the thread this message corresponds to.
+    // Resolve the thread this message corresponds to and pass it along.
     lldb::tid_t tid = message.GetTID();
     LinuxThread *thread = static_cast<LinuxThread*>(
         GetThreadList().FindThreadByID(tid, false).get());
 
-    switch (message.GetKind())
-    {
-    default:
-        assert(false && "Unexpected message kind!");
-        break;
-
-    case ProcessMessage::eExitMessage:
-    case ProcessMessage::eSignalMessage:
-        thread->ExitNotify();
-        break;
-
-    case ProcessMessage::eTraceMessage:
-        thread->TraceNotify();
-        break;
-
-    case ProcessMessage::eBreakpointMessage:
-        thread->BreakNotify();
-        break;
-    }
+    thread->Notify(message);
 
     m_message_queue.pop();
 }
@@ -432,6 +446,11 @@
     return GetSTDOUT(buf, len, error);
 }
 
+UnixSignals &
+ProcessLinux::GetUnixSignals()
+{
+    return m_linux_signals;
+}
 
 //------------------------------------------------------------------------------
 // ProcessInterface protocol.
@@ -482,8 +501,6 @@
     default:
         break;
 
-    case eStateUnloaded:
-    case eStateCrashed:
     case eStateDetached:
     case eStateExited:
         return true;
@@ -491,3 +508,20 @@
 
     return false;
 }
+
+bool
+ProcessLinux::IsStopped()
+{
+    switch (GetPrivateState())
+    {
+    default:
+        break;
+
+    case eStateStopped:
+    case eStateCrashed:
+    case eStateSuspended:
+        return true;
+    }
+
+    return false;
+}

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h?rev=128547&r1=128546&r2=128547&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessLinux.h Wed Mar 30 10:55:52 2011
@@ -17,6 +17,7 @@
 
 // Other libraries and framework includes
 #include "lldb/Target/Process.h"
+#include "LinuxSignals.h"
 #include "ProcessMessage.h"
 
 class ProcessMonitor;
@@ -178,6 +179,9 @@
 
     ProcessMonitor &GetMonitor() { return *m_monitor; }
 
+    lldb_private::UnixSignals &
+    GetUnixSignals();
+
 private:
     /// Target byte order.
     lldb::ByteOrder m_byte_order;
@@ -192,6 +196,19 @@
     lldb_private::Mutex m_message_mutex;
     std::queue<ProcessMessage> m_message_queue;
 
+    /// True when the process has entered a state of "limbo".
+    ///
+    /// This flag qualifies eStateStopped.  It lets us know that when we
+    /// continue from this state the process will exit.  Also, when true,
+    /// Process::m_exit_status is set.
+    bool m_in_limbo;
+
+    /// Drive any exit events to completion.
+    bool m_exit_now;
+
+    /// Linux-specific signal set.
+    LinuxSignals m_linux_signals;
+
     /// Updates the loaded sections provided by the executable.
     ///
     /// FIXME:  It would probably be better to delegate this task to the
@@ -200,6 +217,9 @@
 
     /// Returns true if the process has exited.
     bool HasExited();
+
+    /// Returns true if the process is stopped.
+    bool IsStopped();
 };
 
 #endif  // liblldb_MacOSXProcess_H_

Added: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp?rev=128547&view=auto
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp (added)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.cpp Wed Mar 30 10:55:52 2011
@@ -0,0 +1,91 @@
+//===-- ProcessMessage.cpp --------------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ProcessMessage.h"
+
+using namespace lldb_private;
+
+const char *
+ProcessMessage::GetCrashReasonString(CrashReason reason)
+{
+    const char *str = NULL;
+
+    switch (reason)
+    {
+    default:
+        assert(false && "invalid CrashReason");
+        break;
+
+    case eInvalidAddress:
+        str = "invalid address";
+        break;
+    case ePrivilegedAddress:
+        str = "address access protected";
+        break;
+    case eIllegalOpcode:
+        str = "illegal instruction";
+        break;
+    case eIllegalOperand:
+        str = "illegal instruction operand";
+        break;
+    case eIllegalAddressingMode:
+        str = "illegal addressing mode";
+        break;
+    case eIllegalTrap:
+        str = "illegal trap";
+        break;
+    case ePrivilegedOpcode:
+        str = "privileged instruction";
+        break;
+    case ePrivilegedRegister:
+        str = "privileged register";
+        break;
+    case eCoprocessorError:
+        str = "coprocessor error";
+        break;
+    case eInternalStackError:
+        str = "internal stack error";
+        break;
+    case eIllegalAlignment:
+        str = "illegal alignment";
+        break;
+    case eIllegalAddress:
+        str = "illegal address";
+        break;
+    case eHardwareError:
+        str = "hardware error";
+        break;
+    case eIntegerDivideByZero:
+        str = "integer divide by zero";
+        break;
+    case eIntegerOverflow:
+        str = "integer overflow";
+        break;
+    case eFloatDivideByZero:
+        str = "floating point divide by zero";
+        break;
+    case eFloatOverflow:
+        str = "floating point overflow";
+        break;
+    case eFloatUnderflow:
+        str = "floating point underflow";
+        break;
+    case eFloatInexactResult:
+        str = "inexact floating point result";
+        break;
+    case eFloatInvalidOperation:
+        str = "invalid floating point operation";
+        break;
+    case eFloatSubscriptRange:
+        str = "invalid floating point subscript range";
+        break;
+    }
+
+    return str;
+}

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h?rev=128547&r1=128546&r2=128547&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMessage.h Wed Mar 30 10:55:52 2011
@@ -26,63 +26,134 @@
         eExitMessage,
         eLimboMessage,
         eSignalMessage,
+        eSignalDeliveredMessage,
         eTraceMessage,
-        eBreakpointMessage
+        eBreakpointMessage,
+        eCrashMessage
+    };
+
+    enum CrashReason
+    {
+        eInvalidCrashReason,
+
+        // SIGSEGV crash reasons.
+        eInvalidAddress,
+        ePrivilegedAddress,
+
+        // SIGILL crash reasons.
+        eIllegalOpcode,
+        eIllegalOperand,
+        eIllegalAddressingMode,
+        eIllegalTrap,
+        ePrivilegedOpcode,
+        ePrivilegedRegister,
+        eCoprocessorError,
+        eInternalStackError,
+
+        // SIGBUS crash reasons,
+        eIllegalAlignment,
+        eIllegalAddress,
+        eHardwareError,
+
+        // SIGFPE crash reasons,
+        eIntegerDivideByZero,
+        eIntegerOverflow,
+        eFloatDivideByZero,
+        eFloatOverflow,
+        eFloatUnderflow,
+        eFloatInexactResult,
+        eFloatInvalidOperation,
+        eFloatSubscriptRange
     };
 
     ProcessMessage()
-        : m_kind(eInvalidMessage),
-          m_tid(LLDB_INVALID_PROCESS_ID),
-          m_data(0) { }
+        : m_tid(LLDB_INVALID_PROCESS_ID),
+          m_kind(eInvalidMessage),
+          m_crash_reason(eInvalidCrashReason),
+          m_status(0),
+          m_addr(0) { }
 
     Kind GetKind() const { return m_kind; }
 
     lldb::tid_t GetTID() const { return m_tid; }
 
-    static ProcessMessage Exit(lldb::tid_t tid, int status) {
-        return ProcessMessage(tid, eExitMessage, status);
-    }
-
+    /// Indicates that the thread @p tid is about to exit with status @p status.
     static ProcessMessage Limbo(lldb::tid_t tid, int status) {
         return ProcessMessage(tid, eLimboMessage, status);
     }
 
+    /// Indicates that the thread @p tid had the signal @p signum delivered.
     static ProcessMessage Signal(lldb::tid_t tid, int signum) {
         return ProcessMessage(tid, eSignalMessage, signum);
     }
 
+    /// Indicates that a signal @p signum generated by the debugging process was
+    /// delivered to the thread @p tid.
+    static ProcessMessage SignalDelivered(lldb::tid_t tid, int signum) {
+        return ProcessMessage(tid, eSignalDeliveredMessage, signum);
+    }
+
+    /// Indicates that the thread @p tid encountered a trace point.
     static ProcessMessage Trace(lldb::tid_t tid) {
         return ProcessMessage(tid, eTraceMessage);
     }
 
+    /// Indicates that the thread @p tid encountered a break point.
     static ProcessMessage Break(lldb::tid_t tid) {
         return ProcessMessage(tid, eBreakpointMessage);
     }
 
+    /// Indicates that the thread @p tid crashed.
+    static ProcessMessage Crash(lldb::pid_t pid, CrashReason reason,
+                                int signo, lldb::addr_t fault_addr) {
+        ProcessMessage message(pid, eCrashMessage, signo, fault_addr);
+        message.m_crash_reason = reason;
+        return message;
+    }
+
     int GetExitStatus() const {
         assert(GetKind() == eExitMessage || GetKind() == eLimboMessage);
-        return m_data;
+        return m_status;
     }
 
     int GetSignal() const {
-        assert(GetKind() == eSignalMessage);
-        return m_data;
+        assert(GetKind() == eSignalMessage || GetKind() == eCrashMessage ||
+               GetKind() == eSignalDeliveredMessage);
+        return m_status;
     }
 
     int GetStopStatus() const {
         assert(GetKind() == eSignalMessage);
-        return m_data;
+        return m_status;
+    }
+
+    CrashReason GetCrashReason() const {
+        assert(GetKind() == eCrashMessage);
+        return m_crash_reason;
     }
 
+    lldb::addr_t GetFaultAddress() const {
+        assert(GetKind() == eCrashMessage);
+        return m_addr;
+    }
+
+    static const char *
+    GetCrashReasonString(CrashReason reason);
+
 private:
-    ProcessMessage(lldb::tid_t tid, Kind kind, int data = 0)
-        : m_kind(kind),
-          m_tid(tid),
-          m_data(data) { }
+    ProcessMessage(lldb::tid_t tid, Kind kind, 
+                   int status = 0, lldb::addr_t addr = 0)
+        : m_tid(tid),
+          m_kind(kind),
+          m_crash_reason(eInvalidCrashReason),
+          m_status(status),
+          m_addr(addr) { }
 
-    Kind m_kind;
     lldb::tid_t m_tid;
-    int m_data;
+    Kind        m_kind         : 8;
+    CrashReason m_crash_reason : 8;
+    int m_status;
+    lldb::addr_t m_addr;
 };
 
 #endif // #ifndef liblldb_ProcessMessage_H_

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp?rev=128547&r1=128546&r2=128547&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.cpp Wed Mar 30 10:55:52 2011
@@ -338,20 +338,26 @@
 class ResumeOperation : public Operation
 {
 public:
-    ResumeOperation(lldb::tid_t tid, bool &result) :
-        m_tid(tid), m_result(result) { }
+    ResumeOperation(lldb::tid_t tid, uint32_t signo, bool &result) :
+        m_tid(tid), m_signo(signo), m_result(result) { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
     lldb::tid_t m_tid;
+    uint32_t m_signo;
     bool &m_result;
 };
 
 void
 ResumeOperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_CONT, m_tid, NULL, NULL))
+    int data = 0;
+
+    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
+        data = m_signo;
+
+    if (ptrace(PTRACE_CONT, m_tid, NULL, data))
         m_result = false;
     else
         m_result = true;
@@ -363,20 +369,26 @@
 class SingleStepOperation : public Operation
 {
 public:
-    SingleStepOperation(lldb::tid_t tid, bool &result)
-        : m_tid(tid), m_result(result) { }
+    SingleStepOperation(lldb::tid_t tid, uint32_t signo, bool &result)
+        : m_tid(tid), m_signo(signo), m_result(result) { }
 
     void Execute(ProcessMonitor *monitor);
 
 private:
     lldb::tid_t m_tid;
+    uint32_t m_signo;
     bool &m_result;
 };
 
 void
 SingleStepOperation::Execute(ProcessMonitor *monitor)
 {
-    if (ptrace(PTRACE_SINGLESTEP, m_tid, NULL, NULL))
+    int data = 0;
+
+    if (m_signo != LLDB_INVALID_SIGNAL_NUMBER)
+        data = m_signo;
+
+    if (ptrace(PTRACE_SINGLESTEP, m_tid, NULL, data))
         m_result = false;
     else
         m_result = true;
@@ -457,32 +469,6 @@
         m_result = false;
     else
         m_result = true;
-
-#if 0
-    // First, stop the inferior process.
-    if (kill(pid, SIGSTOP))
-    {
-        m_result = false;
-        return;
-    }
-
-    // Clear any ptrace options.  When PTRACE_O_TRACEEXIT is set, a plain
-    // PTRACE_KILL (or any termination signal) will not truely terminate the
-    // inferior process.  Instead, the process is left in a state of "limbo"
-    // allowing us to interrogate its state.  However in this case we really do
-    // want the process gone.
-    if (ptrace(PTRACE_SETOPTIONS, pid, NULL, 0UL))
-    {
-        m_result = false;
-        return;
-    }
-
-    // Kill it.
-    if (ptrace(PTRACE_KILL, pid, NULL, NULL))
-        m_result = false;
-    else
-        m_result = true;
-#endif
 }
 
 ProcessMonitor::LaunchArgs::LaunchArgs(ProcessMonitor *monitor,
@@ -586,12 +572,7 @@
 
 ProcessMonitor::~ProcessMonitor()
 {
-    StopMonitoringChildProcess();
-    StopOperationThread();
-
-    close(m_terminal_fd);
-    close(m_client_fd);
-    close(m_server_fd);
+    StopMonitor();
 }
 
 //------------------------------------------------------------------------------
@@ -768,50 +749,39 @@
     ProcessMessage message;
     ProcessMonitor *monitor = static_cast<ProcessMonitor*>(callback_baton);
     ProcessLinux *process = monitor->m_process;
+    bool stop_monitoring;
+    siginfo_t info;
 
-    switch (signal)
-    {
-    case 0:
-        // No signal.  The child has exited normally.
-        message = ProcessMessage::Exit(pid, status);
-        break;
-
-    case SIGTRAP:
-        // Specially handle SIGTRAP and form the appropriate message.
-        message = MonitorSIGTRAP(monitor, pid);
-        break;
+    if (!monitor->GetSignalInfo(pid, &info))
+        stop_monitoring = true; // pid is gone.  Bail.
+    else {
+        switch (info.si_signo)
+        {
+        case SIGTRAP:
+            message = MonitorSIGTRAP(monitor, &info, pid);
+            break;
+            
+        default:
+            message = MonitorSignal(monitor, &info, pid);
+            break;
+        }
 
-    default:
-        // For all other signals simply notify the process instance.  Note that
-        // the process exit status is set when the signal resulted in
-        // termination.
-        //
-        // FIXME: We need a specialized message to inform the process instance
-        // about "crashes".
-        if (status)
-            message = ProcessMessage::Exit(pid, status);
-        else
-            message = ProcessMessage::Signal(pid, signal);
+        process->SendMessage(message);
+        stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
     }
 
-    process->SendMessage(message);
-    bool stop_monitoring = message.GetKind() == ProcessMessage::eExitMessage;
     return stop_monitoring;
 }
 
 ProcessMessage
-ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor, lldb::pid_t pid)
+ProcessMonitor::MonitorSIGTRAP(ProcessMonitor *monitor,
+                               const struct siginfo *info, lldb::pid_t pid)
 {
-    siginfo_t info;
     ProcessMessage message;
-    bool status;
-
-    status = monitor->GetSignalInfo(pid, &info);
-    assert(status && "GetSignalInfo failed!");
 
-    assert(info.si_signo == SIGTRAP && "Unexpected child signal!");
+    assert(info->si_signo == SIGTRAP && "Unexpected child signal!");
 
-    switch (info.si_code)
+    switch (info->si_code)
     {
     default:
         assert(false && "Unexpected SIGTRAP code!");
@@ -825,7 +795,7 @@
         unsigned long data = 0;
         if (!monitor->GetEventMessage(pid, &data))
             data = -1;
-        message = ProcessMessage::Exit(pid, (data >> 8));
+        message = ProcessMessage::Limbo(pid, (data >> 8));
         break;
     }
 
@@ -843,6 +813,193 @@
     return message;
 }
 
+ProcessMessage
+ProcessMonitor::MonitorSignal(ProcessMonitor *monitor,
+                              const struct siginfo *info, lldb::pid_t pid)
+{
+    ProcessMessage message;
+    int signo = info->si_signo;
+
+    // POSIX says that process behaviour is undefined after it ignores a SIGFPE,
+    // SIGILL, SIGSEGV, or SIGBUS *unless* that signal was generated by a
+    // kill(2) or raise(3).  Similarly for tgkill(2) on Linux.
+    //
+    // IOW, user generated signals never generate what we consider to be a
+    // "crash".
+    //
+    // Similarly, ACK signals generated by this monitor.
+    if (info->si_code == SI_TKILL || info->si_code == SI_USER)
+    {
+        if (info->si_pid == getpid())
+            return ProcessMessage::SignalDelivered(pid, signo);
+        else
+            return ProcessMessage::Signal(pid, signo);
+    }
+
+    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);
+    }
+
+    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);
+    }
+
+    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);
+    }
+
+    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);
+    }
+
+    // Everything else is "normal" and does not require any special action on
+    // our part.
+    return ProcessMessage::Signal(pid, signo);
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGSEGV(const struct siginfo *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGSEGV);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code) 
+    {
+    default:
+        assert(false && "unexpected si_code for SIGSEGV");
+        break;
+    case SEGV_MAPERR:
+        reason = ProcessMessage::eInvalidAddress;
+        break;
+    case SEGV_ACCERR:
+        reason = ProcessMessage::ePrivilegedAddress;
+        break;
+    }
+        
+    return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGILL(const struct siginfo *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGILL);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code)
+    {
+    default:
+        assert(false && "unexpected si_code for SIGILL");
+        break;
+    case ILL_ILLOPC:
+        reason = ProcessMessage::eIllegalOpcode;
+        break;
+    case ILL_ILLOPN:
+        reason = ProcessMessage::eIllegalOperand;
+        break;
+    case ILL_ILLADR:
+        reason = ProcessMessage::eIllegalAddressingMode;
+        break;
+    case ILL_ILLTRP:
+        reason = ProcessMessage::eIllegalTrap;
+        break;
+    case ILL_PRVOPC:
+        reason = ProcessMessage::ePrivilegedOpcode;
+        break;
+    case ILL_PRVREG:
+        reason = ProcessMessage::ePrivilegedRegister;
+        break;
+    case ILL_COPROC:
+        reason = ProcessMessage::eCoprocessorError;
+        break;
+    case ILL_BADSTK:
+        reason = ProcessMessage::eInternalStackError;
+        break;
+    }
+
+    return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGFPE(const struct siginfo *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGFPE);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code)
+    {
+    default:
+        assert(false && "unexpected si_code for SIGFPE");
+        break;
+    case FPE_INTDIV:
+        reason = ProcessMessage::eIntegerDivideByZero;
+        break;
+    case FPE_INTOVF:
+        reason = ProcessMessage::eIntegerOverflow;
+        break;
+    case FPE_FLTDIV:
+        reason = ProcessMessage::eFloatDivideByZero;
+        break;
+    case FPE_FLTOVF:
+        reason = ProcessMessage::eFloatOverflow;
+        break;
+    case FPE_FLTUND:
+        reason = ProcessMessage::eFloatUnderflow;
+        break;
+    case FPE_FLTRES:
+        reason = ProcessMessage::eFloatInexactResult;
+        break;
+    case FPE_FLTINV:
+        reason = ProcessMessage::eFloatInvalidOperation;
+        break;
+    case FPE_FLTSUB:
+        reason = ProcessMessage::eFloatSubscriptRange;
+        break;
+    }
+
+    return reason;
+}
+
+ProcessMessage::CrashReason
+ProcessMonitor::GetCrashReasonForSIGBUS(const struct siginfo *info)
+{
+    ProcessMessage::CrashReason reason;
+    assert(info->si_signo == SIGBUS);
+
+    reason = ProcessMessage::eInvalidCrashReason;
+
+    switch (info->si_code)
+    {
+    default:
+        assert(false && "unexpected si_code for SIGBUS");
+        break;
+    case BUS_ADRALN:
+        reason = ProcessMessage::eIllegalAlignment;
+        break;
+    case BUS_ADRERR:
+        reason = ProcessMessage::eIllegalAddress;
+        break;
+    case BUS_OBJERR:
+        reason = ProcessMessage::eHardwareError;
+        break;
+    }
+
+    return reason;
+}
+
 void
 ProcessMonitor::ServeOperation(LaunchArgs *args)
 {
@@ -976,19 +1133,19 @@
 }
 
 bool
-ProcessMonitor::Resume(lldb::tid_t tid)
+ProcessMonitor::Resume(lldb::tid_t tid, uint32_t signo)
 {
     bool result;
-    ResumeOperation op(tid, result);
+    ResumeOperation op(tid, signo, result);
     DoOperation(&op);
     return result;
 }
 
 bool
-ProcessMonitor::SingleStep(lldb::tid_t tid)
+ProcessMonitor::SingleStep(lldb::tid_t tid, uint32_t signo)
 {
     bool result;
-    SingleStepOperation op(tid, result);
+    SingleStepOperation op(tid, signo, result);
     DoOperation(&op);
     return result;
 }
@@ -1021,6 +1178,16 @@
 }
 
 bool
+ProcessMonitor::Detach()
+{
+    bool result;
+    KillOperation op(result);
+    DoOperation(&op);
+    StopMonitor();
+    return result;
+}    
+
+bool
 ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
 {
     int target_fd = open(path, flags);
@@ -1043,3 +1210,23 @@
         m_monitor_thread = LLDB_INVALID_HOST_THREAD;
     }
 }
+
+void
+ProcessMonitor::StopMonitor()
+{
+    StopMonitoringChildProcess();
+    StopOperationThread();
+    CloseFD(m_terminal_fd);
+    CloseFD(m_client_fd);
+    CloseFD(m_server_fd);
+}
+
+void
+ProcessMonitor::CloseFD(int &fd)
+{
+    if (fd != -1)
+    {
+        close(fd);
+        fd = -1;
+    }
+}

Modified: lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h?rev=128547&r1=128546&r2=128547&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h (original)
+++ lldb/trunk/source/Plugins/Process/Linux/ProcessMonitor.h Wed Mar 30 10:55:52 2011
@@ -12,6 +12,7 @@
 
 // C Includes
 #include <semaphore.h>
+#include <signal.h>
 
 // C++ Includes
 // Other libraries and framework includes
@@ -127,13 +128,15 @@
     bool
     GetEventMessage(lldb::tid_t tid, unsigned long *message);
 
-    /// Resumes the given thread.
+    /// Resumes the given thread.  If @p signo is anything but
+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
     bool
-    Resume(lldb::tid_t tid);
+    Resume(lldb::tid_t tid, uint32_t signo);
 
-    /// Single steps the given thread.
+    /// Single steps the given thread.  If @p signo is anything but
+    /// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
     bool
-    SingleStep(lldb::tid_t tid);
+    SingleStep(lldb::tid_t tid, uint32_t signo);
 
     /// Sends the inferior process a PTRACE_KILL signal.  The inferior will
     /// still exists and can be interrogated.  Once resumed it will exit as
@@ -141,6 +144,10 @@
     bool
     BringProcessIntoLimbo();
 
+    bool
+    Detach();
+
+
 private:
     ProcessLinux *m_process;
 
@@ -207,13 +214,37 @@
                     lldb::pid_t pid, int signal, int status);
 
     static ProcessMessage
-    MonitorSIGTRAP(ProcessMonitor *monitor, lldb::pid_t pid);
+    MonitorSIGTRAP(ProcessMonitor *monitor,
+                   const struct siginfo *info, lldb::pid_t pid);
+
+    static ProcessMessage
+    MonitorSignal(ProcessMonitor *monitor, 
+                  const struct siginfo *info, lldb::pid_t pid);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGSEGV(const struct siginfo *info);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGILL(const struct siginfo *info);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGFPE(const struct siginfo *info);
+
+    static ProcessMessage::CrashReason
+    GetCrashReasonForSIGBUS(const struct siginfo *info);
 
     void
     DoOperation(Operation *op);
 
     /// Stops the child monitor thread.
-    void StopMonitoringChildProcess();
+    void
+    StopMonitoringChildProcess();
+
+    void 
+    StopMonitor();
+
+    void
+    CloseFD(int &fd);
 };
 
 #endif // #ifndef liblldb_ProcessMonitor_H_





More information about the lldb-commits mailing list