Implement cDAC TraverseLoaderHeap via Loader contract#125129
Implement cDAC TraverseLoaderHeap via Loader contract#125129
Conversation
|
Tagging subscribers to this area: @agocke |
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
… typo fix Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
Co-authored-by: rcj1 <77995559+rcj1@users.noreply.github.com>
…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>
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs
Show resolved
Hide resolved
…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>
There was a problem hiding this comment.
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/LoaderHeapBlockcDAC types (native + managed) andLoaderHeapKinddispatch inILoader. - Implement
TraverseLoaderHeap(kind + no-kind) inSOSDacImplusing theILoaderAPIs 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). |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
...tive/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs
Show resolved
Hide resolved
...tive/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/Contracts/ILoader.cs
Show resolved
Hide resolved
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs
Outdated
Show resolved
Hide resolved
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs
Outdated
Show resolved
Hide resolved
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ISOSDacInterface.cs
Outdated
Show resolved
Hide resolved
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs
Outdated
Show resolved
Hide resolved
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs
Outdated
Show resolved
Hide resolved
|
We should also rebase/merge on top of main and fix any conflicts or problems that arise. |
|
@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. |
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/ISOSDacInterface.cs
Outdated
Show resolved
Hide resolved
This reverts commit 0b34106.
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); |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
Implements
ISOSDacInterface13::TraverseLoaderHeap(with and withoutkind) in the managed cDAC stack via theLoadercontract. Adds separate cDAC types forLoaderHeapandExplicitControlLoaderHeap, with aLoaderHeapKindenum embedded inGetFirstLoaderHeapBlock.Description
C++ VM
loaderheap.h: forward-declarescdac_data<T>, addsfriend struct cdac_data<UnlockedLoaderHeapBaseTraversable>, and provides acdac_data<UnlockedLoaderHeapBaseTraversable>specialization exposingFirstBlock— matching the pattern used inarraylist.handloaderallocator.hpp.datadescriptor.inc: two separate cDAC types (LoaderHeap,ExplicitControlLoaderHeap) each with aFirstBlockfield viacdac_data<UnlockedLoaderHeapBaseTraversable>::FirstBlock;LoaderHeapBlockfields via directoffsetof(public struct members).Managed contracts
LoaderHeapKindenum (Normal = 0,ExplicitControl = 1) inILoader.cs;GetFirstLoaderHeapBlocktakes aLoaderHeapKindand dispatches toData.LoaderHeaporData.ExplicitControlLoaderHeapaccordingly — unknown kinds throwNotImplementedException.Data/ExplicitControlLoaderHeap.cs(IData<T>) readsFirstBlockfrom theExplicitControlLoaderHeapcDAC type.DataType.ExplicitControlLoaderHeapadded.Legacy DAC (
SOSDacImpl.cs)TraverseLoaderHeap(no-kind) andTraverseLoaderHeapWithKindimplemented independently via the sameILoadercontract methods — no cross-dependency.kindmaps toLoaderHeapKind; out-of-range values returnE_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.mdupdated withLoaderHeapKindenum, updatedGetFirstLoaderHeapBlocksignature,ExplicitControlLoaderHeapdata 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.