// If si_code values are available for all signals, use those. DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo, const native_context_t *context) { // IMPORTANT NOTE: This function must not call any signal unsafe functions // since it is called from signal handlers. // That includes ASSERT and TRACE macros. switch (siginfo->si_signo) { case SIGILL: switch (siginfo->si_code) { case ILL_ILLOPC: // Illegal opcode case ILL_ILLOPN: // Illegal operand case ILL_ILLADR: // Illegal addressing mode case ILL_ILLTRP: // Illegal trap case ILL_COPROC: // Co-processor error return EXCEPTION_ILLEGAL_INSTRUCTION; case ILL_PRVOPC: // Privileged opcode case ILL_PRVREG: // Privileged register return EXCEPTION_PRIV_INSTRUCTION; case ILL_BADSTK: // Internal stack error return EXCEPTION_STACK_OVERFLOW; default: break; } break; case SIGFPE: switch (siginfo->si_code) { case FPE_INTDIV: return EXCEPTION_INT_DIVIDE_BY_ZERO; case FPE_INTOVF: return EXCEPTION_INT_OVERFLOW; case FPE_FLTDIV: return EXCEPTION_FLT_DIVIDE_BY_ZERO; case FPE_FLTOVF: return EXCEPTION_FLT_OVERFLOW; case FPE_FLTUND: return EXCEPTION_FLT_UNDERFLOW; case FPE_FLTRES: return EXCEPTION_FLT_INEXACT_RESULT; case FPE_FLTINV: return EXCEPTION_FLT_INVALID_OPERATION; case FPE_FLTSUB: return EXCEPTION_FLT_INVALID_OPERATION; default: break; } break; case SIGSEGV: switch (siginfo->si_code) { case SI_USER: // User-generated signal, sometimes sent // for SIGSEGV under normal circumstances case SEGV_MAPERR: // Address not mapped to object case SEGV_ACCERR: // Invalid permissions for mapped object return EXCEPTION_ACCESS_VIOLATION; #ifdef SI_KERNEL case SI_KERNEL: { // Identify privileged instructions that are not identified as such by the system if (g_getGcMarkerExceptionCode != nullptr) { DWORD exceptionCode = g_getGcMarkerExceptionCode(GetNativeContextPC(context)); if (exceptionCode != 0) { return exceptionCode; } } return EXCEPTION_ACCESS_VIOLATION; } #endif default: break; } break; case SIGBUS: switch (siginfo->si_code) { case BUS_ADRALN: // Invalid address alignment return EXCEPTION_DATATYPE_MISALIGNMENT; case BUS_ADRERR: // Non-existent physical address return EXCEPTION_ACCESS_VIOLATION; case BUS_OBJERR: // Object-specific hardware error default: break; } case SIGTRAP: switch (siginfo->si_code) { #ifdef SI_KERNEL case SI_KERNEL: #endif case SI_USER: case TRAP_BRKPT: // Process breakpoint return EXCEPTION_BREAKPOINT; case TRAP_TRACE: // Process trace trap return EXCEPTION_SINGLE_STEP; default: // Got unknown SIGTRAP signal with code siginfo->si_code; return EXCEPTION_ILLEGAL_INSTRUCTION; } default: break; } // Got unknown signal number siginfo->si_signo with code siginfo->si_code; return EXCEPTION_ILLEGAL_INSTRUCTION; }
// If si_code values are available for all signals, use those. DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo, const native_context_t *context) { switch (siginfo->si_signo) { case SIGILL: switch (siginfo->si_code) { case ILL_ILLOPC: // Illegal opcode case ILL_ILLOPN: // Illegal operand case ILL_ILLADR: // Illegal addressing mode case ILL_ILLTRP: // Illegal trap case ILL_COPROC: // Co-processor error return EXCEPTION_ILLEGAL_INSTRUCTION; case ILL_PRVOPC: // Privileged opcode case ILL_PRVREG: // Privileged register return EXCEPTION_PRIV_INSTRUCTION; case ILL_BADSTK: // Internal stack error return EXCEPTION_STACK_OVERFLOW; default: break; } break; case SIGFPE: switch (siginfo->si_code) { case FPE_INTDIV: return EXCEPTION_INT_DIVIDE_BY_ZERO; case FPE_INTOVF: return EXCEPTION_INT_OVERFLOW; case FPE_FLTDIV: return EXCEPTION_FLT_DIVIDE_BY_ZERO; case FPE_FLTOVF: return EXCEPTION_FLT_OVERFLOW; case FPE_FLTUND: return EXCEPTION_FLT_UNDERFLOW; case FPE_FLTRES: return EXCEPTION_FLT_INEXACT_RESULT; case FPE_FLTINV: return EXCEPTION_FLT_INVALID_OPERATION; case FPE_FLTSUB: return EXCEPTION_FLT_INVALID_OPERATION; default: break; } break; case SIGSEGV: switch (siginfo->si_code) { case SI_USER: // User-generated signal, sometimes sent // for SIGSEGV under normal circumstances case SEGV_MAPERR: // Address not mapped to object case SEGV_ACCERR: // Invalid permissions for mapped object return EXCEPTION_ACCESS_VIOLATION; case SI_KERNEL: { // Identify privileged instructions that are not identified as such by the system if (g_getGcMarkerExceptionCode != nullptr) { DWORD exceptionCode = g_getGcMarkerExceptionCode(GetNativeContextPC(context)); if (exceptionCode != 0) { return exceptionCode; } } // fall through } default: break; } break; case SIGBUS: switch (siginfo->si_code) { case BUS_ADRALN: // Invalid address alignment return EXCEPTION_DATATYPE_MISALIGNMENT; case BUS_ADRERR: // Non-existent physical address return EXCEPTION_ACCESS_VIOLATION; case BUS_OBJERR: // Object-specific hardware error default: break; } case SIGTRAP: switch (siginfo->si_code) { case SI_KERNEL: case SI_USER: case TRAP_BRKPT: // Process breakpoint return EXCEPTION_BREAKPOINT; case TRAP_TRACE: // Process trace trap return EXCEPTION_SINGLE_STEP; default: // We don't want to use ASSERT here since it raises SIGTRAP and we // might again end up here resulting in an infinite loop! // so, we print out an error message and return DBG_PRINTF(DLI_ASSERT, defdbgchan, TRUE) ("Got unknown SIGTRAP signal (%d) with code %d\n", SIGTRAP, siginfo->si_code); return EXCEPTION_ILLEGAL_INSTRUCTION; } default: break; } ASSERT("Got unknown signal number %d with code %d\n", siginfo->si_signo, siginfo->si_code); return EXCEPTION_ILLEGAL_INSTRUCTION; }