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
5 changes: 5 additions & 0 deletions src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1280,6 +1280,11 @@ void InterpCompiler::BuildGCInfo(InterpMethod *pInterpMethod)
gcInfoEncoder->SetStackBaseRegister(0);
gcInfoEncoder->DefineInterruptibleRange(0, ConvertOffset(m_methodCodeSize));

if (pInterpMethod->unmanagedCallersOnly)
{
gcInfoEncoder->SetReversePInvokeFrameSlot(0);
}

GENERIC_CONTEXTPARAM_TYPE paramType;

switch (m_methodInfo->options & CORINFO_GENERICS_CTXT_MASK)
Expand Down
47 changes: 34 additions & 13 deletions src/coreclr/vm/exceptionhandling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3901,7 +3901,7 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
QCALL_CONTRACT;

StackWalkAction retVal = SWA_FAILED;
CLR_BOOL isPropagatingToNativeCode = FALSE;
CLR_BOOL success = FALSE;
Thread* pThread = GET_THREAD();
ExInfo* pTopExInfo = (ExInfo*)pThread->GetExceptionState()->GetCurrentExceptionTracker();

Expand Down Expand Up @@ -3936,24 +3936,40 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
// 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)
{
// The caller of the interpreted code is not managed.
if (pInterpreterFrame->GetReturnAddress() != 0)
{
// 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);
}
}
}
#endif // FEATURE_INTERPRETER

// Check for reverse pinvoke or CallDescrWorkerInternal.
if (pThis->GetFrameState() == StackFrameIterator::SFITER_NATIVE_MARKER_FRAME)
if ((pThis->GetFrameState() == StackFrameIterator::SFITER_NATIVE_MARKER_FRAME)
#ifdef FEATURE_INTERPRETER
|| (pThis->GetFrameState() == StackFrameIterator::SFITER_DONE)
#endif // FEATURE_INTERPRETER
)
{
EECodeInfo codeInfo(preUnwindControlPC);
#ifdef USE_GC_INFO_DECODER
GcInfoDecoder gcInfoDecoder(codeInfo.GetGCInfoToken(), DECODE_REVERSE_PINVOKE_VAR);
isPropagatingToNativeCode = gcInfoDecoder.GetReversePInvokeFrameStackSlot() != NO_REVERSE_PINVOKE_FRAME;
CLR_BOOL isPropagatingToNativeCode = gcInfoDecoder.GetReversePInvokeFrameStackSlot() != NO_REVERSE_PINVOKE_FRAME;
#else // USE_GC_INFO_DECODER
hdrInfo *hdrInfoBody;
codeInfo.DecodeGCHdrInfo(&hdrInfoBody);
isPropagatingToNativeCode = hdrInfoBody->revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET;
CLR_BOOL isPropagatingToNativeCode = hdrInfoBody->revPInvokeOffset != INVALID_REV_PINVOKE_OFFSET;
#endif // USE_GC_INFO_DECODER
bool isPropagatingToExternalNativeCode = false;

Expand Down Expand Up @@ -4036,10 +4052,13 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
}
}

// Unwind to the caller of the managed code
retVal = pThis->Next();
_ASSERTE(retVal != SWA_FAILED);
_ASSERTE(pThis->GetFrameState() != StackFrameIterator::SFITER_SKIPPED_FRAME_FUNCTION);
*pfIsExceptionIntercepted = FALSE;

if (fUnwoundReversePInvoke)
{
*fUnwoundReversePInvoke = TRUE;
}

goto Exit;
}
}
Expand All @@ -4050,7 +4069,6 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
if (pThis->GetFrameState() == StackFrameIterator::SFITER_DONE)
{
EH_LOG((LL_INFO100, "SfiNext (pass=%d): no more managed frames found on stack", pTopExInfo->m_passNumber));
retVal = SWA_FAILED;
goto Exit;
}

Expand Down Expand Up @@ -4137,6 +4155,10 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
{
EH_LOG((LL_INFO100, "SfiNext (pass=%d): failed to get next frame", pTopExInfo->m_passNumber));
}
else
{
success = TRUE;
}

