180814287SRaphael Isemann //===-- CrashReason.cpp ---------------------------------------------------===//
228e57429SChaoren Lin //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
628e57429SChaoren Lin //
728e57429SChaoren Lin //===----------------------------------------------------------------------===//
828e57429SChaoren Lin 
928e57429SChaoren Lin #include "CrashReason.h"
1028e57429SChaoren Lin 
116f8c1f8dSValentina Giusti #include "llvm/Support/raw_ostream.h"
126f8c1f8dSValentina Giusti 
1328e57429SChaoren Lin #include <sstream>
1428e57429SChaoren Lin 
1528e57429SChaoren Lin namespace {
1628e57429SChaoren Lin 
AppendFaultAddr(std::string & str,lldb::addr_t addr)17b9c1b51eSKate Stone void AppendFaultAddr(std::string &str, lldb::addr_t addr) {
1828e57429SChaoren Lin   std::stringstream ss;
1928e57429SChaoren Lin   ss << " (fault address: 0x" << std::hex << addr << ")";
2028e57429SChaoren Lin   str += ss.str();
2128e57429SChaoren Lin }
2228e57429SChaoren Lin 
2373902cc0SDavid Blaikie #if defined(si_lower) && defined(si_upper)
AppendBounds(std::string & str,lldb::addr_t lower_bound,lldb::addr_t upper_bound,lldb::addr_t addr)246f8c1f8dSValentina Giusti void AppendBounds(std::string &str, lldb::addr_t lower_bound,
256f8c1f8dSValentina Giusti                   lldb::addr_t upper_bound, lldb::addr_t addr) {
266f8c1f8dSValentina Giusti   llvm::raw_string_ostream stream(str);
276f8c1f8dSValentina Giusti   if ((unsigned long)addr < lower_bound)
286f8c1f8dSValentina Giusti     stream << ": lower bound violation ";
296f8c1f8dSValentina Giusti   else
306f8c1f8dSValentina Giusti     stream << ": upper bound violation ";
316f8c1f8dSValentina Giusti   stream << "(fault address: 0x";
326f8c1f8dSValentina Giusti   stream.write_hex(addr);
336f8c1f8dSValentina Giusti   stream << ", lower bound: 0x";
346f8c1f8dSValentina Giusti   stream.write_hex(lower_bound);
356f8c1f8dSValentina Giusti   stream << ", upper bound: 0x";
366f8c1f8dSValentina Giusti   stream.write_hex(upper_bound);
376f8c1f8dSValentina Giusti   stream << ")";
386f8c1f8dSValentina Giusti   stream.flush();
396f8c1f8dSValentina Giusti }
4073902cc0SDavid Blaikie #endif
416f8c1f8dSValentina Giusti 
GetCrashReasonForSIGSEGV(const siginfo_t & info)42b9c1b51eSKate Stone CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) {
4328e57429SChaoren Lin   assert(info.si_signo == SIGSEGV);
4428e57429SChaoren Lin 
45b9c1b51eSKate Stone   switch (info.si_code) {
46e0f603faSStephane Sezer #ifdef SI_KERNEL
4728e57429SChaoren Lin   case SI_KERNEL:
48b9c1b51eSKate Stone     // Some platforms will occasionally send nonstandard spurious SI_KERNEL
4905097246SAdrian Prantl     // codes. One way to get this is via unaligned SIMD loads.
5028e57429SChaoren Lin     return CrashReason::eInvalidAddress; // for lack of anything better
51e0f603faSStephane Sezer #endif
5228e57429SChaoren Lin   case SEGV_MAPERR:
5328e57429SChaoren Lin     return CrashReason::eInvalidAddress;
5428e57429SChaoren Lin   case SEGV_ACCERR:
5528e57429SChaoren Lin     return CrashReason::ePrivilegedAddress;
566f8c1f8dSValentina Giusti #ifndef SEGV_BNDERR
576f8c1f8dSValentina Giusti #define SEGV_BNDERR 3
586f8c1f8dSValentina Giusti #endif
596f8c1f8dSValentina Giusti   case SEGV_BNDERR:
606f8c1f8dSValentina Giusti     return CrashReason::eBoundViolation;
61*7e5a187dSPeter Collingbourne #ifdef __linux__
62*7e5a187dSPeter Collingbourne #ifndef SEGV_MTEAERR
63*7e5a187dSPeter Collingbourne #define SEGV_MTEAERR 8
64*7e5a187dSPeter Collingbourne #endif
65*7e5a187dSPeter Collingbourne   case SEGV_MTEAERR:
66*7e5a187dSPeter Collingbourne     return CrashReason::eAsyncTagCheckFault;
67*7e5a187dSPeter Collingbourne #ifndef SEGV_MTESERR
68*7e5a187dSPeter Collingbourne #define SEGV_MTESERR 9
69*7e5a187dSPeter Collingbourne #endif
70*7e5a187dSPeter Collingbourne   case SEGV_MTESERR:
71*7e5a187dSPeter Collingbourne     return CrashReason::eSyncTagCheckFault;
72*7e5a187dSPeter Collingbourne #endif // __linux__
7328e57429SChaoren Lin   }
7428e57429SChaoren Lin 
7528e57429SChaoren Lin   return CrashReason::eInvalidCrashReason;
7628e57429SChaoren Lin }
7728e57429SChaoren Lin 
GetCrashReasonForSIGILL(const siginfo_t & info)78b9c1b51eSKate Stone CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) {
7928e57429SChaoren Lin   assert(info.si_signo == SIGILL);
8028e57429SChaoren Lin 
81b9c1b51eSKate Stone   switch (info.si_code) {
8228e57429SChaoren Lin   case ILL_ILLOPC:
8328e57429SChaoren Lin     return CrashReason::eIllegalOpcode;
8428e57429SChaoren Lin   case ILL_ILLOPN:
8528e57429SChaoren Lin     return CrashReason::eIllegalOperand;
8628e57429SChaoren Lin   case ILL_ILLADR:
8728e57429SChaoren Lin     return CrashReason::eIllegalAddressingMode;
8828e57429SChaoren Lin   case ILL_ILLTRP:
8928e57429SChaoren Lin     return CrashReason::eIllegalTrap;
9028e57429SChaoren Lin   case ILL_PRVOPC:
9128e57429SChaoren Lin     return CrashReason::ePrivilegedOpcode;
9228e57429SChaoren Lin   case ILL_PRVREG:
9328e57429SChaoren Lin     return CrashReason::ePrivilegedRegister;
9428e57429SChaoren Lin   case ILL_COPROC:
9528e57429SChaoren Lin     return CrashReason::eCoprocessorError;
9628e57429SChaoren Lin   case ILL_BADSTK:
9728e57429SChaoren Lin     return CrashReason::eInternalStackError;
9828e57429SChaoren Lin   }
9928e57429SChaoren Lin 
10028e57429SChaoren Lin   return CrashReason::eInvalidCrashReason;
10128e57429SChaoren Lin }
10228e57429SChaoren Lin 
GetCrashReasonForSIGFPE(const siginfo_t & info)103b9c1b51eSKate Stone CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) {
10428e57429SChaoren Lin   assert(info.si_signo == SIGFPE);
10528e57429SChaoren Lin 
106b9c1b51eSKate Stone   switch (info.si_code) {
10728e57429SChaoren Lin   case FPE_INTDIV:
10828e57429SChaoren Lin     return CrashReason::eIntegerDivideByZero;
10928e57429SChaoren Lin   case FPE_INTOVF:
11028e57429SChaoren Lin     return CrashReason::eIntegerOverflow;
11128e57429SChaoren Lin   case FPE_FLTDIV:
11228e57429SChaoren Lin     return CrashReason::eFloatDivideByZero;
11328e57429SChaoren Lin   case FPE_FLTOVF:
11428e57429SChaoren Lin     return CrashReason::eFloatOverflow;
11528e57429SChaoren Lin   case FPE_FLTUND:
11628e57429SChaoren Lin     return CrashReason::eFloatUnderflow;
11728e57429SChaoren Lin   case FPE_FLTRES:
11828e57429SChaoren Lin     return CrashReason::eFloatInexactResult;
11928e57429SChaoren Lin   case FPE_FLTINV:
12028e57429SChaoren Lin     return CrashReason::eFloatInvalidOperation;
12128e57429SChaoren Lin   case FPE_FLTSUB:
12228e57429SChaoren Lin     return CrashReason::eFloatSubscriptRange;
12328e57429SChaoren Lin   }
12428e57429SChaoren Lin 
12528e57429SChaoren Lin   return CrashReason::eInvalidCrashReason;
12628e57429SChaoren Lin }
12728e57429SChaoren Lin 
GetCrashReasonForSIGBUS(const siginfo_t & info)128b9c1b51eSKate Stone CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) {
12928e57429SChaoren Lin   assert(info.si_signo == SIGBUS);
13028e57429SChaoren Lin 
131b9c1b51eSKate Stone   switch (info.si_code) {
13228e57429SChaoren Lin   case BUS_ADRALN:
13328e57429SChaoren Lin     return CrashReason::eIllegalAlignment;
13428e57429SChaoren Lin   case BUS_ADRERR:
13528e57429SChaoren Lin     return CrashReason::eIllegalAddress;
13628e57429SChaoren Lin   case BUS_OBJERR:
13728e57429SChaoren Lin     return CrashReason::eHardwareError;
13828e57429SChaoren Lin   }
13928e57429SChaoren Lin 
14028e57429SChaoren Lin   return CrashReason::eInvalidCrashReason;
14128e57429SChaoren Lin }
14228e57429SChaoren Lin }
14328e57429SChaoren Lin 
GetCrashReasonString(CrashReason reason,const siginfo_t & info)1446f8c1f8dSValentina Giusti std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
14528e57429SChaoren Lin   std::string str;
14628e57429SChaoren Lin 
1471c2c728aSValentina Giusti // make sure that siginfo_t has the bound fields available.
1481c2c728aSValentina Giusti #if defined(si_lower) && defined(si_upper)
1491c2c728aSValentina Giusti   if (reason == CrashReason::eBoundViolation) {
1501c2c728aSValentina Giusti     str = "signal SIGSEGV";
151df6879ecSJan Kratochvil     AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower),
152df6879ecSJan Kratochvil                  reinterpret_cast<uintptr_t>(info.si_upper),
153df6879ecSJan Kratochvil                  reinterpret_cast<uintptr_t>(info.si_addr));
1541c2c728aSValentina Giusti     return str;
1551c2c728aSValentina Giusti   }
1561c2c728aSValentina Giusti #endif
1571c2c728aSValentina Giusti 
1581c2c728aSValentina Giusti   return GetCrashReasonString(reason,
159df6879ecSJan Kratochvil                               reinterpret_cast<uintptr_t>(info.si_addr));
1601c2c728aSValentina Giusti }
1611c2c728aSValentina Giusti 
GetCrashReasonString(CrashReason reason,lldb::addr_t fault_addr)1621c2c728aSValentina Giusti std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
1631c2c728aSValentina Giusti   std::string str;
1641c2c728aSValentina Giusti 
165b9c1b51eSKate Stone   switch (reason) {
16628e57429SChaoren Lin   default:
1674a705e7eSPavel Labath     str = "unknown crash reason";
16828e57429SChaoren Lin     break;
16928e57429SChaoren Lin 
17028e57429SChaoren Lin   case CrashReason::eInvalidAddress:
171c4e25c96SPavel Labath     str = "signal SIGSEGV: invalid address";
1721c2c728aSValentina Giusti     AppendFaultAddr(str, fault_addr);
17328e57429SChaoren Lin     break;
17428e57429SChaoren Lin   case CrashReason::ePrivilegedAddress:
175c4e25c96SPavel Labath     str = "signal SIGSEGV: address access protected";
1761c2c728aSValentina Giusti     AppendFaultAddr(str, fault_addr);
1776f8c1f8dSValentina Giusti     break;
1786f8c1f8dSValentina Giusti   case CrashReason::eBoundViolation:
1791c2c728aSValentina Giusti     str = "signal SIGSEGV: bound violation";
18028e57429SChaoren Lin     break;
181*7e5a187dSPeter Collingbourne   case CrashReason::eAsyncTagCheckFault:
182*7e5a187dSPeter Collingbourne     str = "signal SIGSEGV: async tag check fault";
183*7e5a187dSPeter Collingbourne     break;
184*7e5a187dSPeter Collingbourne   case CrashReason::eSyncTagCheckFault:
185*7e5a187dSPeter Collingbourne     str = "signal SIGSEGV: sync tag check fault";
186*7e5a187dSPeter Collingbourne     AppendFaultAddr(str, fault_addr);
187*7e5a187dSPeter Collingbourne     break;
18828e57429SChaoren Lin   case CrashReason::eIllegalOpcode:
189c4e25c96SPavel Labath     str = "signal SIGILL: illegal instruction";
19028e57429SChaoren Lin     break;
19128e57429SChaoren Lin   case CrashReason::eIllegalOperand:
192c4e25c96SPavel Labath     str = "signal SIGILL: illegal instruction operand";
19328e57429SChaoren Lin     break;
19428e57429SChaoren Lin   case CrashReason::eIllegalAddressingMode:
195c4e25c96SPavel Labath     str = "signal SIGILL: illegal addressing mode";
19628e57429SChaoren Lin     break;
19728e57429SChaoren Lin   case CrashReason::eIllegalTrap:
198c4e25c96SPavel Labath     str = "signal SIGILL: illegal trap";
19928e57429SChaoren Lin     break;
20028e57429SChaoren Lin   case CrashReason::ePrivilegedOpcode:
201c4e25c96SPavel Labath     str = "signal SIGILL: privileged instruction";
20228e57429SChaoren Lin     break;
20328e57429SChaoren Lin   case CrashReason::ePrivilegedRegister:
204c4e25c96SPavel Labath     str = "signal SIGILL: privileged register";
20528e57429SChaoren Lin     break;
20628e57429SChaoren Lin   case CrashReason::eCoprocessorError:
207c4e25c96SPavel Labath     str = "signal SIGILL: coprocessor error";
20828e57429SChaoren Lin     break;
20928e57429SChaoren Lin   case CrashReason::eInternalStackError:
210c4e25c96SPavel Labath     str = "signal SIGILL: internal stack error";
21128e57429SChaoren Lin     break;
21228e57429SChaoren Lin   case CrashReason::eIllegalAlignment:
213c4e25c96SPavel Labath     str = "signal SIGBUS: illegal alignment";
21428e57429SChaoren Lin     break;
21528e57429SChaoren Lin   case CrashReason::eIllegalAddress:
216c4e25c96SPavel Labath     str = "signal SIGBUS: illegal address";
21728e57429SChaoren Lin     break;
21828e57429SChaoren Lin   case CrashReason::eHardwareError:
219c4e25c96SPavel Labath     str = "signal SIGBUS: hardware error";
22028e57429SChaoren Lin     break;
22128e57429SChaoren Lin   case CrashReason::eIntegerDivideByZero:
222c4e25c96SPavel Labath     str = "signal SIGFPE: integer divide by zero";
22328e57429SChaoren Lin     break;
22428e57429SChaoren Lin   case CrashReason::eIntegerOverflow:
225c4e25c96SPavel Labath     str = "signal SIGFPE: integer overflow";
22628e57429SChaoren Lin     break;
22728e57429SChaoren Lin   case CrashReason::eFloatDivideByZero:
228c4e25c96SPavel Labath     str = "signal SIGFPE: floating point divide by zero";
22928e57429SChaoren Lin     break;
23028e57429SChaoren Lin   case CrashReason::eFloatOverflow:
231c4e25c96SPavel Labath     str = "signal SIGFPE: floating point overflow";
23228e57429SChaoren Lin     break;
23328e57429SChaoren Lin   case CrashReason::eFloatUnderflow:
234c4e25c96SPavel Labath     str = "signal SIGFPE: floating point underflow";
23528e57429SChaoren Lin     break;
23628e57429SChaoren Lin   case CrashReason::eFloatInexactResult:
237c4e25c96SPavel Labath     str = "signal SIGFPE: inexact floating point result";
23828e57429SChaoren Lin     break;
23928e57429SChaoren Lin   case CrashReason::eFloatInvalidOperation:
240c4e25c96SPavel Labath     str = "signal SIGFPE: invalid floating point operation";
24128e57429SChaoren Lin     break;
24228e57429SChaoren Lin   case CrashReason::eFloatSubscriptRange:
243c4e25c96SPavel Labath     str = "signal SIGFPE: invalid floating point subscript range";
24428e57429SChaoren Lin     break;
24528e57429SChaoren Lin   }
24628e57429SChaoren Lin 
24728e57429SChaoren Lin   return str;
24828e57429SChaoren Lin }
24928e57429SChaoren Lin 
CrashReasonAsString(CrashReason reason)250b9c1b51eSKate Stone const char *CrashReasonAsString(CrashReason reason) {
25128e57429SChaoren Lin   const char *str = nullptr;
25228e57429SChaoren Lin 
253b9c1b51eSKate Stone   switch (reason) {
25428e57429SChaoren Lin   case CrashReason::eInvalidCrashReason:
25528e57429SChaoren Lin     str = "eInvalidCrashReason";
25628e57429SChaoren Lin     break;
25728e57429SChaoren Lin 
25828e57429SChaoren Lin   // SIGSEGV crash reasons.
25928e57429SChaoren Lin   case CrashReason::eInvalidAddress:
26028e57429SChaoren Lin     str = "eInvalidAddress";
26128e57429SChaoren Lin     break;
26228e57429SChaoren Lin   case CrashReason::ePrivilegedAddress:
26328e57429SChaoren Lin     str = "ePrivilegedAddress";
26428e57429SChaoren Lin     break;
2656f8c1f8dSValentina Giusti   case CrashReason::eBoundViolation:
2666f8c1f8dSValentina Giusti     str = "eBoundViolation";
2676f8c1f8dSValentina Giusti     break;
268*7e5a187dSPeter Collingbourne   case CrashReason::eAsyncTagCheckFault:
269*7e5a187dSPeter Collingbourne     str = "eAsyncTagCheckFault";
270*7e5a187dSPeter Collingbourne     break;
271*7e5a187dSPeter Collingbourne   case CrashReason::eSyncTagCheckFault:
272*7e5a187dSPeter Collingbourne     str = "eSyncTagCheckFault";
273*7e5a187dSPeter Collingbourne     break;
27428e57429SChaoren Lin 
27528e57429SChaoren Lin   // SIGILL crash reasons.
27628e57429SChaoren Lin   case CrashReason::eIllegalOpcode:
27728e57429SChaoren Lin     str = "eIllegalOpcode";
27828e57429SChaoren Lin     break;
27928e57429SChaoren Lin   case CrashReason::eIllegalOperand:
28028e57429SChaoren Lin     str = "eIllegalOperand";
28128e57429SChaoren Lin     break;
28228e57429SChaoren Lin   case CrashReason::eIllegalAddressingMode:
28328e57429SChaoren Lin     str = "eIllegalAddressingMode";
28428e57429SChaoren Lin     break;
28528e57429SChaoren Lin   case CrashReason::eIllegalTrap:
28628e57429SChaoren Lin     str = "eIllegalTrap";
28728e57429SChaoren Lin     break;
28828e57429SChaoren Lin   case CrashReason::ePrivilegedOpcode:
28928e57429SChaoren Lin     str = "ePrivilegedOpcode";
29028e57429SChaoren Lin     break;
29128e57429SChaoren Lin   case CrashReason::ePrivilegedRegister:
29228e57429SChaoren Lin     str = "ePrivilegedRegister";
29328e57429SChaoren Lin     break;
29428e57429SChaoren Lin   case CrashReason::eCoprocessorError:
29528e57429SChaoren Lin     str = "eCoprocessorError";
29628e57429SChaoren Lin     break;
29728e57429SChaoren Lin   case CrashReason::eInternalStackError:
29828e57429SChaoren Lin     str = "eInternalStackError";
29928e57429SChaoren Lin     break;
30028e57429SChaoren Lin 
30128e57429SChaoren Lin   // SIGBUS crash reasons:
30228e57429SChaoren Lin   case CrashReason::eIllegalAlignment:
30328e57429SChaoren Lin     str = "eIllegalAlignment";
30428e57429SChaoren Lin     break;
30528e57429SChaoren Lin   case CrashReason::eIllegalAddress:
30628e57429SChaoren Lin     str = "eIllegalAddress";
30728e57429SChaoren Lin     break;
30828e57429SChaoren Lin   case CrashReason::eHardwareError:
30928e57429SChaoren Lin     str = "eHardwareError";
31028e57429SChaoren Lin     break;
31128e57429SChaoren Lin 
31228e57429SChaoren Lin   // SIGFPE crash reasons:
31328e57429SChaoren Lin   case CrashReason::eIntegerDivideByZero:
31428e57429SChaoren Lin     str = "eIntegerDivideByZero";
31528e57429SChaoren Lin     break;
31628e57429SChaoren Lin   case CrashReason::eIntegerOverflow:
31728e57429SChaoren Lin     str = "eIntegerOverflow";
31828e57429SChaoren Lin     break;
31928e57429SChaoren Lin   case CrashReason::eFloatDivideByZero:
32028e57429SChaoren Lin     str = "eFloatDivideByZero";
32128e57429SChaoren Lin     break;
32228e57429SChaoren Lin   case CrashReason::eFloatOverflow:
32328e57429SChaoren Lin     str = "eFloatOverflow";
32428e57429SChaoren Lin     break;
32528e57429SChaoren Lin   case CrashReason::eFloatUnderflow:
32628e57429SChaoren Lin     str = "eFloatUnderflow";
32728e57429SChaoren Lin     break;
32828e57429SChaoren Lin   case CrashReason::eFloatInexactResult:
32928e57429SChaoren Lin     str = "eFloatInexactResult";
33028e57429SChaoren Lin     break;
33128e57429SChaoren Lin   case CrashReason::eFloatInvalidOperation:
33228e57429SChaoren Lin     str = "eFloatInvalidOperation";
33328e57429SChaoren Lin     break;
33428e57429SChaoren Lin   case CrashReason::eFloatSubscriptRange:
33528e57429SChaoren Lin     str = "eFloatSubscriptRange";
33628e57429SChaoren Lin     break;
33728e57429SChaoren Lin   }
33828e57429SChaoren Lin   return str;
33928e57429SChaoren Lin }
34028e57429SChaoren Lin 
GetCrashReason(const siginfo_t & info)341b9c1b51eSKate Stone CrashReason GetCrashReason(const siginfo_t &info) {
342b9c1b51eSKate Stone   switch (info.si_signo) {
34328e57429SChaoren Lin   case SIGSEGV:
34428e57429SChaoren Lin     return GetCrashReasonForSIGSEGV(info);
34528e57429SChaoren Lin   case SIGBUS:
34628e57429SChaoren Lin     return GetCrashReasonForSIGBUS(info);
34728e57429SChaoren Lin   case SIGFPE:
34828e57429SChaoren Lin     return GetCrashReasonForSIGFPE(info);
34928e57429SChaoren Lin   case SIGILL:
35028e57429SChaoren Lin     return GetCrashReasonForSIGILL(info);
35128e57429SChaoren Lin   }
35228e57429SChaoren Lin 
35328e57429SChaoren Lin   assert(false && "unexpected signal");
35428e57429SChaoren Lin   return CrashReason::eInvalidCrashReason;
35528e57429SChaoren Lin }
356