Skip to content

Change cDAC contract versioning from integer to string identifiers#127020

Open
max-charlamb wants to merge 6 commits intomainfrom
cdac-string-contract-versions
Open

Change cDAC contract versioning from integer to string identifiers#127020
max-charlamb wants to merge 6 commits intomainfrom
cdac-string-contract-versions

Conversation

@max-charlamb
Copy link
Copy Markdown
Member

@max-charlamb max-charlamb commented Apr 16, 2026

Summary

Switch the cDAC contract version type from integer to string throughout the pipeline, enabling descriptive version identifiers (e.g. "c1", "c2") to distinguish CoreCLR contract implementations. This lays the groundwork for other platforms to use a different prefix (e.g. "n1") without integer range collisions.

Changes

Native side

  • datadescriptor.inc (VM): CDAC_GLOBAL_CONTRACT(Thread, c1) — version identifiers are now string tokens
  • datadescriptor.inc (GC): CDAC_GLOBAL_CONTRACT(GC, c1) — updated to match managed registration
  • datadescriptor.cpp: GlobalContractSpec.VersionIdx is a string pool index (was raw uint32_t Version). Version strings are stored in the NamesPool alongside contract names.

Build tool

  • ObjectFileScraper: Reads version as a string pool lookup instead of a raw uint32

Managed pipeline (int to string)

  • ContractDescriptorParser: Dictionary<string, int> to Dictionary<string, string> with ContractsDictionaryConverter for backward compatibility (accepts both integer and string JSON values from older runtimes)
  • ContractRegistry, CachingContractRegistry, IContractFactory: version parameter changed from int to string
  • ContractDescriptorTarget: contracts dict and TryGetContractVersion use string
  • CoreCLRContracts: all Register calls use "c1", "c2", "c3"
  • DataDescriptorModel: contract version fields changed to string

StressLogAnalyzer

  • The StressLogAnalyzer extracts the contract version as an integer from the stress log header and prepends "c" to match the registered contract versions (e.g. "c1", "c2")
  • StressLog contract registrations updated from "1"/"2" to "c1"/"c2"

Tests

  • All 20+ test files updated to use "c1"/"c2"/"c3" version strings
  • New ParseContractsStringVersions test validates string version parsing
  • Existing ParseContractsCaseSensitive test validates backward compat (integer JSON to string)

Documentation

  • contract-descriptor.md and datacontracts_design.md updated to reflect string-based versioning

@dotnet-policy-service
Copy link
Copy Markdown
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
Copy Markdown
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

Updates the cDAC contract versioning scheme from integer versions to string identifiers (e.g., "c1", "c2"), carrying the change through native descriptor emission, the build-time scraper/model, the managed reader pipeline, tests, and documentation to enable prefixed version namespaces (e.g., future NativeAOT "n1").

Changes:

  • Native descriptor now stores contract version identifiers in the string pool (alongside names) and exposes a string-pool index rather than a raw integer.
  • Managed pipeline switches contract version APIs/dictionaries from int to string, including contract registration and descriptor target lookup.
  • Tests/docs updated to use "c#" version identifiers and validate string parsing.

Reviewed changes

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

