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