Share crash information between LLGS and local POSIX debugging with
CrashReason class. Deliver crash information from LLGS to lldb via
description field of thread stop packet.
llvm-svn: 227926
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 13b9c27..918eb4a 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -2255,7 +2255,7 @@
if (thread_sp)
{
- reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGTRAP);
+ reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedByTrace ();
}
// This thread is currently stopped.
@@ -2281,7 +2281,7 @@
// Mark the thread as stopped at breakpoint.
if (thread_sp)
{
- reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedBySignal (SIGTRAP);
+ reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetStoppedByBreakpoint ();
Error error = FixupBreakpointPCAsNeeded (thread_sp);
if (error.Fail ())
{
@@ -2538,8 +2538,7 @@
case SIGFPE:
case SIGBUS:
if (thread_sp)
- reinterpret_cast<NativeThreadLinux*>(thread_sp.get())->SetCrashedWithException(
- signo, reinterpret_cast<lldb::addr_t>(info->si_addr));
+ reinterpret_cast<NativeThreadLinux*> (thread_sp.get ())->SetCrashedWithException (*info);
break;
default:
// This is just a pre-signal-delivery notification of the incoming signal.
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
index c24e3fd..66af7de 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.cpp
@@ -24,6 +24,8 @@
#include "llvm/ADT/SmallString.h"
+#include "Plugins/Process/POSIX/CrashReason.h"
+
#include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
@@ -57,7 +59,8 @@
NativeThreadProtocol (process, tid),
m_state (StateType::eStateInvalid),
m_stop_info (),
- m_reg_context_sp ()
+ m_reg_context_sp (),
+ m_stop_description ()
{
}
@@ -82,9 +85,12 @@
bool
-NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info)
+NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info, std::string& description)
{
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
+
+ description.clear();
+
switch (m_state)
{
case eStateStopped:
@@ -95,8 +101,11 @@
if (log)
LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread:");
stop_info = m_stop_info;
+ if (m_stop_info.reason == StopReason::eStopReasonException)
+ description = m_stop_description;
if (log)
LogThreadStopInfo (*log, stop_info, "returned stop_info:");
+
return true;
case eStateInvalid:
@@ -233,6 +242,7 @@
m_state = new_state;
m_stop_info.reason = StopReason::eStopReasonNone;
+ m_stop_description.clear();
}
void
@@ -301,7 +311,7 @@
MaybeLogStateChange (new_state);
m_state = new_state;
- m_stop_info.reason = StopReason::eStopReasonSignal;
+ m_stop_info.reason = StopReason::eStopReasonBreakpoint;
m_stop_info.details.signal.signo = SIGTRAP;
}
@@ -313,23 +323,34 @@
return false;
// Was the stop reason a signal with signal number SIGTRAP? If not, not a breakpoint.
- return (m_stop_info.reason == StopReason::eStopReasonSignal) &&
+ return (m_stop_info.reason == StopReason::eStopReasonBreakpoint) &&
(m_stop_info.details.signal.signo == SIGTRAP);
}
void
-NativeThreadLinux::SetCrashedWithException (uint64_t exception_type, lldb::addr_t exception_addr)
+NativeThreadLinux::SetStoppedByTrace ()
+{
+ const StateType new_state = StateType::eStateStopped;
+ MaybeLogStateChange (new_state);
+ m_state = new_state;
+
+ m_stop_info.reason = StopReason::eStopReasonTrace;
+ m_stop_info.details.signal.signo = SIGTRAP;
+}
+
+void
+NativeThreadLinux::SetCrashedWithException (const siginfo_t& info)
{
const StateType new_state = StateType::eStateCrashed;
MaybeLogStateChange (new_state);
m_state = new_state;
m_stop_info.reason = StopReason::eStopReasonException;
- m_stop_info.details.exception.type = exception_type;
- m_stop_info.details.exception.data_count = 1;
- m_stop_info.details.exception.data[0] = exception_addr;
-}
+ m_stop_info.details.signal.signo = info.si_signo;
+ const auto reason = GetCrashReason (info);
+ m_stop_description = GetCrashReasonString (reason, reinterpret_cast<lldb::addr_t> (info.si_addr));
+}
void
NativeThreadLinux::SetSuspended ()
@@ -371,33 +392,3 @@
// Log it.
log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
}
-
-uint32_t
-NativeThreadLinux::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const
-{
- switch (stop_info.reason)
- {
- case eStopReasonSignal:
- // No translation.
- return stop_info.details.signal.signo;
-
- case eStopReasonException:
- {
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
- // FIXME I think the eStopReasonException is a xnu/Mach exception, which we
- // shouldn't see on Linux.
- // No translation.
- if (log)
- log->Printf ("NativeThreadLinux::%s saw an exception stop type (signo %"
- PRIu64 "), not expecting to see exceptions on Linux",
- __FUNCTION__,
- stop_info.details.exception.type);
- return static_cast<uint32_t> (stop_info.details.exception.type);
- }
-
- default:
- assert (0 && "unexpected stop_info.reason found");
- return 0;
- }
-}
-
diff --git a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
index 2effd84..1e4ae53 100644
--- a/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeThreadLinux.h
@@ -34,7 +34,7 @@
GetState () override;
bool
- GetStopReason (ThreadStopInfo &stop_info) override;
+ GetStopReason (ThreadStopInfo &stop_info, std::string& description) override;
NativeRegisterContextSP
GetRegisterContext () override;
@@ -45,9 +45,6 @@
Error
RemoveWatchpoint (lldb::addr_t addr) override;
- uint32_t
- TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const override;
-
private:
// ---------------------------------------------------------------------
// Interface for friend classes
@@ -80,7 +77,10 @@
IsStoppedAtBreakpoint ();
void
- SetCrashedWithException (uint64_t exception_type, lldb::addr_t exception_addr);
+ SetStoppedByTrace ();
+
+ void
+ SetCrashedWithException (const siginfo_t& info);
void
SetSuspended ();
@@ -100,6 +100,7 @@
lldb::StateType m_state;
ThreadStopInfo m_stop_info;
NativeRegisterContextSP m_reg_context_sp;
+ std::string m_stop_description;
};
}
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
index 3efeb5d..43a1942 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
+++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.cpp
@@ -46,6 +46,7 @@
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/PseudoTerminal.h"
+#include "Plugins/Process/POSIX/CrashReason.h"
#include "Plugins/Process/POSIX/POSIXThread.h"
#include "ProcessLinux.h"
#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
@@ -1836,27 +1837,14 @@
if (log)
log->Printf ("ProcessMonitor::%s() received signal %s", __FUNCTION__, monitor->m_process->GetUnixSignals().GetSignalAsCString (signo));
- if (signo == SIGSEGV) {
+ switch (signo)
+ {
+ case SIGSEGV:
+ case SIGILL:
+ case SIGFPE:
+ case SIGBUS:
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);
+ const auto reason = GetCrashReason(*info);
return ProcessMessage::Crash(pid, reason, signo, fault_addr);
}
@@ -2114,147 +2102,6 @@
return false;
}
-ProcessMessage::CrashReason
-ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *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 SI_KERNEL:
- // Linux will occasionally send spurious SI_KERNEL codes.
- // (this is poorly documented in sigaction)
- // One way to get this is via unaligned SIMD loads.
- reason = ProcessMessage::eInvalidAddress; // for lack of anything better
- break;
- case SEGV_MAPERR:
- reason = ProcessMessage::eInvalidAddress;
- break;
- case SEGV_ACCERR:
- reason = ProcessMessage::ePrivilegedAddress;
- break;
- }
-
- return reason;
-}
-
-ProcessMessage::CrashReason
-ProcessMonitor::GetCrashReasonForSIGILL(const siginfo_t *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 siginfo_t *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 siginfo_t *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(OperationArgs *args)
{
diff --git a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
index 5e83665..27beaef 100644
--- a/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
+++ b/lldb/source/Plugins/Process/Linux/ProcessMonitor.h
@@ -299,18 +299,6 @@
MonitorSignal(ProcessMonitor *monitor,
const siginfo_t *info, lldb::pid_t pid);
- static ProcessMessage::CrashReason
- GetCrashReasonForSIGSEGV(const siginfo_t *info);
-
- static ProcessMessage::CrashReason
- GetCrashReasonForSIGILL(const siginfo_t *info);
-
- static ProcessMessage::CrashReason
- GetCrashReasonForSIGFPE(const siginfo_t *info);
-
- static ProcessMessage::CrashReason
- GetCrashReasonForSIGBUS(const siginfo_t *info);
-
void
DoOperation(Operation *op);