Skip to content

[cDAC] Remove DT_CONTEXT from DBI layer#130367

Draft
rcj1 wants to merge 9 commits into
dotnet:mainfrom
rcj1:sw-stuff-2
Draft

[cDAC] Remove DT_CONTEXT from DBI layer#130367
rcj1 wants to merge 9 commits into
dotnet:mainfrom
rcj1:sw-stuff-2

Conversation

@rcj1

@rcj1 rcj1 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

In order to encapsulate the target-specific knowledge within the DacDbi and therefore within the cDAC, it is necessary to remove the DT_CONTEXT struct, which represents the target context, from the DBI layer. This PR accomplishes this by:

  • Creating 10 new DacDbi APIs that provide target-specific information especially pertaining to contexts
    int GetTargetContextSize(ContextSizeFlags flags, uint* pSize);
    int WriteRegistersToContext(byte* ctxBuf, uint cb, CorDebugRegister* regs, uint nRegs, ulong* values);
    int ReadRegistersFromContext(byte* ctxBuf, uint cb, CorDebugRegister* regs, uint nRegs, ulong* pValues);
    int GetAvailableRegistersMask(Interop.BOOL fActive, Interop.BOOL fQuickUnwind, uint regCount, byte* pAvailable);
    int ConvertJitRegNumToCorDebugRegister(uint jitRegNum, CorDebugRegister* pReg);
    int ReadFloatRegistersFromContext(byte* ctxBuf, uint cb, uint maxValues, double* values, uint* pValuesCount, int* pFirstFloatReg, uint* pFloatStackTop);
    int GetTargetInfo(TargetInfo* pTargetInfo);
    int ContextHasExtendedRegisters(byte* ctxBuf, uint cb, Interop.BOOL* pResult);
    int CompareControlRegisters(byte* ctxBuf1, uint cb1, byte* ctxBuf2, uint cb2, Interop.BOOL* pResult);
    int CopyContext(byte* dstCtxBuf, uint cbDst, byte* srcCtxBuf, uint cbSrc, uint flags);
  • Using said new DacDbi APIs to replace the architecture-specific reading in (arch)/cordbregisterset.cpp
  • Implementing DacDbi APIs in cDAC
  • Where we are interop live debugging, that is where we know the host is the same as the target, replacing DT_CONTEXT with T_CONTEXT
  • Where target and host context may vary, switching from context structs to opaque byte buffers that are queried through DacDbi

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors the DBI / cDAC boundary so the DBI layer no longer depends on a DT_CONTEXT struct, moving context-layout knowledge behind new IDacDbiInterface APIs and using opaque target-sized byte buffers where host/target layouts may differ.

Changes:

  • Extends IDacDbiInterface (IDL + managed projection) with new context/query/register APIs and switches multiple stackwalk/context entrypoints from DT_CONTEXT* to BYTE*.
  • Updates CoreCLR debugger right-side stackwalking and register-set plumbing to work over opaque context buffers and DAC-provided helpers (e.g., CopyContext, Read/WriteRegistersFromContext).
  • Updates managed contract context models to describe register copy sets/spans and adds an “Extended” register category.
