Skip to content

Implement cDAC TraverseLoaderHeap via Loader contract#125129

Open
Copilot wants to merge 17 commits intomainfrom
copilot/implement-cdac-api-traverse-loader-heap
Open

Implement cDAC TraverseLoaderHeap via Loader contract#125129
Copilot wants to merge 17 commits intomainfrom
copilot/implement-cdac-api-traverse-loader-heap

Conversation

Copy link
Contributor

Copilot AI commented Mar 3, 2026

Implements ISOSDacInterface13::TraverseLoaderHeap (with and without kind) in the managed cDAC stack via the Loader contract. Adds separate cDAC types for LoaderHeap and ExplicitControlLoaderHeap, with a LoaderHeapKind enum embedded in GetFirstLoaderHeapBlock.

Description

C++ VM

  • loaderheap.h: forward-declares cdac_data<T>, adds friend struct cdac_data<UnlockedLoaderHeapBaseTraversable>, and provides a cdac_data<UnlockedLoaderHeapBaseTraversable> specialization exposing FirstBlock — matching the pattern used in arraylist.h and loaderallocator.hpp.
  • datadescriptor.inc: two separate cDAC types (LoaderHeap, ExplicitControlLoaderHeap) each with a FirstBlock field via cdac_data<UnlockedLoaderHeapBaseTraversable>::FirstBlock; LoaderHeapBlock fields via direct offsetof (public struct members).

Managed contracts

  • LoaderHeapKind enum (Normal = 0, ExplicitControl = 1) in ILoader.cs; GetFirstLoaderHeapBlock takes a LoaderHeapKind and dispatches to Data.LoaderHeap or Data.ExplicitControlLoaderHeap accordingly — unknown kinds throw NotImplementedException.
  • New Data/ExplicitControlLoaderHeap.cs (IData<T>) reads FirstBlock from the ExplicitControlLoaderHeap cDAC type.
  • DataType.ExplicitControlLoaderHeap added.

Legacy DAC (SOSDacImpl.cs)

TraverseLoaderHeap (no-kind) and TraverseLoaderHeapWithKind implemented independently via the same ILoader contract methods — no cross-dependency. kind maps to LoaderHeapKind; out-of-range values return E_NOTIMPL.

Tests

28 unit tests covering empty heap, single block, and multi-block scenarios across both heap kinds and 4 pointer-size variants.

Docs

Loader.md updated with LoaderHeapKind enum, updated GetFirstLoaderHeapBlock signature, ExplicitControlLoaderHeap data descriptor row, and revised algorithm pseudocode for both dispatch paths.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@dotnet-policy-service
Copy link
Contributor

Tagging subscribers to this area: @agocke
See info in area-owners.md if you want to be subscribed.

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
… typo fix

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Copilot AI changed the title [WIP] Add cdac API TraverseLoaderHeap implementation Implement cDAC TraverseLoaderHeap via IGC contract Mar 3, 2026
Copilot finished work on behalf of rcj1 March 3, 2026 17:40
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Copilot AI changed the title Implement cDAC TraverseLoaderHeap via IGC contract Implement cDAC TraverseLoaderHeap via Loader contract Mar 3, 2026
Copilot finished work on behalf of rcj1 March 3, 2026 17:52
…ructs for LoaderHeap types

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
…loaderheap.h

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Copilot finished work on behalf of rcj1 March 3, 2026 18:34
…ype; embed kind check in GetFirstLoaderHeapBlock

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
…to loaderheap.h

Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
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

Implements ISOSDacInterface13::TraverseLoaderHeap in the managed cDAC stack using the Loader contract, adding new cDAC data descriptors/types for loader heaps and blocks so SOS can enumerate heap blocks via the contract layer.

Changes:

  • Add LoaderHeap / ExplicitControlLoaderHeap / LoaderHeapBlock cDAC types (native + managed) and LoaderHeapKind dispatch in ILoader.
  • Implement TraverseLoaderHeap (kind + no-kind) in SOSDacImpl using the ILoader APIs and update COM interface callback signatures.
  • Add unit tests and update design docs for the new traversal APIs/descriptors.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/native/managed/cdac/tests/LoaderHeapTests.cs Adds unit tests for normal/explicit-control loader heap traversal.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs Implements TraverseLoaderHeap using the managed ILoader contract (with DEBUG cross-validation).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ISOSDacInterface.cs Updates TraverseLoaderHeap callback signatures to typed unmanaged function pointers.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/LoaderHeapBlock.cs Adds managed IData<> model for LoaderHeapBlock fields.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/LoaderHeap.cs Adds managed IData<> model for normal loader heap FirstBlock.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Data/ExplicitControlLoaderHeap.cs Adds managed IData<> model for explicit-control heap FirstBlock.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/Contracts/Loader_1.cs Implements new ILoader APIs for loader heap traversal.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/DataType.cs Adds new DataType entries for loader heap descriptors.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs Introduces LoaderHeapKind and new loader heap traversal APIs.
