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