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