Skip to content

[cDAC] Implement simple DacDbi methods and IDebugger contract#126032

Draft
max-charlamb wants to merge 2 commits intodotnet:mainfrom
max-charlamb:droid-debug-dacdbi-impl
Draft

[cDAC] Implement simple DacDbi methods and IDebugger contract#126032
max-charlamb wants to merge 2 commits intodotnet:mainfrom
max-charlamb:droid-debug-dacdbi-impl

Conversation

@max-charlamb
Copy link
Member

Summary

Implements 37 IDacDbiInterface methods in managed C# using cDAC contracts, replacing legacy native delegation stubs with actual implementations. Also introduces a new IDebugger contract for debugger state queries.

This builds on top of #125074 (COM conversion of IDacDbiInterface).

New IDebugger Contract

Adds the IDebugger contract with 5 APIs for reading debugger state:

  • Data descriptors in datadescriptor.inc and cdac_data<Debugger>
  • Debugger_1 implementation reading from Debugger data descriptor and CLRJitAttachState/MetadataUpdatesApplied globals
  • Contract documentation in docs/design/datacontracts/Debugger.md

Implemented DacDbi Methods by Contract Group

Debugger: IsLeftSideInitialized, GetDefinesBitField, GetMDStructuresVersion, GetAttachStateFlags, MetadataUpdatesApplied

Thread: EnumerateThreads, IsThreadMarkedDead, TryGetVolatileOSThreadID, GetUniqueThreadID, GetCurrentException, IsThreadSuspendedOrHijacked, HasUnhandledException

Loader: GetAssemblyFromDomainAssembly, GetAppDomainFullName, GetModuleSimpleName, GetAssemblyPath, GetModulePath, GetModuleForDomainAssembly, GetDomainAssemblyFromModule, EnumerateAssembliesInAppDomain, EnumerateModulesInAssembly, IsModuleMapped

Hardcoded: GetAppDomainId, GetAppDomainFromId, GetCurrentAppDomain, EnumerateAppDomains, IsAssemblyFullyTrusted, GetConnectionID, GetTaskID, IsWinRTModule, GetAppDomainIdFromVmObjectHandle, EnableNGENPolicy

Type: GetTypeDef, IsValueType, HasTypeParams

Object: GetObjectFromRefPtr, GetObject, GetVmObjectHandle, IsVmObjectHandleValid, GetHandleAddressFromVmHandle

Code/GC: GetMethodDescPtrFromIP, AreGCStructuresValid, GetGCHeapInformation, GetTypeID, GetTypeIDForType

All methods include #if DEBUG validation against the legacy DAC to verify consistency.

IStringHolder Vtable Calling

