Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 38 additions & 12 deletions src/vm/excep.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand All @@ -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;
}
Expand All @@ -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;
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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))

Expand Down
4 changes: 2 additions & 2 deletions src/vm/excep.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
3 changes: 1 addition & 2 deletions src/vm/threadsuspend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down