[cDAC] Remove DT_CONTEXT from DBI layer#130367
Draft
rcj1 wants to merge 9 commits into
Draft
Conversation
Contributor
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
Contributor
There was a problem hiding this comment.
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 fromDT_CONTEXT*toBYTE*. - 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 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 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)); | |||
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); |
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)); | ||
|
|
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, |
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); | ||
| } |
This was referenced Jul 9, 2026
Open
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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: