You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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_indirectfunction 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:
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.
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_indirectfunction signature mismatch insideMetaDataImport::GetName_IMPL. The corresponding Release configuration runs the identical scenario cleanly on bothbrowserandwasi.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.Unsafexunit test suite under R2R-on-wasm via corerun:Trap occurs during xunit test discovery/execution (reflecting over test method parameters →
RuntimeParameterInfo.get_Name).Observed trap (browser Debug, node)
Root symptom: at
GetName_IMPL,pScope(theIMDInternalImport*=MetadataImport.m_metadataImport2) is garbage (e.g.0x5a53), while the earlierGetMetadataImportFCall returned a valid pointer. The garbagepScope's vtable slot yields a wrong-signature target for thepScope->GetNameOfMethodDefvirtualcall_indirect→ the reported mismatch. Them_metadataImport2field 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_pointershadow-frame family, cf. #130924 / #130384).Configuration matrix (rigorously controlled, incl. a from-scratch clean Debug rebuild)
rm -rf artifacts/{obj,bin}/coreclr/browser.wasm.Debugthen rebuild) still reproduces — not stale artifacts.Hypothesis
The checked JIT (used by the Debug crossgen2) lays out the address-taken
MetadataImporttemp inRuntimeParameterInfo.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 R2Rget_Namefrom Debug vs Release crossgen and/or a live debug read of__stack_pointer+ the temp at the FCall boundary.Impact
Notes
PAL_ProbeMemory,shm_open/shm_unlinkare 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.