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