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