From ca0ee37c3357f7ed94847da379994aab7127faee Mon Sep 17 00:00:00 2001 From: Lee Culver Date: Sat, 14 Feb 2026 20:19:16 -0500 Subject: [PATCH] Stop creating synthetic .il module paths for ReadyToRun assemblies Fix dotnet/diagnostics#3102: EventPipe module names have unexpected .il suffix. TraceLog.ManagedModuleLoadOrUnload was creating synthetic .il.dll paths for ReadyToRun assemblies to maintain separate IL and native PDB entries. This internal implementation detail leaked into user-visible names, causing tools like dotnet-stack, PerfView, and WPA to display module names like 'System.Private.CoreLib.il' instead of 'System.Private.CoreLib'. Remove the synthetic .il path creation at the source instead of stripping it downstream. The IL module now uses the same path as the native module since there's no separate IL-only file on disk. Also strip .ni suffixes from TraceModuleFile.Name for NGEN images. --- src/TraceEvent/AutomatedAnalysis/StackView.cs | 4 ++-- src/TraceEvent/TraceLog.cs | 16 ++++------------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/TraceEvent/AutomatedAnalysis/StackView.cs b/src/TraceEvent/AutomatedAnalysis/StackView.cs index 4b725899d..3c47ca707 100644 --- a/src/TraceEvent/AutomatedAnalysis/StackView.cs +++ b/src/TraceEvent/AutomatedAnalysis/StackView.cs @@ -297,8 +297,8 @@ private static bool SymbolNamesMatch(string requestedName, string foundName) // Allow the found name to be of equivalent or greater length than the requested length. // Example: - // Requested: System.Private.CoreLib.il!System.String.Concat - // Found: System.Private.CoreLib.il!System.String.Concat(class System.String,class System.String) + // Requested: System.Private.CoreLib!System.String.Concat + // Found: System.Private.CoreLib!System.String.Concat(class System.String,class System.String) if (foundName.Length < requestedName.Length) { return false; diff --git a/src/TraceEvent/TraceLog.cs b/src/TraceEvent/TraceLog.cs index c1c550de3..0561a3a47 100644 --- a/src/TraceEvent/TraceLog.cs +++ b/src/TraceEvent/TraceLog.cs @@ -342,7 +342,7 @@ private void SetupInitialRundownCallbacks(EventPipeEventSource rawEvents) clrRundownParser.MethodDCStopVerbose += delegate (MethodLoadUnloadVerboseTraceData data) { // Note: we need this also for non-jitted methods, otherwise we won't resolve some frames, for example: - // "System.Private.CoreLib.il" - "System.Threading.Tasks.Task.Wait()" + // "System.Private.CoreLib" - "System.Threading.Tasks.Task.Wait()" TraceProcess process = processes.GetOrCreateProcess(data.ProcessID, data.TimeStampQPC); process.InsertJITTEDMethod(data.MethodStartAddress, data.MethodSize, delegate () { @@ -7041,18 +7041,10 @@ internal void ManagedModuleLoadOrUnload(ModuleLoadUnloadTraceData data, bool isL } // This is the CoreCLR (First Generation) ReadyToRun case. There still is a native PDB that is distinct // from the IL PDB. Unlike CoreCLR NGEN, it is logged as a IL file, but it has native code (and thus an NativePdbSignature) - // We treat the image as a native image and dummy up a il image to hang the IL PDB information on. + // We treat the image as a native image. The IL module uses the same path since there's no separate IL-only file on disk. else if (nativeModulePath.Length == 0 && nativePdbSignature != Guid.Empty && data.ManagedPdbSignature != Guid.Empty) { - // And make up a fake .il.dll module for the IL - var suffixPos = ilModulePath.LastIndexOf(".", StringComparison.OrdinalIgnoreCase); - if (0 < suffixPos) - { - // We treat the image as the native path - nativeModulePath = ilModulePath; - // and make up a dummy IL path. - ilModulePath = ilModulePath.Substring(0, suffixPos) + ".il" + ilModulePath.Substring(suffixPos); - } + nativeModulePath = ilModulePath; } int index; @@ -8330,7 +8322,7 @@ public SourceLocation GetSourceLine(SymbolReader reader, CodeAddressIndex codeAd { // In CoreCLR, the managed image IS the native image, so has a .ni suffix, remove it if present. var moduleFileName = moduleFile.ManagedModule.Name; - if (moduleFileName.EndsWith(".ni", StringComparison.OrdinalIgnoreCase) || moduleFileName.EndsWith(".il", StringComparison.OrdinalIgnoreCase)) + if (moduleFileName.EndsWith(".ni", StringComparison.OrdinalIgnoreCase)) { moduleFileName = moduleFileName.Substring(0, moduleFileName.Length - 3); }