llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.cpp

317 lines
8.6 KiB
C++

//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "CrashReason.h"
#include <sstream>
namespace {
void
AppendFaultAddr (std::string& str, lldb::addr_t addr)
{
std::stringstream ss;
ss << " (fault address: 0x" << std::hex << addr << ")";
str += ss.str();
}
CrashReason
GetCrashReasonForSIGSEGV(const siginfo_t& info)
{
assert(info.si_signo == SIGSEGV);
switch (info.si_code)
{
#ifdef SI_KERNEL
case SI_KERNEL:
// Some platforms will occasionally send nonstandard spurious SI_KERNEL codes.
// One way to get this is via unaligned SIMD loads.
return CrashReason::eInvalidAddress; // for lack of anything better
#endif
case SEGV_MAPERR:
return CrashReason::eInvalidAddress;
case SEGV_ACCERR:
return CrashReason::ePrivilegedAddress;
}
assert(false && "unexpected si_code for SIGSEGV");
return CrashReason::eInvalidCrashReason;
}
CrashReason
GetCrashReasonForSIGILL(const siginfo_t& info)
{
assert(info.si_signo == SIGILL);
switch (info.si_code)
{
case ILL_ILLOPC:
return CrashReason::eIllegalOpcode;
case ILL_ILLOPN:
return CrashReason::eIllegalOperand;
case ILL_ILLADR:
return CrashReason::eIllegalAddressingMode;
case ILL_ILLTRP:
return CrashReason::eIllegalTrap;
case ILL_PRVOPC:
return CrashReason::ePrivilegedOpcode;
case ILL_PRVREG:
return CrashReason::ePrivilegedRegister;
case ILL_COPROC:
return CrashReason::eCoprocessorError;
case ILL_BADSTK:
return CrashReason::eInternalStackError;
}
assert(false && "unexpected si_code for SIGILL");
return CrashReason::eInvalidCrashReason;
}
CrashReason
GetCrashReasonForSIGFPE(const siginfo_t& info)
{
assert(info.si_signo == SIGFPE);
switch (info.si_code)
{
case FPE_INTDIV:
return CrashReason::eIntegerDivideByZero;
case FPE_INTOVF:
return CrashReason::eIntegerOverflow;
case FPE_FLTDIV:
return CrashReason::eFloatDivideByZero;
case FPE_FLTOVF:
return CrashReason::eFloatOverflow;
case FPE_FLTUND:
return CrashReason::eFloatUnderflow;
case FPE_FLTRES:
return CrashReason::eFloatInexactResult;
case FPE_FLTINV:
return CrashReason::eFloatInvalidOperation;
case FPE_FLTSUB:
return CrashReason::eFloatSubscriptRange;
}
assert(false && "unexpected si_code for SIGFPE");
return CrashReason::eInvalidCrashReason;
}
CrashReason
GetCrashReasonForSIGBUS(const siginfo_t& info)
{
assert(info.si_signo == SIGBUS);
switch (info.si_code)
{
case BUS_ADRALN:
return CrashReason::eIllegalAlignment;
case BUS_ADRERR:
return CrashReason::eIllegalAddress;
case BUS_OBJERR:
return CrashReason::eHardwareError;
}
assert(false && "unexpected si_code for SIGBUS");
return CrashReason::eInvalidCrashReason;
}
}
std::string
GetCrashReasonString (CrashReason reason, lldb::addr_t fault_addr)
{
std::string str;
switch (reason)
{
default:
assert(false && "invalid CrashReason");
break;
case CrashReason::eInvalidAddress:
str = "signal SIGSEGV: invalid address";
AppendFaultAddr (str, fault_addr);
break;
case CrashReason::ePrivilegedAddress:
str = "signal SIGSEGV: address access protected";
AppendFaultAddr (str, fault_addr);
break;
case CrashReason::eIllegalOpcode:
str = "signal SIGILL: illegal instruction";
break;
case CrashReason::eIllegalOperand:
str = "signal SIGILL: illegal instruction operand";
break;
case CrashReason::eIllegalAddressingMode:
str = "signal SIGILL: illegal addressing mode";
break;
case CrashReason::eIllegalTrap:
str = "signal SIGILL: illegal trap";
break;
case CrashReason::ePrivilegedOpcode:
str = "signal SIGILL: privileged instruction";
break;
case CrashReason::ePrivilegedRegister:
str = "signal SIGILL: privileged register";
break;
case CrashReason::eCoprocessorError:
str = "signal SIGILL: coprocessor error";
break;
case CrashReason::eInternalStackError:
str = "signal SIGILL: internal stack error";
break;
case CrashReason::eIllegalAlignment:
str = "signal SIGBUS: illegal alignment";
break;
case CrashReason::eIllegalAddress:
str = "signal SIGBUS: illegal address";
break;
case CrashReason::eHardwareError:
str = "signal SIGBUS: hardware error";
break;
case CrashReason::eIntegerDivideByZero:
str = "signal SIGFPE: integer divide by zero";
break;
case CrashReason::eIntegerOverflow:
str = "signal SIGFPE: integer overflow";
break;
case CrashReason::eFloatDivideByZero:
str = "signal SIGFPE: floating point divide by zero";
break;
case CrashReason::eFloatOverflow:
str = "signal SIGFPE: floating point overflow";
break;
case CrashReason::eFloatUnderflow:
str = "signal SIGFPE: floating point underflow";
break;
case CrashReason::eFloatInexactResult:
str = "signal SIGFPE: inexact floating point result";
break;
case CrashReason::eFloatInvalidOperation:
str = "signal SIGFPE: invalid floating point operation";
break;
case CrashReason::eFloatSubscriptRange:
str = "signal SIGFPE: invalid floating point subscript range";
break;
}
return str;
}
const char *
CrashReasonAsString (CrashReason reason)
{
#ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
// Just return the code in ascii for integration builds.
chcar str[8];
sprintf(str, "%d", reason);
#else
const char *str = nullptr;
switch (reason)
{
case CrashReason::eInvalidCrashReason:
str = "eInvalidCrashReason";
break;
// SIGSEGV crash reasons.
case CrashReason::eInvalidAddress:
str = "eInvalidAddress";
break;
case CrashReason::ePrivilegedAddress:
str = "ePrivilegedAddress";
break;
// SIGILL crash reasons.
case CrashReason::eIllegalOpcode:
str = "eIllegalOpcode";
break;
case CrashReason::eIllegalOperand:
str = "eIllegalOperand";
break;
case CrashReason::eIllegalAddressingMode:
str = "eIllegalAddressingMode";
break;
case CrashReason::eIllegalTrap:
str = "eIllegalTrap";
break;
case CrashReason::ePrivilegedOpcode:
str = "ePrivilegedOpcode";
break;
case CrashReason::ePrivilegedRegister:
str = "ePrivilegedRegister";
break;
case CrashReason::eCoprocessorError:
str = "eCoprocessorError";
break;
case CrashReason::eInternalStackError:
str = "eInternalStackError";
break;
// SIGBUS crash reasons:
case CrashReason::eIllegalAlignment:
str = "eIllegalAlignment";
break;
case CrashReason::eIllegalAddress:
str = "eIllegalAddress";
break;
case CrashReason::eHardwareError:
str = "eHardwareError";
break;
// SIGFPE crash reasons:
case CrashReason::eIntegerDivideByZero:
str = "eIntegerDivideByZero";
break;
case CrashReason::eIntegerOverflow:
str = "eIntegerOverflow";
break;
case CrashReason::eFloatDivideByZero:
str = "eFloatDivideByZero";
break;
case CrashReason::eFloatOverflow:
str = "eFloatOverflow";
break;
case CrashReason::eFloatUnderflow:
str = "eFloatUnderflow";
break;
case CrashReason::eFloatInexactResult:
str = "eFloatInexactResult";
break;
case CrashReason::eFloatInvalidOperation:
str = "eFloatInvalidOperation";
break;
case CrashReason::eFloatSubscriptRange:
str = "eFloatSubscriptRange";
break;
}
#endif
return str;
}
CrashReason
GetCrashReason(const siginfo_t& info)
{
switch(info.si_signo)
{
case SIGSEGV:
return GetCrashReasonForSIGSEGV(info);
case SIGBUS:
return GetCrashReasonForSIGBUS(info);
case SIGFPE:
return GetCrashReasonForSIGFPE(info);
case SIGILL:
return GetCrashReasonForSIGILL(info);
}
assert(false && "unexpected signal");
return CrashReason::eInvalidCrashReason;
}