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