Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/corert.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2016-06-22 21:00:20 +0300
committerJan Kotas <jkotas@microsoft.com>2016-06-22 21:00:20 +0300
commitd8ba6a0def20c2ef44dbfa8a0f53eb0513043001 (patch)
treec9f66e680b0311765c4ff71db91511079d05416c /src/Native/Runtime/EHHelpers.cpp
parent0603b782dc0ab509b4f8c7fa3da1e8923fc24958 (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.cpp66
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();