diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2016-06-22 21:00:20 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2016-06-22 21:00:20 +0300 |
commit | d8ba6a0def20c2ef44dbfa8a0f53eb0513043001 (patch) | |
tree | c9f66e680b0311765c4ff71db91511079d05416c /src/Native/Runtime/EHHelpers.cpp | |
parent | 0603b782dc0ab509b4f8c7fa3da1e8923fc24958 (diff) |
Implement Linux hardware and software exception handling (#1417)
This change implements code manager for Linux, context manipulation
and compiler changes necessary to enable exception handling.
All calls to libunwind are disabled for now on non-OSX though, since
our build system doesn't support specifying additional dynamic
libraries, which prevents us from using the libunwind.
Those pieces of code are under CAN_LINK_SHARED_LIBUNWIND ifdef so
that the ifdef can easily be located and removed after we add
the necessary support to the build system.
On OSX, the unwind functionality is part of the compiler support
libraries, so it works.
I have verified that everything works with the libunwind though
by manually invoking clang to link everything together and adding
the necessary libraries to its command line. The exception handling
test was passing with that.
Diffstat (limited to 'src/Native/Runtime/EHHelpers.cpp')
-rw-r--r-- | src/Native/Runtime/EHHelpers.cpp | 66 |
1 files changed, 57 insertions, 9 deletions
diff --git a/src/Native/Runtime/EHHelpers.cpp b/src/Native/Runtime/EHHelpers.cpp index 6d3e33daf..bf2d1ce70 100644 --- a/src/Native/Runtime/EHHelpers.cpp +++ b/src/Native/Runtime/EHHelpers.cpp @@ -345,19 +345,27 @@ static bool InWriteBarrierHelper(UIntNative faultingIP) return false; } -static UIntNative UnwindWriteBarrierToCaller(_CONTEXT * pContext) + + +static UIntNative UnwindWriteBarrierToCaller( +#ifdef PLATFORM_UNIX + PAL_LIMITED_CONTEXT * pContext +#else + _CONTEXT * pContext +#endif + ) { #if defined(_DEBUG) - UIntNative faultingIP = pContext->GetIP(); + UIntNative faultingIP = pContext->GetIp(); ASSERT(InWriteBarrierHelper(faultingIP)); #endif #if defined(_AMD64_) || defined(_X86_) // simulate a ret instruction - UIntNative sp = pContext->GetSP(); // get the stack pointer + UIntNative sp = pContext->GetSp(); // get the stack pointer UIntNative adjustedFaultingIP = *(UIntNative *)sp - 5; // call instruction will be 6 bytes - act as if start of call instruction + 1 were the faulting IP - pContext->SetSP(sp+sizeof(UIntNative)); // pop the stack + pContext->SetSp(sp+sizeof(UIntNative)); // pop the stack #elif defined(_ARM_) - UIntNative adjustedFaultingIP = pContext->GetLR() - 2; // bl instruction will be 4 bytes - act as if start of call instruction + 2 were the faulting IP + UIntNative adjustedFaultingIP = pContext->GetLr() - 2; // bl instruction will be 4 bytes - act as if start of call instruction + 2 were the faulting IP #elif defined(_ARM64_) PORTABILITY_ASSERT("@TODO: FIXME:ARM64"); UIntNative adjustedFaultingIP = -1; @@ -367,9 +375,49 @@ static UIntNative UnwindWriteBarrierToCaller(_CONTEXT * pContext) return adjustedFaultingIP; } +#ifdef PLATFORM_UNIX + +Int32 __stdcall RhpHardwareExceptionHandler(UIntNative faultCode, UIntNative faultAddress, PAL_LIMITED_CONTEXT* palContext, UIntNative* arg0Reg, UIntNative* arg1Reg) +{ + UIntNative faultingIP = palContext->GetIp(); + + ICodeManager * pCodeManager = GetRuntimeInstance()->FindCodeManagerByAddress((PTR_VOID)faultingIP); + if ((pCodeManager != NULL) || (faultCode == STATUS_ACCESS_VIOLATION && InWriteBarrierHelper(faultingIP))) + { + if (faultCode == STATUS_ACCESS_VIOLATION) + { + if (faultAddress < NULL_AREA_SIZE) + { + faultCode = STATUS_REDHAWK_NULL_REFERENCE; + } + + if (pCodeManager == NULL) + { + // we were AV-ing in a write barrier helper - unwind our way to our caller + faultingIP = UnwindWriteBarrierToCaller(palContext); + } + } + else if (faultCode == STATUS_STACK_OVERFLOW) + { + ASSERT_UNCONDITIONALLY("managed stack overflow"); + RhFailFast(); + } + + *arg0Reg = faultCode; + *arg1Reg = faultingIP; + palContext->SetIp((UIntNative)&RhpThrowHwEx); + + return EXCEPTION_CONTINUE_EXECUTION; + } + + return EXCEPTION_CONTINUE_SEARCH; +} + +#else // PLATFORM_UNIX + Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs) { - UIntNative faultingIP = pExPtrs->ContextRecord->GetIP(); + UIntNative faultingIP = pExPtrs->ContextRecord->GetIp(); ICodeManager * pCodeManager = GetRuntimeInstance()->FindCodeManagerByAddress((PTR_VOID)faultingIP); UIntNative faultCode = pExPtrs->ExceptionRecord->ExceptionCode; @@ -391,14 +439,13 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs) RhFailFast2(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord); } - pExPtrs->ContextRecord->SetIP((UIntNative)&RhpThrowHwEx); + pExPtrs->ContextRecord->SetIp((UIntNative)&RhpThrowHwEx); pExPtrs->ContextRecord->SetArg0Reg(faultCode); pExPtrs->ContextRecord->SetArg1Reg(faultingIP); return EXCEPTION_CONTINUE_EXECUTION; } -#ifndef PLATFORM_UNIX { static UInt8 *s_pbRuntimeModuleLower = NULL; static UInt8 *s_pbRuntimeModuleUpper = NULL; @@ -428,11 +475,12 @@ Int32 __stdcall RhpVectoredExceptionHandler(PEXCEPTION_POINTERS pExPtrs) RhFailFast2(pExPtrs->ExceptionRecord, pExPtrs->ContextRecord); } } -#endif // PLATFORM_UNIX return EXCEPTION_CONTINUE_SEARCH; } +#endif // PLATFORM_UNIX + COOP_PINVOKE_HELPER(void, RhpFallbackFailFast, ()) { RhFailFast(); |