Skip to content

Add cDAC tests and implementation for GetGenerationTable and GetFinalizationFillPointers#124674

Merged
noahfalk merged 7 commits intodotnet:mainfrom
noahfalk:124583_cdac_gc_generation_table
Mar 4, 2026
Merged

Add cDAC tests and implementation for GetGenerationTable and GetFinalizationFillPointers#124674
noahfalk merged 7 commits intodotnet:mainfrom
noahfalk:124583_cdac_gc_generation_table

Conversation

@noahfalk
Copy link
Member

@noahfalk noahfalk commented Feb 20, 2026

Implement the four ISOSDacInterface8 methods in cDAC SOSDacImpl:

  • GetGenerationTable / GetGenerationTableSvr
  • GetFinalizationFillPointers / GetFinalizationFillPointersSvr

Add test infrastructure:

  • TestPlaceholderTarget.Builder: fluent builder that owns MockMemorySpace, accumulates types/globals, and wires contracts via TestContractRegistry.
  • GCHeapBuilder + extension methods (AddGCHeapWks/AddGCHeapSvr): configure GC mock data via Action and build directly into the target.
  • TestContractRegistry: Dictionary<Type, Lazy> replacement for Mock in the builder path.

Add tests:

  • 3 contract-level tests in GCTests.cs (x4 arch = 12)
  • 6 SOSDacImpl-level tests in SOSDacInterface8Tests.cs (x4 arch = 24)

Add documentation:

  • README.md files for cdac/, Legacy/, and tests/ directories
  • Copilot instruction to search for READMEs along the path hierarchy

Add a variety of fixes for pre-existing issues I discovered trying to run the SOS tests on Linux for both Release and Debug flavors. I'm guessing those testing configurations haven't been used much:

  • Fix cDAC library loading on Unix (PAL_GetPalHostModule)
  • Fix Thread data model docs (originally I had fixed the contract impl but a parallel change already took care of it so that part)
  • Fix HRESULT variable shadowing in 8 SOSDacInterface APIs in
    request.cpp where inner HRESULT declarations masked the return value
  • Fix cDAC legacy stack walk not advancing in Release builds
    (ClrDataStackWalk.Next must call legacy outside #if DEBUG)
  • Fix Debug assertion failures: catch VirtualReadException in
    GetAppDomainName and GetObjectData, fall back to legacy in
    EnumMethodInstanceByAddress

Fixes #124692
Fixes #124693
Fixes #124694
Fixes #124695

@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.

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 implements four ISOSDacInterface8 methods in the cDAC SOSDacImpl layer for querying GC generation tables and finalization fill pointers, along with comprehensive test infrastructure and documentation.

Changes:

  • Implements GetGenerationTable, GetGenerationTableSvr, GetFinalizationFillPointers, and GetFinalizationFillPointersSvr in SOSDacImpl.cs by delegating to the existing IGC contract
  • Introduces TestPlaceholderTarget.Builder pattern with fluent API and TestContractRegistry to replace Mock<ContractRegistry> for more maintainable test setup
  • Adds GCHeapBuilder with extension methods (AddGCHeapWks/AddGCHeapSvr) to configure GC mock data declaratively
  • Provides 36 test cases total (3 contract-level + 6 SOSDacImpl-level × 4 architectures each) with proper sign-extension handling
  • Documents the cDAC architecture, test patterns, and SOSDacImpl implementation conventions in new README files

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
src/native/managed/cdac/tests/TestPlaceholderTarget.cs Removes Moq dependency; adds fluent Builder class and TestContractRegistry for programmatic test target construction
src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.GC.cs New file: GCHeapBuilder config class and extension methods to set up workstation/server GC heap mock data
src/native/managed/cdac/tests/GCTests.cs New file: 3 contract-level tests verifying IGC.GetHeapData() correctly reads generation table and fill pointers
src/native/managed/cdac/tests/SOSDacInterface8Tests.cs New file: 6 SOSDacImpl-level tests validating buffer sizing protocol, HResult codes, and pointer sign-extension
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/SOSDacImpl.cs Implements 4 ISOSDacInterface8 methods with proper validation, error handling, and debug cross-validation
src/native/managed/cdac/tests/README.md New documentation: test architecture, builder patterns, sign-extension gotchas, and mock descriptor guidelines
src/native/managed/cdac/README.md New documentation: cDAC architecture overview, project structure, and integration testing workflow
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Legacy/README.md New documentation: SOSDacImpl implementation patterns, HResult conventions, and buffer sizing protocol
.github/copilot-instructions.md Adds instruction to search for README files in directory hierarchy before making changes

@noahfalk noahfalk force-pushed the 124583_cdac_gc_generation_table branch from f9fb24b to 398b718 Compare February 22, 2026 08:08
@noahfalk noahfalk marked this pull request as ready for review February 22, 2026 08:18
Copilot AI review requested due to automatic review settings February 22, 2026 08:18
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 15 out of 15 changed files in this pull request and generated 4 comments.

Copilot AI review requested due to automatic review settings February 26, 2026 09:15
@noahfalk noahfalk force-pushed the 124583_cdac_gc_generation_table branch from 33c4550 to 10ab4c2 Compare February 26, 2026 09:15
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 17 out of 17 changed files in this pull request and generated no new comments.

noahfalk and others added 4 commits March 1, 2026 03:55
…izationFillPointers

Implement the four ISOSDacInterface8 methods in cDAC SOSDacImpl:
- GetGenerationTable / GetGenerationTableSvr
- GetFinalizationFillPointers / GetFinalizationFillPointersSvr

Add test infrastructure:
- TestPlaceholderTarget.Builder: fluent builder that owns MockMemorySpace,
  accumulates types/globals, and wires contracts via TestContractRegistry.
- GCHeapBuilder + extension methods (AddGCHeapWks/AddGCHeapSvr): configure
  GC mock data via Action<GCHeapBuilder> and build directly into the target.
- TestContractRegistry: Dictionary<Type, Lazy<IContract>> replacement for
  Mock<ContractRegistry> in the builder path.

Add tests:
- 3 contract-level tests in GCTests.cs (x4 arch = 12)
- 6 SOSDacImpl-level tests in SOSDacInterface8Tests.cs (x4 arch = 24)

Add documentation:
- README.md files for cdac/, Legacy/, and tests/ directories
- Copilot instruction to search for READMEs along the path hierarchy

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fixes discovered while running SOS integration tests against the new
GetGenerationTable/GetFinalizationFillPointers implementation:

- Fix cDAC library loading on Unix (PAL_GetPalHostModule)
- Fix Thread data model crash on non-Windows (TryGetValue for
  UEWatsonBucketTrackerBuckets)
- Fix HRESULT variable shadowing in 8 SOSDacInterface APIs in
  request.cpp where inner HRESULT declarations masked the return value
- Fix cDAC legacy stack walk not advancing in Release builds
  (ClrDataStackWalk.Next must call legacy outside #if DEBUG)
- Fix Debug assertion failures: catch VirtualReadException in
  GetAppDomainName and GetObjectData, fall back to legacy in
  EnumMethodInstanceByAddress
- Address PR review feedback: add insufficient-buffer tests, pNeeded
  cross-validation assertions, and reduce test data duplication with
  shared helpers
- Update README documentation with VirtualReadException guidance and
  legacy delegation placement

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…atch, use heapData.GenerationTable.Count, and use local buffers for debug cross-validation

- Change void* to DacpGenerationData* in ISOSDacInterface8 methods
- Move null/validation checks inside try/catch blocks per PR dotnet#124814 pattern
- Replace ReadGlobal<uint>(TotalGenerationCount) with heapData.GenerationTable.Count
- Use local buffers for legacy DAC cross-validation to avoid overwriting cDAC data
- Use 'is null'/'is not null' instead of '== null'/'!= null'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 1, 2026 11:55
@noahfalk noahfalk force-pushed the 124583_cdac_gc_generation_table branch from 77081c0 to 6ceae96 Compare March 1, 2026 11:55
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 16 out of 16 changed files in this pull request and generated 6 comments.

…EBUG loop bounds

- GetNumberGenerations: use gc.GetMaxGeneration()+1 via the GC contract
  instead of gc.GetHeapData() which throws on Server GC targets.
- GetGenerationTable/GetFinalizationFillPointers DEBUG cross-validation:
  limit comparison loops to pNeededLocal (the actual written count) instead
  of the caller buffer size to avoid comparing uninitialized trailing entries.
- GetFinalizationFillPointersSvr: use Math.Min(cFillPointers, pNeededLocal)
  for the same reason.

Co-authored-by: Copilot <223556219+Copilot@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.

looks good modulo couple comments

…ally

The legacy enumeration is started and advanced unconditionally in
StartEnumMethodInstancesByAddress and EnumMethodInstanceByAddress,
but EndEnumMethodInstancesByAddress only cleaned up the legacy handle
under #if DEBUG. This would leak the legacy enumeration handle in
Release builds.

Remove the #if DEBUG guard so the cleanup runs in all builds.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 4, 2026 02:27
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 16 out of 16 changed files in this pull request and generated 2 comments.

GetGenerationTable and GetFinalizationFillPointers are WKS-only APIs;
GetGenerationTableSvr and GetFinalizationFillPointersSvr are Server-only.
When called against the wrong GC mode, the native DAC returns E_FAIL,
but the cDAC was returning COR_E_INVALIDOPERATION (from the GC
contract's InvalidOperationException), which would cause a debug assert
mismatch during cross-validation.

Add explicit GC mode checks to all four methods and add 16 unit tests
validating the error behavior in both directions.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@noahfalk noahfalk merged commit 4895491 into dotnet:main Mar 4, 2026
110 of 114 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

4 participants