src/coreclr/vm/datadescriptor/datadescriptor.inc Adds native cDAC descriptors for LoaderHeap, ExplicitControlLoaderHeap, and LoaderHeapBlock.
src/coreclr/inc/loaderheap.h Exposes FirstBlock offset(s) for cDAC via cdac_data<> specializations.
docs/design/datacontracts/Loader.md Documents the new loader heap traversal APIs and descriptors.
docs/design/datacontracts/GC.md Fixes a spelling issue in GC contract docs (with one remaining typo noted).

rcj1 and others added 2 commits March 6, 2026 09:21
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@rcj1 rcj1 marked this pull request as ready for review March 6, 2026 17:23
Copilot AI review requested due to automatic review settings March 6, 2026 17:23
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

Copilot reviewed 13 out of 13 changed files in this pull request and generated 5 comments.

@max-charlamb
Copy link
Member

We should also rebase/merge on top of main and fix any conflicts or problems that arise.

@rcj1
Copy link
Contributor

rcj1 commented Mar 7, 2026

@jkotas adding the virtual destructor did not cause the correct offsetof() to be picked up by the cDAC in, for example, LoaderAllocator. DavidWr has indicated that it is not reliable / platform dependent whether this will be optimized out.

@jkotas
Copy link
Member

jkotas commented Mar 9, 2026

@jkotas adding the virtual destructor did not cause the correct offsetof() to be picked up by the cDAC in, for example, LoaderAllocator. DavidWr has indicated that it is not reliable / platform dependent whether this will be optimized out.

Ok.

I think we are still exposed to the fragility of offsetof and multiple inheritance as copilot pointed it in #125129 (comment) . If it is not causing observable issues, we can leave it like that.


// Returns the first block of the loader heap linked list, or TargetPointer.Null if the heap has no blocks.
// Throws NotImplementedException for unknown kind values.
TargetPointer GetFirstLoaderHeapBlock(TargetPointer loaderHeap, LoaderHeapKind kind);
Copy link
Member

Choose a reason for hiding this comment

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

From what I can see, this LoaderHeapKind appears to have no impact on the final result. Both kinds derive from UnlockedLoaderHeapBaseTraversable and the m_pFirstBlock pointer that we need is also a member of that type. Let me know if I am missing something.

I'm thinking we should drop this kind argument from the API. If we did I'm guessing a number of other things would change too:

  • change the cDac contract to depend on a single UnlockedLoaderHeapBaseTraversable::m_pFirst field instead of per-derived type definitions of the same field.
  • get rid of the kind enum
  • Reduce the two IData types down to a single one for the base class
  • Change SOSDacInterface13.TraverseLoaderHeap impl to ignore the kind argument from the caller

Copy link
Member

Choose a reason for hiding this comment

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

From what I can see, this LoaderHeapKind appears to have no impact on the final result

Unfortunately, it does have an impact as discussed above. Loader heap implementation uses C++ multiple inheritance that introduces multiple different this pointers for the same object.

I agree that it would be nice to do what you are proposing. We would have to get the multiple inheritance under control first.

Copy link
Member

Choose a reason for hiding this comment

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

Ah I walked into the midst unaware!

What if we removed the multiple inheritance with a pattern like this:

class LoaderHeapBackout final : public ILoaderHeapBackout
{
   LoaderHeap* m_owner;
   void RealBackoutMem(...) override { m_owner->RealBackoutMem(...); }
};
   
class UnlockedLoaderHeapBase : public UnlockedLoaderHeapBaseTraversable
{
   LoaderHeapBackout m_backout; // pass out the address of this field when an
                                // ILoaderHeapBackout is needed.
};

IMO the conceptual simplification to data contract would be worth doing a small runtime refactor.

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.

6 participants