Show a summary per file
File Description
src/native/managed/cdac/tests/ThreadTests.cs Updates test target setup to use "c1" contract versions.
src/native/managed/cdac/tests/TestPlaceholderTarget.cs Changes placeholder registry/version plumbing from int to string.
src/native/managed/cdac/tests/SyncBlockTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/RuntimeInfoTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/ReJITTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/PrecodeStubsTests.cs Switches test versioning logic/data from ints to "c1"/"c2" strings.
src/native/managed/cdac/tests/ObjectTests.cs Updates multiple contracts to "c1".
src/native/managed/cdac/tests/NotificationsTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs Switches mock execution manager “version” from int to string and updates version switch cases.
src/native/managed/cdac/tests/MethodTableTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/MethodDescTests.cs Updates contract versions to "c1".
src/native/managed/cdac/tests/LoaderTests.cs Updates contract version to "c1" in multiple test targets.
src/native/managed/cdac/tests/GetRegisterNameTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/GCTests.cs Updates GC contract registration to "c1".
src/native/managed/cdac/tests/GCMemoryRegionTests.cs Updates GC contract version to "c1".
src/native/managed/cdac/tests/ExecutionManager/RangeSectionMapTests.cs Updates execution manager mock version to "c1".
src/native/managed/cdac/tests/ExecutionManager/ExecutionManagerTests.cs Updates execution manager tests to use string versions and generates "c#" values.
src/native/managed/cdac/tests/DebuggerTests.cs Updates debugger contract version to "c1".
src/native/managed/cdac/tests/DacStreamsTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs Updates expected parsed contract version types to string and adds string-version parsing test.
src/native/managed/cdac/tests/ContractDescriptor/ContractDescriptorBuilder.cs Emits "c1" versions in generated contracts JSON.
src/native/managed/cdac/tests/CodeVersionsTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/BuiltInCOMTests.cs Updates contract version to "c1".
src/native/managed/cdac/tests/AuxiliarySymbolsTests.cs Updates contract version to "c1".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs Switches internal contracts map and lookup to Dictionary<string,string> and TryGetContractVersion(..., out string).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorParser.cs Changes Contracts dictionary value type to string and adds a converter to accept both numeric and string JSON values.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs Switches version lookup/creator keying from int to string.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CoreCLRContracts.cs Updates all contract registrations to "c1"/"c2"/"c3".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs Changes factory version parameter from int to string.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs Changes Register version parameter from int to string.
src/coreclr/vm/datadescriptor/datadescriptor.inc Updates CDAC_GLOBAL_CONTRACT(..., c#) tokens to the new string-id scheme.
src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs Reads contract version via string pool index and writes it into the model as string.
src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs Switches contract versions in the model from int to string and updates builder types accordingly.
src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp Stores contract version tokens in the names pool and emits version string-pool indices in the blob.
docs/design/datacontracts/datacontracts_design.md Updates design text to describe string-based contract version identifiers.
docs/design/datacontracts/contract-descriptor.md Updates descriptor format description and example to use string versions (with stated backward-compat parsing behavior).

Comment thread src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs Outdated
Comment thread src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs Outdated
Comment thread docs/design/datacontracts/contract-descriptor.md Outdated
@github-actions

This comment has been minimized.

@max-charlamb max-charlamb force-pushed the cdac-string-contract-versions branch from a3cf17a to 471fc9b Compare April 16, 2026 18:15
Copilot AI review requested due to automatic review settings April 16, 2026 18:25
@max-charlamb max-charlamb force-pushed the cdac-string-contract-versions branch from 471fc9b to ed21be0 Compare April 16, 2026 18:25
@max-charlamb max-charlamb force-pushed the cdac-string-contract-versions branch from ed21be0 to cae106d Compare April 16, 2026 18:28
Copy link
Copy Markdown
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 updates the cDAC contract version representation from integer versions to string identifiers (e.g., "c1", "c2") across the native blob descriptor, build tooling, managed reader pipeline, tests, and documentation to enable descriptive, non-colliding version schemes across runtimes/platforms.

Changes:

  • Switch contract version storage/serialization from int/uint32 to string identifiers across native + managed components.
  • Update the cdac-build-tool model and scraper to resolve contract versions via the shared NamesPool (string pool).
  • Update managed registries/parsing plus broad test and doc updates to use "cN" versions.

Reviewed changes

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

Show a summary per file
File Description
src/native/managed/cdac/tests/ThreadTests.cs Update test target contract version to "c1".
src/native/managed/cdac/tests/TestPlaceholderTarget.cs Change test helper registry/version plumbing from int to string.
src/native/managed/cdac/tests/SyncBlockTests.cs Update contract version to "c1".
src/native/managed/cdac/tests/RuntimeInfoTests.cs Update contract version to "c1".
src/native/managed/cdac/tests/ReJITTests.cs Update contract version to "c1".
src/native/managed/cdac/tests/PrecodeStubsTests.cs Update contract-versioned test data and logic to use "c1"/"c2" strings.
src/native/managed/cdac/tests/ObjectTests.cs Update multiple contract registrations to "c1".
src/native/managed/cdac/tests/NotificationsTests.cs Update contract version to "c1".
src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs Switch mock execution manager versioning and builders to string identifiers.
src/native/managed/cdac/tests/MethodTableTests.cs Update contract version to "c1".
src/native/managed/cdac/tests/MethodDescTests.cs Update contract versions to "c1".
src/native/managed/cdac/tests/LoaderTests.cs Update contract versions to "c1".
src/native/managed/cdac/tests/GetRegisterNameTests.cs Update contract version to "c1".
src/native/managed/cdac/tests/GCTests.cs Update GC contract version to "c1".
src/native/managed/cdac/tests/GCMemoryRegionTests.cs Update GC contract version to "c1".
src/native/managed/cdac/tests/ExecutionManager/RangeSectionMapTests.cs Update execution manager builder construction to "c1".
src/native/managed/cdac/tests/ExecutionManager/ExecutionManagerTests.cs Switch parameter and test data generation to "cN" strings.
src/native/managed/cdac/tests/DebuggerTests.cs Update debugger contract version to "c1".
src/native/managed/cdac/tests/DacStreamsTests.cs Update DacStreams contract version to "c1".
src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs Update contract parsing tests for string versions and add a new string-version test.
src/native/managed/cdac/tests/ContractDescriptor/ContractDescriptorBuilder.cs Emit "c1" string contract values in generated JSON.
src/native/managed/cdac/tests/CodeVersionsTests.cs Update CodeVersions contract version to "c1".
src/native/managed/cdac/tests/BuiltInCOMTests.cs Update BuiltInCOM contract version to "c1".
src/native/managed/cdac/tests/AuxiliarySymbolsTests.cs Update AuxiliarySymbols contract version to "c1".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs Store/read contract versions as string in the target descriptor.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorParser.cs Change descriptor model Contracts type to Dictionary<string,string> for JSON parsing.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs Update registry version keying and delegate signatures to string.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CoreCLRContracts.cs Register CoreCLR contracts using "cN" version strings.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs Update factory API to accept string versions.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs Update abstract Register signature to accept string versions.
src/coreclr/vm/datadescriptor/datadescriptor.inc Switch native contract macro uses from ints to cN tokens.
src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs Read contract version as a string-pool index and add it to the model.
src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs Update contracts dictionary and builder model to string versions.
src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp Encode contract version identifiers into NamesPool and store their indices in GlobalContractValues.
docs/design/datacontracts/datacontracts_design.md Document contract versions as string identifiers rather than integers.
docs/design/datacontracts/contract-descriptor.md Update JSON examples and text to show string contract versions.

Comment thread src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs
Comment thread src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs Outdated
@max-charlamb max-charlamb marked this pull request as ready for review April 16, 2026 18:49
Copilot AI review requested due to automatic review settings April 16, 2026 18:49
Copy link
Copy Markdown
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 migrates cDAC contract versioning from integer values to string identifiers (e.g., "c1", "c2") across the native descriptor blob, the build tool JSON model, and the managed reader/registry APIs, with corresponding test and documentation updates.

Changes:

  • Native blob and scraper: store contract version identifiers in the names pool and scrape them as strings.
  • Managed pipeline: change contract-version APIs and descriptor models from int to string.
  • Tests/docs: update test targets and docs to use string-based contract versions.

Reviewed changes

Copilot reviewed 37 out of 37 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/native/managed/cdac/tests/ThreadTests.cs Update test target setup to use "c1" contract version.
src/native/managed/cdac/tests/TestPlaceholderTarget.cs Change placeholder registry and builder APIs to use string versions.
src/native/managed/cdac/tests/SyncBlockTests.cs Update test target contract version to "c1".
src/native/managed/cdac/tests/RuntimeInfoTests.cs Update test target contract version to "c1".
src/native/managed/cdac/tests/ReJITTests.cs Update test target contract version to "c1".
src/native/managed/cdac/tests/README.md Update sample usage of contract factory to pass "c1".
src/native/managed/cdac/tests/PrecodeStubsTests.cs Convert precode contract-version parameterization to strings ("c1", "c2").
src/native/managed/cdac/tests/ObjectTests.cs Update multiple contract registrations to "c1".
src/native/managed/cdac/tests/NotificationsTests.cs Update contract registration to "c1".
src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs Convert execution manager mock version selection logic to string identifiers.
src/native/managed/cdac/tests/MethodTableTests.cs Update contract registration to "c1".
src/native/managed/cdac/tests/MethodDescTests.cs Update contract registrations to "c1".
src/native/managed/cdac/tests/LoaderTests.cs Update contract registrations to "c1".
src/native/managed/cdac/tests/GetRegisterNameTests.cs Update runtime info contract registration to "c1".
src/native/managed/cdac/tests/GCTests.cs Update GC contract registration to "c1".
src/native/managed/cdac/tests/GCMemoryRegionTests.cs Update GC contract registration to "c1".
src/native/managed/cdac/tests/ExecutionManager/RangeSectionMapTests.cs Update mock execution manager version to "c1".
src/native/managed/cdac/tests/ExecutionManager/ExecutionManagerTests.cs Convert execution manager contract-version parameterization to string identifiers.
src/native/managed/cdac/tests/DebuggerTests.cs Update debugger contract registration to "c1".
src/native/managed/cdac/tests/DacStreamsTests.cs Update DAC streams contract registration to "c1".
src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs Update contract parsing tests to expect string versions and add a string-version parsing test.
src/native/managed/cdac/tests/ContractDescriptor/ContractDescriptorBuilder.cs Emit "c1" for contract versions when building JSON.
src/native/managed/cdac/tests/CodeVersionsTests.cs Update code versions contract registration to "c1".
src/native/managed/cdac/tests/BuiltInCOMTests.cs Update BuiltInCOM contract registration to "c1".
src/native/managed/cdac/tests/AuxiliarySymbolsTests.cs Update auxiliary symbols contract registration to "c1".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs Store and expose contract versions as strings.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorParser.cs Change contract descriptor contracts map value type to string.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs Change contract lookup/registration to use string versions.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CoreCLRContracts.cs Register CoreCLR contract implementations using "c1", "c2", "c3" identifiers.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs Update factory interface to accept string version.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs Update registry API to register by string version.
src/coreclr/vm/datadescriptor/datadescriptor.inc Switch contract version tokens from numeric literals to stringified identifiers (e.g., c1).
src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs Scrape contract versions from the names pool (string) via VersionIdx.
src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs Change build-tool model’s contract-version storage from int to string.
src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp Store contract version identifiers in the names pool and reference them by pool index.
docs/design/datacontracts/datacontracts_design.md Update design doc text to describe string-based version identifiers.
docs/design/datacontracts/contract-descriptor.md Update contract descriptor schema/examples to show JSON string versions.
Comments suppressed due to low confidence (1)

src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs:634

  • ReadGlobalContractSpecs skips padding using header.GlobalPointerSpecSize. This happens to work while GlobalContractSpec stays layout-compatible with GlobalPointerSpec, but it’s an implicit coupling that will silently break if either spec size changes. Consider plumbing an explicit GlobalContractSpecSize through the blob directory/header (or at least centralize the assumption with a named constant/comment) so the scraper stays correct if layouts diverge.
            globalSpecs[i].VersionIdx = state.ReadUInt32();
            bytesRead += sizeof(uint);
            // skip padding
            if (bytesRead < header.GlobalPointerSpecSize)
            {

Comment thread docs/design/datacontracts/datacontracts_design.md
Comment thread src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs
Copilot AI review requested due to automatic review settings April 16, 2026 20:48
@max-charlamb max-charlamb force-pushed the cdac-string-contract-versions branch from 298bfa2 to 7c32b00 Compare April 16, 2026 20:48
@max-charlamb max-charlamb force-pushed the cdac-string-contract-versions branch from 7c32b00 to f5bfe29 Compare April 16, 2026 20:52
Copy link
Copy Markdown
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

Updates cDAC contract versioning end-to-end (native blob emission, build tooling, managed reader, tests, and docs) to use string version identifiers (e.g., "c1", "c2") instead of integers, enabling descriptive and prefix-scoped versioning across platforms.

Changes:

  • Switch contract version representations from int/uint32 to string across the native descriptor, build tool model, and managed parsing/registry APIs.
  • Update managed contract resolution/registration to key contract implementations by string version identifiers (e.g., "c1", "c2", "c3").
  • Update tests and documentation to use and describe string-based contract versions.

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/tools/StressLogAnalyzer/src/Program.cs Adjusts StressLog contract version handling to string identifiers.
src/native/managed/cdac/tests/ThreadTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/TestPlaceholderTarget.cs Updates test contract registry plumbing to use string versions.
src/native/managed/cdac/tests/SyncBlockTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/RuntimeInfoTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/ReJITTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/README.md Updates example factory call to pass "c1".
src/native/managed/cdac/tests/PrecodeStubsTests.cs Updates parameterization and version gating logic to string versions.
src/native/managed/cdac/tests/ObjectTests.cs Updates multiple contract versions to "c1".
src/native/managed/cdac/tests/NotificationsTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs Updates mock execution manager builder to use string versions and improves unknown-version error.
src/native/managed/cdac/tests/MethodTableTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/MethodDescTests.cs Updates test target contract versions to "c1".
src/native/managed/cdac/tests/LoaderTests.cs Updates test target contract version to "c1" in multiple places.
src/native/managed/cdac/tests/GetRegisterNameTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/GCTests.cs Updates GC contract registration in helper builders to "c1".
src/native/managed/cdac/tests/GCMemoryRegionTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/ExecutionManager/RangeSectionMapTests.cs Updates execution manager builder version to "c1".
src/native/managed/cdac/tests/ExecutionManager/ExecutionManagerTests.cs Updates test matrix to supply "cN" strings and updates method signatures accordingly.
src/native/managed/cdac/tests/DebuggerTests.cs Updates debugger contract version to "c1" in multiple target builders.
src/native/managed/cdac/tests/DacStreamsTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs Updates contract parsing assertions for string versions and adds a string-version parsing test.
src/native/managed/cdac/tests/ContractDescriptor/ContractDescriptorBuilder.cs Updates mock descriptor contract JSON generation to emit "c1" strings.
src/native/managed/cdac/tests/CodeVersionsTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/BuiltInCOMTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/AuxiliarySymbolsTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs Updates in-memory contracts map and TryGetContractVersion to use string versions.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorParser.cs Updates ContractDescriptor.Contracts to Dictionary<string, string>.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs Updates registry creator map and lookup to use string versions.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CoreCLRContracts.cs Updates CoreCLR contract registrations to use "c1", "c2", "c3".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs Updates factory API to accept string versions.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs Updates registration API to accept string versions.
src/coreclr/vm/datadescriptor/datadescriptor.inc Updates native contract declarations to use string tokens (e.g., c1, c2).
src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs Updates scraping to treat contract version as string-pool index and store string version.
src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs Updates build-tool model to store contract versions as strings.
src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp Updates native blob emission to include contract version strings in the names pool and store indices.
docs/design/datacontracts/datacontracts_design.md Updates design doc language to describe string version identifiers.
docs/design/datacontracts/contract-descriptor.md Updates contract descriptor doc and examples to use JSON string versions.
Comments suppressed due to low confidence (1)

src/tools/StressLogAnalyzer/src/Program.cs:523

  • BaseContractDescriptor is parsed from an embedded JSON blob later in this file, but that JSON still uses a numeric contract version (e.g., "StressLog": 2). With the new string-based Contracts dictionary, this will fail to deserialize unless the parser supports numeric-to-string contract version conversion. Update the JSON to use string versions (e.g., "c2") or rely on the same backward-compat converter used by ContractDescriptorParser.

Comment thread src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs
@max-charlamb max-charlamb force-pushed the cdac-string-contract-versions branch from f5bfe29 to af9ef52 Compare April 16, 2026 20:56
@github-actions

This comment has been minimized.

Comment thread src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp Outdated
Comment thread src/coreclr/vm/datadescriptor/datadescriptor.inc Outdated
max-charlamb and others added 3 commits April 17, 2026 12:32
Switch the contract version type from int to string throughout the cDAC
pipeline and rename versions to use "c<number>" format (e.g. "c1", "c2",
"c3") to distinguish CoreCLR contract implementations.

Native changes:
- datadescriptor.inc: CDAC_GLOBAL_CONTRACT now takes string identifiers
  (e.g. c1, c2) instead of integers
- datadescriptor.cpp: GlobalContractSpec.Version (uint32) replaced with
  VersionIdx (string pool index). Version strings stored in NamesPool.

Managed changes:
- ContractDescriptorParser: Dictionary<string, int> -> Dictionary<string, string>
  with ContractsDictionaryConverter for backward compat (accepts both int and
  string JSON values)
- ContractRegistry, CachingContractRegistry, IContractFactory: int -> string
- ContractDescriptorTarget: contracts dict and TryGetContractVersion use string
- CoreCLRContracts: all Register calls use "c1", "c2", "c3"

Build tool:
- ObjectFileScraper reads version as string pool index instead of raw uint32
- DataDescriptorModel uses string contract versions

Tests and documentation updated.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Update tests/README.md example to use string version ("c1") instead of integer
- Change ObjectFileScraper log message from "value" to "version"

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
StressLog uses numeric string versions ('1', '2') rather than the 'c'
prefix convention since the version is extracted from the stress log
file header as a raw integer.

Update the contract registration, data descriptor, and StressLogAnalyzer
to use numeric strings consistently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 17, 2026 16:36
@max-charlamb max-charlamb force-pushed the cdac-string-contract-versions branch from af9ef52 to 0b8e41c Compare April 17, 2026 16:36
Copy link
Copy Markdown
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 updates the cDAC “contract version” concept across the native blob, the cdac-build-tool, and the managed reader/tests to use string version identifiers (e.g., "c1", "c2") instead of integers, enabling non-colliding identifiers across different runtime implementations.

Changes:

  • Switched contract version storage/transport from uint32/int to string identifiers across the native descriptor blob, build tool model/scraper, and managed reader APIs.
  • Updated managed registries/factories/targets and CoreCLR contract registrations to use string versions; updated many cdac tests accordingly.
  • Updated design/docs to describe string-valued "contracts" entries.

Reviewed changes

Copilot reviewed 38 out of 38 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/tools/StressLogAnalyzer/src/Program.cs Updates StressLog contract version handling to string-based identifiers.
src/native/managed/cdac/tests/ThreadTests.cs Updates test target contract version to "c1".
src/native/managed/cdac/tests/TestPlaceholderTarget.cs Updates test registry and builder APIs from int to string versions.
src/native/managed/cdac/tests/SyncBlockTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/RuntimeInfoTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/ReJITTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/README.md Updates example contract creation to use string versions.
src/native/managed/cdac/tests/PrecodeStubsTests.cs Updates versioned test matrix and logic to use "c1"/"c2" strings.
src/native/managed/cdac/tests/ObjectTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/NotificationsTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs Converts mock execution manager “Version” to string identifiers and updates switch logic.
src/native/managed/cdac/tests/MethodTableTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/MethodDescTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/LoaderTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/GetRegisterNameTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/GCTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/GCMemoryRegionTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/ExecutionManager/RangeSectionMapTests.cs Updates execution manager version inputs to "c1".
src/native/managed/cdac/tests/ExecutionManager/ExecutionManagerTests.cs Updates version parameter types and version data generation to "cN" strings.
src/native/managed/cdac/tests/DebuggerTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/DacStreamsTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs Updates contract parsing expectations to string versions and adds a string-version parsing test.
src/native/managed/cdac/tests/ContractDescriptor/ContractDescriptorBuilder.cs Updates generated descriptor JSON to emit "c1" string versions.
src/native/managed/cdac/tests/CodeVersionsTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/BuiltInCOMTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/tests/AuxiliarySymbolsTests.cs Updates contract version usage to "c1".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs Updates contract map/version lookup plumbing to use strings.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorParser.cs Changes Contracts to Dictionary<string,string> and updates source-gen metadata accordingly.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs Switches version resolution/creator lookup keys from int to string.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CoreCLRContracts.cs Registers CoreCLR contract implementations under string version identifiers.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs Changes factory API to accept string version.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs Changes registry registration API to accept string version.
src/coreclr/vm/datadescriptor/datadescriptor.inc Changes CDAC_GLOBAL_CONTRACT version tokens to cN identifiers for most contracts.
src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs Interprets contract version as a string-pool index instead of a numeric value.
src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs Switches model’s contracts mapping from int to string.
src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp Stores contract version strings in the blob names pool and emits version indices in contract specs.
docs/design/datacontracts/datacontracts_design.md Updates design text to describe string version identifiers.
docs/design/datacontracts/contract-descriptor.md Updates spec/examples to show contract versions as JSON strings.
Comments suppressed due to low confidence (1)

src/tools/StressLogAnalyzer/src/Program.cs:524

  • Contracts now carries string version identifiers. Make sure any existing embedded descriptors in this file (e.g., the BaseContractDescriptor JSON) also use string-valued contract versions; otherwise ParseCompact will start throwing after the Contracts type change.

Comment thread src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs
Comment thread src/coreclr/vm/datadescriptor/datadescriptor.inc
Comment thread src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs Outdated
Comment thread src/tools/StressLogAnalyzer/src/Program.cs Outdated
Max Charlamb and others added 2 commits April 17, 2026 12:50
Address review feedback: rename GlobalContractSpec.VersionIdx to Version
in native datadescriptor.cpp for consistency (Name + Version, no Idx suffix).
Managed ObjectFileScraper keeps NameIdx/VersionIdx convention matching
other managed structs. Also fix == null to is null in DataDescriptorModel.cs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align StressLog contract versions with the naming convention used by all
other contracts. The StressLogAnalyzer now prepends 'c' to the integer
version extracted from the stress log header.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

This comment has been minimized.

The GC datadescriptor was still using a bare integer version (1) while
CoreCLRContracts.cs registers IGC with version "c1". This mismatch would
cause the GC contract to fail to resolve at runtime.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 17, 2026 20:35
Copy link
Copy Markdown
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 updates cDAC contract versioning from integer versions to string identifiers (for example "c1", "c2"), aligning the native data descriptor blob, build tooling, managed contract resolution, StressLogAnalyzer, tests, and design docs around the new representation.

Changes:

  • Switch contract version payloads from int/uint32 to string end-to-end (native descriptor emission → object scraper → managed descriptor parsing/target/registries).
  • Update CoreCLR contract registrations and all impacted tests to use "cN" version tokens.
  • Update documentation to describe contracts as string-versioned.

Reviewed changes

Copilot reviewed 39 out of 39 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/tools/StressLogAnalyzer/src/Program.cs Derives StressLog contract version as "c{n}" and updates descriptor plumbing to use string versions.
src/native/managed/cdac/tests/ThreadTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/TestPlaceholderTarget.cs Changes test registry/version plumbing to use string versions.
src/native/managed/cdac/tests/SyncBlockTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/RuntimeInfoTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/ReJITTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/README.md Updates sample code to create contracts using "c1".
src/native/managed/cdac/tests/PrecodeStubsTests.cs Switches precode contract versioning in tests from numeric to "cN" strings.
src/native/managed/cdac/tests/ObjectTests.cs Updates test contract versions to "c1".
src/native/managed/cdac/tests/NotificationsTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/MockDescriptors/MockDescriptors.ExecutionManager.cs Updates mock execution manager version selection to "c1"/"c2" strings.
src/native/managed/cdac/tests/MethodTableTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/MethodDescTests.cs Updates test contract versions to "c1".
src/native/managed/cdac/tests/LoaderTests.cs Updates test contract versions to "c1".
src/native/managed/cdac/tests/GetRegisterNameTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/GCTests.cs Updates GC contract registration in tests to "c1".
src/native/managed/cdac/tests/GCMemoryRegionTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/ExecutionManager/RangeSectionMapTests.cs Updates test versions to "c1".
src/native/managed/cdac/tests/ExecutionManager/ExecutionManagerTests.cs Updates versioned test matrix to produce "cN" strings.
src/native/managed/cdac/tests/DebuggerTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/DacStreamsTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/ContractDescriptor/ParserTests.cs Updates parsing expectations to string contract versions and adds a string-version parsing test.
src/native/managed/cdac/tests/ContractDescriptor/ContractDescriptorBuilder.cs Updates generated descriptor JSON to emit "c1" string contract versions.
src/native/managed/cdac/tests/CodeVersionsTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/BuiltInCOMTests.cs Updates test contract version to "c1".
src/native/managed/cdac/tests/AuxiliarySymbolsTests.cs Updates test contract version to "c1".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorTarget.cs Stores and returns contract versions as strings.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/ContractDescriptorParser.cs Changes descriptor model to Dictionary<string, string> for contracts (string versions).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader/CachingContractRegistry.cs Resolves implementations keyed by (Type, stringVersion).
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Contracts/CoreCLRContracts.cs Registers CoreCLR contract implementations under "c1", "c2", "c3".
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/IContractFactory.cs Updates factory signature to accept string version.
src/native/managed/cdac/Microsoft.Diagnostics.DataContractReader.Abstractions/ContractRegistry.cs Updates registry API to register by string version.
src/coreclr/vm/datadescriptor/datadescriptor.inc Emits contract versions as string tokens (c1, c2, …) in the CoreCLR descriptor list.
src/coreclr/tools/cdac-build-tool/ObjectFileScraper.cs Reads contract version via string pool index and emits string versions into the model.
src/coreclr/tools/cdac-build-tool/DataDescriptorModel.cs Updates descriptor model contract version types to string.
src/coreclr/gc/datadescriptor/datadescriptor.inc Updates GC-side contract version token to c1.
src/coreclr/debug/datadescriptor-shared/datadescriptor.cpp Extends string pool to include contract version token strings in emitted blobs.
docs/design/datacontracts/datacontracts_design.md Updates design docs to describe string-based contract versioning.
docs/design/datacontracts/contract-descriptor.md Updates contract descriptor docs/examples to use JSON string versions.
Comments suppressed due to low confidence (1)

src/tools/StressLogAnalyzer/src/Program.cs:524

  • The base descriptor JSON still contains numeric contract versions (e.g. "contracts": { "StressLog": 2 }), but ContractDescriptor.Contracts now expects string values. Without a contracts converter, ParseCompact will fail when initializing BaseContractDescriptor, preventing the tool from running. Update the embedded JSON to use the new string version tokens (or remove the contracts section from the base descriptor if it's always overridden).

Comment on lines 60 to 65
public class ContractDescriptor
{
public int? Version { get; set; }
public string? Baseline { get; set; }
public Dictionary<string, int>? Contracts { get; set; }
public Dictionary<string, string>? Contracts { get; set; }

Comment on lines 100 to +116
@@ -111,8 +111,29 @@ public void ParseContractsCaseSensitive()
Assert.Equal(0, descriptor.Version);
Assert.Equal("empty", descriptor.Baseline);
Assert.Equal(2, descriptor.Contracts.Count);
Assert.Equal(1, descriptor.Contracts["foo"]);
Assert.Equal(2, descriptor.Contracts["Foo"]);
Assert.Equal("c1", descriptor.Contracts["foo"]);
Assert.Equal("c2", descriptor.Contracts["Foo"]);
}
@github-actions
Copy link
Copy Markdown
Contributor

🤖 Copilot Code Review — PR #127020

Note

This review was generated by Copilot. Models used: Claude Opus 4.6 (primary), Claude Sonnet 4.5, GPT-5.3-Codex (secondary).

Holistic Assessment

Motivation: The PR changes cDAC contract versioning from integer identifiers to string identifiers (e.g., 1"c1"). Contract versions were described as "not ordinal" (higher doesn't mean newer), so string identifiers better communicate those semantics. The change is well-motivated.

Approach: The approach is thorough — it touches all layers consistently: native C++ macros/structs, the build tool, managed abstractions, the JSON parser, contract implementations, StressLogAnalyzer, and all tests. The "c" prefix convention is reasonable.

Summary: ❌ Needs Changes. One missed conversion in StressLogAnalyzer will cause a runtime failure. The embedded JSON in BaseContractDescriptor still uses "StressLog": 2 (integer) but the parser now expects Dictionary<string, string>. Two advisory warnings on version comparison semantics and public API break.


Detailed Findings

❌ StressLogAnalyzer BaseContractDescriptor — Missed conversion will cause JsonException

File: src/tools/StressLogAnalyzer/src/Program.cs, line 587

The embedded JSON literal for BaseContractDescriptor still contains an integer contract version:

"contracts": {
    "StressLog": 2,
}

Since ContractDescriptor.Contracts is now Dictionary<string, string> and the JSON source-generated serializer expects a string token for dictionary values, ParseCompact will throw a JsonException when encountering the number token 2. This occurs during static field initialization (line 529), causing a TypeInitializationException the first time BaseContractDescriptor is accessed.

Fix: Change line 587 to:

"StressLog": "c2",

Note: Even though GetDescriptor() (line 523) overrides Contracts with a properly-formatted string, the BaseContractDescriptor static field must parse successfully first. The Types and Globals from BaseContractDescriptor are used by GetDescriptor, so this parse failure blocks the entire tool.

Flagged by GPT-5.3-Codex.

✅ Native string pool macro changes — Correctly implemented

The new macros in datadescriptor.cpp correctly compute string pool sizes and offsets for the version strings. The #value stringification produces the right result — e.g., CDAC_GLOBAL_CONTRACT(Thread, c1) stringifies c1 to "c1". The string pool population (#name "\0" #value "\0") and the spec assignment (GET_GLOBALCONTRACT_VALUE(name)) are both consistent.

✅ Managed scraper correctly reads string versions

ObjectFileScraper.ReadGlobalContractSpecs reads the two uint32_t fields in order (NameIdx, then VersionIdx), matching the native struct layout. The rename from Value to VersionIdx correctly reflects the new semantics.

✅ JSON parser type change and [JsonSerializable] cleanup — Correct

ContractDescriptor.Contracts correctly changed from Dictionary<string, int> to Dictionary<string, string>. The [JsonSerializable] attributes were cleaned up correctly. A new test ParseContractsStringVersions validates arbitrary string versions.

[NotNullWhen(true)] annotation — Correct

The backing _contracts dictionary is Dictionary<string, string> (non-nullable values), so when TryGetValue returns true, version is guaranteed non-null. The annotation is accurate.

✅ Contract registrations — All consistently updated

All 30+ registry.Register<T>() calls in CoreCLRContracts.cs and all CDAC_GLOBAL_CONTRACT declarations in both datadescriptor.inc files use c-prefixed strings consistently.

✅ StressLogAnalyzer version construction — Correct (at the call site)

$"c{(int)(header->version & 0xFFFF)}" correctly converts binary header versions to string format. The issue is only in the BaseContractDescriptor embedded JSON.

⚠️ Version comparison semantics — Fragile pattern (advisory, not blocking)

In PrecodeStubsTests.cs and PrecodeBuilder, the old numeric comparison contractVersion >= 2 was replaced with contractVersion is not "c1". The old pattern established an ordering (version 2 and all higher). The new pattern means "anything except c1," which is correct today (only c1, c2, c3 exist) but could silently include future versions that may not support ThisPtrRetBufPrecodeData. This is test-only code, so it's not a production correctness issue. A brief inline comment documenting the assumption would help future maintainers.

Flagged by all three models.

⚠️ Public API break on IContractFactory<T> and ContractRegistry.Register (advisory, not blocking)

These are source-breaking changes. Mitigating factors: Both packages are marked <IsShipping>false</IsShipping> ("Do not produce a public package. This ships as part of the runtime."). Downstream diagnostic tools that reference these packages will need coordinated updates.

Flagged by all three models.

💡 Documentation — Consider documenting the version string convention

The "c" prefix is a convention worth documenting. The test ParseContractsStringVersions shows non-c prefixes are also valid (e.g., "N2"). A brief note in datacontracts_design.md about what version strings should look like and when to use which prefix would help.

✅ Test coverage — Comprehensive

All 20+ test files were updated consistently with string versions. New parser test added. The ExecutionManagerTests.StdArchAllVersions() correctly generates $"c{version}" strings.

Generated by Code Review for issue #127020 ·

@max-charlamb max-charlamb enabled auto-merge (squash) April 18, 2026 02:47
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