xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/POSIX/CrashReason.cpp (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
1dda28197Spatrick //===-- CrashReason.cpp ---------------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick 
9061da546Spatrick #include "CrashReason.h"
10061da546Spatrick 
11061da546Spatrick #include "llvm/Support/raw_ostream.h"
12061da546Spatrick 
13061da546Spatrick #include <sstream>
14061da546Spatrick 
15061da546Spatrick namespace {
16061da546Spatrick 
AppendFaultAddr(std::string & str,lldb::addr_t addr)17061da546Spatrick void AppendFaultAddr(std::string &str, lldb::addr_t addr) {
18061da546Spatrick   std::stringstream ss;
19061da546Spatrick   ss << " (fault address: 0x" << std::hex << addr << ")";
20061da546Spatrick   str += ss.str();
21061da546Spatrick }
22061da546Spatrick 
23061da546Spatrick #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)24061da546Spatrick void AppendBounds(std::string &str, lldb::addr_t lower_bound,
25061da546Spatrick                   lldb::addr_t upper_bound, lldb::addr_t addr) {
26061da546Spatrick   llvm::raw_string_ostream stream(str);
27061da546Spatrick   if ((unsigned long)addr < lower_bound)
28061da546Spatrick     stream << ": lower bound violation ";
29061da546Spatrick   else
30061da546Spatrick     stream << ": upper bound violation ";
31061da546Spatrick   stream << "(fault address: 0x";
32061da546Spatrick   stream.write_hex(addr);
33061da546Spatrick   stream << ", lower bound: 0x";
34061da546Spatrick   stream.write_hex(lower_bound);
35061da546Spatrick   stream << ", upper bound: 0x";
36061da546Spatrick   stream.write_hex(upper_bound);
37061da546Spatrick   stream << ")";
38061da546Spatrick   stream.flush();
39061da546Spatrick }
40061da546Spatrick #endif
41061da546Spatrick 
GetCrashReasonForSIGSEGV(const siginfo_t & info)42061da546Spatrick CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) {
43061da546Spatrick   assert(info.si_signo == SIGSEGV);
44061da546Spatrick 
45061da546Spatrick   switch (info.si_code) {
46061da546Spatrick #ifdef SI_KERNEL
47061da546Spatrick   case SI_KERNEL:
48061da546Spatrick     // Some platforms will occasionally send nonstandard spurious SI_KERNEL
49061da546Spatrick     // codes. One way to get this is via unaligned SIMD loads.
50061da546Spatrick     return CrashReason::eInvalidAddress; // for lack of anything better
51061da546Spatrick #endif
52061da546Spatrick   case SEGV_MAPERR:
53061da546Spatrick     return CrashReason::eInvalidAddress;
54061da546Spatrick   case SEGV_ACCERR:
55061da546Spatrick     return CrashReason::ePrivilegedAddress;
56061da546Spatrick #ifndef SEGV_BNDERR
57061da546Spatrick #define SEGV_BNDERR 3
58061da546Spatrick #endif
59061da546Spatrick   case SEGV_BNDERR:
60061da546Spatrick     return CrashReason::eBoundViolation;
61*be691f3bSpatrick #ifdef __linux__
62*be691f3bSpatrick #ifndef SEGV_MTEAERR
63*be691f3bSpatrick #define SEGV_MTEAERR 8
64*be691f3bSpatrick #endif
65*be691f3bSpatrick   case SEGV_MTEAERR:
66*be691f3bSpatrick     return CrashReason::eAsyncTagCheckFault;
67*be691f3bSpatrick #ifndef SEGV_MTESERR
68*be691f3bSpatrick #define SEGV_MTESERR 9
69*be691f3bSpatrick #endif
70*be691f3bSpatrick   case SEGV_MTESERR:
71*be691f3bSpatrick     return CrashReason::eSyncTagCheckFault;
72*be691f3bSpatrick #endif // __linux__
73061da546Spatrick   }
74061da546Spatrick 
75061da546Spatrick   return CrashReason::eInvalidCrashReason;
76061da546Spatrick }
77061da546Spatrick 
GetCrashReasonForSIGILL(const siginfo_t & info)78061da546Spatrick CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) {
79061da546Spatrick   assert(info.si_signo == SIGILL);
80061da546Spatrick 
81061da546Spatrick   switch (info.si_code) {
82061da546Spatrick   case ILL_ILLOPC:
83061da546Spatrick     return CrashReason::eIllegalOpcode;
84061da546Spatrick   case ILL_ILLOPN:
85061da546Spatrick     return CrashReason::eIllegalOperand;
86061da546Spatrick   case ILL_ILLADR:
87061da546Spatrick     return CrashReason::eIllegalAddressingMode;
88061da546Spatrick   case ILL_ILLTRP:
89061da546Spatrick     return CrashReason::eIllegalTrap;
90061da546Spatrick   case ILL_PRVOPC:
91061da546Spatrick     return CrashReason::ePrivilegedOpcode;
92061da546Spatrick   case ILL_PRVREG:
93061da546Spatrick     return CrashReason::ePrivilegedRegister;
94061da546Spatrick   case ILL_COPROC:
95061da546Spatrick     return CrashReason::eCoprocessorError;
96061da546Spatrick   case ILL_BADSTK:
97061da546Spatrick     return CrashReason::eInternalStackError;
98061da546Spatrick   }
99061da546Spatrick 
100061da546Spatrick   return CrashReason::eInvalidCrashReason;
101061da546Spatrick }
102061da546Spatrick 
GetCrashReasonForSIGFPE(const siginfo_t & info)103061da546Spatrick CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) {
104061da546Spatrick   assert(info.si_signo == SIGFPE);
105061da546Spatrick 
106061da546Spatrick   switch (info.si_code) {
107061da546Spatrick   case FPE_INTDIV:
108061da546Spatrick     return CrashReason::eIntegerDivideByZero;
109061da546Spatrick   case FPE_INTOVF:
110061da546Spatrick     return CrashReason::eIntegerOverflow;
111061da546Spatrick   case FPE_FLTDIV:
112061da546Spatrick     return CrashReason::eFloatDivideByZero;
113061da546Spatrick   case FPE_FLTOVF:
114061da546Spatrick     return CrashReason::eFloatOverflow;
115061da546Spatrick   case FPE_FLTUND:
116061da546Spatrick     return CrashReason::eFloatUnderflow;
117061da546Spatrick   case FPE_FLTRES:
118061da546Spatrick     return CrashReason::eFloatInexactResult;
119061da546Spatrick   case FPE_FLTINV:
120061da546Spatrick     return CrashReason::eFloatInvalidOperation;
121061da546Spatrick   case FPE_FLTSUB:
122061da546Spatrick     return CrashReason::eFloatSubscriptRange;
123061da546Spatrick   }
124061da546Spatrick 
125061da546Spatrick   return CrashReason::eInvalidCrashReason;
126061da546Spatrick }
127061da546Spatrick 
GetCrashReasonForSIGBUS(const siginfo_t & info)128061da546Spatrick CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) {
129061da546Spatrick   assert(info.si_signo == SIGBUS);
130061da546Spatrick 
131061da546Spatrick   switch (info.si_code) {
132061da546Spatrick   case BUS_ADRALN:
133061da546Spatrick     return CrashReason::eIllegalAlignment;
134061da546Spatrick   case BUS_ADRERR:
135061da546Spatrick     return CrashReason::eIllegalAddress;
136061da546Spatrick   case BUS_OBJERR:
137061da546Spatrick     return CrashReason::eHardwareError;
138061da546Spatrick   }
139061da546Spatrick 
140061da546Spatrick   return CrashReason::eInvalidCrashReason;
141061da546Spatrick }
142061da546Spatrick }
143061da546Spatrick 
GetCrashReasonString(CrashReason reason,const siginfo_t & info)144061da546Spatrick std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
145061da546Spatrick   std::string str;
146061da546Spatrick 
147061da546Spatrick // make sure that siginfo_t has the bound fields available.
148061da546Spatrick #if defined(si_lower) && defined(si_upper)
149061da546Spatrick   if (reason == CrashReason::eBoundViolation) {
150061da546Spatrick     str = "signal SIGSEGV";
151061da546Spatrick     AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower),
152061da546Spatrick                  reinterpret_cast<uintptr_t>(info.si_upper),
153061da546Spatrick                  reinterpret_cast<uintptr_t>(info.si_addr));
154061da546Spatrick     return str;
155061da546Spatrick   }
156061da546Spatrick #endif
157061da546Spatrick 
158061da546Spatrick   return GetCrashReasonString(reason,
159061da546Spatrick                               reinterpret_cast<uintptr_t>(info.si_addr));
160061da546Spatrick }
161061da546Spatrick 
GetCrashReasonString(CrashReason reason,lldb::addr_t fault_addr)162061da546Spatrick std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
163061da546Spatrick   std::string str;
164061da546Spatrick 
165061da546Spatrick   switch (reason) {
166061da546Spatrick   default:
167061da546Spatrick     str = "unknown crash reason";
168061da546Spatrick     break;
169061da546Spatrick 
170061da546Spatrick   case CrashReason::eInvalidAddress:
171061da546Spatrick     str = "signal SIGSEGV: invalid address";
172061da546Spatrick     AppendFaultAddr(str, fault_addr);
173061da546Spatrick     break;
174061da546Spatrick   case CrashReason::ePrivilegedAddress:
175061da546Spatrick     str = "signal SIGSEGV: address access protected";
176061da546Spatrick     AppendFaultAddr(str, fault_addr);
177061da546Spatrick     break;
178061da546Spatrick   case CrashReason::eBoundViolation:
179061da546Spatrick     str = "signal SIGSEGV: bound violation";
180061da546Spatrick     break;
181*be691f3bSpatrick   case CrashReason::eAsyncTagCheckFault:
182*be691f3bSpatrick     str = "signal SIGSEGV: async tag check fault";
183*be691f3bSpatrick     break;
184*be691f3bSpatrick   case CrashReason::eSyncTagCheckFault:
185*be691f3bSpatrick     str = "signal SIGSEGV: sync tag check fault";
186*be691f3bSpatrick     AppendFaultAddr(str, fault_addr);
187*be691f3bSpatrick     break;
188061da546Spatrick   case CrashReason::eIllegalOpcode:
189061da546Spatrick     str = "signal SIGILL: illegal instruction";
190061da546Spatrick     break;
191061da546Spatrick   case CrashReason::eIllegalOperand:
192061da546Spatrick     str = "signal SIGILL: illegal instruction operand";
193061da546Spatrick     break;
194061da546Spatrick   case CrashReason::eIllegalAddressingMode:
195061da546Spatrick     str = "signal SIGILL: illegal addressing mode";
196061da546Spatrick     break;
197061da546Spatrick   case CrashReason::eIllegalTrap:
198061da546Spatrick     str = "signal SIGILL: illegal trap";
199061da546Spatrick     break;
200061da546Spatrick   case CrashReason::ePrivilegedOpcode:
201061da546Spatrick     str = "signal SIGILL: privileged instruction";
202061da546Spatrick     break;
203061da546Spatrick   case CrashReason::ePrivilegedRegister:
204061da546Spatrick     str = "signal SIGILL: privileged register";
205061da546Spatrick     break;
206061da546Spatrick   case CrashReason::eCoprocessorError:
207061da546Spatrick     str = "signal SIGILL: coprocessor error";
208061da546Spatrick     break;
209061da546Spatrick   case CrashReason::eInternalStackError:
210061da546Spatrick     str = "signal SIGILL: internal stack error";
211061da546Spatrick     break;
212061da546Spatrick   case CrashReason::eIllegalAlignment:
213061da546Spatrick     str = "signal SIGBUS: illegal alignment";
214061da546Spatrick     break;
215061da546Spatrick   case CrashReason::eIllegalAddress:
216061da546Spatrick     str = "signal SIGBUS: illegal address";
217061da546Spatrick     break;
218061da546Spatrick   case CrashReason::eHardwareError:
219061da546Spatrick     str = "signal SIGBUS: hardware error";
220061da546Spatrick     break;
221061da546Spatrick   case CrashReason::eIntegerDivideByZero:
222061da546Spatrick     str = "signal SIGFPE: integer divide by zero";
223061da546Spatrick     break;
224061da546Spatrick   case CrashReason::eIntegerOverflow:
225061da546Spatrick     str = "signal SIGFPE: integer overflow";
226061da546Spatrick     break;
227061da546Spatrick   case CrashReason::eFloatDivideByZero:
228061da546Spatrick     str = "signal SIGFPE: floating point divide by zero";
229061da546Spatrick     break;
230061da546Spatrick   case CrashReason::eFloatOverflow:
231061da546Spatrick     str = "signal SIGFPE: floating point overflow";
232061da546Spatrick     break;
233061da546Spatrick   case CrashReason::eFloatUnderflow:
234061da546Spatrick     str = "signal SIGFPE: floating point underflow";
235061da546Spatrick     break;
236061da546Spatrick   case CrashReason::eFloatInexactResult:
237061da546Spatrick     str = "signal SIGFPE: inexact floating point result";
238061da546Spatrick     break;
239061da546Spatrick   case CrashReason::eFloatInvalidOperation:
240061da546Spatrick     str = "signal SIGFPE: invalid floating point operation";
241061da546Spatrick     break;
242061da546Spatrick   case CrashReason::eFloatSubscriptRange:
243061da546Spatrick     str = "signal SIGFPE: invalid floating point subscript range";
244061da546Spatrick     break;
245061da546Spatrick   }
246061da546Spatrick 
247061da546Spatrick   return str;
248061da546Spatrick }
249061da546Spatrick 
CrashReasonAsString(CrashReason reason)250061da546Spatrick const char *CrashReasonAsString(CrashReason reason) {
251061da546Spatrick   const char *str = nullptr;
252061da546Spatrick 
253061da546Spatrick   switch (reason) {
254061da546Spatrick   case CrashReason::eInvalidCrashReason:
255061da546Spatrick     str = "eInvalidCrashReason";
256061da546Spatrick     break;
257061da546Spatrick 
258061da546Spatrick   // SIGSEGV crash reasons.
259061da546Spatrick   case CrashReason::eInvalidAddress:
260061da546Spatrick     str = "eInvalidAddress";
261061da546Spatrick     break;
262061da546Spatrick   case CrashReason::ePrivilegedAddress:
263061da546Spatrick     str = "ePrivilegedAddress";
264061da546Spatrick     break;
265061da546Spatrick   case CrashReason::eBoundViolation:
266061da546Spatrick     str = "eBoundViolation";
267061da546Spatrick     break;
268*be691f3bSpatrick   case CrashReason::eAsyncTagCheckFault:
269*be691f3bSpatrick     str = "eAsyncTagCheckFault";
270*be691f3bSpatrick     break;
271*be691f3bSpatrick   case CrashReason::eSyncTagCheckFault:
272*be691f3bSpatrick     str = "eSyncTagCheckFault";
273*be691f3bSpatrick     break;
274061da546Spatrick 
275061da546Spatrick   // SIGILL crash reasons.
276061da546Spatrick   case CrashReason::eIllegalOpcode:
277061da546Spatrick     str = "eIllegalOpcode";
278061da546Spatrick     break;
279061da546Spatrick   case CrashReason::eIllegalOperand:
280061da546Spatrick     str = "eIllegalOperand";
281061da546Spatrick     break;
282061da546Spatrick   case CrashReason::eIllegalAddressingMode:
283061da546Spatrick     str = "eIllegalAddressingMode";
284061da546Spatrick     break;
285061da546Spatrick   case CrashReason::eIllegalTrap:
286061da546Spatrick     str = "eIllegalTrap";
287061da546Spatrick     break;
288061da546Spatrick   case CrashReason::ePrivilegedOpcode:
289061da546Spatrick     str = "ePrivilegedOpcode";
290061da546Spatrick     break;
291061da546Spatrick   case CrashReason::ePrivilegedRegister:
292061da546Spatrick     str = "ePrivilegedRegister";
293061da546Spatrick     break;
294061da546Spatrick   case CrashReason::eCoprocessorError:
295061da546Spatrick     str = "eCoprocessorError";
296061da546Spatrick     break;
297061da546Spatrick   case CrashReason::eInternalStackError:
298061da546Spatrick     str = "eInternalStackError";
299061da546Spatrick     break;
300061da546Spatrick 
301061da546Spatrick   // SIGBUS crash reasons:
302061da546Spatrick   case CrashReason::eIllegalAlignment:
303061da546Spatrick     str = "eIllegalAlignment";
304061da546Spatrick     break;
305061da546Spatrick   case CrashReason::eIllegalAddress:
306061da546Spatrick     str = "eIllegalAddress";
307061da546Spatrick     break;
308061da546Spatrick   case CrashReason::eHardwareError:
309061da546Spatrick     str = "eHardwareError";
310061da546Spatrick     break;
311061da546Spatrick 
312061da546Spatrick   // SIGFPE crash reasons:
313061da546Spatrick   case CrashReason::eIntegerDivideByZero:
314061da546Spatrick     str = "eIntegerDivideByZero";
315061da546Spatrick     break;
316061da546Spatrick   case CrashReason::eIntegerOverflow:
317061da546Spatrick     str = "eIntegerOverflow";
318061da546Spatrick     break;
319061da546Spatrick   case CrashReason::eFloatDivideByZero:
320061da546Spatrick     str = "eFloatDivideByZero";
321061da546Spatrick     break;
322061da546Spatrick   case CrashReason::eFloatOverflow:
323061da546Spatrick     str = "eFloatOverflow";
324061da546Spatrick     break;
325061da546Spatrick   case CrashReason::eFloatUnderflow:
326061da546Spatrick     str = "eFloatUnderflow";
327061da546Spatrick     break;
328061da546Spatrick   case CrashReason::eFloatInexactResult:
329061da546Spatrick     str = "eFloatInexactResult";
330061da546Spatrick     break;
331061da546Spatrick   case CrashReason::eFloatInvalidOperation:
332061da546Spatrick     str = "eFloatInvalidOperation";
333061da546Spatrick     break;
334061da546Spatrick   case CrashReason::eFloatSubscriptRange:
335061da546Spatrick     str = "eFloatSubscriptRange";
336061da546Spatrick     break;
337061da546Spatrick   }
338061da546Spatrick   return str;
339061da546Spatrick }
340061da546Spatrick 
GetCrashReason(const siginfo_t & info)341061da546Spatrick CrashReason GetCrashReason(const siginfo_t &info) {
342061da546Spatrick   switch (info.si_signo) {
343061da546Spatrick   case SIGSEGV:
344061da546Spatrick     return GetCrashReasonForSIGSEGV(info);
345061da546Spatrick   case SIGBUS:
346061da546Spatrick     return GetCrashReasonForSIGBUS(info);
347061da546Spatrick   case SIGFPE:
348061da546Spatrick     return GetCrashReasonForSIGFPE(info);
349061da546Spatrick   case SIGILL:
350061da546Spatrick     return GetCrashReasonForSIGILL(info);
351061da546Spatrick   }
352061da546Spatrick 
353061da546Spatrick   assert(false && "unexpected signal");
354061da546Spatrick   return CrashReason::eInvalidCrashReason;
355061da546Spatrick }
356