1 //===-- CrashReason.cpp ---------------------------------------------------===// 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 #ifdef __linux__ 62 #ifndef SEGV_MTEAERR 63 #define SEGV_MTEAERR 8 64 #endif 65 case SEGV_MTEAERR: 66 return CrashReason::eAsyncTagCheckFault; 67 #ifndef SEGV_MTESERR 68 #define SEGV_MTESERR 9 69 #endif 70 case SEGV_MTESERR: 71 return CrashReason::eSyncTagCheckFault; 72 #endif // __linux__ 73 } 74 75 return CrashReason::eInvalidCrashReason; 76 } 77 78 CrashReason GetCrashReasonForSIGILL(const siginfo_t &info) { 79 assert(info.si_signo == SIGILL); 80 81 switch (info.si_code) { 82 case ILL_ILLOPC: 83 return CrashReason::eIllegalOpcode; 84 case ILL_ILLOPN: 85 return CrashReason::eIllegalOperand; 86 case ILL_ILLADR: 87 return CrashReason::eIllegalAddressingMode; 88 case ILL_ILLTRP: 89 return CrashReason::eIllegalTrap; 90 case ILL_PRVOPC: 91 return CrashReason::ePrivilegedOpcode; 92 case ILL_PRVREG: 93 return CrashReason::ePrivilegedRegister; 94 case ILL_COPROC: 95 return CrashReason::eCoprocessorError; 96 case ILL_BADSTK: 97 return CrashReason::eInternalStackError; 98 } 99 100 return CrashReason::eInvalidCrashReason; 101 } 102 103 CrashReason GetCrashReasonForSIGFPE(const siginfo_t &info) { 104 assert(info.si_signo == SIGFPE); 105 106 switch (info.si_code) { 107 case FPE_INTDIV: 108 return CrashReason::eIntegerDivideByZero; 109 case FPE_INTOVF: 110 return CrashReason::eIntegerOverflow; 111 case FPE_FLTDIV: 112 return CrashReason::eFloatDivideByZero; 113 case FPE_FLTOVF: 114 return CrashReason::eFloatOverflow; 115 case FPE_FLTUND: 116 return CrashReason::eFloatUnderflow; 117 case FPE_FLTRES: 118 return CrashReason::eFloatInexactResult; 119 case FPE_FLTINV: 120 return CrashReason::eFloatInvalidOperation; 121 case FPE_FLTSUB: 122 return CrashReason::eFloatSubscriptRange; 123 } 124 125 return CrashReason::eInvalidCrashReason; 126 } 127 128 CrashReason GetCrashReasonForSIGBUS(const siginfo_t &info) { 129 assert(info.si_signo == SIGBUS); 130 131 switch (info.si_code) { 132 case BUS_ADRALN: 133 return CrashReason::eIllegalAlignment; 134 case BUS_ADRERR: 135 return CrashReason::eIllegalAddress; 136 case BUS_OBJERR: 137 return CrashReason::eHardwareError; 138 } 139 140 return CrashReason::eInvalidCrashReason; 141 } 142 } 143 144 std::string GetCrashReasonString(CrashReason reason, const siginfo_t &info) { 145 std::string str; 146 147 // make sure that siginfo_t has the bound fields available. 148 #if defined(si_lower) && defined(si_upper) 149 if (reason == CrashReason::eBoundViolation) { 150 str = "signal SIGSEGV"; 151 AppendBounds(str, reinterpret_cast<uintptr_t>(info.si_lower), 152 reinterpret_cast<uintptr_t>(info.si_upper), 153 reinterpret_cast<uintptr_t>(info.si_addr)); 154 return str; 155 } 156 #endif 157 158 return GetCrashReasonString(reason, 159 reinterpret_cast<uintptr_t>(info.si_addr)); 160 } 161 162 std::string GetCrashReasonString(CrashReason reason, lldb::addr_t fault_addr) { 163 std::string str; 164 165 switch (reason) { 166 default: 167 str = "unknown crash reason"; 168 break; 169 170 case CrashReason::eInvalidAddress: 171 str = "signal SIGSEGV: invalid address"; 172 AppendFaultAddr(str, fault_addr); 173 break; 174 case CrashReason::ePrivilegedAddress: 175 str = "signal SIGSEGV: address access protected"; 176 AppendFaultAddr(str, fault_addr); 177 break; 178 case CrashReason::eBoundViolation: 179 str = "signal SIGSEGV: bound violation"; 180 break; 181 case CrashReason::eAsyncTagCheckFault: 182 str = "signal SIGSEGV: async tag check fault"; 183 break; 184 case CrashReason::eSyncTagCheckFault: 185 str = "signal SIGSEGV: sync tag check fault"; 186 AppendFaultAddr(str, fault_addr); 187 break; 188 case CrashReason::eIllegalOpcode: 189 str = "signal SIGILL: illegal instruction"; 190 break; 191 case CrashReason::eIllegalOperand: 192 str = "signal SIGILL: illegal instruction operand"; 193 break; 194 case CrashReason::eIllegalAddressingMode: 195 str = "signal SIGILL: illegal addressing mode"; 196 break; 197 case CrashReason::eIllegalTrap: 198 str = "signal SIGILL: illegal trap"; 199 break; 200 case CrashReason::ePrivilegedOpcode: 201 str = "signal SIGILL: privileged instruction"; 202 break; 203 case CrashReason::ePrivilegedRegister: 204 str = "signal SIGILL: privileged register"; 205 break; 206 case CrashReason::eCoprocessorError: 207 str = "signal SIGILL: coprocessor error"; 208 break; 209 case CrashReason::eInternalStackError: 210 str = "signal SIGILL: internal stack error"; 211 break; 212 case CrashReason::eIllegalAlignment: 213 str = "signal SIGBUS: illegal alignment"; 214 break; 215 case CrashReason::eIllegalAddress: 216 str = "signal SIGBUS: illegal address"; 217 break; 218 case CrashReason::eHardwareError: 219 str = "signal SIGBUS: hardware error"; 220 break; 221 case CrashReason::eIntegerDivideByZero: 222 str = "signal SIGFPE: integer divide by zero"; 223 break; 224 case CrashReason::eIntegerOverflow: 225 str = "signal SIGFPE: integer overflow"; 226 break; 227 case CrashReason::eFloatDivideByZero: 228 str = "signal SIGFPE: floating point divide by zero"; 229 break; 230 case CrashReason::eFloatOverflow: 231 str = "signal SIGFPE: floating point overflow"; 232 break; 233 case CrashReason::eFloatUnderflow: 234 str = "signal SIGFPE: floating point underflow"; 235 break; 236 case CrashReason::eFloatInexactResult: 237 str = "signal SIGFPE: inexact floating point result"; 238 break; 239 case CrashReason::eFloatInvalidOperation: 240 str = "signal SIGFPE: invalid floating point operation"; 241 break; 242 case CrashReason::eFloatSubscriptRange: 243 str = "signal SIGFPE: invalid floating point subscript range"; 244 break; 245 } 246 247 return str; 248 } 249 250 const char *CrashReasonAsString(CrashReason reason) { 251 const char *str = nullptr; 252 253 switch (reason) { 254 case CrashReason::eInvalidCrashReason: 255 str = "eInvalidCrashReason"; 256 break; 257 258 // SIGSEGV crash reasons. 259 case CrashReason::eInvalidAddress: 260 str = "eInvalidAddress"; 261 break; 262 case CrashReason::ePrivilegedAddress: 263 str = "ePrivilegedAddress"; 264 break; 265 case CrashReason::eBoundViolation: 266 str = "eBoundViolation"; 267 break; 268 case CrashReason::eAsyncTagCheckFault: 269 str = "eAsyncTagCheckFault"; 270 break; 271 case CrashReason::eSyncTagCheckFault: 272 str = "eSyncTagCheckFault"; 273 break; 274 275 // SIGILL crash reasons. 276 case CrashReason::eIllegalOpcode: 277 str = "eIllegalOpcode"; 278 break; 279 case CrashReason::eIllegalOperand: 280 str = "eIllegalOperand"; 281 break; 282 case CrashReason::eIllegalAddressingMode: 283 str = "eIllegalAddressingMode"; 284 break; 285 case CrashReason::eIllegalTrap: 286 str = "eIllegalTrap"; 287 break; 288 case CrashReason::ePrivilegedOpcode: 289 str = "ePrivilegedOpcode"; 290 break; 291 case CrashReason::ePrivilegedRegister: 292 str = "ePrivilegedRegister"; 293 break; 294 case CrashReason::eCoprocessorError: 295 str = "eCoprocessorError"; 296 break; 297 case CrashReason::eInternalStackError: 298 str = "eInternalStackError"; 299 break; 300 301 // SIGBUS crash reasons: 302 case CrashReason::eIllegalAlignment: 303 str = "eIllegalAlignment"; 304 break; 305 case CrashReason::eIllegalAddress: 306 str = "eIllegalAddress"; 307 break; 308 case CrashReason::eHardwareError: 309 str = "eHardwareError"; 310 break; 311 312 // SIGFPE crash reasons: 313 case CrashReason::eIntegerDivideByZero: 314 str = "eIntegerDivideByZero"; 315 break; 316 case CrashReason::eIntegerOverflow: 317 str = "eIntegerOverflow"; 318 break; 319 case CrashReason::eFloatDivideByZero: 320 str = "eFloatDivideByZero"; 321 break; 322 case CrashReason::eFloatOverflow: 323 str = "eFloatOverflow"; 324 break; 325 case CrashReason::eFloatUnderflow: 326 str = "eFloatUnderflow"; 327 break; 328 case CrashReason::eFloatInexactResult: 329 str = "eFloatInexactResult"; 330 break; 331 case CrashReason::eFloatInvalidOperation: 332 str = "eFloatInvalidOperation"; 333 break; 334 case CrashReason::eFloatSubscriptRange: 335 str = "eFloatSubscriptRange"; 336 break; 337 } 338 return str; 339 } 340 341 CrashReason GetCrashReason(const siginfo_t &info) { 342 switch (info.si_signo) { 343 case SIGSEGV: 344 return GetCrashReasonForSIGSEGV(info); 345 case SIGBUS: 346 return GetCrashReasonForSIGBUS(info); 347 case SIGFPE: 348 return GetCrashReasonForSIGFPE(info); 349 case SIGILL: 350 return GetCrashReasonForSIGILL(info); 351 } 352 353 assert(false && "unexpected signal"); 354 return CrashReason::eInvalidCrashReason; 355 } 356