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