]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm-project/lldb/source/Plugins/Process/POSIX/CrashReason.cpp
MFC r355940:
[FreeBSD/FreeBSD.git] / contrib / llvm-project / lldb / source / Plugins / Process / POSIX / CrashReason.cpp
1 //===-- CrashReason.cpp -----------------------------------------*- C++ -*-===//
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
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)
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
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
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
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
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
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<lldb::addr_t>(info.si_lower),
140                  reinterpret_cast<lldb::addr_t>(info.si_upper),
141                  reinterpret_cast<lldb::addr_t>(info.si_addr));
142     return str;
143   }
144 #endif
145
146   return GetCrashReasonString(reason,
147                               reinterpret_cast<lldb::addr_t>(info.si_addr));
148 }
149
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
231 const char *CrashReasonAsString(CrashReason reason) {
232 #ifdef LLDB_CONFIGURATION_BUILDANDINTEGRATION
233   // Just return the code in ascii for integration builds.
234   chcar str[8];
235   sprintf(str, "%d", reason);
236 #else
237   const char *str = nullptr;
238
239   switch (reason) {
240   case CrashReason::eInvalidCrashReason:
241     str = "eInvalidCrashReason";
242     break;
243
244   // SIGSEGV crash reasons.
245   case CrashReason::eInvalidAddress:
246     str = "eInvalidAddress";
247     break;
248   case CrashReason::ePrivilegedAddress:
249     str = "ePrivilegedAddress";
250     break;
251   case CrashReason::eBoundViolation:
252     str = "eBoundViolation";
253     break;
254
255   // SIGILL crash reasons.
256   case CrashReason::eIllegalOpcode:
257     str = "eIllegalOpcode";
258     break;
259   case CrashReason::eIllegalOperand:
260     str = "eIllegalOperand";
261     break;
262   case CrashReason::eIllegalAddressingMode:
263     str = "eIllegalAddressingMode";
264     break;
265   case CrashReason::eIllegalTrap:
266     str = "eIllegalTrap";
267     break;
268   case CrashReason::ePrivilegedOpcode:
269     str = "ePrivilegedOpcode";
270     break;
271   case CrashReason::ePrivilegedRegister:
272     str = "ePrivilegedRegister";
273     break;
274   case CrashReason::eCoprocessorError:
275     str = "eCoprocessorError";
276     break;
277   case CrashReason::eInternalStackError:
278     str = "eInternalStackError";
279     break;
280
281   // SIGBUS crash reasons:
282   case CrashReason::eIllegalAlignment:
283     str = "eIllegalAlignment";
284     break;
285   case CrashReason::eIllegalAddress:
286     str = "eIllegalAddress";
287     break;
288   case CrashReason::eHardwareError:
289     str = "eHardwareError";
290     break;
291
292   // SIGFPE crash reasons:
293   case CrashReason::eIntegerDivideByZero:
294     str = "eIntegerDivideByZero";
295     break;
296   case CrashReason::eIntegerOverflow:
297     str = "eIntegerOverflow";
298     break;
299   case CrashReason::eFloatDivideByZero:
300     str = "eFloatDivideByZero";
301     break;
302   case CrashReason::eFloatOverflow:
303     str = "eFloatOverflow";
304     break;
305   case CrashReason::eFloatUnderflow:
306     str = "eFloatUnderflow";
307     break;
308   case CrashReason::eFloatInexactResult:
309     str = "eFloatInexactResult";
310     break;
311   case CrashReason::eFloatInvalidOperation:
312     str = "eFloatInvalidOperation";
313     break;
314   case CrashReason::eFloatSubscriptRange:
315     str = "eFloatSubscriptRange";
316     break;
317   }
318 #endif
319
320   return str;
321 }
322
323 CrashReason GetCrashReason(const siginfo_t &info) {
324   switch (info.si_signo) {
325   case SIGSEGV:
326     return GetCrashReasonForSIGSEGV(info);
327   case SIGBUS:
328     return GetCrashReasonForSIGBUS(info);
329   case SIGFPE:
330     return GetCrashReasonForSIGFPE(info);
331   case SIGILL:
332     return GetCrashReasonForSIGILL(info);
333   }
334
335   assert(false && "unexpected signal");
336   return CrashReason::eInvalidCrashReason;
337 }