Skip to content

[cDAC][wasm] Resolve ReadyToRun virtual IP ranges - #133917

Open
lewing wants to merge 3 commits into
dotnet:mainfrom
lewing:lewing-cdac-wasm-virtual-ips
Open

lewing wants to merge 3 commits into
dotnet:mainfrom
lewing:lewing-cdac-wasm-virtual-ips

Conversation

@lewing

@lewing lewing commented Sep 14, 2026

Copy link
Copy Markdown
Member

Summary

Fix cDAC live resolution of WebAssembly ReadyToRun virtual IPs by matching the runtime's existing lookup model:

  • expose ExecutionManager::s_pVirtualIPRangeList and VirtualIPRangeSection through the data descriptor;
  • resolve encoded virtual IPs through that intrusive list using cycle detection and a 65,536-node per-lookup reader resource budget, with no map fallback when an encoded VIP is absent;
  • mask the WebAssembly funclet flag from RUNTIME_FUNCTION.BeginAddress for ordering and address arithmetic while preserving funclet identity;
  • keep the virtual code base (MinVirtualIP) separate from the loaded-image base used for unwind, debug, GC, exception, and thunk RVA reads;
  • handle the actual WASM descriptor shape, where hot/cold metadata and delay-load thunk metadata are absent.

Root cause

The model added in #130988 was already false when that PR merged. On TARGET_WASM, ReadyToRun modules are not added to RangeSectionMap; ReadyToRunInfo::RegisterVirtualIPRange registers them in ExecutionManager::s_pVirtualIPRangeList, and native FindCodeRange checks that list first.

The prior unit test synthesized a RangeSectionMap entry with an address that did not satisfy native IsVirtualIP, so it validated a mock-only model rather than the live runtime layout. This is a test-model gap, not a reviewer fault. The prior review explicitly noted that the WebAssembly specifics had not been run locally and should be added to cDAC CI: #130988 (review).

Blast radius and scope

This affects ReadyToRun code on all CoreCLR WebAssembly hosts, including browser and WASI. Interpreter code is unaffected.

The list lookup, descriptor feature gating, funclet masking, and image-base separation are inseparable: exposing the list alone would still throw while reading absent WASM fields, or could return the wrong method or read RVA data from the synthetic virtual address space.

This PR is independent of #133086 and intentionally excludes variable producer/decoder work. #133890 depends on this PR for correct shared code lookup and function identity.

Validation

  • ./build.sh clr+libs+host
  • PATH="/opt/homebrew/bin:$PATH" ./build.sh -os browser -c Debug -subset clr+libs
  • cDAC UnitTests: 3161 passed
  • cDAC DataGeneratorTests: 46 passed
  • cDAC UsageTests: 4 passed
  • generated contract documentation check: up to date
  • focused ExecutionManager / RuntimeFunction / WasmR2R tests: 221 passed

The durable tests cover:

  • captured/live-shaped VIP 0x80010109, exact MethodDesc, module, and runtime-function index;
  • the actual WASM descriptor shape: 8-byte RUNTIME_FUNCTION records with no EndAddress, and absent hot/cold and delay-load thunk fields;
  • start/end boundaries and adjacent ranges;
  • encoded VIP absent from the list with no RangeSectionMap fallback;
  • self-cycle, two-node cycle, inverted range, null module, and overlapping ambiguity;
  • unrelated partially registered nodes not blocking initialized ranges, while an uninitialized candidate fails closed;
  • valid 1,024/1,025-node lists, exact 65,536-node budget success, and budget+1 fail-closed behavior even when the head matches, with a read counter proving the extra node is never dereferenced;
  • root/funclet resolution with a flagged funclet entry that breaks raw ordering;
  • exact loaded-image debug, unwind, GC, and exception-clause reads while entrypoint lookup uses MinVirtualIP;
  • missing list capability and unchanged ordinary architecture behavior.

Mutation proofs were applied, confirmed in source, run red, restored, and rerun green:

  1. Removing the VIP-list branch fails the captured 0x80010109 test at the exact code-block assertion.
  2. Using raw BeginAddress fails the funclet identity test.
  3. Using startVIP as the loaded-image base fails the GC/unwind test with a read at 0x80010081 instead of the loaded image.
  4. Raising the reader budget from 65,536 to 65,537 makes the budget+1 test fail at its read-boundary assertion (highest node index 65,536 instead of 65,535); restoring the budget returns the suite to green.

The finite list cutoff is an intentional diagnostic-reader resource policy, not a native registration limit or a claim that an over-budget list is corrupt.

Note

This pull request description was generated with GitHub Copilot.

Expose WebAssembly ReadyToRun virtual IP ranges through the runtime data descriptor and resolve them before the RangeSectionMap. Mask funclet flags and keep virtual code identity separate from loaded-image RVA reads.

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

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

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

@lewing lewing added the arch-wasm WebAssembly architecture label Sep 14, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to 'arch-wasm': @lewing, @pavelsavara
See info in area-owners.md if you want to be subscribed.

lewing and others added 2 commits September 14, 2026 19:25
Handle feature-gated hot/cold metadata, isolate candidate module validation during registration, and remove the unsupported virtual-IP list length limit. Match WASM descriptor layouts and cover long lists, partial registration, and root/funclet image metadata.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Allow up to 65,536 nodes while retaining full-list ambiguity and cycle checks. Reject an over-budget chain before reading its next node, even after a match. Document the budget as reader policy and cover exact-budget success, budget+1 rejection, and the read boundary with a compact fixture.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@lewing
lewing marked this pull request as ready for review September 15, 2026 00:33
Copilot AI lite review requested due to automatic review settings September 15, 2026 00:33
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 5 pipeline(s).
11 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot review overview

🔵 Needs a closer look

The changes require final human review because they are too complex or risky for automated approval.

Review tier: Lite
Findings: None

What changed in this PR

Fixes cDAC WebAssembly ReadyToRun virtual-IP resolution to match the runtime’s intrusive-list model and descriptor layout.

Changes:

  • Adds virtual-IP range-list descriptors and bounded, cycle-safe lookup.
  • Separates virtual code bases from loaded-image bases and masks WASM funclet flags.
  • Adds extensive WASM-shaped mocks and regression tests.
File Description
src/​native/​managed/​cdac/​tests/​UnitTests/​WasmR2RInfoTests.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​tests/​UnitTests/​MockDescriptors/​MockDescriptors.ExecutionManager.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​tests/​UnitTests/​ExecutionManager/​ExecutionManagerTests.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​DataType.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Data/​VirtualIPRangeSection.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Data/​ReadyToRunInfo.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Contracts/​StackWalk/​Context/​Wasm/​WasmR2RInfo.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Contracts/​ExecutionManager/​Helpers/​UnwindDataSize.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Contracts/​ExecutionManager/​Helpers/​RuntimeFunctionLookup.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Contracts/​ExecutionManager/​ExecutionManagerCore.ReadyToRunJitManager.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Contracts/​ExecutionManager/​ExecutionManagerCore.cs Updated as part of this pull request.
src/​native/​managed/​cdac/​Microsoft.Diagnostics.DataContractReader.Contracts/​Constants.cs Updated as part of this pull request.
src/​coreclr/​vm/​datadescriptor/​datadescriptor.inc Updated as part of this pull request.
src/​coreclr/​vm/​codeman.h Updated as part of this pull request.
docs/​design/​datacontracts/​ExecutionManager.md Updated as part of this pull request.
docs/​design/​datacontracts/​data-descriptor-meanings.json Updated as part of this pull request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

arch-wasm WebAssembly architecture area-Diagnostics-cdac

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants