cDAC: Add metadata locator callback for heap dump support#126369
cDAC: Add metadata locator callback for heap dump support#126369max-charlamb wants to merge 3 commits intomainfrom
Conversation
Add a GetReadOnlyMetadataDelegate callback to ContractDescriptorTarget that allows hosts to provide PE metadata from disk when it cannot be read from target memory (e.g., heap dumps where PE read-only sections are absent). - Target.cs: Add TryLocateReadOnlyMetadata virtual method (default: false) - ContractDescriptorTarget.cs: Add delegate type, TryCreate overload, store in DataTargetDelegates alongside existing callbacks - EcmaMetadata_1.cs: Catch VirtualReadException on the ReadOnly path and fall back to Target.TryLocateReadOnlyMetadata, mirroring the legacy DAC's ICLRMetadataLocator pattern - ClrMdDumpHost.cs: Implement callback by trying the module's on-disk path first, then ClrMD's IFileLocator.FindPEImage for symbol server resolution - DumpTestBase.cs: Wire callback into ContractDescriptorTarget.TryCreate Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
With the metadata locator callback in place, most dump tests no longer need full dumps. Switch 11 of 14 test classes and 9 debuggee projects from full to heap dumps, reducing dump sizes by 4-6x. Three test classes remain on full dumps because they read R2R PE section data that is inherently absent from heap dumps (and the legacy DAC also cannot access from heap dumps): - ExceptionHandlingInfoDumpTests: R2R exception clause tables - EcmaMetadataDumpTests: tests PE-memory metadata address path directly - AsyncContinuationDumpTests: R2R section headers Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Tagging subscribers to this area: @steveisok, @tommcdon, @dotnet/dotnet-diag |
- EcmaMetadata.md: Document the VirtualReadException fallback to Target.TryLocateReadOnlyMetadata in GetMetadata, and note that GetReadOnlyMetadataAddress does not use this fallback. - DumpTests/README.md: Update debuggee dump type table to reflect the switch to heap dumps. Add Metadata Locator Callback section explaining the architecture and ClrMdDumpHost implementation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
20ee599 to
9da2258
Compare
|
Note This review was generated by Copilot (Claude Opus 4.6) with multi-model cross-validation (GPT-5.2, Claude Sonnet 4.5). 🤖 Copilot Code Review — PR #126369Holistic AssessmentMotivation: The PR addresses a real gap — cDAC cannot resolve ECMA-335 metadata from heap dumps because PE read-only sections are absent. This mirrors the legacy DAC's Approach: The dual mechanism (virtual method on Summary: Detailed Findings❌ LoaderDumpTests DumpType mismatch — tests will silently be skipped
This means The README.md table correctly still shows MultiModule as "Full", confirming this was unintentional. Fix: Restore
|
| _target.ReadBuffer(address.Address, data); | ||
| return MetadataReaderProvider.FromMetadataImage(ImmutableCollectionsMarshal.AsImmutableArray(data)).GetMetadataReader(); | ||
| } | ||
| catch (VirtualReadException) |
There was a problem hiding this comment.
ClrMD does this automatically, as does SOS and as far as Noah knows, VS does this too. Why do we need this?
There was a problem hiding this comment.
It automatically redirects reads to the known PE metadata? We are currently using ClrMD to load and read the dumps.
There was a problem hiding this comment.
There was a problem hiding this comment.
It automatically redirects reads to the known PE metadata?
Its not specific to metadata btw, it applies to any data in the module.
Note
This PR was generated with the assistance of GitHub Copilot.
Summary
Add a metadata locator callback to the cDAC
Target, enablingEcmaMetadata_1to resolve PE metadata from disk when it cannot be read from target memory. This unblocks heap dump support for most dump tests, reducing dump sizes by 4-6x.Problem
EcmaMetadata_1.GetReadOnlyMetadataAddressreads the entire loaded PE image (~3.6 MB forSystem.Private.CoreLib.dll) viaTargetStreamto parse PE headers and locate metadata. Heap dumps (MiniDumpWithPrivateReadWriteMemory) don't include PE read-only sections, causingVirtualReadException. This forced all tests that need metadata resolution (stackwalking, method name lookup, etc.) to use full dumps (135-149 MB each).The cDAC stackwalk itself works perfectly on heap dumps — the only blocker was metadata resolution.
Solution
Add a
GetReadOnlyMetadataDelegatecallback toContractDescriptorTarget, mirroring the legacy DAC'sICLRMetadataLocatorpattern (implemented by SOS viaISymbolService.GetMetadataLocatorin the diagnostics repo).Architecture
Changes
cDAC core (commit 1):
Target.cs— newTryLocateReadOnlyMetadatavirtual method (default returns false)ContractDescriptorTarget.cs— newGetReadOnlyMetadataDelegatetype stored inDataTargetDelegates, newTryCreateoverloadEcmaMetadata_1.cs— try/catchVirtualReadExceptionfallback to metadata locatorClrMdDumpHost.cs— implement callback: try module path on disk, thenIFileLocator.FindPEImageDumpTestBase.cs— wire callback into target creationTest changes (commit 2):
DumpType => "full"override from 11 test classes (inherit default"heap").csprojfiles fromDumpTypes=FulltoDumpTypes=HeapExceptionHandlingInfoDumpTests— reads R2R exception clause tables from PE sectionsEcmaMetadataDumpTests— explicitly tests the PE-memory metadata pathAsyncContinuationDumpTests— reads R2R section headers from PE imageDocumentation (commit 3):
docs/design/datacontracts/EcmaMetadata.md— document the fallback behaviortests/DumpTests/README.md— update debuggee table, add Metadata Locator sectionTest results
Dump size comparison