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

316 lines
8.2 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)
{
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.
return CrashReason::eInvalidAddress; // for lack of anything better
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 = "invalid address";
AppendFaultAddr (str, fault_addr);
break;
case CrashReason::ePrivilegedAddress:
str = "address access protected";
AppendFaultAddr (str, fault_addr);
break;
case CrashReason::eIllegalOpcode:
str = "illegal instruction";
break;
case CrashReason::eIllegalOperand:
str = "illegal instruction operand";
break;
case CrashReason::eIllegalAddressingMode:
str = "illegal addressing mode";
break;
case CrashReason::eIllegalTrap:
str = "illegal trap";
break;
case CrashReason::ePrivilegedOpcode:
str = "privileged instruction";
break;
case CrashReason::ePrivilegedRegister:
str = "privileged register";
break;
case CrashReason::eCoprocessorError:
str = "coprocessor error";
break;
case CrashReason::eInternalStackError:
str = "internal stack error";
break;
case CrashReason::eIllegalAlignment:
str = "illegal alignment";
break;
case CrashReason::eIllegalAddress:
str = "illegal address";
break;
case CrashReason::eHardwareError:
str = "hardware error";
break;
case CrashReason::eIntegerDivideByZero:
str = "integer divide by zero";
break;
case CrashReason::eIntegerOverflow:
str = "integer overflow";
break;
case CrashReason::eFloatDivideByZero:
str = "floating point divide by zero";
break;
case CrashReason::eFloatOverflow:
str = "floating point overflow";
break;
case CrashReason::eFloatUnderflow:
str = "floating point underflow";
break;
case CrashReason::eFloatInexactResult:
str = "inexact floating point result";
break;
case CrashReason::eFloatInvalidOperation:
str = "invalid floating point operation";
break;
case CrashReason::eFloatSubscriptRange:
str = "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;
}