Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,13 @@ class AsmOffsets
#if TARGET_64BIT
public const int OFFSETOF__REGDISPLAY__m_pCurrentContext = 0x8;
#if FEATURE_INTERPRETER
#if TARGET_AMD64 && !TARGET_UNIX
public const int SIZEOF__StackFrameIterator = 0x178;
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x170;
#else
public const int SIZEOF__StackFrameIterator = 0x170;
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x168;
#endif
#else
public const int SIZEOF__StackFrameIterator = 0x150;
public const int OFFSETOF__StackFrameIterator__m_AdjustedControlPC = 0x148;
Expand Down
56 changes: 34 additions & 22 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3116,6 +3116,17 @@ void CallCatchFunclet(OBJECTREF throwable, BYTE* pHandlerIP, REGDISPLAY* pvRegDi
exInfo->m_ScannedStackRange.ExtendUpperBound(exInfo->m_frameIter.m_crawl.GetRegisterSet()->SP);
DWORD_PTR dwResumePC = 0;
UINT_PTR callerTargetSp = 0;

#ifdef FEATURE_INTERPRETER
if (GetControlPC(pvRegDisplay) == InterpreterFrame::DummyCallerIP)
{
// This is a case when we have unwound out of an interpreted filter funclet. The "Next" moves the
// REGDISPLAY to the native code context that was there before we started to iterate over the
// interpreted frames.
exInfo->m_frameIter.Next();
}
#endif // FEATURE_INTERPRETER

#if defined(HOST_AMD64) && defined(HOST_WINDOWS)
size_t targetSSP = exInfo->m_frameIter.m_crawl.GetRegisterSet()->SSP;
// Verify the SSP points to the slot that matches the ControlPC of the frame containing the catch funclet.
Expand Down Expand Up @@ -3949,32 +3960,33 @@ CLR_BOOL SfiNextWorker(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR
if (isNativeTransition &&
(GetIP(pThis->m_crawl.GetRegisterSet()->pCurrentContext) == InterpreterFrame::DummyCallerIP))
{
// The callerIP is InterpreterFrame::DummyCallerIP when we are going to unwind from the first interpreted frame belonging to an InterpreterFrame.
// That means it is at a transition where non-interpreted code called interpreted one.
// Move the stack frame iterator to the InterpreterFrame and extract the IP of the real caller of the interpreted code.
retVal = pThis->Next();
_ASSERTE(retVal != SWA_FAILED);
_ASSERTE(pThis->GetFrameState() == StackFrameIterator::SFITER_FRAME_FUNCTION);
_ASSERTE(pThis->m_crawl.GetFrame()->GetFrameIdentifier() == FrameIdentifier::InterpreterFrame);
InterpreterFrame *pInterpreterFrame = (InterpreterFrame *)pThis->m_crawl.GetFrame();
// Move to the caller of the interpreted code
retVal = pThis->Next();
_ASSERTE(retVal != SWA_FAILED);
if (pThis->GetFrameState() != StackFrameIterator::SFITER_FRAMELESS_METHOD)
// If the GetReturnAddress returns 0, it means the caller is InterpreterCodeManager::CallFunclet.
// We don't have any TransitionFrame to update the regdisplay from in that case.
if (pInterpreterFrame->GetReturnAddress() != 0)
{
// The caller of the interpreted code is not managed.
if (pInterpreterFrame->GetReturnAddress() != 0)
// The callerIP is InterpreterFrame::DummyCallerIP when we are going to unwind from the first interpreted frame belonging to an InterpreterFrame.
// That means it is at a transition where non-interpreted code called interpreted one.
// Move the stack frame iterator to the InterpreterFrame and extract the IP of the real caller of the interpreted code.
retVal = pThis->Next();
_ASSERTE(retVal != SWA_FAILED);
_ASSERTE(pThis->GetFrameState() == StackFrameIterator::SFITER_FRAME_FUNCTION);
_ASSERTE(pThis->m_crawl.GetFrame()->GetFrameIdentifier() == FrameIdentifier::InterpreterFrame);
// Move to the caller of the interpreted code
retVal = pThis->Next();
_ASSERTE(retVal != SWA_FAILED);
if (pThis->GetFrameState() != StackFrameIterator::SFITER_FRAMELESS_METHOD)
{
// The caller is a managed code, so we can update the regdisplay to point to it.
pInterpreterFrame->UpdateRegDisplay(pThis->m_crawl.GetRegisterSet(), /* updateFloats */ true);
}
else
{
// The caller is not InterpreterCodeManager::CallFunclet, so we can update the regdisplay
// (The CallFunclet has no TransitionFrame to update from)
pInterpreterFrame->UpdateRegDisplay(pThis->m_crawl.GetRegisterSet(), /* updateFloats */ true);
// The caller of the interpreted code is managed.
isNativeTransition = false;
}
}
else
{
// The caller of the interpreted code is managed.
isNativeTransition = false;
}
}
#endif // FEATURE_INTERPRETER

Expand Down Expand Up @@ -4021,12 +4033,12 @@ CLR_BOOL SfiNextWorker(StackFrameIterator* pThis, uint* uExCollideClauseIdx, CLR
// Propagating to CallDescrWorkerInternal, filter funclet or CallEHFunclet.
if (IsCallDescrWorkerInternalReturnAddress(GetIP(pThis->m_crawl.GetRegisterSet()->pCurrentContext)))
{
EH_LOG((LL_INFO100, "SfiNext: the native frame is CallDescrWorkerInternal"));
EH_LOG((LL_INFO100, "SfiNext: the native frame is CallDescrWorkerInternal\n"));
isPropagatingToNativeCode = TRUE;
}
else if (doingFuncletUnwind && codeInfo.GetJitManager()->IsFilterFunclet(&codeInfo))
{
EH_LOG((LL_INFO100, "SfiNext: current frame is filter funclet"));
EH_LOG((LL_INFO100, "SfiNext: current frame is filter funclet\n"));
isPropagatingToNativeCode = TRUE;
}
}
Expand Down
10 changes: 9 additions & 1 deletion src/coreclr/vm/stackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2812,7 +2812,9 @@ void StackFrameIterator::ProcessCurrentFrame(void)
m_interpExecMethodSP = GetSP(pRD->pCurrentContext);
m_interpExecMethodFP = GetFP(pRD->pCurrentContext);
m_interpExecMethodFirstArgReg = GetFirstArgReg(pRD->pCurrentContext);

#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
m_interpExecMethodSSP = pRD->SSP;
#endif
((PTR_InterpreterFrame)m_crawl.pFrame)->SetContextToInterpMethodContextFrame(pRD->pCurrentContext);
if (pRD->pCurrentContext->ContextFlags & CONTEXT_EXCEPTION_ACTIVE)
{
Expand All @@ -2833,6 +2835,9 @@ void StackFrameIterator::ProcessCurrentFrame(void)
SetSP(pRD->pCurrentContext, m_interpExecMethodSP);
SetFP(pRD->pCurrentContext, m_interpExecMethodFP);
SetFirstArgReg(pRD->pCurrentContext, m_interpExecMethodFirstArgReg);
#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
pRD->SSP = m_interpExecMethodSSP;
#endif
SyncRegDisplayToCurrentContext(pRD);
}
}
Expand All @@ -2844,6 +2849,9 @@ void StackFrameIterator::ProcessCurrentFrame(void)
m_interpExecMethodSP = GetSP(pRD->pCurrentContext);
m_interpExecMethodFP = GetFP(pRD->pCurrentContext);
m_interpExecMethodFirstArgReg = GetFirstArgReg(pRD->pCurrentContext);
#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
m_interpExecMethodSSP = pRD->SSP;
#endif
}
}
#endif // FEATURE_INTERPRETER
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/stackwalk.h
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,9 @@ class StackFrameIterator
TADDR m_interpExecMethodSP;
TADDR m_interpExecMethodFP;
TADDR m_interpExecMethodFirstArgReg;
#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
TADDR m_interpExecMethodSSP;
#endif // TARGET_AMD64 && TARGET_WINDOWS
#endif // FEATURE_INTERPRETER

#if defined(RECORD_RESUMABLE_FRAME_SP)
Expand Down