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 } 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<uintptr_t>(info.si_lower), 140 reinterpret_cast<uintptr_t>(info.si_upper), 141 reinterpret_cast<uintptr_t>(info.si_addr)); 142 return str; 143 } 144 #endif 145 146 return GetCrashReasonString(reason, 147 reinterpret_cast<uintptr_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 const char *str = nullptr; 233 234 switch (reason) { 235 case CrashReason::eInvalidCrashReason: 236 str = "eInvalidCrashReason"; 237 break; 238 239 // SIGSEGV crash reasons. 240 case CrashReason::eInvalidAddress: 241 str = "eInvalidAddress"; 242 break; 243 case CrashReason::ePrivilegedAddress: 244 str = "ePrivilegedAddress"; 245 break; 246 case CrashReason::eBoundViolation: 247 str = "eBoundViolation"; 248 break; 249 250 // SIGILL crash reasons. 251 case CrashReason::eIllegalOpcode: 252 str = "eIllegalOpcode"; 253 break; 254 case CrashReason::eIllegalOperand: 255 str = "eIllegalOperand"; 256 break; 257 case CrashReason::eIllegalAddressingMode: 258 str = "eIllegalAddressingMode"; 259 break; 260 case CrashReason::eIllegalTrap: 261 str = "eIllegalTrap"; 262 break; 263 case CrashReason::ePrivilegedOpcode: 264 str = "ePrivilegedOpcode"; 265 break; 266 case CrashReason::ePrivilegedRegister: 267 str = "ePrivilegedRegister"; 268 break; 269 case CrashReason::eCoprocessorError: 270 str = "eCoprocessorError"; 271 break; 272 case CrashReason::eInternalStackError: 273 str = "eInternalStackError"; 274 break; 275 276 // SIGBUS crash reasons: 277 case CrashReason::eIllegalAlignment: 278 str = "eIllegalAlignment"; 279 break; 280 case CrashReason::eIllegalAddress: 281 str = "eIllegalAddress"; 282 break; 283 case CrashReason::eHardwareError: 284 str = "eHardwareError"; 285 break; 286 287 // SIGFPE crash reasons: 288 case CrashReason::eIntegerDivideByZero: 289 str = "eIntegerDivideByZero"; 290 break; 291 case CrashReason::eIntegerOverflow: 292 str = "eIntegerOverflow"; 293 break; 294 case CrashReason::eFloatDivideByZero: 295 str = "eFloatDivideByZero"; 296 break; 297 case CrashReason::eFloatOverflow: 298 str = "eFloatOverflow"; 299 break; 300 case CrashReason::eFloatUnderflow: 301 str = "eFloatUnderflow"; 302 break; 303 case CrashReason::eFloatInexactResult: 304 str = "eFloatInexactResult"; 305 break; 306 case CrashReason::eFloatInvalidOperation: 307 str = "eFloatInvalidOperation"; 308 break; 309 case CrashReason::eFloatSubscriptRange: 310 str = "eFloatSubscriptRange"; 311 break; 312 } 313 return str; 314 } 315 316 CrashReason GetCrashReason(const siginfo_t &info) { 317 switch (info.si_signo) { 318 case SIGSEGV: 319 return GetCrashReasonForSIGSEGV(info); 320 case SIGBUS: 321 return GetCrashReasonForSIGBUS(info); 322 case SIGFPE: 323 return GetCrashReasonForSIGFPE(info); 324 case SIGILL: 325 return GetCrashReasonForSIGILL(info); 326 } 327 328 assert(false && "unexpected signal"); 329 return CrashReason::eInvalidCrashReason; 330 } 331