Show a summary per file
File Description
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/IDacDbiInterface.cs Updates STRData ctx to BYTE* and adds new DacDbi APIs + related enums/structs for context/register operations.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs Adds scalar/wide register copy metadata; adjusts register classifications and extended-reg handling.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/RISCV64Context.cs Adds scalar/wide register copy metadata; adjusts control/general register typing.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/RegisterAttribute.cs Adds RegisterType.Extended.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/LoongArch64Context.cs Updates context sizing and floating-point layout; adds scalar/wide register copy metadata and register typing changes.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformContext.cs Adds default properties for extended-register sizing and new register copy metadata accessors.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/IPlatformAgnosticContext.cs Adds abstract extended-register properties and register copy metadata accessors used for flag-gated copies.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ContextHolder.cs Forwards new extended-register properties and register copy metadata accessors.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ARMContext.cs Adds scalar/wide register copy metadata; adjusts register typing.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/ARM64Context.cs Adds scalar/wide register copy metadata; adjusts register typing.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/AMD64Context.cs Adds scalar/wide register copy metadata and explicit XMM span; adjusts register typing and FP/debug tagging.
src/coreclr/inc/dacdbi.idl Removes DT_CONTEXT typedef; switches context parameters to BYTE*; adds new DacDbi context/register APIs and TargetInfo.
src/coreclr/debug/shared/riscv64/primitives.cpp Switches CORDbgCopyThreadContext to T_CONTEXT and uses CONTEXT_* flags.
src/coreclr/debug/shared/loongarch64/primitives.cpp Switches CORDbgCopyThreadContext to T_CONTEXT and uses CONTEXT_* flags; updates FP span sizing.
src/coreclr/debug/shared/i386/primitives.cpp Switches CORDbgCopyThreadContext to T_CONTEXT and uses CONTEXT_* flags.
src/coreclr/debug/shared/arm64/primitives.cpp Switches CORDbgCopyThreadContext to T_CONTEXT and uses CONTEXT_* flags.
src/coreclr/debug/shared/arm/primitives.cpp Switches CORDbgCopyThreadContext to T_CONTEXT and uses CONTEXT_* flags; updates debug span constant.
src/coreclr/debug/shared/amd64/primitives.cpp Switches CORDbgCopyThreadContext to T_CONTEXT.
src/coreclr/debug/inc/riscv64/primitives.h Switches helpers to T_CONTEXT.
src/coreclr/debug/inc/loongarch64/primitives.h Switches helpers to T_CONTEXT.
src/coreclr/debug/inc/i386/primitives.h Switches helpers to T_CONTEXT.
src/coreclr/debug/inc/dbgipcevents.h Removes arch-specific float count and SP/FP address helpers; introduces CORDB_MAX_FLOAT_REGISTERS.
src/coreclr/debug/inc/dacdbistructures.h Changes Debugger_STRData::ctx to BYTE* and documents as opaque target context bytes.
src/coreclr/debug/inc/dacdbiinterface.h Switches various context params to BYTE*; adds new DacDbi context/register APIs and target info enums/struct.
src/coreclr/debug/inc/common.h Updates CORDbgCopyThreadContext signature to T_CONTEXT.
src/coreclr/debug/inc/arm64/primitives.h Switches helpers to T_CONTEXT; removes unused typedef.
src/coreclr/debug/inc/arm/primitives.h Switches helpers to T_CONTEXT; removes unused typedef.
src/coreclr/debug/inc/arm_primitives.h Switches helpers to T_CONTEXT and adjusts breakpoint-PC logic preprocessor condition.
src/coreclr/debug/inc/amd64/primitives.h Switches helpers to T_CONTEXT; removes unused typedef.
src/coreclr/debug/ee/debugger.cpp Removes DT_CONTEXT casts when calling breakpoint-PC and SS-flag helpers.
src/coreclr/debug/ee/controller.cpp Removes DT_CONTEXT casts when calling SS-flag and IP helpers.
src/coreclr/debug/di/valuehome.cpp Replaces architecture-specific context/register mutations with DAC register read/write and target-sized buffers.
src/coreclr/debug/di/stdafx.h Replaces per-arch thread-context macros with unified DbiGet/SetThreadContext(T_CONTEXT*) declarations.
src/coreclr/debug/di/shimstackwalk.cpp Uses DAC register reads for SP and converts shim contexts to opaque target-sized buffers.
src/coreclr/debug/di/shimpriv.h Updates shim stackwalk state to own target-sized context buffers and passes sizes through.
src/coreclr/debug/di/shimlocaldatatarget.cpp Switches local datatarget thread-context casts from DT_CONTEXT to T_CONTEXT.
src/coreclr/debug/di/rsstackwalk.cpp Converts stackwalk internal state from DT_CONTEXT to opaque buffers and uses DAC CopyContext.
src/coreclr/debug/di/rsregsetcommon.cpp Converts register-set state from cached DT_CONTEXT to opaque buffers and uses DAC CopyContext.
src/coreclr/debug/di/rspriv.h Updates many signatures/fields from DT_CONTEXT to BYTE*/T_CONTEXT; adds context-size caching and DAC register helpers.
src/coreclr/debug/di/process.cpp Adds target-context-size caching via DAC; switches SafeRead/WriteThreadContext to operate on opaque buffers and target info queries.
src/coreclr/debug/di/platformspecific.cpp Stops including per-arch cordbregisterset.cpp implementations; keeps per-arch primitives.
src/coreclr/debug/di/module.cpp Routes JIT-reg-num → CorDebugRegister mapping through DAC-backed helper on CordbProcess.
src/coreclr/debug/di/cordb.cpp Unifies DbiGet/SetThreadContext implementation around T_CONTEXT and updated alignment logic.
src/coreclr/debug/di/CMakeLists.txt Adds a shared cordbregisterset.cpp (new common register-set impl) and removes floatconversion ASM wiring.
src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp Switches DacDbi stackwalk context entrypoints to BYTE* but reinterprets to DT_CONTEXT internally.
src/coreclr/debug/daccess/dacdbiimpl.h Updates interface signatures for BYTE* contexts and declares new DacDbi context/register APIs.
src/coreclr/debug/di/riscv64/floatconversion.S Removes unused float conversion assembly.
src/coreclr/debug/di/riscv64/cordbregisterset.cpp Removes per-arch register-set implementation.
src/coreclr/debug/di/loongarch64/floatconversion.S Removes unused float conversion assembly.
src/coreclr/debug/di/loongarch64/cordbregisterset.cpp Removes per-arch register-set implementation.
src/coreclr/debug/di/i386/cordbregisterset.cpp Removes per-arch register-set implementation.
src/coreclr/debug/di/arm64/floatconversion.S Removes unused float conversion assembly.
src/coreclr/debug/di/arm64/floatconversion.asm Removes unused float conversion assembly.
src/coreclr/debug/di/arm64/cordbregisterset.cpp Removes per-arch register-set implementation.
src/coreclr/debug/di/arm/floatconversion.S Removes unused float conversion assembly.
src/coreclr/debug/di/arm/cordbregisterset.cpp Removes per-arch register-set implementation.
src/coreclr/debug/di/amd64/floatconversion.S Removes unused float conversion assembly.
src/coreclr/debug/di/amd64/FloatConversion.asm Removes unused float conversion assembly.
src/coreclr/debug/di/amd64/cordbregisterset.cpp Removes per-arch register-set implementation.

