From 7bd2c6804c67312cc240b4b2eec7efc026e08c03 Mon Sep 17 00:00:00 2001 From: Jonghyun Park Date: Tue, 24 Jan 2017 21:39:37 +0900 Subject: [PATCH] [x86/Linux] Fix EH Region Mismatch (dotnet/coreclr#9043) Commit migrated from https://github.com/dotnet/coreclr/commit/617c0cf4448b3728b1f07f9aec5f2dc2a40ce5f9 --- src/coreclr/src/pal/inc/pal.h | 9 +++++++++ src/coreclr/src/pal/inc/rt/palrt.h | 1 + src/coreclr/src/pal/src/exception/seh-unwind.cpp | 4 ++-- src/coreclr/src/unwinder/i386/unwinder_i386.cpp | 2 ++ src/coreclr/src/vm/exceptionhandling.cpp | 11 +++++++---- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/coreclr/src/pal/inc/pal.h b/src/coreclr/src/pal/inc/pal.h index 6e88553..fdcec58 100644 --- a/src/coreclr/src/pal/inc/pal.h +++ b/src/coreclr/src/pal/inc/pal.h @@ -1726,6 +1726,15 @@ QueueUserAPC( #define CONTEXT_EXCEPTION_REQUEST 0x40000000L #define CONTEXT_EXCEPTION_REPORTING 0x80000000L +// +// This flag is set by the unwinder if it has unwound to a call +// site, and cleared whenever it unwinds through a trap frame. +// It is used by language-specific exception handlers to help +// differentiate exception scopes during dispatching. +// + +#define CONTEXT_UNWOUND_TO_CALL 0x20000000 + typedef struct _FLOATING_SAVE_AREA { DWORD ControlWord; DWORD StatusWord; diff --git a/src/coreclr/src/pal/inc/rt/palrt.h b/src/coreclr/src/pal/inc/rt/palrt.h index 6811666..059d3a6 100644 --- a/src/coreclr/src/pal/inc/rt/palrt.h +++ b/src/coreclr/src/pal/inc/rt/palrt.h @@ -1506,6 +1506,7 @@ typedef struct _DISPATCHER_CONTEXT { PEXCEPTION_ROUTINE LanguageHandler; PVOID HandlerData; PUNWIND_HISTORY_TABLE HistoryTable; + BOOLEAN ControlPcIsUnwound; } DISPATCHER_CONTEXT, *PDISPATCHER_CONTEXT; #else diff --git a/src/coreclr/src/pal/src/exception/seh-unwind.cpp b/src/coreclr/src/pal/src/exception/seh-unwind.cpp index fa2f109..e3fa09f 100644 --- a/src/coreclr/src/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/src/pal/src/exception/seh-unwind.cpp @@ -322,14 +322,14 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP if (unw_is_signal_frame(&cursor) > 0) { context->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE; -#if defined(_ARM_) || defined(_ARM64_) +#if defined(_ARM_) || defined(_ARM64_) || defined(_X86_) context->ContextFlags &= ~CONTEXT_UNWOUND_TO_CALL; #endif // _ARM_ || _ARM64_ } else { context->ContextFlags &= ~CONTEXT_EXCEPTION_ACTIVE; -#if defined(_ARM_) || defined(_ARM64_) +#if defined(_ARM_) || defined(_ARM64_) || defined(_X86_) context->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; #endif // _ARM_ || _ARM64_ } diff --git a/src/coreclr/src/unwinder/i386/unwinder_i386.cpp b/src/coreclr/src/unwinder/i386/unwinder_i386.cpp index 05fa4a1..f4490ac 100644 --- a/src/coreclr/src/unwinder/i386/unwinder_i386.cpp +++ b/src/coreclr/src/unwinder/i386/unwinder_i386.cpp @@ -118,6 +118,8 @@ OOPStackUnwinderX86::VirtualUnwind( #undef CALLEE_SAVED_REGISTER } + ContextRecord->ContextFlags |= CONTEXT_UNWOUND_TO_CALL; + ContextRecord->Esp = rd.SP; ContextRecord->Eip = rd.ControlPC; ContextRecord->Ebp = *rd.pEbp; diff --git a/src/coreclr/src/vm/exceptionhandling.cpp b/src/coreclr/src/vm/exceptionhandling.cpp index 5fe8a26..d3485e3 100644 --- a/src/coreclr/src/vm/exceptionhandling.cpp +++ b/src/coreclr/src/vm/exceptionhandling.cpp @@ -1376,6 +1376,8 @@ void ExceptionTracker::InitializeCrawlFrame(CrawlFrame* pcfThisFrame, Thread* pT // pThread->InitRegDisplay(pcfThisFrame->pRD, pDispatcherContext->ContextRecord, true); + bool fAdjustRegdisplayControlPC = false; + // The "if" check below is trying to determine when we have a valid current context in DC->ContextRecord and whether, or not, // RegDisplay needs to be fixed up to set SP and ControlPC to have the values for the current frame for which personality routine // is invoked. @@ -1421,7 +1423,6 @@ void ExceptionTracker::InitializeCrawlFrame(CrawlFrame* pcfThisFrame, Thread* pT // However, we do this *only* when "ControlPCForEHSearch" is the same as "DispatcherContext->ControlPC", // indicating we are not using the thread-abort reraise loop prevention logic. // - bool fAdjustRegdisplayControlPC = false; if (pDispatcherContext->ControlPc == ControlPCForEHSearch) { // Since DispatcherContext->ControlPc is used to initialize the @@ -1437,7 +1438,9 @@ void ExceptionTracker::InitializeCrawlFrame(CrawlFrame* pcfThisFrame, Thread* pT // Remove the Thumb bit ControlPCForEHSearch = ThumbCodeToDataPointer(ControlPCForEHSearch); #endif +#endif // _TARGET_ARM_ || _TARGET_ARM64_ +#if defined(_TARGET_ARM_) || defined(_TARGET_ARM64_) || defined(_TARGET_X86_) // If the OS indicated that the IP is a callsite, then adjust the ControlPC by decrementing it // by two. This is done because unwinding at callsite will make ControlPC point to the // instruction post the callsite. If a protected region ends "at" the callsite, then @@ -1460,7 +1463,7 @@ void ExceptionTracker::InitializeCrawlFrame(CrawlFrame* pcfThisFrame, Thread* pT pcfThisFrame->isIPadjusted = true; } } -#endif // _TARGET_ARM_ || _TARGET_ARM64_ +#endif // _TARGET_ARM_ || _TARGET_ARM64_ || _TARGET_X86_ pcfThisFrame->codeInfo.Init(ControlPCForEHSearch); @@ -4337,7 +4340,7 @@ VOID UnwindManagedExceptionPass2(PAL_SEHException& ex, CONTEXT* unwindStartConte dispatcherContext.FunctionEntry = codeInfo.GetFunctionEntry(); dispatcherContext.ControlPc = controlPc; dispatcherContext.ImageBase = codeInfo.GetModuleBase(); -#if defined(_TARGET_ARM_) +#if defined(_TARGET_ARM_) || defined(_TARGET_X86_) dispatcherContext.ControlPcIsUnwound = !!(currentFrameContext->ContextFlags & CONTEXT_UNWOUND_TO_CALL); #endif // Check whether we have a function table entry for the current controlPC. @@ -4488,7 +4491,7 @@ VOID DECLSPEC_NORETURN UnwindManagedExceptionPass1(PAL_SEHException& ex, CONTEXT dispatcherContext.FunctionEntry = codeInfo.GetFunctionEntry(); dispatcherContext.ControlPc = controlPc; dispatcherContext.ImageBase = codeInfo.GetModuleBase(); -#if defined(_TARGET_ARM_) +#if defined(_TARGET_ARM_) || defined(_TARGET_X86_) dispatcherContext.ControlPcIsUnwound = !!(frameContext->ContextFlags & CONTEXT_UNWOUND_TO_CALL); #endif -- 2.7.4