Skip to content
4 changes: 2 additions & 2 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7223,7 +7223,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetAssemblyFromModule(VMPTR_Modul

HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::ParseContinuation(
CORDB_ADDRESS continuationAddress,
OUT PCODE* pDiagnosticIP,
OUT CORDB_ADDRESS* pDiagnosticIP,
OUT CORDB_ADDRESS* pNextContinuation,
OUT UINT32* pState)
{
Expand Down Expand Up @@ -7274,7 +7274,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::ParseContinuation(
return E_FAIL;
}

*pDiagnosticIP = pResumeInfo->pDiagnosticIP;
*pDiagnosticIP = static_cast<CORDB_ADDRESS>(pResumeInfo->pDiagnosticIP);
*pNextContinuation = static_cast<CORDB_ADDRESS>(dac_cast<TADDR>(OBJECTREFToObject(pNext)));
*pState = state;

Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/debug/daccess/dacdbiimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class DacDbiInterfaceImpl :
HRESULT STDMETHODCALLTYPE EnableGCNotificationEvents(BOOL fEnable);
HRESULT STDMETHODCALLTYPE GetAssemblyFromModule(VMPTR_Module vmModule, OUT VMPTR_Assembly *pvmAssembly);
HRESULT STDMETHODCALLTYPE ParseContinuation(CORDB_ADDRESS continuationAddress,
OUT PCODE *pDiagnosticIP,
OUT CORDB_ADDRESS *pDiagnosticIP,
OUT CORDB_ADDRESS *pNextContinuation,
OUT UINT32 *pState);
HRESULT STDMETHODCALLTYPE EnumerateAsyncLocals(VMPTR_MethodDesc vmMethod, CORDB_ADDRESS codeAddr, UINT32 state, FP_ASYNC_LOCAL_CALLBACK fpCallback, CALLBACK_DATA pUserData);
Expand Down Expand Up @@ -716,7 +716,7 @@ class DacDbiInterfaceImpl :
ULONG32 GetStackParameterSize(EECodeInfo * pCodeInfo);

// Return the FramePointer of the current frame at which the stackwalker is stopped.
HRESULT STDMETHODCALLTYPE GetFramePointer(StackWalkHandle pSFIHandle, OUT FramePointer * pRetVal);
HRESULT STDMETHODCALLTYPE GetFramePointer(StackWalkHandle pSFIHandle, OUT CORDB_ADDRESS * pRetVal);

FramePointer GetFramePointerWorker(StackFrameIterator * pIter);

Expand Down
23 changes: 13 additions & 10 deletions src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,9 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thr
Frame * pFrame = pThread->GetFrame();
AppDomain * pAppDomain = AppDomain::GetCurrentDomain();

// cStubFrame entries have no DT_CONTEXT buffer; leave ctx as 0 so consumers
// (and the cDAC cross-check, which sets ctx = 0) don't observe a garbage value.
frameData.ctx = 0;
frameData.eType = Debugger_STRData::cStubFrame;

while (pFrame != FRAME_TOP)
Expand Down Expand Up @@ -581,7 +584,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::EnumerateInternalFrames(VMPTR_Thr
frameData.stubFrame.frameType = GetInternalFrameType(pFrame);
if (frameData.stubFrame.frameType != STUBFRAME_NONE)
{
frameData.fp = FramePointer::MakeFramePointer(PTR_HOST_TO_TADDR(pFrame));
frameData.fp = PTR_TO_CORDB_ADDRESS(PTR_HOST_TO_TADDR(pFrame));

frameData.vmCurrentAppDomainToken.SetHostPtr(pAppDomain);

Expand Down Expand Up @@ -638,7 +641,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetStackParameterSize(CORDB_ADDRE
}

// Return the FramePointer of the current frame at which the stackwalker is stopped.
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetFramePointer(StackWalkHandle pSFIHandle, OUT FramePointer * pRetVal)
HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetFramePointer(StackWalkHandle pSFIHandle, OUT CORDB_ADDRESS * pRetVal)
{
DD_ENTER_MAY_THROW;

Expand All @@ -647,7 +650,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetFramePointer(StackWalkHandle p
{

StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle);
*pRetVal = GetFramePointerWorker(pIter);
*pRetVal = PTR_TO_CORDB_ADDRESS(GetFramePointerWorker(pIter).GetSPValue());
}
EX_CATCH_HRESULT(hr);
return hr;
Expand Down Expand Up @@ -746,16 +749,16 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter,
// do common initialization of Debugger_STRData for both managed stack frames and explicit frames
//

pFrameData->fp = GetFramePointerWorker(pIter);
pFrameData->fp = PTR_TO_CORDB_ADDRESS(GetFramePointerWorker(pIter).GetSPValue());

pFrameData->vmCurrentAppDomainToken.SetHostPtr(AppDomain::GetCurrentDomain());

if (ft == kNativeRuntimeUnwindableStackFrame)
{
pFrameData->eType = Debugger_STRData::cRuntimeNativeFrame;

_ASSERTE(pFrameData->ctx != NULL);
GetStackWalkCurrentContext(pIter, pFrameData->ctx);
_ASSERTE(pFrameData->ctx != 0);
GetStackWalkCurrentContext(pIter, (DT_CONTEXT *)CORDB_ADDRESS_TO_PTR(pFrameData->ctx));
}
else if (ft == kManagedStackFrame)
{
Expand Down Expand Up @@ -785,8 +788,8 @@ void DacDbiInterfaceImpl::InitFrameData(StackFrameIterator * pIter,

pFrameData->eType = Debugger_STRData::cMethodFrame;

_ASSERTE(pFrameData->ctx != NULL);
GetStackWalkCurrentContext(pIter, pFrameData->ctx);
_ASSERTE(pFrameData->ctx != 0);
GetStackWalkCurrentContext(pIter, (DT_CONTEXT *)CORDB_ADDRESS_TO_PTR(pFrameData->ctx));

//
// initialize the fields in Debugger_STRData::v
Expand Down Expand Up @@ -948,7 +951,7 @@ void DacDbiInterfaceImpl::InitParentFrameInfo(CrawlFrame * pCF,
// to the ExInfo when we are checking if a particular frame is the parent frame.
//

pJITFuncData->fpParentOrSelf = FramePointer::MakeFramePointer(sfParent.SP);
pJITFuncData->fpParentOrSelf = PTR_TO_CORDB_ADDRESS(sfParent.SP);
pJITFuncData->parentNativeOffset = dwParentOffset;
}
else
Expand All @@ -961,7 +964,7 @@ void DacDbiInterfaceImpl::InitParentFrameInfo(CrawlFrame * pCF,
// to the ExInfo when we are checking if a particular frame is the parent frame.
//

pJITFuncData->fpParentOrSelf = FramePointer::MakeFramePointer(sfSelf.SP);
pJITFuncData->fpParentOrSelf = PTR_TO_CORDB_ADDRESS(sfSelf.SP);
pJITFuncData->parentNativeOffset = 0;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/debug/di/process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2407,7 +2407,7 @@ COM_METHOD CordbProcess::GetAsyncStack(CORDB_ADDRESS continuationAddress, ICorDe
ThrowHR(E_INVALIDARG);
}

PCODE diagnosticIP;
CORDB_ADDRESS diagnosticIP;
CORDB_ADDRESS nextContinuation;
UINT32 state;
if (FAILED(m_pDacPrimitives->ParseContinuation(
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/debug/di/rsstackwalk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -583,7 +583,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame)
// populated context through this pointer.
DT_CONTEXT frameCtx;
ZeroMemory(&frameCtx, sizeof(frameCtx));
frameData.ctx = &frameCtx;
frameData.ctx = PTR_TO_CORDB_ADDRESS(&frameCtx);

IDacDbiInterface::FrameType ft = IDacDbiInterface::kInvalid;

Expand Down Expand Up @@ -686,7 +686,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame)

// Create the native frame.
CordbNativeFrame* pNativeFrame = new CordbNativeFrame(m_pCordbThread,
frameData.fp,
FramePointer::MakeFramePointer(CORDB_ADDRESS_TO_PTR(frameData.fp)),
pNativeCode,
(SIZE_T)pJITFuncData->nativeOffset,
(TADDR)frameData.v.taAmbientESP,
Expand Down Expand Up @@ -829,7 +829,7 @@ HRESULT CordbStackWalk::GetFrameWorker(ICorDebugFrame ** ppFrame)
_ASSERTE(pCurrentAppDomain != NULL);

CordbRuntimeUnwindableFrame * pRuntimeFrame = new CordbRuntimeUnwindableFrame(m_pCordbThread,
frameData.fp,
FramePointer::MakeFramePointer(CORDB_ADDRESS_TO_PTR(frameData.fp)),
pCurrentAppDomain,
&frameCtx);

Expand Down Expand Up @@ -896,7 +896,7 @@ HRESULT CordbAsyncStackWalk::PopulateFrame()

while (true)
{
PCODE diagnosticIP;
CORDB_ADDRESS diagnosticIP = 0;
CORDB_ADDRESS nextContinuation;
UINT32 state;

Expand Down Expand Up @@ -993,7 +993,7 @@ HRESULT CordbAsyncStackWalk::Next()
if (m_continuationAddress == 0)
ThrowHR(CORDBG_E_PAST_END_OF_STACK);

PCODE diagnosticIP;
CORDB_ADDRESS diagnosticIP = 0;
CORDB_ADDRESS nextContinuation;
UINT32 state;
IfFailThrow(m_pProcess->GetDAC()->ParseContinuation(
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/debug/di/rsthread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2286,7 +2286,7 @@ void CordbThread::GetActiveInternalFramesCallback(const Debugger_STRData * pFram

// Create a CordbInternalFrame.
CordbInternalFrame * pInternalFrame = new CordbInternalFrame(pThis,
pFrameData->fp,
FramePointer::MakeFramePointer(CORDB_ADDRESS_TO_PTR(pFrameData->fp)),
pAppDomain,
pFrameData);

Expand Down Expand Up @@ -5433,7 +5433,7 @@ CordbMiscFrame::CordbMiscFrame()
CordbMiscFrame::CordbMiscFrame(Debugger_JITFuncData * pJITFuncData)
{
this->parentIP = (SIZE_T)pJITFuncData->parentNativeOffset;
this->fpParentOrSelf = pJITFuncData->fpParentOrSelf;
this->fpParentOrSelf = FramePointer::MakeFramePointer(CORDB_ADDRESS_TO_PTR(pJITFuncData->fpParentOrSelf));
this->fIsFilterFunclet = (pJITFuncData->fIsFilterFrame == TRUE);
}

Expand Down
7 changes: 4 additions & 3 deletions src/coreclr/debug/inc/dacdbiinterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1233,8 +1233,9 @@ IDacDbiInterface : public IUnknown
//
// The FramePointer of an explicit frame is just the stack address of the explicit frame.
//

virtual HRESULT STDMETHODCALLTYPE GetFramePointer(StackWalkHandle pSFIHandle, OUT FramePointer * pRetVal) = 0;
// Returned as a CORDB_ADDRESS (fixed 64-bit); the caller reconstructs a FramePointer from it.
//
virtual HRESULT STDMETHODCALLTYPE GetFramePointer(StackWalkHandle pSFIHandle, OUT CORDB_ADDRESS * pRetVal) = 0;

Comment thread
tommcdon marked this conversation as resolved.
Comment thread
tommcdon marked this conversation as resolved.
//
// Check whether the specified CONTEXT is the CONTEXT of the leaf frame. This function doesn't care
Expand Down Expand Up @@ -2195,7 +2196,7 @@ IDacDbiInterface : public IUnknown

virtual HRESULT STDMETHODCALLTYPE ParseContinuation(
CORDB_ADDRESS continuationAddress,
OUT PCODE* pDiagnosticIP,
OUT CORDB_ADDRESS* pDiagnosticIP,
OUT CORDB_ADDRESS* pNextContinuation,
OUT UINT32* pState) = 0;
Comment on lines 2197 to 2201

Expand Down
9 changes: 6 additions & 3 deletions src/coreclr/debug/inc/dacdbistructures.h
Original file line number Diff line number Diff line change
Expand Up @@ -519,7 +519,8 @@ struct MSLAYOUT Debugger_JITFuncData

BOOL fIsFilterFrame;
ULONG64 parentNativeOffset;
FramePointer fpParentOrSelf;
// FramePointer as CORDB_ADDRESS (fixed 64-bit); RS converts to/from FramePointer.
CORDB_ADDRESS fpParentOrSelf;

// indicates if the MethodDesc is a generic function or a method inside a generic class (or
// both!).
Expand All @@ -538,8 +539,10 @@ struct MSLAYOUT Debugger_JITFuncData
#endif // ARM context structures have a 16-byte alignment requirement
struct MSLAYOUT Debugger_STRData
{
FramePointer fp;
DT_CONTEXT * ctx;
// fp and ctx are CORDB_ADDRESS (fixed 64-bit) rather than host-sized FramePointer /
// DT_CONTEXT*; the RS converts to/from the host representation at the boundary.
CORDB_ADDRESS fp;
CORDB_ADDRESS ctx;
VMPTR_AppDomain vmCurrentAppDomainToken;


Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/dacdbi.idl
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ interface IDacDbiInterface : IUnknown
HRESULT GetCountOfInternalFrames([in] VMPTR_Thread vmThread, [out] ULONG32 * pRetVal);
HRESULT EnumerateInternalFrames([in] VMPTR_Thread vmThread, [in] FP_INTERNAL_FRAME_ENUMERATION_CALLBACK fpCallback, [in] CALLBACK_DATA pUserData);
HRESULT GetStackParameterSize([in] CORDB_ADDRESS controlPC, [out] ULONG32 * pRetVal);
HRESULT GetFramePointer([in] StackWalkHandle pSFIHandle, [out] FramePointer * pRetVal);
HRESULT GetFramePointer([in] StackWalkHandle pSFIHandle, [out] CORDB_ADDRESS * pRetVal);
HRESULT IsLeafFrame([in] VMPTR_Thread vmThread, [in] const DT_CONTEXT * pContext, [out] BOOL * pResult);
HRESULT GetContext([in] VMPTR_Thread vmThread, [out] DT_CONTEXT * pContextBuffer);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,12 @@ private bool Next(StackWalkData handle)
case StackWalkState.InitialNativeContext:
case StackWalkState.NativeMarker:
{
// Match native UnwindStackWalkFrame: cbStackParameterSize is a fresh
// per-step value set only when leaving a frameless managed method, so the
// x86 callee-popped-args adjustment applies only at an immediate
// frameless -> native-marker transition. Reset when leaving a native frame
// so consecutive native markers don't reuse a stale parameter size.
handle.LastFramelessStackParameterSize = 0;
Comment on lines +858 to +863
TargetCodePointer ip = handle.Context.InstructionPointer;
HijackKind hijackKind = _target.Contracts.Debugger.GetHijackKind(ip);
if (hijackKind != HijackKind.None)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ public struct Debugger_JITFuncData
public ulong vmNativeCodeMethodDescToken;
public Interop.BOOL fIsFilterFrame;
public ulong parentNativeOffset;
public ulong fpParentOrSelf;
public ulong fpParentOrSelf; // FramePointer (CORDB_ADDRESS)
public Interop.BOOL isInstantiatedGeneric;
public Interop.BOOL justAfterILThrow;
}
Expand Down Expand Up @@ -224,14 +224,10 @@ public struct DebuggerIPCE_STRData_StubFrame
public int frameType; // CorDebugInternalFrameType
}

// Holds data for each stack frame or chain. This data is passed from the RC to
// the DI during a stack walk. Mirrors the native Debugger_STRData struct
// defined in src/coreclr/debug/inc/dbgipcevents.h.
//
// `ctx` is a pointer into dbi-allocated memory.
// The DAC writes the populated context through this pointer rather
// than storing it inline. Code paths that do not produce a context
// (e.g. EnumerateInternalFrames for cStubFrame entries) leave it as 0.
// Holds data for each stack frame or chain, passed from the RC to the DI during a
// stack walk. Mirrors the native Debugger_STRData in src/coreclr/debug/inc/dacdbistructures.h.
// ctx addresses a dbi-allocated DT_CONTEXT buffer the DAC writes through; paths that
// produce no context (e.g. EnumerateInternalFrames cStubFrame entries) leave it 0.
[StructLayout(LayoutKind.Explicit)]
public struct Debugger_STRData
{
Expand All @@ -242,10 +238,11 @@ public enum EType
cRuntimeNativeFrame = 2,
}

[FieldOffset(0)] public ulong fp; // FramePointer
[FieldOffset(8)] public ulong ctx; // DT_CONTEXT*
[FieldOffset(0)] public ulong fp; // FramePointer (CORDB_ADDRESS)
[FieldOffset(8)] public ulong ctx; // DT_CONTEXT* (CORDB_ADDRESS)
[FieldOffset(16)] public ulong vmCurrentAppDomainToken; // VMPTR_AppDomain
[FieldOffset(24)] public EType eType;
// v (method frame) and stubFrame overlap, mirroring the native anonymous union.
[FieldOffset(32)] public DebuggerIPCE_STRData_MethodFrame v;
[FieldOffset(32)] public DebuggerIPCE_STRData_StubFrame stubFrame;
}
Expand Down