Copilot's findings

  • Files reviewed: 62/62 changed files
  • Comments generated: 5

Comment thread src/coreclr/debug/ee/controller.cpp
Comment thread src/coreclr/debug/di/rsregsetcommon.cpp
Comment thread src/coreclr/debug/inc/arm_primitives.h
Comment thread src/coreclr/debug/di/CMakeLists.txt
Copilot AI review requested due to automatic review settings July 8, 2026 18:09

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 65/65 changed files
  • Comments generated: 5

Comment thread src/coreclr/debug/inc/arm_primitives.h
Comment thread src/coreclr/debug/ee/controller.cpp
Comment thread src/coreclr/debug/di/rsregsetcommon.cpp Outdated
Comment thread src/coreclr/debug/di/cordbregisterset.cpp
Copilot AI review requested due to automatic review settings July 8, 2026 18:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 65/65 changed files
  • Comments generated: 3

Comment thread src/coreclr/debug/di/rsregsetcommon.cpp
Comment on lines +5920 to +5938
HRESULT hr = S_OK;
DWORD sizeToWrite = sizeof(T_CONTEXT);

if (contextSize < sizeof(DT_CONTEXT))
BYTE * pRemoteContext = (BYTE*) pContext.UnsafeGet();
BYTE * pCtxSource = (BYTE*) pCtx;