Since IStringHolder is not a COM interface (it's a plain C++ abstract class with a single virtual method), the managed implementation calls through its vtable directly using delegate* unmanaged function pointers.

Testing

  • 48 unit tests for the IDebugger contract (DebuggerTests.cs)
  • 29 dump tests across 6 test classes (DacDbi*DumpTests.cs) validating against real crash dumps
  • cDAC build: 0 errors, 0 warnings

Implement 37 IDacDbiInterface methods using cDAC contracts, replacing
legacy delegation stubs with actual implementations:

IDebugger contract (new):
- Add IDebugger interface with 5 APIs for debugger state
- Debugger_1 implementation reading from Debugger data descriptor
  and CLRJitAttachState/MetadataUpdatesApplied globals
- Data descriptors in datadescriptor.inc and cdac_data<Debugger>
- Contract documentation in docs/design/datacontracts/Debugger.md

Implemented DacDbi methods by contract group:
- Debugger: IsLeftSideInitialized, GetDefinesBitField,
  GetMDStructuresVersion, GetAttachStateFlags, MetadataUpdatesApplied
- Thread: EnumerateThreads, IsThreadMarkedDead,
  TryGetVolatileOSThreadID, GetUniqueThreadID, GetCurrentException,
  IsThreadSuspendedOrHijacked, HasUnhandledException
- Loader: GetAssemblyFromDomainAssembly, GetAppDomainFullName,
  GetModuleSimpleName, GetAssemblyPath, GetModulePath,
  GetModuleForDomainAssembly, GetDomainAssemblyFromModule,
  EnumerateAssembliesInAppDomain, EnumerateModulesInAssembly,
  IsModuleMapped
- Hardcoded: GetAppDomainId, GetAppDomainFromId, GetCurrentAppDomain,
  EnumerateAppDomains, IsAssemblyFullyTrusted, GetConnectionID,
  GetTaskID, IsWinRTModule, GetAppDomainIdFromVmObjectHandle,
  EnableNGENPolicy
- Type: GetTypeDef, IsValueType, HasTypeParams
- Object: GetObjectFromRefPtr, GetObject, GetVmObjectHandle,
  IsVmObjectHandleValid, GetHandleAddressFromVmHandle
- Code/GC: GetMethodDescPtrFromIP, AreGCStructuresValid,
  GetGCHeapInformation, GetTypeID, GetTypeIDForType

All methods include #if DEBUG validation against legacy DAC.

Tests:
- 48 unit tests for IDebugger contract (DebuggerTests.cs)
- 29 dump tests across 6 test classes (DacDbi*DumpTests.cs)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dotnet-policy-service
Copy link
Contributor

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

@rcj1
Copy link
Contributor

rcj1 commented Mar 24, 2026

@noahfalk

Copy link
Contributor

Copilot AI left a comment

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 adds a new Debugger cDAC contract and begins implementing IDacDbiInterface in managed C# using cDAC contracts, with accompanying unit tests and dump-based integration tests. It also wires up CoreCLR data descriptors/globals so the contract can read debugger state from targets.

Changes:

  • Introduce IDebugger contract (data descriptor + managed contract implementation) and register it in the contract registry.
  • Add a managed DacDbiImpl implementation (COM-visible) intended to replace legacy native delegation stubs for a set of IDacDbiInterface methods.
  • Add unit tests for the Debugger contract plus multiple dump-based DacDbi integration test classes.

Reviewed changes

Copilot reviewed 21 out of 21 changed files in this pull request and generated 16 comments.

Show a summary per file
File Description
src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiThreadDumpTests.cs Adds dump-based tests for DacDbi thread APIs (enumeration, thread state, OS thread id, exception).
src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiObjectDumpTests.cs Adds dump-based tests for DacDbi object-handle identity and AppDomain-id-from-handle behavior.
src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiLoaderDumpTests.cs Adds dump-based tests for loader/module/assembly DacDbi APIs, including string-returning methods and enumeration callbacks.
src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiGCDumpTests.cs Adds dump-based tests for DacDbi GC APIs and cross-validation with GC contract.
src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiDebuggerDumpTests.cs Adds dump-based tests for DacDbi Debugger-related APIs and cross-validation with Debugger contract.
src/native/managed/cdac/tests/DumpTests/DacDbi/DacDbiAppDomainDumpTests.cs Adds dump-based tests for AppDomain/misc policy/flags-related DacDbi APIs.
src/native/managed/cdac/tests/DebuggerTests.cs Adds unit tests for the new IDebugger contract using mock targets/memory.
src/native/managed/cdac/mscordaccore_universal/Entrypoints.cs Adds unmanaged entrypoint for creating the managed COM DacDbi interface implementation.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs Registers the Debugger contract factory so it’s available via Target.Contracts.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/Dbi/DacDbiImpl.cs Introduces the managed COM class implementing IDacDbiInterface methods via cDAC contracts (with DEBUG cross-validation against legacy DAC).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/Debugger.cs Adds processed-data reader for the Debugger data descriptor.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Debugger_1.cs Implements IDebugger v1 using globals + processed data.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/DebuggerFactory.cs Creates the correct Debugger contract implementation for a given version.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Constants.cs Adds global names used by the Debugger contract implementation.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs Adds DataType.Debugger for the new data descriptor.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/CorDbHResults.cs Adds CORDBG_E_NOTREADY constant used by Debugger contract error behavior.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/IDebugger.cs Defines the IDebugger contract surface and default stub implementation.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs Exposes Target.Contracts.Debugger accessor on the base registry.
src/coreclr/vm/datadescriptor/datadescriptor.inc Adds Debugger data descriptor fields and global pointers (Debugger, CLRJitAttachState, MetadataUpdatesApplied) and registers the Debugger contract.
src/coreclr/debug/ee/debugger.h Exposes Debugger field offsets to cDAC via cdac_data specialization.
docs/design/datacontracts/Debugger.md Documents the Debugger contract’s APIs, globals, data descriptors, and algorithms.

@max-charlamb max-charlamb changed the title Implement cDAC DacDbi methods and IDebugger contract [cDAC] Implement simple DacDbi methods and IDebugger contract Mar 24, 2026
@max-charlamb max-charlamb marked this pull request as draft March 24, 2026 16:36
…mplement 3 new methods

- Redesign IDebugger: TryGetDebuggerData replaces separate APIs
- Use Marshal.GetExceptionForHR, ReadGlobalPointer for CLRJitAttachState
- Implement GetModuleSimpleName, GetCurrentException, EnumerateModulesInAssembly
- Fix GetAppDomainIdFromVmObjectHandle null handle, allow null legacy in entrypoint
- Fix test BOOL types, add checkedCount assertions, filter Dead/Unstarted threads
- Replace TestStringHolder with NativeStringHolder (native vtable layout)
- Update Debugger.md doc format, include cdacdata.h, remove unnecessary friend decl

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
namespace Microsoft.Diagnostics.DataContractReader.DumpTests;

/// <summary>
/// Creates a native-memory object that mimics the C++ IStringHolder vtable layout.
Copy link
Member

Choose a reason for hiding this comment

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

Should we just make IStringHolder a COM interface so that our standard COM marshalling techniques work? Seems like it might be a little simpler.

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.

4 participants