• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- CrashReason.cpp ---------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "CrashReason.h"
10 
11 #include "llvm/Support/raw_ostream.h"
12 
13 #include <sstream>
14 
15 namespace {
16 
AppendFaultAddr(std::string & str,lldb::addr_t addr)17 void AppendFaultAddr(std::string &str, lldb::addr_t addr) {
18   std::stringstream ss;
19   ss << " (fault address: 0x" << std::hex << addr << ")";
20   str += ss.str();
21 }
22 
23 #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)24 void AppendBounds(std::string &str, lldb::addr_t lower_bound,
25                   lldb::addr_t upper_bound, lldb::addr_t addr) {
26   llvm::raw_string_ostream stream(str);
27   if ((unsigned long)addr < lower_bound)
28     stream << ": lower bound violation ";
29   else
30     stream << ": upper bound violation ";
31   stream << "(fault address: 0x";
32   stream.write_hex(addr);
33   stream << ", lower bound: 0x";
34   stream.write_hex(lower_bound);
35   stream << ", upper bound: 0x";
36   stream.write_hex(upper_bound);
37   stream << ")";
38   stream.flush();
39 }
40 #endif
41 
GetCrashReasonForSIGSEGV(const siginfo_t & info)42 CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) {
43   assert(info.si_signo == SIGSEGV);
44 
45   switch (info.si_code) {
46 #ifdef SI_KERNEL
47   case SI_KERNEL:
48     // Some platforms will occasionally send nonstandard spurious SI_KERNEL
49     // codes. One way to get this is via unaligned SIMD loads.
50     return CrashReason::eInvalidAddress; // for lack of anything better
51 #endif
52   case SEGV_MAPERR:
53     return CrashReason::eInvalidAddress;
54   case SEGV_ACCERR:
55     return CrashReason::ePrivilegedAddress;
56 #ifndef SEGV_BNDERR
57 #define SEGV_BNDERR 3
58 #endif
59   case SEGV_BNDERR:
60     return CrashReason::eBoundViolation;
61   }
62 
63   return CrashReason::eInvalidCrashReason;
64 }
65 
GetCrashReasonForSIGILL(const siginfo_t & info)66 CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) {
67   assert(info.si_signo == SIGILL);
68 
69   switch (info.si_code) {
70   case ILL_ILLOPC:
71     return CrashReason::eIllegalOpcode;
72   case ILL_ILLOPN:
73     return CrashReason::eIllegalOperand;
74   case ILL_ILLADR:
75     return CrashReason::eIllegalAddressingMode;
76   case ILL_ILLTRP:
77     return CrashReason::eIllegalTrap;
78   case ILL_PRVOPC:
79     return CrashReason::ePrivilegedOpcode;
80   case ILL_PRVREG:
81     return CrashReason::ePrivilegedRegister;
82   case ILL_COPROC:
83     return CrashReason::eCoprocessorError;
84   case ILL_BADSTK:
85     return CrashReason::eInternalStackError;
86   }
87 
88   return CrashReason::eInvalidCrashReason;
89 }
90 
GetCrashReasonForSIGFPE(const siginfo_t & info)91 CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) {
92   assert(info.si_signo == SIGFPE);
93 
94   switch (info.si_code) {
95   case FPE_INTDIV:
96     return CrashReason::eIntegerDivideByZero;
97   case FPE_INTOVF:
98     return CrashReason::eIntegerOverflow;
99   case FPE_FLTDIV:
100     return CrashReason::eFloatDivideByZero;
101   case FPE_FLTOVF:
102     return CrashReason::eFloatOverflow;
103   case FPE_FLTUND:
104     return CrashReason::eFloatUnderflow;
105   case FPE_FLTRES:
106     return CrashReason::eFloatInexactResult;
107   case FPE_FLTINV:
108     return CrashReason::eFloatInvalidOperation;
109   case FPE_FLTSUB:
110     return CrashReason::eFloatSubscriptRange;
111   }
112 
113   return CrashReason::eInvalidCrashReason;
114 }
115 
GetCrashReasonForSIGBUS(const siginfo_t & info)116 CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) {
117   assert(info.si_signo == SIGBUS);
118 
119   switch (info.si_code) {
120   case BUS_ADRALN:
121     return CrashReason::eIllegalAlignment;
122   case BUS_ADRERR:
123     return CrashReason::eIllegalAddress;
124   case BUS_OBJERR:
125     return CrashReason::eHardwareError;
126   }
127 
128   return CrashReason::eInvalidCrashReason;
129 }
130 }
131 
GetCrashReasonString(CrashReason reason,const siginfo_t & info)132 std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) {
133   std::string str;
134 
135 // make sure that siginfo_t has the bound fields available.
136 #if defined(si_lower) && defined(si_upper)
137   if (reason == CrashReason::eBoundViolation) {
138     str = "signal SIGSEGV";
139     AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower),
140                  reinterpret_cast<uintptr_t>(info.si_upper),
141                  reinterpret_cast<uintptr_t>(info.si_addr));
142     return str;
143   }
144 #endif
145 
146   return GetCrashReasonString(reason,
147                               reinterpret_cast<uintptr_t>(info.si_addr));
148 }
149 
GetCrashReasonString(CrashReason reason,lldb::addr_t fault_addr)150 std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
151   std::string str;
152 
153   switch (reason) {
154   default:
155     str = "unknown crash reason";
156     break;
157 
158   case CrashReason::eInvalidAddress:
159     str = "signal SIGSEGV: invalid address";
160     AppendFaultAddr(str, fault_addr);
161     break;
162   case CrashReason::ePrivilegedAddress:
163     str = "signal SIGSEGV: address access protected";
164     AppendFaultAddr(str, fault_addr);
165     break;
166   case CrashReason::eBoundViolation:
167     str = "signal SIGSEGV: bound violation";
168     break;
169   case CrashReason::eIllegalOpcode:
170     str = "signal SIGILL: illegal instruction";
171     break;
172   case CrashReason::eIllegalOperand:
173     str = "signal SIGILL: illegal instruction operand";
174     break;
175   case CrashReason::eIllegalAddressingMode:
176     str = "signal SIGILL: illegal addressing mode";
177     break;
178   case CrashReason::eIllegalTrap:
179     str = "signal SIGILL: illegal trap";
180     break;
181   case CrashReason::ePrivilegedOpcode:
182     str = "signal SIGILL: privileged instruction";
183     break;
184   case CrashReason::ePrivilegedRegister:
185     str = "signal SIGILL: privileged register";
186     break;
187   case CrashReason::eCoprocessorError:
188     str = "signal SIGILL: coprocessor error";
189     break;
190   case CrashReason::eInternalStackError:
191     str = "signal SIGILL: internal stack error";
192     break;
193   case CrashReason::eIllegalAlignment:
194     str = "signal SIGBUS: illegal alignment";
195     break;
196   case CrashReason::eIllegalAddress:
197     str = "signal SIGBUS: illegal address";
198     break;
199   case CrashReason::eHardwareError:
200     str = "signal SIGBUS: hardware error";
201     break;
202   case CrashReason::eIntegerDivideByZero:
203     str = "signal SIGFPE: integer divide by zero";
204     break;
205   case CrashReason::eIntegerOverflow:
206     str = "signal SIGFPE: integer overflow";
207     break;
208   case CrashReason::eFloatDivideByZero:
209     str = "signal SIGFPE: floating point divide by zero";
210     break;
211   case CrashReason::eFloatOverflow:
212     str = "signal SIGFPE: floating point overflow";
213     break;
214   case CrashReason::eFloatUnderflow:
215     str = "signal SIGFPE: floating point underflow";
216     break;
217   case CrashReason::eFloatInexactResult:
218     str = "signal SIGFPE: inexact floating point result";
219     break;
220   case CrashReason::eFloatInvalidOperation:
221     str = "signal SIGFPE: invalid floating point operation";
222     break;
223   case CrashReason::eFloatSubscriptRange:
224     str = "signal SIGFPE: invalid floating point subscript range";
225     break;
226   }
227 
228   return str;
229 }
230 
CrashReasonAsString(CrashReason reason)231 const char *CrashReasonAsString(CrashReason reason) {
232   const char *str = nullptr;
233 
234   switch (reason) {
235   case CrashReason::eInvalidCrashReason:
236     str = "eInvalidCrashReason";
237     break;
238 
239   // SIGSEGV crash reasons.
240   case CrashReason::eInvalidAddress:
241     str = "eInvalidAddress";
242     break;
243   case CrashReason::ePrivilegedAddress:
244     str = "ePrivilegedAddress";
245     break;
246   case CrashReason::eBoundViolation:
247     str = "eBoundViolation";
248     break;
249 
250   // SIGILL crash reasons.
251   case CrashReason::eIllegalOpcode:
252     str = "eIllegalOpcode";
253     break;
254   case CrashReason::eIllegalOperand:
255     str = "eIllegalOperand";
256     break;
257   case CrashReason::eIllegalAddressingMode:
258     str = "eIllegalAddressingMode";
259     break;
260   case CrashReason::eIllegalTrap:
261     str = "eIllegalTrap";
262     break;
263   case CrashReason::ePrivilegedOpcode:
264     str = "ePrivilegedOpcode";
265     break;
266   case CrashReason::ePrivilegedRegister:
267     str = "ePrivilegedRegister";
268     break;
269   case CrashReason::eCoprocessorError:
270     str = "eCoprocessorError";
271     break;
272   case CrashReason::eInternalStackError:
273     str = "eInternalStackError";
274     break;
275 
276   // SIGBUS crash reasons:
277   case CrashReason::eIllegalAlignment:
278     str = "eIllegalAlignment";
279     break;
280   case CrashReason::eIllegalAddress:
281     str = "eIllegalAddress";
282     break;
283   case CrashReason::eHardwareError:
284     str = "eHardwareError";
285     break;
286 
287   // SIGFPE crash reasons:
288   case CrashReason::eIntegerDivideByZero:
289     str = "eIntegerDivideByZero";
290     break;
291   case CrashReason::eIntegerOverflow:
292     str = "eIntegerOverflow";
293     break;
294   case CrashReason::eFloatDivideByZero:
295     str = "eFloatDivideByZero";
296     break;
297   case CrashReason::eFloatOverflow:
298     str = "eFloatOverflow";
299     break;
300   case CrashReason::eFloatUnderflow:
301     str = "eFloatUnderflow";
302     break;
303   case CrashReason::eFloatInexactResult:
304     str = "eFloatInexactResult";
305     break;
306   case CrashReason::eFloatInvalidOperation:
307     str = "eFloatInvalidOperation";
308     break;
309   case CrashReason::eFloatSubscriptRange:
310     str = "eFloatSubscriptRange";
311     break;
312   }
313   return str;
314 }
315 
GetCrashReason(const siginfo_t & info)316 CrashReason GetCrashReason(const siginfo_t &info) {
317   switch (info.si_signo) {
318   case SIGSEGV:
319     return GetCrashReasonForSIGSEGV(info);
320   case SIGBUS:
321     return GetCrashReasonForSIGBUS(info);
322   case SIGFPE:
323     return GetCrashReasonForSIGFPE(info);
324   case SIGILL:
325     return GetCrashReasonForSIGILL(info);
326   }
327 
328   assert(false && "unexpected signal");
329   return CrashReason::eInvalidCrashReason;
330 }
331