#if defined(CONTEXT_EXTENDED_REGISTERS)
if ((pCtx->ContextFlags & CONTEXT_EXTENDED_REGISTERS) != CONTEXT_EXTENDED_REGISTERS)
{
LOG((LF_CORDB, LL_INFO10000, "CP::GTC: thread=0x%x, context size is invalid.\n", threadID));
return E_INVALIDARG;
sizeToWrite = offsetof(T_CONTEXT, SegSs) + sizeof(pCtx->SegSs);
}
#endif

pContext = reinterpret_cast<DT_CONTEXT *>(context);
EX_TRY
{
TargetBuffer tb(pRemoteContext, sizeToWrite);
SafeWriteBuffer(tb, (const BYTE*) pCtxSource);
}
Comment thread src/coreclr/debug/ee/controller.cpp
Copilot AI review requested due to automatic review settings July 8, 2026 20:14

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 69/69 changed files
  • Comments generated: 3

Comment thread src/coreclr/debug/di/rsregsetcommon.cpp Outdated
Comment on lines +90 to +101
// Load the float cache up front so its register range can classify the
// requested bits into GPR and float batches.
HRESULT hr = EnsureFloatStateLoaded(pThread);
bool areFloatsValid = !!SUCCEEDED(hr);

int firstFloat = -1;
int lastFloat = -1;
if (pThread->m_floatValuesCount > 0 && pThread->m_firstFloatReg >= 0 && areFloatsValid)
{
firstFloat = pThread->m_firstFloatReg;
lastFloat = firstFloat + (int)pThread->m_floatValuesCount - 1;
}
Comment on lines 158 to +169
@@ -166,7 +166,7 @@ HRESULT STDMETHODCALLTYPE DacDbiInterfaceImpl::GetStackWalkCurrentContext(StackW

StackFrameIterator * pIter = GetIteratorFromHandle(pSFIHandle);

GetStackWalkCurrentContext(pIter, pContext);
GetStackWalkCurrentContext(pIter, reinterpret_cast<DT_CONTEXT *>(pContext));
Copilot AI review requested due to automatic review settings July 8, 2026 20:21

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 69/69 changed files
  • Comments generated: 2

Comment on lines 1446 to 1457
if (m_pDacPrimitives != NULL)
{
m_pDacPrimitives->Release();
m_pDacPrimitives = NULL;
}

if (m_hDacModule != NULL)
{
LOG((LF_CORDB, LL_INFO1000, "Unloading DAC\n"));
m_hDacModule.Free();
}
}
Comment on lines +392 to +399
ULONG32 cbCtx = GetProcess()->GetTargetContextSize();
NewArrayHolder<BYTE> tmpCtx(new BYTE[cbCtx]);
memcpy(tmpCtx, m_pContextBuffer, cbCtx);
// flags == 0: tmpCtx already carries the desired ContextFlags (copied above).
IfFailThrow(pDAC->CopyContext(tmpCtx, cbCtx, context, contextSize, 0));
IfFailThrow(pDAC->CheckContext(m_pCordbThread->m_vmThreadToken, tmpCtx));

memcpy(m_pContextBuffer, tmpCtx, cbCtx);
Copilot AI review requested due to automatic review settings July 8, 2026 20:56

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 70/70 changed files
  • Comments generated: 2

Comment on lines +90 to +101
// Load the float cache up front so its register range can classify the
// requested bits into GPR and float batches.
HRESULT hr = EnsureFloatStateLoaded(pThread);
bool areFloatsValid = !!SUCCEEDED(hr);

