summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonghyun Park <parjong@gmail.com>2017-03-02 18:58:55 +0900
committerJan Vorlicek <janvorli@microsoft.com>2017-03-02 10:58:55 +0100
commit4d30a572f64a5a43d8280970cad944a61b2e92fd (patch)
treeb0d8512a349cb40933353c6a313bc43970212e01
parent542ca8e3fe40dcea5c7c69bc20915ca41b8b3f97 (diff)
downloadcoreclr-4d30a572f64a5a43d8280970cad944a61b2e92fd.tar.gz
coreclr-4d30a572f64a5a43d8280970cad944a61b2e92fd.tar.bz2
coreclr-4d30a572f64a5a43d8280970cad944a61b2e92fd.zip
[x86/Linux] Initial filter support (#9820)
* [x86/Linux] Initial Filter Support
-rw-r--r--src/pal/inc/pal.h9
-rw-r--r--src/pal/inc/rt/palrt.h1
-rw-r--r--src/vm/exceptionhandling.cpp41
3 files changed, 49 insertions, 2 deletions
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h
index eedfbe7640..8d099aff0f 100644
--- a/src/pal/inc/pal.h
+++ b/src/pal/inc/pal.h
@@ -1794,6 +1794,15 @@ typedef struct _CONTEXT {
// support any other values in the ExtendedRegisters) but we might as well be as accurate as we can.
#define CONTEXT_EXREG_XMM_OFFSET 160
+typedef struct _KNONVOLATILE_CONTEXT {
+
+ DWORD Edi;
+ DWORD Esi;
+ DWORD Ebx;
+ DWORD Ebp;
+
+} KNONVOLATILE_CONTEXT, *PKNONVOLATILE_CONTEXT;
+
typedef struct _KNONVOLATILE_CONTEXT_POINTERS {
// The ordering of these fields should be aligned with that
diff --git a/src/pal/inc/rt/palrt.h b/src/pal/inc/rt/palrt.h
index 9360058833..c1362d4c2d 100644
--- a/src/pal/inc/rt/palrt.h
+++ b/src/pal/inc/rt/palrt.h
@@ -1497,6 +1497,7 @@ typedef struct _DISPATCHER_CONTEXT {
PRUNTIME_FUNCTION FunctionEntry;
DWORD EstablisherFrame;
DWORD TargetIp;
+ PKNONVOLATILE_CONTEXT CurrentNonVolatileContextRecord;
PCONTEXT ContextRecord;
PEXCEPTION_ROUTINE LanguageHandler;
PVOID HandlerData;
diff --git a/src/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp
index 69bb1f1d79..4fa36f9d56 100644
--- a/src/vm/exceptionhandling.cpp
+++ b/src/vm/exceptionhandling.cpp
@@ -17,6 +17,10 @@
#include "eventtrace.h"
#include "virtualcallstub.h"
+#if defined(_TARGET_X86_)
+#define USE_CURRENT_CONTEXT_IN_FILTER
+#endif // _TARGET_X86_
+
#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) || defined(_TARGET_X86_)
#define ADJUST_PC_UNWOUND_TO_CALL
#define STACK_RANGE_BOUNDS_ARE_CALLER_SP
@@ -29,6 +33,21 @@
#define ESTABLISHER_FRAME_ADDRESS_IS_CALLER_SP
#endif // _TARGET_ARM_ || _TARGET_ARM64_ || _TARGET_X86_
+#ifdef USE_CURRENT_CONTEXT_IN_FILTER
+inline void CaptureNonvolatileRegisters(PKNONVOLATILE_CONTEXT pNonvolatileContext, PCONTEXT pContext)
+{
+#define CALLEE_SAVED_REGISTER(reg) pNonvolatileContext->reg = pContext->reg;
+ ENUM_CALLEE_SAVED_REGISTERS();
+#undef CALLEE_SAVED_REGISTER
+}
+
+inline void RestoreNonvolatileRegisters(PCONTEXT pContext, PKNONVOLATILE_CONTEXT pNonvolatileContext)
+{
+#define CALLEE_SAVED_REGISTER(reg) pContext->reg = pNonvolatileContext->reg;
+ ENUM_CALLEE_SAVED_REGISTERS();
+#undef CALLEE_SAVED_REGISTER
+}
+#endif
#ifndef DACCESS_COMPILE
// o Functions and funclets are tightly associated. In fact, they are laid out in contiguous memory.
@@ -1287,9 +1306,13 @@ void ExceptionTracker::InitializeCurrentContextForCrawlFrame(CrawlFrame* pcfThis
{
REGDISPLAY *pRD = pcfThisFrame->pRD;
+#ifndef USE_CURRENT_CONTEXT_IN_FILTER
INDEBUG(memset(pRD->pCurrentContext, 0xCC, sizeof(*(pRD->pCurrentContext))));
// Ensure that clients can tell the current context isn't valid.
SetIP(pRD->pCurrentContext, 0);
+#else // !USE_CURRENT_CONTEXT_IN_FILTER
+ RestoreNonvolatileRegisters(pRD->pCurrentContext, pDispatcherContext->CurrentNonVolatileContextRecord);
+#endif // USE_CURRENT_CONTEXT_IN_FILTER
*(pRD->pCallerContext) = *(pDispatcherContext->ContextRecord);
pRD->IsCallerContextValid = TRUE;
@@ -2884,8 +2907,14 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame(
// Assert our invariants (we had set them up in InitializeCrawlFrame):
REGDISPLAY *pCurRegDisplay = pcfThisFrame->GetRegisterSet();
+ CONTEXT *pContext = NULL;
+#ifndef USE_CURRENT_CONTEXT_IN_FILTER
// 1) In first pass, we dont have a valid current context IP
- _ASSERTE(GetIP(pCurRegDisplay->pCurrentContext) == 0);
+ _ASSERTE(GetIP(pCurRegDisplay->pCurrentContext) == 0);
+ pContext = pCurRegDisplay->pCallerContext;
+#else
+ pContext = pCurRegDisplay->pCurrentContext;
+#endif // !USE_CURRENT_CONTEXT_IN_FILTER
#ifdef USE_CALLER_SP_IN_FUNCLET
// 2) Our caller context and caller SP are valid
_ASSERTE(pCurRegDisplay->IsCallerContextValid && pCurRegDisplay->IsCallerSPValid);
@@ -2896,7 +2925,7 @@ CLRUnwindStatus ExceptionTracker::ProcessManagedCallFrame(
{
// CallHandler expects to be in COOP mode.
GCX_COOP();
- dwResult = CallHandler(dwFilterStartPC, sf, &EHClause, pMD, Filter X86_ARG(pCurRegDisplay->pCallerContext) ARM_ARG(pCurRegDisplay->pCallerContext) ARM64_ARG(pCurRegDisplay->pCallerContext));
+ dwResult = CallHandler(dwFilterStartPC, sf, &EHClause, pMD, Filter X86_ARG(pContext) ARM_ARG(pContext) ARM64_ARG(pContext));
}
}
EX_CATCH
@@ -4508,6 +4537,11 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT
// and then check whether an exception handler exists for the frame.
if (dispatcherContext.FunctionEntry != NULL)
{
+#ifdef USE_CURRENT_CONTEXT_IN_FILTER
+ KNONVOLATILE_CONTEXT currentNonVolatileContext;
+ CaptureNonvolatileRegisters(&currentNonVolatileContext, frameContext);
+#endif // USE_CURRENT_CONTEXT_IN_FILTER
+
RtlVirtualUnwind(UNW_FLAG_EHANDLER,
dispatcherContext.ImageBase,
dispatcherContext.ControlPc,
@@ -4526,6 +4560,9 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT
}
dispatcherContext.EstablisherFrame = establisherFrame;
+#ifdef USE_CURRENT_CONTEXT_IN_FILTER
+ dispatcherContext.CurrentNonVolatileContextRecord = &currentNonVolatileContext;
+#endif // USE_CURRENT_CONTEXT_IN_FILTER
dispatcherContext.ContextRecord = frameContext;
// Find exception handler in the current frame