Skip to content

Commit 7da2acb

Browse files
tommcdonCopilot
andauthored
Restore E_NOTIMPL fallback in DacDbiInterfaceImpl::GetContext (#128499)
On platforms where ICorDebugDataTarget::GetThreadContext returns E_NOTIMPL, restore the fallback that walks the thread's Frame chain to reconstruct a register context from REGDISPLAY. This is needed for managed debugging stack walks on non-Windows platforms. The fallback was removed in 5391e9e. Found using internal Visual Studio testing Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2dce83a commit 7da2acb

1 file changed

Lines changed: 49 additions & 2 deletions

File tree

src/coreclr/debug/daccess/dacdbiimpl.cpp

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5682,10 +5682,57 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetContext(VMPTR_Thread vmThread,
56825682
{
56835683
// If the filter context is NULL, then we use the true context of the thread.
56845684
pContextBuffer->ContextFlags = DT_CONTEXT_ALL;
5685-
IfFailThrow(m_pTarget->GetThreadContext(pThread->GetOSThreadId(),
5685+
HRESULT hrContext = m_pTarget->GetThreadContext(pThread->GetOSThreadId(),
56865686
pContextBuffer->ContextFlags,
56875687
sizeof(DT_CONTEXT),
5688-
reinterpret_cast<BYTE *>(pContextBuffer)));
5688+
reinterpret_cast<BYTE *>(pContextBuffer));
5689+
if (hrContext == E_NOTIMPL)
5690+
{
5691+
// GetThreadContext is not implemented on this data target (e.g. Linux).
5692+
// That's why we have to make do with context we can obtain from Frames explicitly stored in Thread object.
5693+
// It suffices for managed debugging stackwalk.
5694+
REGDISPLAY tmpRd = {};
5695+
T_CONTEXT tmpContext = {};
5696+
FillRegDisplay(&tmpRd, &tmpContext);
5697+
5698+
// Going through thread Frames and looking for first (deepest one) one that
5699+
// that has context available for stackwalking (SP and PC)
5700+
// For example: RedirectedThreadFrame, InlinedCallFrame, DynamicHelperFrame
5701+
Frame *frame = pThread->GetFrame();
5702+
5703+
while (frame != NULL && frame != FRAME_TOP)
5704+
{
5705+
#ifdef FEATURE_INTERPRETER
5706+
if (frame->GetFrameIdentifier() == FrameIdentifier::InterpreterFrame)
5707+
{
5708+
PTR_InterpreterFrame pInterpreterFrame = dac_cast<PTR_InterpreterFrame>(frame);
5709+
pInterpreterFrame->SetContextToInterpMethodContextFrame(&tmpContext);
5710+
CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer));
5711+
return S_OK;
5712+
}
5713+
#endif // FEATURE_INTERPRETER
5714+
frame->UpdateRegDisplay(&tmpRd);
5715+
if (GetRegdisplaySP(&tmpRd) != 0 && GetControlPC(&tmpRd) != 0)
5716+
{
5717+
UpdateContextFromRegDisp(&tmpRd, &tmpContext);
5718+
CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer));
5719+
pContextBuffer->ContextFlags = DT_CONTEXT_CONTROL
5720+
#if defined(TARGET_AMD64) || defined(TARGET_ARM)
5721+
| DT_CONTEXT_INTEGER
5722+
#endif
5723+
;
5724+
return S_OK;
5725+
}
5726+
frame = frame->Next();
5727+
}
5728+
5729+
// It looks like this thread is not running managed code.
5730+
ZeroMemory(pContextBuffer, sizeof(*pContextBuffer));
5731+
}
5732+
else
5733+
{
5734+
IfFailThrow(hrContext);
5735+
}
56895736
}
56905737
else
56915738
{

0 commit comments

Comments
 (0)