int firstFloat = -1;
int lastFloat = -1;
if (pThread->m_floatValuesCount > 0 && pThread->m_firstFloatReg >= 0 && areFloatsValid)
{
firstFloat = pThread->m_firstFloatReg;
lastFloat = firstFloat + (int)pThread->m_floatValuesCount - 1;
}
Comment on lines 5556 to 5562
// allocate a new CordbRegisterSet object
RSInitHolder<CordbRegisterSet> pRegisterSet(new CordbRegisterSet(m_pThread,
&m_context,
RSInitHolder<CordbRegisterSet> pRegisterSet(new CordbRegisterSet(m_pContextBuffer,
GetProcess()->GetTargetContextSize(),
m_pThread,
IsLeafFrame(),
false));

Copilot AI review requested due to automatic review settings July 8, 2026 21:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 70/70 changed files
  • Comments generated: 4

Comment on lines +131 to 136
IDacDbiInterface * pDAC = GetProcess()->GetDAC();
ULONG32 targetContextSize = GetProcess()->GetTargetContextSize();

// Just to be safe, zero out the buffer we got in while preserving the ContextFlags.
// On X64 the ContextFlags field is not the first 4 bytes of the DT_CONTEXT.
DWORD dwContextFlags = pInputContext->ContextFlags;
ZeroMemory(context, contextSize);
pInputContext->ContextFlags = dwContextFlags;

// Augment the leafmost (active) register w/ information from the current context.
DT_CONTEXT * pLeafContext = NULL;
BYTE * pLeafContext = NULL;
if (m_active)
{
Comment on lines 5877 to 5889
HRESULT hr = S_OK;
DWORD sizeToWrite = sizeof(DT_CONTEXT);
ULONG32 sizeToWrite;
BOOL hasExtendedRegisters = FALSE;
IfFailThrow(GetDAC()->ContextHasExtendedRegisters(const_cast<BYTE *>(pCtx), GetTargetContextSize(), &hasExtendedRegisters));
IfFailThrow(GetDAC()->GetTargetContextSize(
hasExtendedRegisters ? IDacDbiInterface::kContextSizeExtendedRegisters : IDacDbiInterface::kContextSizeBase,
&sizeToWrite));
IDacDbiInterface::TargetInfo targetInfo;

BYTE * pRemoteContext = (BYTE*) pContext.UnsafeGet();
BYTE * pCtxSource = (BYTE*) pCtx;


#if defined(DT_CONTEXT_EXTENDED_REGISTERS)
// If our context has extended registers, then write the whole thing. Otherwise, just write the minimum part.
if ((pCtx->ContextFlags & DT_CONTEXT_EXTENDED_REGISTERS) != DT_CONTEXT_EXTENDED_REGISTERS)
{
sizeToWrite = offsetof(DT_CONTEXT, ExtendedRegisters);
}
#endif
IfFailThrow(GetDAC()->GetTargetInfo(&targetInfo));

Comment on lines +90 to +101
// Load the float cache up front so its register range can classify the
// requested bits into GPR and float batches.
HRESULT hr = EnsureFloatStateLoaded(pThread);
bool areFloatsValid = !!SUCCEEDED(hr);

int firstFloat = -1;
int lastFloat = -1;
if (pThread->m_floatValuesCount > 0 && pThread->m_firstFloatReg >= 0 && areFloatsValid)
{
firstFloat = pThread->m_firstFloatReg;
lastFloat = firstFloat + (int)pThread->m_floatValuesCount - 1;
}
Comment on lines +33 to +36
IDacDbiInterface * pDAC = pThread->GetProcess()->GetDAC();
IfFailThrow(pDAC->ReadRegistersFromContext(
const_cast<BYTE *>(pCtx),
ctxSize,
Copilot AI review requested due to automatic review settings July 8, 2026 23:47

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

  • Files reviewed: 70/70 changed files
  • Comments generated: 2

Comment on lines 1452 to 1457
if (m_hDacModule != NULL)
{
LOG((LF_CORDB, LL_INFO1000, "Unloading DAC\n"));
m_hDacModule.Free();
}
}
Comment on lines +5897 to +5902
if (targetInfo.arch == IDacDbiInterface::kArchAMD64)
{
pRemoteContext += offsetof(CONTEXT, ContextFlags); // immediately follows the 6 parameters P1-P6
pCtxSource += offsetof(CONTEXT, ContextFlags);
sizeToWrite -= offsetof(CONTEXT, ContextFlags);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants