diff --git a/src/coreclr/debug/daccess/dacdbiimpl.cpp b/src/coreclr/debug/daccess/dacdbiimpl.cpp index 93f85aa3a7e7cf..187bec38581ef2 100644 --- a/src/coreclr/debug/daccess/dacdbiimpl.cpp +++ b/src/coreclr/debug/daccess/dacdbiimpl.cpp @@ -5679,10 +5679,57 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetContext(VMPTR_Thread vmThread, { // If the filter context is NULL, then we use the true context of the thread. pContextBuffer->ContextFlags = DT_CONTEXT_ALL; - IfFailThrow(m_pTarget->GetThreadContext(pThread->GetOSThreadId(), + HRESULT hrContext = m_pTarget->GetThreadContext(pThread->GetOSThreadId(), pContextBuffer->ContextFlags, sizeof(DT_CONTEXT), - reinterpret_cast(pContextBuffer))); + reinterpret_cast(pContextBuffer)); + if (hrContext == E_NOTIMPL) + { + // GetThreadContext is not implemented on this data target (e.g. Linux). + // That's why we have to make do with context we can obtain from Frames explicitly stored in Thread object. + // It suffices for managed debugging stackwalk. + REGDISPLAY tmpRd = {}; + T_CONTEXT tmpContext = {}; + FillRegDisplay(&tmpRd, &tmpContext); + + // Going through thread Frames and looking for first (deepest one) one that + // that has context available for stackwalking (SP and PC) + // For example: RedirectedThreadFrame, InlinedCallFrame, DynamicHelperFrame + Frame *frame = pThread->GetFrame(); + + while (frame != NULL && frame != FRAME_TOP) + { +#ifdef FEATURE_INTERPRETER + if (frame->GetFrameIdentifier() == FrameIdentifier::InterpreterFrame) + { + PTR_InterpreterFrame pInterpreterFrame = dac_cast(frame); + pInterpreterFrame->SetContextToInterpMethodContextFrame(&tmpContext); + CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer)); + return S_OK; + } +#endif // FEATURE_INTERPRETER + frame->UpdateRegDisplay(&tmpRd); + if (GetRegdisplaySP(&tmpRd) != 0 && GetControlPC(&tmpRd) != 0) + { + UpdateContextFromRegDisp(&tmpRd, &tmpContext); + CopyMemory(pContextBuffer, &tmpContext, sizeof(*pContextBuffer)); + pContextBuffer->ContextFlags = DT_CONTEXT_CONTROL + #if defined(TARGET_AMD64) || defined(TARGET_ARM) + | DT_CONTEXT_INTEGER + #endif + ; + return S_OK; + } + frame = frame->Next(); + } + + // It looks like this thread is not running managed code. + ZeroMemory(pContextBuffer, sizeof(*pContextBuffer)); + } + else + { + IfFailThrow(hrContext); + } } else {