if (!isCollided)
{
Expand All @@ -4146,7 +4168,7 @@ extern "C" CLR_BOOL QCALLTYPE SfiNext(StackFrameIterator* pThis, uint* uExCollid
Exit:;
END_QCALL;

if (retVal != SWA_FAILED)
if (success)
{
TADDR controlPC = pThis->m_crawl.GetRegisterSet()->ControlPC;
if (!pThis->m_crawl.HasFaulted() && !pThis->m_crawl.IsIPadjusted())
Expand All @@ -4159,7 +4181,7 @@ Exit:;

if (fUnwoundReversePInvoke)
{
*fUnwoundReversePInvoke = isPropagatingToNativeCode;
*fUnwoundReversePInvoke = FALSE;
}

if (pThis->GetFrameState() == StackFrameIterator::SFITER_FRAMELESS_METHOD)
Expand All @@ -4168,10 +4190,9 @@ Exit:;
pTopExInfo->m_passNumber, controlPC, GetRegdisplaySP(pThis->m_crawl.GetRegisterSet()),
pThis->m_crawl.GetFunction()->m_pszDebugClassName, pThis->m_crawl.GetFunction()->m_pszDebugMethodName));
}
return TRUE;
}

return FALSE;
return success;
}

namespace AsmOffsetsAsserts
Expand Down
12 changes: 12 additions & 0 deletions src/coreclr/vm/stackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1515,6 +1515,11 @@ void StackFrameIterator::SkipTo(StackFrameIterator *pOtherStackFrameIterator)
*pRD->pCurrentContextPointers = *pOtherRD->pCurrentContextPointers;
SetIP(pRD->pCurrentContext, GetIP(pOtherRD->pCurrentContext));
SetSP(pRD->pCurrentContext, GetSP(pOtherRD->pCurrentContext));
#ifdef FEATURE_INTERPRETER
// May contain InterpreterFrame address
SetFirstArgReg(pRD->pCurrentContext, GetFirstArgReg(pOtherRD->pCurrentContext));
#endif

#if defined(TARGET_AMD64) && defined(TARGET_WINDOWS)
pRD->SSP = pOtherRD->SSP;
#endif
Expand All @@ -1533,6 +1538,10 @@ void StackFrameIterator::SkipTo(StackFrameIterator *pOtherStackFrameIterator)
*pRD->pCallerContextPointers = *pOtherRD->pCallerContextPointers;
SetIP(pRD->pCallerContext, GetIP(pOtherRD->pCallerContext));
SetSP(pRD->pCallerContext, GetSP(pOtherRD->pCallerContext));
#ifdef FEATURE_INTERPRETER
// May contain InterpreterFrame address
SetFirstArgReg(pRD->pCallerContext, GetFirstArgReg(pOtherRD->pCallerContext));
#endif

#define CALLEE_SAVED_REGISTER(regname) pRD->pCallerContext->regname = (pRD->pCallerContextPointers->regname == NULL) ? pOtherRD->pCallerContext->regname : *pRD->pCallerContextPointers->regname;
ENUM_CALLEE_SAVED_REGISTERS();
Expand Down Expand Up @@ -2851,6 +2860,7 @@ void StackFrameIterator::ProcessCurrentFrame(void)
// Switch to walking the underlying interpreted frames.
// Save the registers the interpreter frames walking reuses so that we can restore them
// after we are done with the interpreter frames.
LOG((LF_GCROOTS, LL_INFO10000, "STACKWALK: Switching to interpreted frames for InterpreterFrame %p, saving SP=%p, IP=%p\n", m_crawl.pFrame, GetIP(pRD->pCurrentContext), GetSP(pRD->pCurrentContext)));
m_interpExecMethodIP = GetIP(pRD->pCurrentContext);
m_interpExecMethodSP = GetSP(pRD->pCurrentContext);
m_interpExecMethodFP = GetFP(pRD->pCurrentContext);
Expand All @@ -2870,6 +2880,8 @@ void StackFrameIterator::ProcessCurrentFrame(void)
{
// We have finished walking the interpreted frames. Process the InterpreterFrame itself.
// Restore the registers to the values they had before we started walking the interpreter frames.
LOG((LF_GCROOTS, LL_INFO10000, "STACKWALK: Completed walking of interpreted frames for InterpreterFrame %p, restoring SP=%p, IP=%p\n", m_crawl.pFrame, m_interpExecMethodSP, m_interpExecMethodIP));
_ASSERTE(dac_cast<TADDR>(m_crawl.pFrame) == GetFirstArgReg(pRD->pCurrentContext));
SetIP(pRD->pCurrentContext, m_interpExecMethodIP);
SetSP(pRD->pCurrentContext, m_interpExecMethodSP);
SetFP(pRD->pCurrentContext, m_interpExecMethodFP);
Expand Down
Loading