Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit c2e8c9f

Browse files
authored
port fix for InlinedCallFrame corruption to 3.1 (#28090)
1 parent 8f1aa8e commit c2e8c9f

File tree

1 file changed

+34
-16
lines changed

1 file changed

+34
-16
lines changed

src/vm/i386/excepx86.cpp

Lines changed: 34 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1868,21 +1868,6 @@ NOINLINE LPVOID COMPlusEndCatchWorker(Thread * pThread)
18681868
// Sync managed exception state, for the managed thread, based upon any active exception tracker
18691869
pThread->SyncManagedExceptionState(fIsDebuggerHelperThread);
18701870

1871-
if (InlinedCallFrame::FrameHasActiveCall(pThread->m_pFrame))
1872-
{
1873-
// When unwinding an exception in ReadyToRun, the JIT_PInvokeEnd helper which unlinks the ICF from
1874-
// the thread will be skipped. This is because unlike jitted code, each pinvoke is wrapped by calls
1875-
// to the JIT_PInvokeBegin and JIT_PInvokeEnd helpers, which push and pop the ICF on the thread. The
1876-
// ICF is not linked at the method prolog and unlined at the epilog when running R2R code. Since the
1877-
// JIT_PInvokeEnd helper will be skipped, we need to unlink the ICF here. If the executing method
1878-
// has another pinovoke, it will re-link the ICF again when the JIT_PInvokeBegin helper is called
1879-
1880-
if (ExecutionManager::IsReadyToRunCode(((InlinedCallFrame*)pThread->m_pFrame)->m_pCallerReturnAddress))
1881-
{
1882-
pThread->m_pFrame->Pop(pThread);
1883-
}
1884-
}
1885-
18861871
LOG((LF_EH, LL_INFO1000, "COMPlusPEndCatch: esp=%p\n", esp));
18871872

18881873
return esp;
@@ -3138,6 +3123,39 @@ void ResumeAtJitEH(CrawlFrame* pCf,
31383123
*pHandlerEnd = EHClausePtr->HandlerEndPC;
31393124
}
31403125

3126+
MethodDesc* pMethodDesc = pCf->GetCodeInfo()->GetMethodDesc();
3127+
TADDR startAddress = pCf->GetCodeInfo()->GetStartAddress();
3128+
if (InlinedCallFrame::FrameHasActiveCall(pThread->m_pFrame))
3129+
{
3130+
// When unwinding an exception in ReadyToRun, the JIT_PInvokeEnd helper which unlinks the ICF from
3131+
// the thread will be skipped. This is because unlike jitted code, each pinvoke is wrapped by calls
3132+
// to the JIT_PInvokeBegin and JIT_PInvokeEnd helpers, which push and pop the ICF on the thread. The
3133+
// ICF is not linked at the method prolog and unlinked at the epilog when running R2R code. Since the
3134+
// JIT_PInvokeEnd helper will be skipped, we need to unlink the ICF here. If the executing method
3135+
// has another pinvoke, it will re-link the ICF again when the JIT_PInvokeBegin helper is called.
3136+
3137+
// Check that the InlinedCallFrame is in the method with the exception handler. There can be other
3138+
// InlinedCallFrame somewhere up the call chain that is not related to the current exception
3139+
// handling.
3140+
3141+
#ifdef DEBUG
3142+
TADDR handlerFrameSP = pCf->GetRegisterSet()->SP;
3143+
#endif // DEBUG
3144+
// Find the ESP of the caller of the method with the exception handler.
3145+
bool unwindSuccess = pCf->GetCodeManager()->UnwindStackFrame(pCf->GetRegisterSet(),
3146+
pCf->GetCodeInfo(),
3147+
pCf->GetCodeManagerFlags(),
3148+
pCf->GetCodeManState(),
3149+
NULL /* StackwalkCacheUnwindInfo* */);
3150+
_ASSERTE(unwindSuccess);
3151+
3152+
if (((TADDR)pThread->m_pFrame < pCf->GetRegisterSet()->SP) && ExecutionManager::IsReadyToRunCode(((InlinedCallFrame*)pThread->m_pFrame)->m_pCallerReturnAddress))
3153+
{
3154+
_ASSERTE((TADDR)pThread->m_pFrame >= handlerFrameSP);
3155+
pThread->m_pFrame->Pop(pThread);
3156+
}
3157+
}
3158+
31413159
// save esp so that endcatch can restore it (it always restores, so want correct value)
31423160
ExInfo* pExInfo = &(pThread->GetExceptionState()->m_currentExInfo);
31433161
pExInfo->m_dEsp = (LPVOID)context.GetSP();
@@ -3251,7 +3269,7 @@ void ResumeAtJitEH(CrawlFrame* pCf,
32513269
// that the handle for the current ExInfo has been freed has been delivered
32523270
pExInfo->m_EHClauseInfo.SetManagedCodeEntered(TRUE);
32533271

3254-
ETW::ExceptionLog::ExceptionCatchBegin(pCf->GetCodeInfo()->GetMethodDesc(), (PVOID)pCf->GetCodeInfo()->GetStartAddress());
3272+
ETW::ExceptionLog::ExceptionCatchBegin(pMethodDesc, (PVOID)startAddress);
32553273

32563274
ResumeAtJitEHHelper(&context);
32573275
UNREACHABLE_MSG("Should never return from ResumeAtJitEHHelper!");

0 commit comments

Comments
 (0)