summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Vorlicek <janvorli@microsoft.com>2018-09-24 23:51:44 (GMT)
committerWoongsuk Cho <ws77.cho@samsung.com>2019-03-07 06:27:38 (GMT)
commitb123f4f2eb22ec1d34c657a08e1309a7b19b2c12 (patch)
treefb054b9bff2f50a504dc00ba36e26f533e45952b
parent76d2d2dd465ab9beb50786793876608279983885 (diff)
downloadcoreclr-b123f4f2eb22ec1d34c657a08e1309a7b19b2c12.zip
coreclr-b123f4f2eb22ec1d34c657a08e1309a7b19b2c12.tar.gz
coreclr-b123f4f2eb22ec1d34c657a08e1309a7b19b2c12.tar.bz2
Fix hijacking for ARM/ARM64/x86 on Unix (#20042)refs/changes/15/201015/1
* Fix hijacking for ARM/ARM64/x86 on Unix We were not checking the case when we have interrupted a thread inside of a function epilog for other architectures than amd64. When such an interruption happens, GS cookie check in a stack walking has failed, since we are unable to decode GS cookie location when the IP is in epilog. This fix implements IsIPInEpilog for all architectures and makes the check unconditional. Change-Id: I9adafe6df13ecaff90fc2bf32d8a8db5f40bdcda
-rw-r--r--src/vm/excep.cpp50
-rw-r--r--src/vm/excep.h4
-rw-r--r--src/vm/threadsuspend.cpp3
3 files changed, 41 insertions, 16 deletions
diff --git a/src/vm/excep.cpp b/src/vm/excep.cpp
index e5c024e..860e517 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 6df9a98..c2984b5 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 12fbc90..0f3ff6b 100644
--- a/src/vm/threadsuspend.cpp
+++ b/src/vm/threadsuspend.cpp
@@ -7467,10 +7467,9 @@ void HandleGCSuspensionForInterruptedThread(CONTEXT *interruptedContext)
pThread->InitRegDisplay(&regDisplay, 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