diff options
author | Jonghyun Park <parjong@gmail.com> | 2017-01-24 21:39:37 +0900 |
---|---|---|
committer | Jan Vorlicek <janvorli@microsoft.com> | 2017-01-24 13:39:37 +0100 |
commit | 617c0cf4448b3728b1f07f9aec5f2dc2a40ce5f9 (patch) | |
tree | 57e3dc023b311c6c0685e28348108affe026ff66 | |
parent | 69e3c50ee80a16fd4d2c287422ed7c4d1056b667 (diff) | |
download | coreclr-617c0cf4448b3728b1f07f9aec5f2dc2a40ce5f9.tar.gz coreclr-617c0cf4448b3728b1f07f9aec5f2dc2a40ce5f9.tar.bz2 coreclr-617c0cf4448b3728b1f07f9aec5f2dc2a40ce5f9.zip |
[x86/Linux] Fix EH Region Mismatch (#9043)
-rw-r--r-- | src/pal/inc/pal.h | 9 | ||||
-rw-r--r-- | src/pal/inc/rt/palrt.h | 1 | ||||
-rw-r--r-- | src/pal/src/exception/seh-unwind.cpp | 4 | ||||
-rw-r--r-- | src/unwinder/i386/unwinder_i386.cpp | 2 | ||||
-rw-r--r-- | src/vm/exceptionhandling.cpp | 11 |
5 files changed, 21 insertions, 6 deletions
diff --git a/src/pal/inc/pal.h b/src/pal/inc/pal.h index 6e88553b85..fdcec58c24 100644 --- a/src/pal/inc/pal.h +++ b/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/pal/inc/rt/palrt.h b/src/pal/inc/rt/palrt.h index 6811666e0d..059d3a68a5 100644 --- a/src/pal/inc/rt/palrt.h +++ b/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/pal/src/exception/seh-unwind.cpp b/src/pal/src/exception/seh-unwind.cpp index fa2f109875..e3fa09f7c8 100644 --- a/src/pal/src/exception/seh-unwind.cpp +++ b/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/unwinder/i386/unwinder_i386.cpp b/src/unwinder/i386/unwinder_i386.cpp index 05fa4a1540..f4490ace7e 100644 --- a/src/unwinder/i386/unwinder_i386.cpp +++ b/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/vm/exceptionhandling.cpp b/src/vm/exceptionhandling.cpp index 5fe8a26ecd..d3485e3671 100644 --- a/src/vm/exceptionhandling.cpp +++ b/src/vm/exceptionhandling.cpp @@ -1376,6 +1376,8 @@ void ExceptionTracker::InitializeCrawlFrame(CrawlFrame* pcfThisFrame, Thread* pT // </ARM and ARM64> 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<DWORD_PTR, DWORD_PTR>(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 |