Skip to content

[wasm] Fix R2R stackwalk for inline P/Invoke frames and composite-image RVA base#131243

Merged
lewing merged 3 commits into
dotnet:mainfrom
lewing:wasi-r2r-stackwalk-rva
Jul 23, 2026
Merged

[wasm] Fix R2R stackwalk for inline P/Invoke frames and composite-image RVA base#131243
lewing merged 3 commits into
dotnet:mainfrom
lewing:wasi-r2r-stackwalk-rva

Conversation

@lewing

@lewing lewing commented Jul 22, 2026

Copy link
Copy Markdown
Member

Summary

Two wasm-only R2R stackwalk correctness fixes, needed once R2R-compiled managed code participates in a stackwalk (exception unwind, GetCallersAssembly, Assembly.Load, GetExecutingAssembly, …).

1. Inline P/Invoke sentinel resolution (stackwalk.cpp, frames.h, helpers.cpp)

An R2R inline P/Invoke InlinedCallFrame carries the sentinel return address INLINED_PINVOKE_FROM_R2R (== 1) instead of a real native address; the real caller virtual IP is derived from m_pCallSiteSP (this infrastructure — the sentinel assignment and InlinedCallFrame::UpdateRegDisplay_Impl — already exists on main). But StackFrameIterator::NextRaw fed that sentinel straight to ProcessIp, which cannot recognize it as managed code, so the same active frame repeated forever — an infinite loop in any stackwalk that crosses an R2R inline-P/Invoke frame.

Resolve the sentinel to the caller virtual IP via GetWasmVirtualIPFromStackPointer before ProcessIp, failing the walk (SWA_FAILED) if the lookup returns null. The sentinel constant moves from a helpers.cpp #define to a typed static constexpr in frames.h so the stack walker can reference it (existing helpers.cpp uses are unchanged semantically).

2. Composite R2R image RVA base (codeman.inl)

JitTokenToModuleRVABase resolved wasm virtual-IP ranges against the IL module base (GetModuleBaseAddress()), which is wrong for a composite R2R (WbIL) image — unwind-frame RVAs decoded against the wrong base. Use the R2R image base (ReadyToRunInfo()->GetImage()->GetBase()), correct for both composite and standalone R2R.

Validation

  • WASI CoreCLR build (clr -os wasi -c Release): 0W/0E; stackwalk.cpp/helpers.cpp objects recompile clean.
  • Validated end-to-end against minimal Assembly.Load / GetExecutingAssembly R2R repros that previously looped forever in StackFrameIterator.

Note

This PR was authored with the assistance of GitHub Copilot.

…ge RVA base

Two wasm-only stackwalk correctness fixes, needed once R2R-compiled managed code
participates in a stackwalk (exception unwind, GetCallersAssembly, Assembly.Load):

1. Inline-P/Invoke sentinel resolution (stackwalk.cpp, frames.h, helpers.cpp):
   An R2R inline P/Invoke frame carries the sentinel return address
   INLINED_PINVOKE_FROM_R2R (== 1) instead of a real native address; the real
   caller virtual IP is derived from m_pCallSiteSP. StackFrameIterator::NextRaw fed
   that sentinel straight to ProcessIp, which cannot recognize it as managed code,
   so the same active frame repeated forever. Resolve the sentinel to the caller
   virtual IP via GetWasmVirtualIPFromStackPointer before ProcessIp, failing the
   walk (SWA_FAILED) if the lookup returns null. The sentinel constant is moved from
   a helpers.cpp #define into frames.h so the stack walker can reference it.

2. Composite R2R image RVA base (codeman.inl): JitTokenToModuleRVABase resolved
   wasm virtual-IP ranges against the IL module base (GetModuleBaseAddress()), which
   is wrong for a composite R2R (WbIL) image. Use the R2R image base
   (ReadyToRunInfo()->GetImage()->GetBase()) so unwind-frame RVAs decode against the
   correct composite base.

Verified: WASI CoreCLR build (clr -os wasi -c Release) 0W/0E; validated end-to-end
against minimal Assembly.Load / GetExecutingAssembly R2R repros that previously
looped forever in StackFrameIterator.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 2902374a-f352-4c46-bcec-8a35c97733ae
Copilot AI review requested due to automatic review settings July 22, 2026 23:45
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 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: @agocke
See info in area-owners.md if you want to be subscribed.

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.

Pull request overview

This PR makes two WebAssembly-only correctness fixes for ReadyToRun (R2R) stack walking: (1) properly handling the sentinel “return address” used by inline P/Invoke frames in R2R, and (2) using the correct image base when mapping unwind RVAs for composite R2R images.

Changes:

  • Resolve the wasm R2R inline-P/Invoke sentinel return address to a real virtual IP before calling ProcessIp during stack walking.
  • Move the sentinel constant to a typed static constexpr in frames.h so it’s accessible to stack-walk code.
  • Fix wasm JitTokenToModuleRVABase to use the R2R image base (not the IL module base) for RANGE_SECTION_VIRTUALIP sections.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/coreclr/vm/wasm/helpers.cpp Removes the local macro sentinel definition; continues using the sentinel for active inline P/Invoke frames.
src/coreclr/vm/stackwalk.cpp Adds wasm-specific handling to translate the inline P/Invoke sentinel to a virtual IP prior to ProcessIp.
src/coreclr/vm/frames.h Introduces a typed sentinel constant and declares GetWasmVirtualIPFromStackPointer for wasm.
src/coreclr/vm/codeman.inl Updates wasm virtual-IP RVA base resolution to use the R2R image base address.

Comment thread src/coreclr/vm/stackwalk.cpp Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings July 23, 2026 00:02
@lewing
lewing requested a review from davidwrighton July 23, 2026 00:03

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.

Pull request overview

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

Comment thread src/coreclr/vm/stackwalk.cpp
@lewing
lewing requested a review from AndyAyersMS July 23, 2026 01:07
@lewing
lewing marked this pull request as ready for review July 23, 2026 01:13
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 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 review requested due to automatic review settings July 23, 2026 15:11

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.

Pull request overview

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

@lewing
lewing enabled auto-merge (squash) July 23, 2026 17:31
@lewing

lewing commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

/ba-g native-aot infra failures are not related

@lewing
lewing merged commit 309ac56 into dotnet:main Jul 23, 2026
118 of 127 checks passed
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