1 //===-- CrashReason.cpp -----------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "CrashReason.h"
11 
12 #include <sstream>
13 
14 namespace {
15 
16 void AppendFaultAddr(std::string &str, lldb::addr_t addr) {
17   std::stringstream ss;
18   ss << " (fault address: 0x" << std::hex << addr << ")";
19   str += ss.str();
20 }
21 
22 CrashReason GetCrashReasonForSIGSEGV(const siginfo_t &info) {
23   assert(info.si_signo == SIGSEGV);
24 
25   switch (info.si_code) {
26 #ifdef SI_KERNEL
27   case SI_KERNEL:
28     // Some platforms will occasionally send nonstandard spurious SI_KERNEL
29     // codes.
30     // One way to get this is via unaligned SIMD loads.
31     return CrashReason::eInvalidAddress; // for lack of anything better
32 #endif
33   case SEGV_MAPERR:
34     return CrashReason::eInvalidAddress;
35   case SEGV_ACCERR:
36     return CrashReason::ePrivilegedAddress;
37   }
38 
39   assert(false && "unexpected si_code for SIGSEGV");
40   return CrashReason::eInvalidCrashReason;
41 }
42 
43 CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) {
44   assert(info.si_signo == SIGILL);
45 
46   switch (info.si_code) {
47   case ILL_ILLOPC:
48     return CrashReason::eIllegalOpcode;
49   case ILL_ILLOPN:
50     return CrashReason::eIllegalOperand;
51   case ILL_ILLADR:
52     return CrashReason::eIllegalAddressingMode;
53   case ILL_ILLTRP:
54     return CrashReason::eIllegalTrap;
55   case ILL_PRVOPC:
56     return CrashReason::ePrivilegedOpcode;
57   case ILL_PRVREG:
58     return CrashReason::ePrivilegedRegister;
59   case ILL_COPROC:
60     return CrashReason::eCoprocessorError;
61   case ILL_BADSTK:
62     return CrashReason::eInternalStackError;
63   }
64 
65   assert(false && "unexpected si_code for SIGILL");
66   return CrashReason::eInvalidCrashReason;
67 }
68 
69 CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) {
70   assert(info.si_signo == SIGFPE);
71 
72   switch (info.si_code) {
73   case FPE_INTDIV:
74     return CrashReason::eIntegerDivideByZero;
75   case FPE_INTOVF:
76     return CrashReason::eIntegerOverflow;
77   case FPE_FLTDIV:
78     return CrashReason::eFloatDivideByZero;
79   case FPE_FLTOVF:
80     return CrashReason::eFloatOverflow;
81   case FPE_FLTUND:
82     return CrashReason::eFloatUnderflow;
83   case FPE_FLTRES:
84     return CrashReason::eFloatInexactResult;
85   case FPE_FLTINV:
86     return CrashReason::eFloatInvalidOperation;
87   case FPE_FLTSUB:
88     return CrashReason::eFloatSubscriptRange;
89   }
90 
91   assert(false && "unexpected si_code for SIGFPE");
92   return CrashReason::eInvalidCrashReason;
93 }
94 
95 CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) {
96   assert(info.si_signo == SIGBUS);
97 
98   switch (info.si_code) {
99   case BUS_ADRALN:
100     return CrashReason::eIllegalAlignment;
101   case BUS_ADRERR:
102     return CrashReason::eIllegalAddress;
103   case BUS_OBJERR:
104     return CrashReason::eHardwareError;
105   }
106 
107   assert(false && "unexpected si_code for SIGBUS");
108   return CrashReason::eInvalidCrashReason;
109 }
110 }
111 
112 std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) {
113   std::string str;
114 
115   switch (reason) {
116   default:
117     assert(false && "invalid CrashReason");
118     break;
119 
120   case CrashReason::eInvalidAddress:
121     str = "signal SIGSEGV: invalid address";
122     AppendFaultAddr(str, fault_addr);
123     break;
124   case CrashReason::ePrivilegedAddress:
125     str = "signal SIGSEGV: address access protected";
126     AppendFaultAddr(str, fault_addr);
127     break;
128   case CrashReason::eIllegalOpcode:
129     str = "signal SIGILL: illegal instruction";
130     break;
131   case CrashReason::eIllegalOperand:
132     str = "signal SIGILL: illegal instruction operand";
133     break;
134   case CrashReason::eIllegalAddressingMode:
135     str = "signal SIGILL: illegal addressing mode";
136     break;
137   case CrashReason::eIllegalTrap:
138     str = "signal SIGILL: illegal trap";
139     break;
140   case CrashReason::ePrivilegedOpcode:
141     str = "signal SIGILL: privileged instruction";
142     break;
143   case CrashReason::ePrivilegedRegister:
144     str = "signal SIGILL: privileged register";
145     break;
146   case CrashReason::eCoprocessorError:
147     str = "signal SIGILL: coprocessor error";
148     break;
149   case CrashReason::eInternalStackError:
150     str = "signal SIGILL: internal stack error";
151     break;
152   case CrashReason::eIllegalAlignment:
153     str = "signal SIGBUS: illegal alignment";
154     break;
155   case CrashReason::eIllegalAddress:
156     str = "signal SIGBUS: illegal address";
157     break;
158   case CrashReason::eHardwareError:
159     str = "signal SIGBUS: hardware error";
160     break;
161   case CrashReason::eIntegerDivideByZero:
162     str = "signal SIGFPE: integer divide by zero";
163     break;
164   case CrashReason::eIntegerOverflow:
165     str = "signal SIGFPE: integer overflow";
166     break;
167   case CrashReason::eFloatDivideByZero:
168     str = "signal SIGFPE: floating point divide by zero";
169     break;
170   case CrashReason::eFloatOverflow:
171     str = "signal SIGFPE: floating point overflow";
172     break;
173   case CrashReason::eFloatUnderflow:
174     str = "signal SIGFPE: floating point underflow";
175     break;
176   case CrashReason::eFloatInexactResult:
177     str = "signal SIGFPE: inexact floating point result";
178     break;
179   case CrashReason::eFloatInvalidOperation:
180     str = "signal SIGFPE: invalid floating point operation";
181     break;
182   case CrashReason::eFloatSubscriptRange:
183     str = "signal SIGFPE: invalid floating point subscript range";
184     break;
185   }
186 
187   return str;
188 }
189 
190 const char *CrashReasonAsString(CrashReason reason) {
191 #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
192   // Just return the code in ascii for integration builds.
193   chcar str[8];
194   sprintf(str, "%d", reason);
195 #else
196   const char *str = nullptr;
197 
198   switch (reason) {
199   case CrashReason::eInvalidCrashReason:
200     str = "eInvalidCrashReason";
201     break;
202 
203   // SIGSEGV crash reasons.
204   case CrashReason::eInvalidAddress:
205     str = "eInvalidAddress";
206     break;
207   case CrashReason::ePrivilegedAddress:
208     str = "ePrivilegedAddress";
209     break;
210 
211   // SIGILL crash reasons.
212   case CrashReason::eIllegalOpcode:
213     str = "eIllegalOpcode";
214     break;
215   case CrashReason::eIllegalOperand:
216     str = "eIllegalOperand";
217     break;
218   case CrashReason::eIllegalAddressingMode:
219     str = "eIllegalAddressingMode";
220     break;
221   case CrashReason::eIllegalTrap:
222     str = "eIllegalTrap";
223     break;
224   case CrashReason::ePrivilegedOpcode:
225     str = "ePrivilegedOpcode";
226     break;
227   case CrashReason::ePrivilegedRegister:
228     str = "ePrivilegedRegister";
229     break;
230   case CrashReason::eCoprocessorError:
231     str = "eCoprocessorError";
232     break;
233   case CrashReason::eInternalStackError:
234     str = "eInternalStackError";
235     break;
236 
237   // SIGBUS crash reasons:
238   case CrashReason::eIllegalAlignment:
239     str = "eIllegalAlignment";
240     break;
241   case CrashReason::eIllegalAddress:
242     str = "eIllegalAddress";
243     break;
244   case CrashReason::eHardwareError:
245     str = "eHardwareError";
246     break;
247 
248   // SIGFPE crash reasons:
249   case CrashReason::eIntegerDivideByZero:
250     str = "eIntegerDivideByZero";
251     break;
252   case CrashReason::eIntegerOverflow:
253     str = "eIntegerOverflow";
254     break;
255   case CrashReason::eFloatDivideByZero:
256     str = "eFloatDivideByZero";
257     break;
258   case CrashReason::eFloatOverflow:
259     str = "eFloatOverflow";
260     break;
261   case CrashReason::eFloatUnderflow:
262     str = "eFloatUnderflow";
263     break;
264   case CrashReason::eFloatInexactResult:
265     str = "eFloatInexactResult";
266     break;
267   case CrashReason::eFloatInvalidOperation:
268     str = "eFloatInvalidOperation";
269     break;
270   case CrashReason::eFloatSubscriptRange:
271     str = "eFloatSubscriptRange";
272     break;
273   }
274 #endif
275 
276   return str;
277 }
278 
279 CrashReason GetCrashReason(const siginfo_t &info) {
280   switch (info.si_signo) {
281   case SIGSEGV:
282     return GetCrashReasonForSIGSEGV(info);
283   case SIGBUS:
284     return GetCrashReasonForSIGBUS(info);
285   case SIGFPE:
286     return GetCrashReasonForSIGFPE(info);
287   case SIGILL:
288     return GetCrashReasonForSIGILL(info);
289   }
290 
291   assert(false && "unexpected signal");
292   return CrashReason::eInvalidCrashReason;
293 }
294