diff options
-rw-r--r-- | src/vm/excep.cpp | 50 | ||||
-rw-r--r-- | src/vm/excep.h | 4 | ||||
-rw-r--r-- | src/vm/threadsuspend.cpp | 3 |
3 files changed, 41 insertions, 16 deletions
diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp index e5c024e89c..860e5171a5 100644 --- a/src/vm/excep.cpp +++ b/src/vm/excep.cpp @@ -7870,7 +7870,7 @@ BOOL IsIPInEE(void *ip) } } -#if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK) +#if defined(FEATURE_HIJACK) && (!defined(_TARGET_X86_) || defined(FEATURE_PAL)) // This function is used to check if the specified IP is in the prolog or not. bool IsIPInProlog(EECodeInfo *pCodeInfo) @@ -7887,6 +7887,9 @@ bool IsIPInProlog(EECodeInfo *pCodeInfo) _ASSERTE(pCodeInfo->IsValid()); +#ifdef _TARGET_AMD64_ + + // Optimized version for AMD64 that doesn't need to go through the GC info decoding PTR_RUNTIME_FUNCTION funcEntry = pCodeInfo->GetFunctionEntry(); // We should always get a function entry for a managed method @@ -7896,8 +7899,31 @@ bool IsIPInProlog(EECodeInfo *pCodeInfo) PUNWIND_INFO pUnwindInfo = (PUNWIND_INFO)(pCodeInfo->GetModuleBase() + funcEntry->UnwindData); // Check if the specified IP is beyond the prolog or not. - DWORD dwPrologLen = pUnwindInfo->SizeOfProlog; - if (pCodeInfo->GetRelOffset() >= dwPrologLen) + DWORD prologLen = pUnwindInfo->SizeOfProlog; + +#else // _TARGET_AMD64_ + + GCInfoToken gcInfoToken = pCodeInfo->GetGCInfoToken(); + +#ifdef USE_GC_INFO_DECODER + + GcInfoDecoder gcInfoDecoder( + gcInfoToken, + DECODE_PROLOG_LENGTH + ); + + DWORD prologLen = gcInfoDecoder.GetPrologSize(); + +#else // USE_GC_INFO_DECODER + + size_t prologLen; + pCodeInfo->GetCodeManager()->IsInPrologOrEpilog(0, gcInfoToken, &prologLen); + +#endif // USE_GC_INFO_DECODER + +#endif // _TARGET_AMD64_ + + if (pCodeInfo->GetRelOffset() >= prologLen) { fInsideProlog = false; } @@ -7920,11 +7946,11 @@ bool IsIPInEpilog(PTR_CONTEXT pContextToCheck, EECodeInfo *pCodeInfo, BOOL *pSaf CONTRACTL_END; TADDR ipToCheck = GetIP(pContextToCheck); - + _ASSERTE(pCodeInfo->IsValid()); - + // The Codeinfo should correspond to the IP we are interested in. - _ASSERTE(ipToCheck == pCodeInfo->GetCodeAddress()); + _ASSERTE(PCODEToPINSTR(ipToCheck) == pCodeInfo->GetCodeAddress()); // By default, assume its safe to inject the abort. *pSafeToInjectThreadAbort = TRUE; @@ -7951,11 +7977,10 @@ bool IsIPInEpilog(PTR_CONTEXT pContextToCheck, EECodeInfo *pCodeInfo, BOOL *pSaf // RtlVirtualUnwind against "ipToCheck" results in a NULL personality routine, it implies that we are inside // the epilog. - DWORD64 imageBase = 0; - PUNWIND_INFO pUnwindInfo = NULL; + DWORD_PTR imageBase = 0; CONTEXT tempContext; PVOID HandlerData; - DWORD64 establisherFrame = 0; + DWORD_PTR establisherFrame = 0; PEXCEPTION_ROUTINE personalityRoutine = NULL; // Lookup the function entry for the IP @@ -7965,7 +7990,6 @@ bool IsIPInEpilog(PTR_CONTEXT pContextToCheck, EECodeInfo *pCodeInfo, BOOL *pSaf _ASSERTE(funcEntry != NULL); imageBase = pCodeInfo->GetModuleBase(); - pUnwindInfo = (PUNWIND_INFO)(imageBase+ funcEntry->UnwindData); ZeroMemory(&tempContext, sizeof(CONTEXT)); CopyOSContext(&tempContext, pContextToCheck); @@ -7988,13 +8012,15 @@ bool IsIPInEpilog(PTR_CONTEXT pContextToCheck, EECodeInfo *pCodeInfo, BOOL *pSaf // We are in epilog. fIsInEpilog = true; +#ifdef _TARGET_AMD64_ // Check if context pointers has returned the address of the stack location in the hijacked function // from where RBP was restored. If the address is NULL, then it implies that RBP has been popped off. // Since JIT64 ensures that pop of RBP is the last instruction before ret/jmp, it implies its not safe // to inject an abort @ this point as EstablisherFrame (which will be based // of RBP for managed code since that is the FramePointer register, as indicated in the UnwindInfo) // will be off and can result in bad managed exception dispatch. - if (ctxPtrs.Rbp == NULL) + if (ctxPtrs.Rbp == NULL) +#endif { *pSafeToInjectThreadAbort = FALSE; } @@ -8003,7 +8029,7 @@ bool IsIPInEpilog(PTR_CONTEXT pContextToCheck, EECodeInfo *pCodeInfo, BOOL *pSaf return fIsInEpilog; } -#endif // defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK) +#endif // FEATURE_HIJACK && (!_TARGET_X86_ || FEATURE_PAL) #define EXCEPTION_VISUALCPP_DEBUGGER ((DWORD) (1<<30 | 0x6D<<16 | 5000)) diff --git a/src/vm/excep.h b/src/vm/excep.h index 6df9a98452..c2984b5720 100644 --- a/src/vm/excep.h +++ b/src/vm/excep.h @@ -25,13 +25,13 @@ class Thread; BOOL IsExceptionFromManagedCode(const EXCEPTION_RECORD * pExceptionRecord); bool IsIPInMarkedJitHelper(UINT_PTR uControlPc); -#if defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK) +#if defined(FEATURE_HIJACK) && (!defined(_TARGET_X86_) || defined(FEATURE_PAL)) // General purpose functions for use on an IP in jitted code. bool IsIPInProlog(EECodeInfo *pCodeInfo); bool IsIPInEpilog(PTR_CONTEXT pContextToCheck, EECodeInfo *pCodeInfo, BOOL *pSafeToInjectThreadAbort); -#endif // defined(_TARGET_AMD64_) && defined(FEATURE_HIJACK) +#endif // FEATURE_HIJACK && (!_TARGET_X86_ || FEATURE_PAL) void RaiseFailFastExceptionOnWin7(PEXCEPTION_RECORD pExceptionRecord, PT_CONTEXT pContext); diff --git a/src/vm/threadsuspend.cpp b/src/vm/threadsuspend.cpp index 12fbc901a9..0f3ff6bec9 100644 --- a/src/vm/threadsuspend.cpp +++ b/src/vm/threadsuspend.cpp @@ -7467,10 +7467,9 @@ void HandleGCSuspensionForInterruptedThread(CONTEXT *interruptedContext) pThread->InitRegDisplay(®Display, interruptedContext, true /* validContext */); BOOL unused; -#if defined(_TARGET_AMD64_) + if (IsIPInEpilog(interruptedContext, &codeInfo, &unused)) return; -#endif // Use StackWalkFramesEx to find the location of the return address. This will locate the // return address by checking relative to the caller frame's SP, which is preferable to |