Skip to content

[wasm][R2R] Checked/Debug-config R2R reflection FCall traps at MetaDataImport::GetName (call_indirect signature mismatch) #131298

Description

@lewing

Summary

When running managed reflection under ReadyToRun on WebAssembly in a Debug/checked configuration, a reflection call chain that reads a parameter/member name traps with a wasm call_indirect function signature mismatch inside MetaDataImport::GetName_IMPL. The corresponding Release configuration runs the identical scenario cleanly on both browser and wasi.

This is a checked/Debug-config-specific codegen/layout issue, not an OS-specific one. My earlier investigation mislabeled it "browser-specific" because the browser rig was always built Debug while the WASI rig was Release.

Repro

Run the System.Runtime.CompilerServices.Unsafe xunit test suite under R2R-on-wasm via corerun:

DOTNET_ReadyToRun=1 <corerun> WasmTestRunner.dll System.Runtime.CompilerServices.Unsafe.Tests.dll

Trap occurs during xunit test discovery/execution (reflecting over test method parameters → RuntimeParameterInfo.get_Name).

Observed trap (browser Debug, node)

RuntimeError: function signature mismatch
  at MetaDataImport::GetName_IMPL(unsigned long, IMDInternalImport*, unsigned int, char const**, unsigned long)   [corerun func 17289]
  at MetaDataImport::GetName(...)                                                                                  [corerun func 17288]
  at wasm-function[15975]   (R2R MetadataImport.GetName(int))
  at wasm-function[16520]   (R2R RuntimeParameterInfo.get_Name)
  at CallFunc_This_RetI32_PE(...)      (interp→R2R thunk)
  at InvokeCalliStub / InvokeManagedMethod / ExecuteInterpretedMethodWithArgs_PortableEntryPoint

Root symptom: at GetName_IMPL, pScope (the IMDInternalImport* = MetadataImport.m_metadataImport2) is garbage (e.g. 0x5a53), while the earlier GetMetadataImport FCall returned a valid pointer. The garbage pScope's vtable slot yields a wrong-signature target for the pScope->GetNameOfMethodDef virtual call_indirect → the reported mismatch. The m_metadataImport2 field lives in an address-taken R2R frame temp that appears to be clobbered by a native FCall's shadow frame before it is read (the __stack_pointer shadow-frame family, cf. #130924 / #130384).

Configuration matrix (rigorously controlled, incl. a from-scratch clean Debug rebuild)

crossgen2 + corerun config OS Result
Debug/checked (standalone) browser TRAPS
Debug/checked (composite) browser TRAPS
Release (composite) browser PASSES 128/128
Release (composite) wasi PASSES 128/128
  • A full clean Debug rebuild (rm -rf artifacts/{obj,bin}/coreclr/browser.wasm.Debug then rebuild) still reproduces — not stale artifacts.
  • Cross-config runs (Debug-R2R + Release-corerun, and vice-versa) fail with different errors (assert / OOB) because the R2R codegen and runtime shadow-stack conventions are config-coupled.

Hypothesis

The checked JIT (used by the Debug crossgen2) lays out the address-taken MetadataImport temp in RuntimeParameterInfo.get_Name / MetadataImport.GetName(int) such that an intervening native FCall's shadow frame (allocated off __stack_pointer) overlaps and clobbers it; the release JIT's layout avoids the overlap. Needs confirmation by disassembling the R2R get_Name from Debug vs Release crossgen and/or a live debug read of __stack_pointer + the temp at the FCall boundary.

Impact

  • Release / shipping R2R-on-wasm is unaffected (green on browser and wasi).
  • Affects checked/Debug runtime bring-up and diagnostics for R2R-on-wasm.

Notes

  • WASI Debug does not currently link (PAL_ProbeMemory, shm_open/shm_unlink are Debug-only undefined symbols); getting a WASI Debug corerun would allow a high-fidelity DWARF debug of this trap.

Note

This issue was authored with the assistance of GitHub Copilot.

Metadata

Metadata

Assignees

Labels

arch-wasmWebAssembly architecturearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions