Skip to content

[cDAC] Remove DT_CONTEXT from DBI layer#130367

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

[cDAC] Remove DT_CONTEXT from DBI layer#130367
rcj1 wants to merge 32 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 Outdated
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 thread src/coreclr/debug/di/process.cpp
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 thread src/coreclr/debug/di/cordbregisterset.cpp Outdated
Comment thread src/coreclr/debug/daccess/dacdbiimplstackwalk.cpp Outdated
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 thread src/coreclr/debug/di/process.cpp
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 thread src/coreclr/debug/di/cordbregisterset.cpp Outdated
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 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

Comments suppressed due to low confidence (1)

src/coreclr/debug/inc/common.h:64

  • The comment claims the buffers "only need to be at least sizeof(DT_CONTEXT)", but the helper APIs below (ContextSizeForFlags/CheckContextSizeForFlags) and the x86 implementation allow smaller buffers when CONTEXT_EXTENDED_REGISTERS isn’t requested. This comment should describe the actual contract (size is flag-dependent) so future callers don’t over-allocate or assume a hard minimum of sizeof(DT_CONTEXT).
  • Files reviewed: 74/74 changed files
  • Comments generated: 1

Comment thread src/coreclr/debug/di/shimlocaldatatarget.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 22, 2026 23:46

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

Comments suppressed due to low confidence (2)

src/coreclr/debug/di/rsstackwalk.cpp:357

  • The destination ContextFlags are not being merged with the incoming context's ContextFlags before calling CopyContext. With flags==0, CopyContext preserves the destination's existing flags and the chunk-wise copy only updates chunks where (dstFlags & srcFlags) contains the chunk flag. This differs from the previous logic that OR'ed the flags (tmpCtx.ContextFlags |= pSrcContext->ContextFlags), and can silently skip applying updates from the incoming context when the cached context lacks those flags.
    memcpy(tmpCtx, m_pContextBuffer, cbCtx);
    // flags == 0: tmpCtx already carries the desired ContextFlags (copied above).
    ContextBuffer temporaryContext = { tmpCtx, cbCtx };
    ContextBuffer sourceContext = { context, contextSize };
    IfFailThrow(pDAC->CopyContext(temporaryContext, sourceContext, 0));

src/coreclr/debug/inc/common.h:65

  • This comment says the buffers must be at least sizeof(DT_CONTEXT), but the implementation (e.g. i386 CopyThreadContext) explicitly allows smaller buffers when ContextFlags do not include extended register state. The doc here should match the actual size contract (ContextFlags + the regions selected by those flags).
  • Files reviewed: 74/74 changed files
  • Comments generated: 1

Comment thread src/coreclr/inc/dacdbi.idl Outdated
Comment thread src/coreclr/debug/inc/dacdbistructures.h Outdated
Copilot AI review requested due to automatic review settings July 23, 2026 04:52

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

Comments suppressed due to low confidence (3)

src/coreclr/debug/di/rsstackwalk.cpp:357

  • SetContextWorker no longer ORs the destination ContextFlags with the incoming context's flags before copying, so CopyContext(..., flags: 0) may skip copying chunks that are present in the incoming context but not already enabled in the cached context flags. The old code explicitly did tmpCtx.ContextFlags |= pSrcContext->ContextFlags before copying. Consider stamping the destination flags when calling CopyContext so the copy doesn't depend on the cached ContextFlags value.
    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).
    ContextBuffer temporaryContext = { tmpCtx, cbCtx };
    ContextBuffer sourceContext = { context, contextSize };
    IfFailThrow(pDAC->CopyContext(temporaryContext, sourceContext, 0));

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs:220

  • TryWriteFloatingPointRegister assumes any value length other than 4 bytes is an 8-byte double and calls ReadInt64LittleEndian(value). If a caller passes an unexpected size (e.g. 0, 2, 10), this will throw instead of returning false. Add an explicit length check for 4/8 bytes before decoding.
    src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs:231
  • TryGetX87SlotOffset reads StatusWord via context.Slice(statusWordOffset) without checking context length first. If the caller passes a truncated context buffer, this will throw. Other platform implementations return false on undersized spans; this helper should do the same.
  • Files reviewed: 74/74 changed files
  • Comments generated: 1

Comment on lines +1465 to +1467
ULONG32 size = 0;
IfFailThrow(GetDAC()->GetTargetContextSize(0x00000020L, &size)); // CONTEXT_EXTENDED_REGISTERS
m_ctxSize = size;
Copilot AI review requested due to automatic review settings July 23, 2026 05:01

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

Comments suppressed due to low confidence (2)

src/coreclr/debug/inc/common.h:64

  • The comment says the buffers only need to be at least sizeof(DT_CONTEXT), but the codebase also supports smaller CONTEXT buffers when ContextFlags omits trailing regions (e.g., x86 without CONTEXT_EXTENDED_REGISTERS via ContextSizeForFlags / CheckContextSizeForBuffer). Please update the comment to reflect the actual minimum size requirement so callers don’t assume they must always allocate sizeof(DT_CONTEXT).
    src/coreclr/debug/di/rsstackwalk.cpp:357
  • SetContextWorker no longer merges the incoming ContextFlags into the temporary context before calling CopyContext with flags==0 (which preserves the destination flags). If the current cached context has fewer flags than the incoming context, CopyContext will skip copying those requested chunks, changing behavior vs the previous tmpCtx.ContextFlags |= pSrcContext->ContextFlags logic.
    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).
    ContextBuffer temporaryContext = { tmpCtx, cbCtx };
    ContextBuffer sourceContext = { context, contextSize };
    IfFailThrow(pDAC->CopyContext(temporaryContext, sourceContext, 0));
  • Files reviewed: 74/74 changed files
  • Comments generated: 0 new

Copilot AI review requested due to automatic review settings July 23, 2026 20:00

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

Comments suppressed due to low confidence (2)

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs:221

  • TryWriteFloatingPointRegister assumes the incoming byte payload is either 4 or 8 bytes, but it doesn't validate this. Any other length will currently fall into the 8-byte path and can throw (e.g. ReadInt64LittleEndian on a short span) or encode garbage, which is risky given this helper sits underneath the DacDbi register-write path. Consider explicitly rejecting non-(4|8) sized inputs and returning false.
    src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/SimdRegisterAccess.cs:44
  • SimdRegisterAccess.TryWriteRegister advertises writing a scalar value that is "(4 or 8 bytes)", but it currently accepts any length and will blindly copy it into the register slot. Since this helper feeds the DacDbi float/SIMD scalar register write path, it's safer to enforce the documented 4/8-byte contract and reject other sizes to avoid corrupting the CONTEXT image.
  • Files reviewed: 74/74 changed files
  • Comments generated: 1

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 24, 2026 22:03

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

Comments suppressed due to low confidence (2)

src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs:220

  • TryWriteFloatingPointRegister assumes the value span is either 4 or 8 bytes; any other length will throw from BinaryPrimitives.ReadInt64LittleEndian instead of returning false. Since this is exposed via IPlatformContext/IPlatformAgnosticContext, it should validate input length and fail gracefully.
    src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs:238
  • TryGetX87SlotOffset reads StatusWord via context.Slice(...) without checking the span length first. If an undersized context buffer is ever passed in, this will throw instead of returning false. Add a bounds check before reading the status word so the helper fails gracefully.
  • Files reviewed: 74/74 changed files
  • Comments generated: 1

Comment on lines +163 to +169
// A variable sized host memory context buffer in target architecture specific layout.
// The currently supported layout matches the CONTEXT structure for the
// target architecture and OS.
// Not (yet) supported:
// - Optional trailing XState feature data in the buffer
// - Add an architecture enum field to make the struct self-describing
struct MSLAYOUT ContextBuffer
Copilot AI review requested due to automatic review settings July 24, 2026 22: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

Comments suppressed due to low confidence (4)

src/coreclr/debug/di/rsthread.cpp:5531

  • CordbNativeFrame::GetRegisterSet creates a CordbRegisterSet that holds a raw pointer to the frame’s context buffer (GetContext()) but does not take ownership / make a copy. If the caller releases the ICorDebugFrame but keeps the ICorDebugRegisterSet alive (legal COM usage), the frame’s context buffer can be freed while the register set still uses it, leading to use-after-free when reading registers.
        // allocate a new CordbRegisterSet object
        RSInitHolder<CordbRegisterSet> pRegisterSet(new CordbRegisterSet(GetContext(),
                                                                         m_pThread,
                                                                         IsLeafFrame(),
                                                                         false));

src/coreclr/debug/inc/common.h:64

  • The comment claims the context buffers must be at least sizeof(DT_CONTEXT), but the helpers below (ContextSizeForFlags / CheckContextSizeForBuffer) and the x86 copy logic allow smaller buffers when trailing regions (e.g., extended registers) are not requested via ContextFlags. The documentation should match the actual size contract.
    src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs:220
  • TryWriteFloatingPointRegister treats any value length other than 4 as an 8-byte double and then reads with ReadInt64LittleEndian, which will throw for unexpected lengths. Since the API contract is 4 or 8 bytes, this should validate the input length and return false for anything else.
    src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/StackWalk/Context/X86Context.cs:232
  • TryGetX87SlotOffset reads the StatusWord using context.Slice(offset) without validating that the buffer is large enough. If an undersized context span is passed, this will throw instead of returning false.
  • Files reviewed: 74/74 changed files
  • Comments generated: 0 new

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.

5 participants