From 7b21c3c55923feccd8f2bed86fff89b883abb021 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Tue, 15 Sep 2026 22:41:52 -0500 Subject: [PATCH 1/3] Fix Wasm R2R EventPipe address resolution Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- src/coreclr/vm/eventtrace.cpp | 24 ++++++++++++++++--- .../Blazor/EventPipeDiagnosticsTests.cs | 13 ++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/src/coreclr/vm/eventtrace.cpp b/src/coreclr/vm/eventtrace.cpp index 85a13a08ffa506..885ecb33feeb2c 100644 --- a/src/coreclr/vm/eventtrace.cpp +++ b/src/coreclr/vm/eventtrace.cpp @@ -4473,13 +4473,31 @@ TADDR MethodAndStartAddressToEECodeInfoPointer(MethodDesc *pMethodDesc, PCODE pN } CONTRACTL_END; // MethodDesc ==> Code Address ==>JitManager - TADDR start = pNativeCodeStartAddress ? pNativeCodeStartAddress : pMethodDesc->GetNativeCode(); - if(start == 0) { + TADDR entryPoint = pNativeCodeStartAddress ? pNativeCodeStartAddress : pMethodDesc->GetNativeCode(); + if(entryPoint == 0) { // this method hasn't been jitted return 0; } - return GetInterpreterCodeFromEntryPointIfPresent(start); + TADDR start = GetInterpreterCodeFromEntryPointIfPresent(entryPoint); + +#if defined(TARGET_WASM) && defined(FEATURE_PORTABLE_ENTRYPOINTS) + if (start == entryPoint && entryPoint == pMethodDesc->GetPortableEntryPointIfExists() && + PortableEntryPoint::HasNativeEntryPoint((PCODE)entryPoint)) + { + // Native R2R portable entry points store a function-table index rather than an address + // registered with ExecutionManager. EventPipe needs the corresponding synthetic virtual IP. + DWORD functionTableIndex = + static_cast(reinterpret_cast(PortableEntryPoint::GetActualCode((PCODE)entryPoint))); + TADDR virtualIP = ExecutionManager::GetWasmVirtualIPFromFunctionTableIndex(functionTableIndex); + if (virtualIP != 0) + { + start = virtualIP; + } + } +#endif // TARGET_WASM && FEATURE_PORTABLE_ENTRYPOINTS + + return start; } /****************************************************************************/ diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs index aa9daf674b9198..cf488fb21a1c0b 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs @@ -41,7 +41,6 @@ public EventPipeDiagnosticsTests(ITestOutputHelper output, SharedBuildPerTestCla [Theory] [InlineData(Configuration.Debug, false)] [InlineData(Configuration.Release, false)] - [ActiveIssue("https://github.com/dotnet/runtime/issues/132410", typeof(BuildTestBase), nameof(IsCoreClrRuntime))] public async Task BlazorEventPipeTestWithCpuSamples(Configuration config, bool aot) { string extraProperties = @" @@ -76,20 +75,24 @@ await RunForBuildWithDotnetRun(new BlazorRunOptions( } )); - var methodFound = false; + bool appMethodFound = false; + bool readyToRunMethodFound = false; using (var source = TraceLog.OpenOrConvert(ConvertTrace(info, "cpuprofile.nettrace"))) { - methodFound = source.CallStacks.Any(stack => stack.CodeAddress.FullMethodName == "BlazorBasicTestApp.Pages.Counter.IncrementCount()"); - if (!methodFound) + appMethodFound = source.CallStacks.Any(stack => stack.CodeAddress.FullMethodName == "BlazorBasicTestApp.Pages.Counter.IncrementCount()"); + if (!appMethodFound) { foreach (var stack in source.CallStacks) { _testOutput.WriteLine($"Stack: {stack.CodeAddress.FullMethodName}"); } } + + readyToRunMethodFound = source.CodeAddresses.Any(address => address.FullMethodName.StartsWith("System.Buffer.Memmove(")); } - Assert.True(methodFound, "The cpuprofile.nettrace should contain stack frames for the 'Counter.IncrementCount' method"); + Assert.True(appMethodFound, "The cpuprofile.nettrace should contain stack frames for the 'Counter.IncrementCount' method"); + Assert.True(readyToRunMethodFound, "The cpuprofile.nettrace should contain rundown information for the ReadyToRun 'System.Buffer.Memmove' method"); } [Fact] From de40a4096c19f57e2e85f402e35a691fc8872ee8 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Tue, 15 Sep 2026 22:47:42 -0500 Subject: [PATCH 2/3] Use ordinal comparison in EventPipe test Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs index cf488fb21a1c0b..21c1a1da4ffdce 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs @@ -88,7 +88,7 @@ await RunForBuildWithDotnetRun(new BlazorRunOptions( } } - readyToRunMethodFound = source.CodeAddresses.Any(address => address.FullMethodName.StartsWith("System.Buffer.Memmove(")); + readyToRunMethodFound = source.CodeAddresses.Any(address => address.FullMethodName.StartsWith("System.Buffer.Memmove(", StringComparison.Ordinal)); } Assert.True(appMethodFound, "The cpuprofile.nettrace should contain stack frames for the 'Counter.IncrementCount' method"); From 72647cc56f2965c969f5af0a273708f5561883f5 Mon Sep 17 00:00:00 2001 From: Larry Ewing Date: Tue, 15 Sep 2026 23:34:40 -0500 Subject: [PATCH 3/3] Guard R2R EventPipe assertion on CoreCLR Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --- .../Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs b/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs index 21c1a1da4ffdce..1bfbbb78d61224 100644 --- a/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs +++ b/src/mono/wasm/Wasm.Build.Tests/Blazor/EventPipeDiagnosticsTests.cs @@ -92,7 +92,10 @@ await RunForBuildWithDotnetRun(new BlazorRunOptions( } Assert.True(appMethodFound, "The cpuprofile.nettrace should contain stack frames for the 'Counter.IncrementCount' method"); - Assert.True(readyToRunMethodFound, "The cpuprofile.nettrace should contain rundown information for the ReadyToRun 'System.Buffer.Memmove' method"); + if (BuildTestBase.IsCoreClrRuntime) + { + Assert.True(readyToRunMethodFound, "The cpuprofile.nettrace should contain rundown information for the ReadyToRun 'System.Buffer.Memmove' method"); + } } [Fact]