Files
clang-p2996/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
Chandler Carruth 2946cd7010 Update the file headers across all of the LLVM projects in the monorepo
to reflect the new license.

We understand that people may be surprised that we're moving the header
entirely to discuss the new license. We checked this carefully with the
Foundation's lawyer and we believe this is the correct approach.

Essentially, all code in the project is now made available by the LLVM
project under our new license, so you will see that the license headers
include that license only. Some of our contributors have contributed
code under our old license, and accordingly, we have retained a copy of
our old license notice in the top-level files in each project and
repository.

llvm-svn: 351636
2019-01-19 08:50:56 +00:00

338 lines
9.1 KiB
C++

//===-- CrashReason.cpp -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "CrashReason.h"
#include "llvm/Support/raw_ostream.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();
}
#if defined(si_lower) && defined(si_upper)
void AppendBounds(std::string &str, lldb::addr_t lower_bound,
lldb::addr_t upper_bound, lldb::addr_t addr) {
llvm::raw_string_ostream stream(str);
if ((unsigned long)addr < lower_bound)
stream << ": lower bound violation ";
else
stream << ": upper bound violation ";
stream << "(fault address: 0x";
stream.write_hex(addr);
stream << ", lower bound: 0x";
stream.write_hex(lower_bound);
stream << ", upper bound: 0x";
stream.write_hex(upper_bound);
stream << ")";
stream.flush();
}
#endif
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;
#ifndef SEGV_BNDERR
#define SEGV_BNDERR 3
#endif
case SEGV_BNDERR:
return CrashReason::eBoundViolation;
}
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;
}
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;
}
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;
}
return CrashReason::eInvalidCrashReason;
}
}
std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
std::string str;
// make sure that siginfo_t has the bound fields available.
#if defined(si_lower) && defined(si_upper)
if (reason == CrashReason::eBoundViolation) {
str = "signal SIGSEGV";
AppendBounds(str, reinterpret_cast<lldb::addr_t>(info.si_lower),
reinterpret_cast<lldb::addr_t>(info.si_upper),
reinterpret_cast<lldb::addr_t>(info.si_addr));
return str;
}
#endif
return GetCrashReasonString(reason,
reinterpret_cast<lldb::addr_t>(info.si_addr));
}
std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
std::string str;
switch (reason) {
default:
str = "unknown crash reason";
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::eBoundViolation:
str = "signal SIGSEGV: bound violation";
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;
case CrashReason::eBoundViolation:
str = "eBoundViolation";
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;
}