Skip to content

Commit 44b7251

Browse files
Use enum for frametype not v table (#112166)
This change refactors the frame identification mechanism in the runtime by replacing the use of the VTable with an enum FrameIdentifier. The VTable-based approach more suited to C++ code, but presented challenges for assembly code and out-of-process inspections. By using FrameIdentifier, polymorphic dispatch is now handled via if-statements. This change also eliminates the need for GS cookies on Frame objects, as it is no longer necessary to protect the VTable. Key changes include: Renaming FrameType to FrameIdentifier Introducing a GetFrameIdentifier method This update streamlines frame management while improving performance and flexibility for various platforms.
1 parent ec118c7 commit 44b7251

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+1286
-1698
lines changed

src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ ULONG32 DacDbiInterfaceImpl::GetCountOfInternalFrames(VMPTR_Thread vmThread)
465465
if (g_isNewExceptionHandlingEnabled && InlinedCallFrame::FrameHasActiveCall(pFrame))
466466
{
467467
// Skip new exception handling helpers
468-
InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pFrame;
468+
InlinedCallFrame *pInlinedCallFrame = dac_cast<PTR_InlinedCallFrame>(pFrame);
469469
PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum;
470470
TADDR datum = dac_cast<TADDR>(pMD);
471471
if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper)
@@ -518,7 +518,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread
518518
if (g_isNewExceptionHandlingEnabled && InlinedCallFrame::FrameHasActiveCall(pFrame))
519519
{
520520
// Skip new exception handling helpers
521-
InlinedCallFrame *pInlinedCallFrame = (InlinedCallFrame *)pFrame;
521+
InlinedCallFrame *pInlinedCallFrame = dac_cast<PTR_InlinedCallFrame>(pFrame);
522522
PTR_NDirectMethodDesc pMD = pInlinedCallFrame->m_Datum;
523523
TADDR datum = dac_cast<TADDR>(pMD);
524524
if ((datum & (TADDR)InlinedCallFrameMarker::Mask) == (TADDR)InlinedCallFrameMarker::ExceptionHandlingHelper)
@@ -558,7 +558,7 @@ void DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thread
558558
// it. In this case, pMD will remain NULL.
559559
EX_TRY_ALLOW_DATATARGET_MISSING_MEMORY
560560
{
561-
if (pFrame->GetVTablePtr() == ComMethodFrame::GetMethodFrameVPtr())
561+
if (pFrame->GetFrameIdentifier() == FrameIdentifier::ComMethodFrame)
562562
{
563563
ComMethodFrame * pCOMFrame = dac_cast<PTR_ComMethodFrame>(pFrame);
564564
PTR_VOID pUnkStackSlot = pCOMFrame->GetPointerToArguments();
@@ -1142,7 +1142,7 @@ CorDebugInternalFrameType DacDbiInterfaceImpl::GetInternalFrameType(Frame * pFra
11421142
}
11431143
else if (ft == Frame::TYPE_EXIT)
11441144
{
1145-
if ((pFrame->GetVTablePtr() != InlinedCallFrame::GetMethodFrameVPtr()) ||
1145+
if ((pFrame->GetFrameIdentifier() != FrameIdentifier::InlinedCallFrame) ||
11461146
InlinedCallFrame::FrameHasActiveCall(pFrame))
11471147
{
11481148
resultType = STUBFRAME_M2U;
@@ -1153,7 +1153,7 @@ CorDebugInternalFrameType DacDbiInterfaceImpl::GetInternalFrameType(Frame * pFra
11531153

11541154
case Frame::TT_M2U:
11551155
// Refer to the comment in DebuggerWalkStackProc() for StubDispatchFrame.
1156-
if (pFrame->GetVTablePtr() != StubDispatchFrame::GetMethodFrameVPtr())
1156+
if (pFrame->GetFrameIdentifier() != FrameIdentifier::StubDispatchFrame)
11571157
{
11581158
if (it == Frame::INTERCEPTION_SECURITY)
11591159
{

src/coreclr/debug/ee/debugger.cpp

Lines changed: 253 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13475,10 +13475,7 @@ void Debugger::UnhandledHijackWorker(CONTEXT * pContext, EXCEPTION_RECORD * pRec
1347513475
fSOException))
1347613476
{
1347713477

13478-
FrameWithCookie<FaultingExceptionFrame> fef;
13479-
#if defined(FEATURE_EH_FUNCLETS)
13480-
*((&fef)->GetGSCookiePtr()) = GetProcessGSCookie();
13481-
#endif // FEATURE_EH_FUNCLETS
13478+
FaultingExceptionFrame fef;
1348213479
if ((pContext != NULL) && fSOException)
1348313480
{
1348413481
GCX_COOP(); // Must be cooperative to modify frame chain.
@@ -16799,4 +16796,256 @@ void Debugger::ExternalMethodFixupNextStep(PCODE address)
1679916796
}
1680016797
#endif //DACCESS_COMPILE
1680116798

16799+
unsigned FuncEvalFrame::GetFrameAttribs_Impl(void)
16800+
{
16801+
LIMITED_METHOD_DAC_CONTRACT;
16802+
16803+
if (GetDebuggerEval()->m_evalDuringException)
16804+
{
16805+
return FRAME_ATTR_NONE;
16806+
}
16807+
else
16808+
{
16809+
return FRAME_ATTR_RESUMABLE; // Treat the next frame as the top frame.
16810+
}
16811+
}
16812+
16813+
TADDR FuncEvalFrame::GetReturnAddressPtr_Impl()
16814+
{
16815+
LIMITED_METHOD_DAC_CONTRACT;
16816+
16817+
if (GetDebuggerEval()->m_evalDuringException)
16818+
{
16819+
return (TADDR)NULL;
16820+
}
16821+
else
16822+
{
16823+
return PTR_HOST_MEMBER_TADDR(FuncEvalFrame, this, m_ReturnAddress);
16824+
}
16825+
}
16826+
16827+
//
16828+
// This updates the register display for a FuncEvalFrame.
16829+
//
16830+
void FuncEvalFrame::UpdateRegDisplay_Impl(const PREGDISPLAY pRD, bool updateFloats)
16831+
{
16832+
SUPPORTS_DAC;
16833+
DebuggerEval * pDE = GetDebuggerEval();
16834+
16835+
// No context to update if we're doing a func eval from within exception processing.
16836+
if (pDE->m_evalDuringException)
16837+
{
16838+
return;
16839+
}
16840+
16841+
#ifndef FEATURE_EH_FUNCLETS
16842+
// Reset pContext; it's only valid for active (top-most) frame.
16843+
pRD->pContext = NULL;
16844+
#endif // !FEATURE_EH_FUNCLETS
16845+
16846+
16847+
#ifdef TARGET_X86
16848+
// Update all registers in the reg display from the CONTEXT we stored when the thread was hijacked for this func
16849+
// eval. We have to update all registers, not just the callee saved registers, because we can hijack a thread at any
16850+
// point for a func eval, not just at a call site.
16851+
pRD->SetEdiLocation(&(pDE->m_context.Edi));
16852+
pRD->SetEsiLocation(&(pDE->m_context.Esi));
16853+
pRD->SetEbxLocation(&(pDE->m_context.Ebx));
16854+
pRD->SetEdxLocation(&(pDE->m_context.Edx));
16855+
pRD->SetEcxLocation(&(pDE->m_context.Ecx));
16856+
pRD->SetEaxLocation(&(pDE->m_context.Eax));
16857+
pRD->SetEbpLocation(&(pDE->m_context.Ebp));
16858+
pRD->PCTAddr = GetReturnAddressPtr();
16859+
16860+
#ifdef FEATURE_EH_FUNCLETS
16861+
16862+
pRD->IsCallerContextValid = FALSE;
16863+
pRD->IsCallerSPValid = FALSE; // Don't add usage of this field. This is only temporary.
16864+
16865+
pRD->pCurrentContext->Eip = *PTR_PCODE(pRD->PCTAddr);
16866+
pRD->pCurrentContext->Esp = (DWORD)GetSP(&pDE->m_context);
16867+
16868+
SyncRegDisplayToCurrentContext(pRD);
16869+
16870+
#else // FEATURE_EH_FUNCLETS
16871+
16872+
pRD->ControlPC = *PTR_PCODE(pRD->PCTAddr);
16873+
pRD->SP = (DWORD)GetSP(&pDE->m_context);
16874+
16875+
#endif // FEATURE_EH_FUNCLETS
16876+
16877+
#elif defined(TARGET_AMD64)
16878+
pRD->IsCallerContextValid = FALSE;
16879+
pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
16880+
16881+
memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(CONTEXT));
16882+
16883+
pRD->pCurrentContextPointers->Rax = &(pDE->m_context.Rax);
16884+
pRD->pCurrentContextPointers->Rcx = &(pDE->m_context.Rcx);
16885+
pRD->pCurrentContextPointers->Rdx = &(pDE->m_context.Rdx);
16886+
pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8);
16887+
pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9);
16888+
pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10);
16889+
pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11);
16890+
16891+
pRD->pCurrentContextPointers->Rbx = &(pDE->m_context.Rbx);
16892+
pRD->pCurrentContextPointers->Rsi = &(pDE->m_context.Rsi);
16893+
pRD->pCurrentContextPointers->Rdi = &(pDE->m_context.Rdi);
16894+
pRD->pCurrentContextPointers->Rbp = &(pDE->m_context.Rbp);
16895+
pRD->pCurrentContextPointers->R12 = &(pDE->m_context.R12);
16896+
pRD->pCurrentContextPointers->R13 = &(pDE->m_context.R13);
16897+
pRD->pCurrentContextPointers->R14 = &(pDE->m_context.R14);
16898+
pRD->pCurrentContextPointers->R15 = &(pDE->m_context.R15);
16899+
16900+
// SyncRegDisplayToCurrentContext() sets the pRD->SP and pRD->ControlPC on AMD64.
16901+
SyncRegDisplayToCurrentContext(pRD);
16902+
16903+
#elif defined(TARGET_ARM)
16904+
pRD->IsCallerContextValid = FALSE;
16905+
pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
16906+
16907+
memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT));
16908+
16909+
pRD->pCurrentContextPointers->R4 = &(pDE->m_context.R4);
16910+
pRD->pCurrentContextPointers->R5 = &(pDE->m_context.R5);
16911+
pRD->pCurrentContextPointers->R6 = &(pDE->m_context.R6);
16912+
pRD->pCurrentContextPointers->R7 = &(pDE->m_context.R7);
16913+
pRD->pCurrentContextPointers->R8 = &(pDE->m_context.R8);
16914+
pRD->pCurrentContextPointers->R9 = &(pDE->m_context.R9);
16915+
pRD->pCurrentContextPointers->R10 = &(pDE->m_context.R10);
16916+
pRD->pCurrentContextPointers->R11 = &(pDE->m_context.R11);
16917+
pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr);
16918+
16919+
pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0);
16920+
pRD->volatileCurrContextPointers.R1 = &(pDE->m_context.R1);
16921+
pRD->volatileCurrContextPointers.R2 = &(pDE->m_context.R2);
16922+
pRD->volatileCurrContextPointers.R3 = &(pDE->m_context.R3);
16923+
pRD->volatileCurrContextPointers.R12 = &(pDE->m_context.R12);
16924+
16925+
SyncRegDisplayToCurrentContext(pRD);
16926+
16927+
#elif defined(TARGET_ARM64)
16928+
pRD->IsCallerContextValid = FALSE;
16929+
pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
16930+
16931+
memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT));
16932+
16933+
pRD->pCurrentContextPointers->X19 = &(pDE->m_context.X19);
16934+
pRD->pCurrentContextPointers->X20 = &(pDE->m_context.X20);
16935+
pRD->pCurrentContextPointers->X21 = &(pDE->m_context.X21);
16936+
pRD->pCurrentContextPointers->X22 = &(pDE->m_context.X22);
16937+
pRD->pCurrentContextPointers->X23 = &(pDE->m_context.X23);
16938+
pRD->pCurrentContextPointers->X24 = &(pDE->m_context.X24);
16939+
pRD->pCurrentContextPointers->X25 = &(pDE->m_context.X25);
16940+
pRD->pCurrentContextPointers->X26 = &(pDE->m_context.X26);
16941+
pRD->pCurrentContextPointers->X27 = &(pDE->m_context.X27);
16942+
pRD->pCurrentContextPointers->X28 = &(pDE->m_context.X28);
16943+
pRD->pCurrentContextPointers->Lr = &(pDE->m_context.Lr);
16944+
pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp);
16945+
16946+
pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0);
16947+
pRD->volatileCurrContextPointers.X1 = &(pDE->m_context.X1);
16948+
pRD->volatileCurrContextPointers.X2 = &(pDE->m_context.X2);
16949+
pRD->volatileCurrContextPointers.X3 = &(pDE->m_context.X3);
16950+
pRD->volatileCurrContextPointers.X4 = &(pDE->m_context.X4);
16951+
pRD->volatileCurrContextPointers.X5 = &(pDE->m_context.X5);
16952+
pRD->volatileCurrContextPointers.X6 = &(pDE->m_context.X6);
16953+
pRD->volatileCurrContextPointers.X7 = &(pDE->m_context.X7);
16954+
pRD->volatileCurrContextPointers.X8 = &(pDE->m_context.X8);
16955+
pRD->volatileCurrContextPointers.X9 = &(pDE->m_context.X9);
16956+
pRD->volatileCurrContextPointers.X10 = &(pDE->m_context.X10);
16957+
pRD->volatileCurrContextPointers.X11 = &(pDE->m_context.X11);
16958+
pRD->volatileCurrContextPointers.X12 = &(pDE->m_context.X12);
16959+
pRD->volatileCurrContextPointers.X13 = &(pDE->m_context.X13);
16960+
pRD->volatileCurrContextPointers.X14 = &(pDE->m_context.X14);
16961+
pRD->volatileCurrContextPointers.X15 = &(pDE->m_context.X15);
16962+
pRD->volatileCurrContextPointers.X16 = &(pDE->m_context.X16);
16963+
pRD->volatileCurrContextPointers.X17 = &(pDE->m_context.X17);
16964+
16965+
SyncRegDisplayToCurrentContext(pRD);
16966+
#elif defined(TARGET_RISCV64)
16967+
pRD->IsCallerContextValid = FALSE;
16968+
pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
16969+
16970+
memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT));
16971+
16972+
pRD->pCurrentContextPointers->S1 = &(pDE->m_context.S1);
16973+
pRD->pCurrentContextPointers->S2 = &(pDE->m_context.S2);
16974+
pRD->pCurrentContextPointers->S3 = &(pDE->m_context.S3);
16975+
pRD->pCurrentContextPointers->S4 = &(pDE->m_context.S4);
16976+
pRD->pCurrentContextPointers->S5 = &(pDE->m_context.S5);
16977+
pRD->pCurrentContextPointers->S6 = &(pDE->m_context.S6);
16978+
pRD->pCurrentContextPointers->S7 = &(pDE->m_context.S7);
16979+
pRD->pCurrentContextPointers->S8 = &(pDE->m_context.S8);
16980+
pRD->pCurrentContextPointers->S9 = &(pDE->m_context.S9);
16981+
pRD->pCurrentContextPointers->S10 = &(pDE->m_context.S10);
16982+
pRD->pCurrentContextPointers->S11 = &(pDE->m_context.S11);
16983+
pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp);
16984+
pRD->pCurrentContextPointers->Gp = &(pDE->m_context.Gp);
16985+
pRD->pCurrentContextPointers->Tp = &(pDE->m_context.Tp);
16986+
pRD->pCurrentContextPointers->Ra = &(pDE->m_context.Ra);
16987+
16988+
pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0);
16989+
pRD->volatileCurrContextPointers.A0 = &(pDE->m_context.A0);
16990+
pRD->volatileCurrContextPointers.A1 = &(pDE->m_context.A1);
16991+
pRD->volatileCurrContextPointers.A2 = &(pDE->m_context.A2);
16992+
pRD->volatileCurrContextPointers.A3 = &(pDE->m_context.A3);
16993+
pRD->volatileCurrContextPointers.A4 = &(pDE->m_context.A4);
16994+
pRD->volatileCurrContextPointers.A5 = &(pDE->m_context.A5);
16995+
pRD->volatileCurrContextPointers.A6 = &(pDE->m_context.A6);
16996+
pRD->volatileCurrContextPointers.A7 = &(pDE->m_context.A7);
16997+
pRD->volatileCurrContextPointers.T0 = &(pDE->m_context.T0);
16998+
pRD->volatileCurrContextPointers.T1 = &(pDE->m_context.T1);
16999+
pRD->volatileCurrContextPointers.T2 = &(pDE->m_context.T2);
17000+
pRD->volatileCurrContextPointers.T3 = &(pDE->m_context.T3);
17001+
pRD->volatileCurrContextPointers.T4 = &(pDE->m_context.T4);
17002+
pRD->volatileCurrContextPointers.T5 = &(pDE->m_context.T5);
17003+
pRD->volatileCurrContextPointers.T6 = &(pDE->m_context.T6);
17004+
17005+
SyncRegDisplayToCurrentContext(pRD);
17006+
#elif defined(TARGET_LOONGARCH64)
17007+
pRD->IsCallerContextValid = FALSE;
17008+
pRD->IsCallerSPValid = FALSE; // Don't add usage of this flag. This is only temporary.
17009+
17010+
memcpy(pRD->pCurrentContext, &(pDE->m_context), sizeof(T_CONTEXT));
17011+
17012+
pRD->pCurrentContextPointers->S0 = &(pDE->m_context.S0);
17013+
pRD->pCurrentContextPointers->S1 = &(pDE->m_context.S1);
17014+
pRD->pCurrentContextPointers->S2 = &(pDE->m_context.S2);
17015+
pRD->pCurrentContextPointers->S3 = &(pDE->m_context.S3);
17016+
pRD->pCurrentContextPointers->S4 = &(pDE->m_context.S4);
17017+
pRD->pCurrentContextPointers->S5 = &(pDE->m_context.S5);
17018+
pRD->pCurrentContextPointers->S6 = &(pDE->m_context.S6);
17019+
pRD->pCurrentContextPointers->S7 = &(pDE->m_context.S7);
17020+
pRD->pCurrentContextPointers->S8 = &(pDE->m_context.S8);
17021+
pRD->pCurrentContextPointers->Fp = &(pDE->m_context.Fp);
17022+
pRD->pCurrentContextPointers->Ra = &(pDE->m_context.Ra);
17023+
17024+
pRD->volatileCurrContextPointers.R0 = &(pDE->m_context.R0);
17025+
pRD->volatileCurrContextPointers.A0 = &(pDE->m_context.A0);
17026+
pRD->volatileCurrContextPointers.A1 = &(pDE->m_context.A1);
17027+
pRD->volatileCurrContextPointers.A2 = &(pDE->m_context.A2);
17028+
pRD->volatileCurrContextPointers.A3 = &(pDE->m_context.A3);
17029+
pRD->volatileCurrContextPointers.A4 = &(pDE->m_context.A4);
17030+
pRD->volatileCurrContextPointers.A5 = &(pDE->m_context.A5);
17031+
pRD->volatileCurrContextPointers.A6 = &(pDE->m_context.A6);
17032+
pRD->volatileCurrContextPointers.A7 = &(pDE->m_context.A7);
17033+
pRD->volatileCurrContextPointers.T0 = &(pDE->m_context.T0);
17034+
pRD->volatileCurrContextPointers.T1 = &(pDE->m_context.T1);
17035+
pRD->volatileCurrContextPointers.T2 = &(pDE->m_context.T2);
17036+
pRD->volatileCurrContextPointers.T3 = &(pDE->m_context.T3);
17037+
pRD->volatileCurrContextPointers.T4 = &(pDE->m_context.T4);
17038+
pRD->volatileCurrContextPointers.T5 = &(pDE->m_context.T5);
17039+
pRD->volatileCurrContextPointers.T6 = &(pDE->m_context.T6);
17040+
pRD->volatileCurrContextPointers.T7 = &(pDE->m_context.T7);
17041+
pRD->volatileCurrContextPointers.T8 = &(pDE->m_context.T8);
17042+
pRD->volatileCurrContextPointers.X0 = &(pDE->m_context.X0);
17043+
17044+
SyncRegDisplayToCurrentContext(pRD);
17045+
17046+
#else
17047+
PORTABILITY_ASSERT("FuncEvalFrame::UpdateRegDisplay is not implemented on this platform.");
17048+
#endif
17049+
}
17050+
1680217051
#endif //DEBUGGING_SUPPORTED

0 commit comments

Comments
 (0)