Skip to content

Comments

Implement ISOSDacInterface::GetLoaderAllocatorHeapNames and GetLoaderAllocatorHeaps in cDAC SOSDacImpl#124818

Draft
Copilot wants to merge 8 commits intomainfrom
copilot/implement-get-loader-allocator-heap-names
Draft

Implement ISOSDacInterface::GetLoaderAllocatorHeapNames and GetLoaderAllocatorHeaps in cDAC SOSDacImpl#124818
Copilot wants to merge 8 commits intomainfrom
copilot/implement-get-loader-allocator-heap-names

Conversation

Copy link
Contributor

Copilot AI commented Feb 24, 2026

Description

Implements ISOSDacInterface13.GetLoaderAllocatorHeapNames and ISOSDacInterface13.GetLoaderAllocatorHeaps in the managed cDAC SOSDacImpl.cs, replacing the legacy DAC delegation stubs. Based on ClrDataAccess::GetLoaderAllocatorHeapNames and ClrDataAccess::GetLoaderAllocatorHeaps in request.cpp.

Native Data Descriptors

  • Added heap fields to cdac_data<LoaderAllocator> in loaderallocator.hpp: StaticsHeap, ExecutableHeap, FixupPrecodeHeap (#ifdef HAS_FIXUP_PRECODE), NewStubPrecodeHeap (#ifndef FEATURE_PORTABLE_ENTRYPOINTS), DynamicHelpersStubHeap (FEATURE_READYTORUN && FEATURE_STUBPRECODE_DYNAMIC_HELPERS), VirtualCallStubManager
  • Added new cdac_data<VirtualCallStubManager> in virtualcallstub.h: IndcellHeap (unconditional), CacheEntryHeap (#ifdef FEATURE_VIRTUAL_STUB_DISPATCH)
  • Added corresponding entries to datadescriptor.inc with matching feature guards
  • Added VirtualCallStubManager to DataType enum
  • Added #include "virtualcallstub.h" to datadescriptor.h so cdac_data<VirtualCallStubManager> is visible when datadescriptor.inc is compiled

Managed Data Classes

  • Updated Data/LoaderAllocator.cs with optional heap fields (FixupPrecodeHeap, NewStubPrecodeHeap, DynamicHelpersStubHeap as nullable) and always-present fields (StaticsHeap, ExecutableHeap, VirtualCallStubManager)
  • Created Data/VirtualCallStubManager.cs with IndcellHeap and optional CacheEntryHeap

ILoader Contract

  • Added single GetLoaderAllocatorHeaps(TargetPointer) method to ILoader interface returning IReadOnlyDictionary<string, TargetPointer> — dictionary keys are heap names, values are heap pointers
  • Implemented in Loader_1.cs with dynamic dictionary building based on data descriptor field presence via ContainsKey checks, matching the native #ifdef conditional compilation
  • Dictionary keys use nameof(Data.LoaderAllocator.X) and nameof(Data.VirtualCallStubManager.X) instead of hardcoded strings
  • Feature-conditional heaps (FixupPrecodeHeap, NewStubPrecodeHeap, DynamicHelpersStubHeap) are only included when the data descriptor field exists
  • VirtualCallStubManager heaps (IndcellHeap, CacheEntryHeap) are excluded entirely when VirtualCallStubManager is null

SOSDacImpl

  • GetLoaderAllocatorHeapNames: Queries global loader allocator via ILoader.GetLoaderAllocatorHeaps to get heap names from dictionary keys. Lazily initializes ANSI string pointers via Marshal.StringToHGlobalAnsi, cached on the instance. Standard cDAC pattern with try/catch, S_FALSE when buffer is insufficient, #if DEBUG legacy count comparison
  • GetLoaderAllocatorHeaps: Reads heap pointers through the ILoader contract dictionary, fills LoaderHeapKindNormal for all heaps

Tests

  • 8 test methods in LoaderTests.cs × 4 architectures = 32 new test cases
    • GetLoaderAllocatorHeapNames: Count query, full name retrieval, insufficient buffer, null pNeeded
    • GetLoaderAllocatorHeaps: Count query, full heap retrieval, insufficient buffer, null address
  • All 864 cDAC tests pass (832 existing + 32 new)

💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Feb 24, 2026
Copilot AI and others added 2 commits February 24, 2026 20:45
Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Copilot AI changed the title [WIP] Implement GetLoaderAllocatorHeapNames in SOSDacImpl.cs Implement ISOSDacInterface::GetLoaderAllocatorHeapNames in cDAC SOSDacImpl Feb 24, 2026
Comment on lines 4260 to 4286
private static readonly string[] s_loaderAllocatorHeapNames =
[
"LowFrequencyHeap",
"HighFrequencyHeap",
"StaticsHeap",
"StubHeap",
"ExecutableHeap",
"FixupPrecodeHeap",
"NewStubPrecodeHeap",
"IndcellHeap",
"CacheEntryHeap",
];

private static readonly nint[] s_loaderAllocatorHeapNamePtrs = InitializeHeapNamePtrs();

private static nint[] InitializeHeapNamePtrs()
{
nint[] ptrs = new nint[s_loaderAllocatorHeapNames.Length];
for (int i = 0; i < s_loaderAllocatorHeapNames.Length; i++)
{
ptrs[i] = Marshal.StringToHGlobalAnsi(s_loaderAllocatorHeapNames[i]);
}
return ptrs;
}

int ISOSDacInterface13.GetLoaderAllocatorHeapNames(int count, char** ppNames, int* pNeeded)
=> _legacyImpl13 is not null ? _legacyImpl13.GetLoaderAllocatorHeapNames(count, ppNames, pNeeded) : HResults.E_NOTIMPL;
{
Copy link
Member

Choose a reason for hiding this comment

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

@copilot , this is not quite correct. If you look at the runtime implementation, there are #defines that remove some elements from the list under certain conditions. We will need to do something similar here.

While we are at it, lets expand the scope of this PR to include implementing GetLoaderAllocatorHeaps is SOSDacImpl.cs since they are very related.

@max-charlamb max-charlamb added area-Diagnostics-coreclr and removed needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners labels Feb 24, 2026
@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.

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
@max-charlamb
Copy link
Member

@copilot, try again

…dd missing using

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 24, 2026

@copilot, try again

Implementation reworked in commits up to 0554c43. Changes:

Feature-conditional heap names: GetLoaderAllocatorHeapNames in Loader_1.cs dynamically builds the names list by checking ContainsKey on the data descriptor fields - DynamicHelpersStubHeap is conditional on FEATURE_READYTORUN && FEATURE_STUBPRECODE_DYNAMIC_HELPERS, and CacheEntryHeap is conditional on FEATURE_VIRTUAL_STUB_DISPATCH, matching the native LoaderAllocatorLoaderHeapNames array.

GetLoaderAllocatorHeaps: Fully implemented in SOSDacImpl.cs, reading heap pointers through the ILoader contract. The contract reads from LoaderAllocator and VirtualCallStubManager data classes, handling null VcsManager by padding with TargetPointer.Null.

Native data descriptors: Added cdac_data<LoaderAllocator> fields (StaticsHeap, ExecutableHeap, FixupPrecodeHeap, NewStubPrecodeHeap, DynamicHelpersStubHeap, VirtualCallStubManager) and new cdac_data<VirtualCallStubManager> (IndcellHeap, CacheEntryHeap) in loaderallocator.hpp, virtualcallstub.h, and datadescriptor.inc.

Tests: 32 new test cases (8 test methods × 4 architectures) covering both methods. All 864 cDAC tests pass.

Copilot AI changed the title Implement ISOSDacInterface::GetLoaderAllocatorHeapNames in cDAC SOSDacImpl Implement ISOSDacInterface::GetLoaderAllocatorHeapNames and GetLoaderAllocatorHeaps in cDAC SOSDacImpl Feb 24, 2026
Copy link
Member

@max-charlamb max-charlamb left a comment

Choose a reason for hiding this comment

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

@copilot , address feedback

Comment on lines 97 to 98
IReadOnlyList<string> GetLoaderAllocatorHeapNames() => throw new NotImplementedException();
IReadOnlyList<TargetPointer> GetLoaderAllocatorHeaps(TargetPointer loaderAllocatorPointer) => throw new NotImplementedException();
Copy link
Member

Choose a reason for hiding this comment

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

Instead of hardcoding these, lets have a single API that returns a dictionary. If the ISOSDacInterface APIs only want the names, we can query the global loader allocator and return the values. That way we don't care about ordering.

…ps API

Replace separate GetLoaderAllocatorHeapNames() and GetLoaderAllocatorHeaps(TargetPointer)
with a single GetLoaderAllocatorHeaps(TargetPointer) returning IReadOnlyDictionary<string, TargetPointer>.

SOSDacImpl.GetLoaderAllocatorHeapNames now queries the global loader allocator to get
names from the dictionary. GetLoaderAllocatorHeaps iterates dictionary values.

Tests updated to use dictionary-based mock and verify unordered name/address sets.

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Copy link
Member

@max-charlamb max-charlamb left a comment

Choose a reason for hiding this comment

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

@copilot , address feedback

…tionary

- Use nameof(Data.LoaderAllocator.X) instead of hardcoded strings for all
  dictionary keys in GetLoaderAllocatorHeaps
- Make FixupPrecodeHeap and NewStubPrecodeHeap conditional on ContainsKey
  (exclude from dictionary when field absent from data descriptor)
- Remove else branch that padded IndcellHeap/CacheEntryHeap with null when
  VirtualCallStubManager is null - only include them when VcsManager exists
- All 864 cDAC tests pass

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 24, 2026

@copilot , address feedback

Addressed all three review comments in e0e9cd5nameof for dict keys, conditional inclusion for FixupPrecodeHeap/NewStubPrecodeHeap, and no null-padding for VcsManager heaps. All 864 tests pass.

@copilot, try again

Addressed all three review comments in e0e9cd5nameof for dict keys, conditional inclusion for FixupPrecodeHeap/NewStubPrecodeHeap, and no null-padding for VcsManager heaps. All 864 tests pass.

@max-charlamb
Copy link
Member

@copilot , please fix build break

datadescriptor.h did not include virtualcallstub.h, so the
cdac_data<VirtualCallStubManager> template specialization was not visible
when datadescriptor.inc was compiled. This caused a build failure
referencing cdac_data<VirtualCallStubManager>::IndcellHeap and
cdac_data<VirtualCallStubManager>::CacheEntryHeap.

Co-authored-by: max-charlamb <44248479+max-charlamb@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 24, 2026

@copilot , please fix build break

Fixed in 3f63f2f. The issue was that datadescriptor.h did not include virtualcallstub.h, so cdac_data<VirtualCallStubManager> was not visible when datadescriptor.inc was compiled. Added #include "virtualcallstub.h" to datadescriptor.h.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • https://api.github.com/graphql
    • Triggering command: /usr/bin/gh gh pr checks 124818 --json name,state,link (http block)
    • Triggering command: /usr/bin/gh /usr/bin/gh pr checks 124818 --repo dotnet/runtime (http block)
    • Triggering command: /usr/bin/gh gh pr view 124818 --json statusCheckRollup --jq .statusCheckRollup[] | select(.state == &#34;FAILURE&#34; or .state == &#34;ERROR&#34;) | {name: .name, state: .state, link: .targetUrl} (http block)

If you need me to access, download, or install something from one of these locations, you can either:

TargetPointer GetDynamicIL(ModuleHandle handle, uint token) => throw new NotImplementedException();
IReadOnlyList<string> GetLoaderAllocatorHeapNames() => throw new NotImplementedException();
IReadOnlyList<TargetPointer> GetLoaderAllocatorHeaps(TargetPointer loaderAllocatorPointer) => throw new NotImplementedException();
IReadOnlyDictionary<string, TargetPointer> GetLoaderAllocatorHeaps(TargetPointer loaderAllocatorPointer) => throw new NotImplementedException();
Copy link
Member

Choose a reason for hiding this comment

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

I don't see any docs for this in the contract doc. I assume we need to add it.

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.

3 participants