diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/AssemblyInfo.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/AssemblyInfo.cs new file mode 100644 index 0000000000000..02ff300e617e8 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/AssemblyInfo.cs @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; + +namespace ILCompiler.Diagnostics +{ + public struct AssemblyInfo + { + public readonly string Name; + public readonly Guid Mvid; + + public AssemblyInfo(string name, Guid mvid) + { + Name = name; + Mvid = mvid; + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj index 8c9419db564aa..8fe3bd1982d47 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj @@ -17,4 +17,8 @@ Debug;Release;Checked + + + + diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs index 4696bc9e2d18f..dd494b9fdcf9a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs @@ -4,11 +4,27 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Security.Cryptography; + +using Internal.TypeSystem; namespace ILCompiler.Diagnostics { public class PerfMapWriter { + public const int LegacyCrossgen1FormatVersion = 0; + + public const int CurrentFormatVersion = 1; + + public enum PseudoRVA : uint + { + OutputGuid = 0xFFFFFFFF, + TargetOS = 0xFFFFFFFE, + TargetArchitecture = 0xFFFFFFFD, + FormatVersion = 0xFFFFFFFC, + } + private TextWriter _writer; private PerfMapWriter(TextWriter writer) @@ -16,11 +32,32 @@ private PerfMapWriter(TextWriter writer) _writer = writer; } - public static void Write(string perfMapFileName, IEnumerable methods) + public static void Write(string perfMapFileName, int perfMapFormatVersion, IEnumerable methods, IEnumerable inputAssemblies, TargetOS targetOS, TargetArchitecture targetArch) { + if (perfMapFormatVersion > CurrentFormatVersion) + { + throw new NotSupportedException(perfMapFormatVersion.ToString()); + } + using (TextWriter writer = new StreamWriter(perfMapFileName)) { + IEnumerable orderedInputs = inputAssemblies.OrderBy(asm => asm.Name, StringComparer.OrdinalIgnoreCase); + PerfMapWriter perfMapWriter = new PerfMapWriter(writer); + + List inputHash = new List(); + foreach (AssemblyInfo inputAssembly in orderedInputs) + { + inputHash.AddRange(inputAssembly.Mvid.ToByteArray()); + } + inputHash.Add((byte)targetOS); + inputHash.Add((byte)targetArch); + Guid outputGuid = new Guid(MD5.HashData(inputHash.ToArray())); + perfMapWriter.WriteLine(outputGuid.ToString(), (uint)PseudoRVA.OutputGuid, 0); + perfMapWriter.WriteLine(targetOS.ToString(), (uint)PseudoRVA.TargetOS, 0); + perfMapWriter.WriteLine(targetArch.ToString(), (uint)PseudoRVA.TargetArchitecture, 0); + perfMapWriter.WriteLine(CurrentFormatVersion.ToString(), (uint)PseudoRVA.FormatVersion, 0); + foreach (MethodInfo methodInfo in methods) { if (methodInfo.HotRVA != 0 && methodInfo.HotLength != 0) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index 74da51246b620..6404f77fbac06 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -45,6 +45,12 @@ internal class ReadyToRunObjectWriter /// private readonly EcmaModule _componentModule; + /// + /// Compilation input files. Input files are emitted as perfmap entries and used + /// to calculate the output GUID of the ReadyToRun executable for symbol indexation. + /// + private readonly IEnumerable _inputFiles; + /// /// Nodes to emit into the output executable as collected by the dependency analysis. /// @@ -101,9 +107,9 @@ internal class ReadyToRunObjectWriter private string _perfMapPath; /// - /// MVID of the input managed module to embed in the perfmap file name. + /// Requested version of the perfmap file format /// - private Guid? _perfMapMvid; + private int _perfMapFormatVersion; /// /// If non-zero, the PE file will be laid out such that it can naturally be mapped with a higher alignment than 4KB. @@ -132,6 +138,7 @@ public NodeInfo(ISymbolNode node, int nodeIndex, int symbolIndex) public ReadyToRunObjectWriter( string objectFilePath, EcmaModule componentModule, + IEnumerable inputFiles, IEnumerable nodes, NodeFactory factory, bool generateMapFile, @@ -140,13 +147,14 @@ public NodeInfo(ISymbolNode node, int nodeIndex, int symbolIndex) string pdbPath, bool generatePerfMapFile, string perfMapPath, - Guid? perfMapMvid, + int perfMapFormatVersion, bool generateProfileFile, CallChainProfile callChainProfile, int customPESectionAlignment) { _objectFilePath = objectFilePath; _componentModule = componentModule; + _inputFiles = inputFiles; _nodes = nodes; _nodeFactory = factory; _customPESectionAlignment = customPESectionAlignment; @@ -156,7 +164,7 @@ public NodeInfo(ISymbolNode node, int nodeIndex, int symbolIndex) _pdbPath = pdbPath; _generatePerfMapFile = generatePerfMapFile; _perfMapPath = perfMapPath; - _perfMapMvid = perfMapMvid; + _perfMapFormatVersion = perfMapFormatVersion; bool generateMap = (generateMapFile || generateMapCsvFile); bool generateSymbols = (generatePdbFile || generatePerfMapFile); @@ -329,6 +337,11 @@ public void EmitPortableExecutable() if (_outputInfoBuilder != null) { + foreach (string inputFile in _inputFiles) + { + _outputInfoBuilder.AddInputModule(_nodeFactory.TypeSystemContext.GetModuleFromPath(inputFile)); + } + r2rPeBuilder.AddSections(_outputInfoBuilder); if (_generateMapFile) @@ -361,7 +374,7 @@ public void EmitPortableExecutable() { path = Path.GetDirectoryName(_objectFilePath); } - _symbolFileBuilder.SavePerfMap(path, _objectFilePath, _perfMapMvid); + _symbolFileBuilder.SavePerfMap(path, _perfMapFormatVersion, _objectFilePath, _nodeFactory.Target.OperatingSystem, _nodeFactory.Target.Architecture); } if (_profileFileBuilder != null) @@ -430,6 +443,7 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node public static void EmitObject( string objectFilePath, EcmaModule componentModule, + IEnumerable inputFiles, IEnumerable nodes, NodeFactory factory, bool generateMapFile, @@ -438,7 +452,7 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node string pdbPath, bool generatePerfMapFile, string perfMapPath, - Guid? perfMapMvid, + int perfMapFormatVersion, bool generateProfileFile, CallChainProfile callChainProfile, int customPESectionAlignment) @@ -447,6 +461,7 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node ReadyToRunObjectWriter objectWriter = new ReadyToRunObjectWriter( objectFilePath, componentModule, + inputFiles, nodes, factory, generateMapFile: generateMapFile, @@ -455,7 +470,7 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node pdbPath: pdbPath, generatePerfMapFile: generatePerfMapFile, perfMapPath: perfMapPath, - perfMapMvid: perfMapMvid, + perfMapFormatVersion: perfMapFormatVersion, generateProfileFile: generateProfileFile, callChainProfile, customPESectionAlignment); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 1dce9f8f67f53..ac7058bf90dae 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -247,7 +247,7 @@ public sealed class ReadyToRunCodegenCompilation : Compilation private readonly string _pdbPath; private readonly bool _generatePerfMapFile; private readonly string _perfMapPath; - private readonly Guid? _perfMapMvid; + private readonly int _perfMapFormatVersion; private readonly bool _generateProfileFile; private readonly Func _printReproInstructions; @@ -283,7 +283,7 @@ public sealed class ReadyToRunCodegenCompilation : Compilation string pdbPath, bool generatePerfMapFile, string perfMapPath, - Guid? perfMapMvid, + int perfMapFormatVersion, bool generateProfileFile, int parallelism, ProfileDataManager profileData, @@ -309,7 +309,7 @@ public sealed class ReadyToRunCodegenCompilation : Compilation _pdbPath = pdbPath; _generatePerfMapFile = generatePerfMapFile; _perfMapPath = perfMapPath; - _perfMapMvid = perfMapMvid; + _perfMapFormatVersion = perfMapFormatVersion; _generateProfileFile = generateProfileFile; _customPESectionAlignment = customPESectionAlignment; SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory, verifyTypeAndFieldLayout); @@ -347,6 +347,7 @@ public override void Compile(string outputFile) ReadyToRunObjectWriter.EmitObject( outputFile, componentModule: null, + inputFiles: _inputFiles, nodes, NodeFactory, generateMapFile: _generateMapFile, @@ -355,7 +356,7 @@ public override void Compile(string outputFile) pdbPath: _pdbPath, generatePerfMapFile: _generatePerfMapFile, perfMapPath: _perfMapPath, - perfMapMvid: _perfMapMvid, + perfMapFormatVersion: _perfMapFormatVersion, generateProfileFile: _generateProfileFile, callChainProfile: _profileData.CallChainProfile, _customPESectionAlignment); @@ -427,6 +428,7 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow ReadyToRunObjectWriter.EmitObject( outputFile, componentModule: inputModule, + inputFiles: new string[] { inputFile }, componentGraph.MarkedNodeList, componentFactory, generateMapFile: false, @@ -435,7 +437,7 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow pdbPath: null, generatePerfMapFile: false, perfMapPath: null, - perfMapMvid: null, + perfMapFormatVersion: _perfMapFormatVersion, generateProfileFile: false, _profileData.CallChainProfile, customPESectionAlignment: 0); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index fa4d3182e9afb..c1207a4b5b2f0 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -31,7 +31,7 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder private string _pdbPath; private bool _generatePerfMapFile; private string _perfMapPath; - private Guid? _perfMapMvid; + private int _perfMapFormatVersion; private bool _generateProfileFile; private int _parallelism; Func _printReproInstructions; @@ -156,11 +156,11 @@ public ReadyToRunCodegenCompilationBuilder UsePdbFile(bool generatePdbFile, stri return this; } - public ReadyToRunCodegenCompilationBuilder UsePerfMapFile(bool generatePerfMapFile, string perfMapPath, Guid? inputModuleMvid) + public ReadyToRunCodegenCompilationBuilder UsePerfMapFile(bool generatePerfMapFile, string perfMapPath, int perfMapFormatVersion) { _generatePerfMapFile = generatePerfMapFile; _perfMapPath = perfMapPath; - _perfMapMvid = inputModuleMvid; + _perfMapFormatVersion = perfMapFormatVersion; return this; } @@ -312,7 +312,7 @@ public override ICompilation ToCompilation() pdbPath: _pdbPath, generatePerfMapFile: _generatePerfMapFile, perfMapPath: _perfMapPath, - perfMapMvid: _perfMapMvid, + perfMapFormatVersion: _perfMapFormatVersion, generateProfileFile: _generateProfileFile, _parallelism, _profileData, diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs index 82145e37999da..ca6efc9edb111 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs @@ -106,6 +106,7 @@ public OutputSymbol(int sectionIndex, int offset, string name) /// public class OutputInfoBuilder { + private readonly List _inputModules; private readonly List _nodes; private readonly List _symbols; private readonly List
_sections; @@ -117,6 +118,7 @@ public class OutputInfoBuilder public OutputInfoBuilder() { + _inputModules = new List(); _nodes = new List(); _symbols = new List(); _sections = new List
(); @@ -127,6 +129,11 @@ public OutputInfoBuilder() _relocCounts = new Dictionary(); } + public void AddInputModule(EcmaModule module) + { + _inputModules.Add(module); + } + public void AddNode(OutputNode node, ISymbolDefinitionNode symbol) { _nodes.Add(node); @@ -197,6 +204,16 @@ public IEnumerable EnumerateMethods() } } + public IEnumerable EnumerateInputAssemblies() + { + foreach (EcmaModule inputModule in _inputModules) + { + yield return new AssemblyInfo( + inputModule.Assembly.GetName().Name, + inputModule.MetadataReader.GetGuid(inputModule.MetadataReader.GetModuleDefinition().Mvid)); + } + } + private string FormatMethodName(MethodDesc method, TypeNameFormatter typeNameFormatter) { StringBuilder output = new StringBuilder(); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs index 7ec93572f6fc2..8cd0ad481cc6d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading.Tasks; +using Internal.TypeSystem; using ILCompiler.Diagnostics; namespace ILCompiler.PEWriter @@ -28,12 +29,34 @@ public void SavePdb(string pdbPath, string dllFileName) new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, _outputInfoBuilder.EnumerateMethods()); } - public void SavePerfMap(string perfMapPath, string dllFileName, Guid? perfMapMvid) + public void SavePerfMap(string perfMapPath, int perfMapFormatVersion, string dllFileName, TargetOS targetOS, TargetArchitecture targetArch) { - string mvidComponent = (perfMapMvid.HasValue ? perfMapMvid.Value.ToString() : "composite"); - string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + ".ni.{" + mvidComponent + "}.map"); + string perfMapExtension; + if (perfMapFormatVersion == PerfMapWriter.LegacyCrossgen1FormatVersion) + { + string mvidComponent = null; + foreach (AssemblyInfo inputAssembly in _outputInfoBuilder.EnumerateInputAssemblies()) + { + if (mvidComponent == null) + { + mvidComponent = inputAssembly.Mvid.ToString(); + } + else + { + mvidComponent = "composite"; + break; + } + } + perfMapExtension = ".ni.{" + mvidComponent + "}.map"; + } + else + { + perfMapExtension = ".ni.r2rmap"; + } + + string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + perfMapExtension); Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); - PerfMapWriter.Write(perfMapFileName, _outputInfoBuilder.EnumerateMethods()); + PerfMapWriter.Write(perfMapFileName, perfMapFormatVersion, _outputInfoBuilder.EnumerateMethods(), _outputInfoBuilder.EnumerateInputAssemblies(), targetOS, targetArch); } } } diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj index 1424375efc4e3..0d332d59f91d0 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ILCompiler.Reflection.ReadyToRun.csproj @@ -7,7 +7,7 @@ AnyCPU Open true - netstandard2.0 + $(NetCoreAppToolCurrent) false 8002,NU1701 win-x64;win-x86 @@ -27,6 +27,9 @@ - + + + + diff --git a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs index f727ed872e03f..821a38f545e20 100644 --- a/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs +++ b/src/coreclr/tools/aot/ILCompiler.Reflection.ReadyToRun/ReadyToRunReader.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.IO; +using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; @@ -15,9 +16,9 @@ using Internal.CorConstants; using Internal.Runtime; using Internal.ReadyToRunConstants; +using Internal.TypeSystem; using Debug = System.Diagnostics.Debug; -using System.Linq; namespace ILCompiler.Reflection.ReadyToRun { @@ -79,6 +80,8 @@ public IReadOnlyList Methods public sealed class ReadyToRunReader { + public const int GuidByteSize = 16; + private const string SystemModuleName = "System.Private.CoreLib"; /// @@ -176,6 +179,33 @@ public Machine Machine } } + /// + /// Conversion of the PE machine ID to TargetArchitecture used by TargetDetails. + /// + public TargetArchitecture TargetArchitecture + { + get + { + switch (Machine) + { + case Machine.I386: + return TargetArchitecture.X86; + + case Machine.Amd64: + return TargetArchitecture.X64; + + case Machine.ArmThumb2: + return TargetArchitecture.ARM; + + case Machine.Arm64: + return TargetArchitecture.ARM64; + + default: + throw new NotImplementedException(_machine.ToString()); + } + } + } + /// /// Targeting operating system for the R2R executable /// @@ -188,6 +218,36 @@ public OperatingSystem OperatingSystem } } + /// + /// Targeting operating system converted to the enumeration used by TargetDetails. + /// + public TargetOS TargetOperatingSystem + { + get + { + switch (OperatingSystem) + { + case OperatingSystem.Windows: + return TargetOS.Windows; + + case OperatingSystem.Linux: + return TargetOS.Linux; + + case OperatingSystem.Apple: + return TargetOS.OSX; + + case OperatingSystem.FreeBSD: + return TargetOS.FreeBSD; + + case OperatingSystem.NetBSD: + return TargetOS.FreeBSD; + + default: + throw new NotImplementedException(OperatingSystem.ToString()); + } + } + } + /// /// Targeting processor architecture of the R2R executable /// @@ -537,6 +597,12 @@ public IAssemblyMetadata GetGlobalMetadata() return (_composite ? null : _assemblyCache[0]); } + public string GetGlobalAssemblyName() + { + MetadataReader mdReader = GetGlobalMetadata().MetadataReader; + return mdReader.GetString(mdReader.GetAssemblyDefinition().Name); + } + private unsafe void EnsureHeader() { if (_readyToRunHeader != null) @@ -1087,6 +1153,26 @@ public int GetAssemblyIndex(ReadyToRunSection section) } } + public Guid GetAssemblyMvid(int assemblyIndex) + { + EnsureHeader(); + if (_composite) + { + if (!ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.ManifestAssemblyMvids, out ReadyToRunSection mvidSection)) + { + return Guid.Empty; + } + int mvidOffset = GetOffset(mvidSection.RelativeVirtualAddress) + GuidByteSize * assemblyIndex; + return new Guid(new ReadOnlySpan(Image, mvidOffset, ReadyToRunReader.GuidByteSize)); + } + else + { + Debug.Assert(assemblyIndex == 0); + MetadataReader mdReader = GetGlobalMetadata().MetadataReader; + return mdReader.GetGuid(mdReader.GetModuleDefinition().Mvid); + } + } + /// /// Iterates through a native hashtable to get all RIDs /// diff --git a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs index 573b1eb5cb497..c91e615eb73a8 100644 --- a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs +++ b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs @@ -12,6 +12,8 @@ namespace ILCompiler { internal class CommandLineOptions { + public const int DefaultPerfMapFormatVersion = 0; + public bool Help; public string HelpText; @@ -56,6 +58,7 @@ internal class CommandLineOptions public string PdbPath; public bool PerfMap; public string PerfMapPath; + public int PerfMapFormatVersion; public int Parallelism; public int CustomPESectionAlignment; public string MethodLayout; @@ -81,6 +84,7 @@ public CommandLineOptions(string[] args) MibcFilePaths = Array.Empty(); CodegenOptions = Array.Empty(); + PerfMapFormatVersion = DefaultPerfMapFormatVersion; Parallelism = Environment.ProcessorCount; SingleMethodGenericArg = null; @@ -139,6 +143,7 @@ public CommandLineOptions(string[] args) syntax.DefineOption("pdb-path", ref PdbPath, SR.PdbFilePathOption); syntax.DefineOption("perfmap", ref PerfMap, SR.PerfMapFileOption); syntax.DefineOption("perfmap-path", ref PerfMapPath, SR.PerfMapFilePathOption); + syntax.DefineOption("perfmap-format-version", ref PerfMapFormatVersion, SR.PerfMapFormatVersionOption); syntax.DefineOption("method-layout", ref MethodLayout, SR.MethodLayoutOption); syntax.DefineOption("file-layout", ref FileLayout, SR.FileLayoutOption); diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index 2f84f6fb5a7e6..aeeb9f57bb3c4 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -517,7 +517,6 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru List inputModules = new List(); List rootingModules = new List(); - Guid? inputModuleMvid = null; foreach (var inputFile in inFilePaths) { @@ -526,10 +525,6 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru rootingModules.Add(module); versionBubbleModulesHash.Add(module); - if (!_commandLineOptions.Composite && !inputModuleMvid.HasValue) - { - inputModuleMvid = module.MetadataReader.GetGuid(module.MetadataReader.GetModuleDefinition().Mvid); - } if (!_commandLineOptions.CompositeOrInputBubble) { @@ -687,7 +682,7 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru .UseMapFile(_commandLineOptions.Map) .UseMapCsvFile(_commandLineOptions.MapCsv) .UsePdbFile(_commandLineOptions.Pdb, _commandLineOptions.PdbPath) - .UsePerfMapFile(_commandLineOptions.PerfMap, _commandLineOptions.PerfMapPath, inputModuleMvid) + .UsePerfMapFile(_commandLineOptions.PerfMap, _commandLineOptions.PerfMapPath, _commandLineOptions.PerfMapFormatVersion) .UseProfileFile(jsonProfile != null) .UseParallelism(_commandLineOptions.Parallelism) .UseProfileData(profileDataManager) diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx index 084138ebc7c4d..c031f303e44e0 100644 --- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx +++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx @@ -345,4 +345,7 @@ Explicit specification of the PerfMap file path - + + Explicitly request a particular PerfMap format version + + \ No newline at end of file diff --git a/src/coreclr/tools/r2rdump/CommandLineOptions.cs b/src/coreclr/tools/r2rdump/CommandLineOptions.cs index 8857cdbae87ac..9a1296bdbd65d 100644 --- a/src/coreclr/tools/r2rdump/CommandLineOptions.cs +++ b/src/coreclr/tools/r2rdump/CommandLineOptions.cs @@ -40,6 +40,7 @@ public static RootCommand RootCommand() command.AddOption(new Option(new[] { "--pdb-path" }, "PDB output path for --create-pdb")); command.AddOption(new Option(new[] { "--create-perfmap" }, "Create PerfMap")); command.AddOption(new Option(new[] { "--perfmap-path" }, "PerfMap output path for --create-perfmap")); + command.AddOption(new Option(new[] { "--perfmap-format-version" }, "PerfMap format version for --create-perfmap")); return command; } } diff --git a/src/coreclr/tools/r2rdump/R2RDump.cs b/src/coreclr/tools/r2rdump/R2RDump.cs index 8a24273302b56..94d71835966e5 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.cs +++ b/src/coreclr/tools/r2rdump/R2RDump.cs @@ -20,6 +20,7 @@ using ILCompiler.Reflection.ReadyToRun; using Internal.Runtime; +using Internal.TypeSystem; namespace R2RDump { @@ -55,6 +56,7 @@ public class DumpOptions : IAssemblyResolver public bool CreatePerfmap { get; set; } public string PerfmapPath { get; set; } + public int PerfmapFormatVersion { get; set; } public FileInfo[] Reference { get; set; } @@ -65,6 +67,11 @@ public class DumpOptions : IAssemblyResolver private SignatureFormattingOptions signatureFormattingOptions; + public DumpOptions() + { + PerfmapFormatVersion = PerfMapWriter.CurrentFormatVersion; + } + /// /// Probing extensions to use when looking up assemblies under reference paths. /// @@ -425,9 +432,9 @@ public void Dump(ReadyToRunReader r2r) string perfmapPath = _options.PerfmapPath; if (string.IsNullOrEmpty(perfmapPath)) { - perfmapPath = Path.ChangeExtension(r2r.Filename, ".map"); - PerfMapWriter.Write(perfmapPath, ProduceDebugInfoMethods(r2r)); + perfmapPath = Path.ChangeExtension(r2r.Filename, ".r2rmap"); } + PerfMapWriter.Write(perfmapPath, _options.PerfmapFormatVersion, ProduceDebugInfoMethods(r2r), ProduceDebugInfoAssemblies(r2r), r2r.TargetOperatingSystem, r2r.TargetArchitecture); } if (standardDump) @@ -457,6 +464,21 @@ IEnumerable ProduceDebugInfoMethods(ReadyToRunReader r2r) } } + IEnumerable ProduceDebugInfoAssemblies(ReadyToRunReader r2r) + { + if (r2r.Composite) + { + foreach (KeyValuePair kvpRefAssembly in r2r.ManifestReferenceAssemblies.OrderBy(kvp => kvp.Key, StringComparer.OrdinalIgnoreCase)) + { + yield return new AssemblyInfo(kvpRefAssembly.Key, r2r.GetAssemblyMvid(kvpRefAssembly.Value)); + } + } + else + { + yield return new AssemblyInfo(r2r.GetGlobalAssemblyName(), r2r.GetAssemblyMvid(0)); + } + } + /// /// Returns true if the name, signature or id of method matches query /// diff --git a/src/coreclr/tools/r2rdump/R2RDump.sln b/src/coreclr/tools/r2rdump/R2RDump.sln index 6596a597f104a..e8f71beb5a007 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.sln +++ b/src/coreclr/tools/r2rdump/R2RDump.sln @@ -8,38 +8,89 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Reflection.Ready EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Diagnostics", "..\aot\ILCompiler.Diagnostics\ILCompiler.Diagnostics.csproj", "{4E9512BA-F963-472A-B689-37D4D32456F3}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.TypeSystem.ReadyToRun", "..\aot\ILCompiler.TypeSystem.ReadyToRun\ILCompiler.TypeSystem.ReadyToRun.csproj", "{F9CC5645-9E5D-41EE-ACD3-120F661DDA51}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Checked|Any CPU = Checked|Any CPU + Checked|x64 = Checked|x64 + Checked|x86 = Checked|x86 Debug|Any CPU = Debug|Any CPU Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Checked|Any CPU.ActiveCfg = Release|Any CPU + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Checked|Any CPU.Build.0 = Release|Any CPU + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Checked|x64.ActiveCfg = Release|x64 + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Checked|x64.Build.0 = Release|x64 + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Checked|x86.ActiveCfg = Debug|x86 + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Checked|x86.Build.0 = Debug|x86 {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|Any CPU.ActiveCfg = Debug|x64 {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|Any CPU.Build.0 = Debug|x64 {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|x64.ActiveCfg = Debug|x64 {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|x64.Build.0 = Debug|x64 + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|x86.ActiveCfg = Debug|x86 + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|x86.Build.0 = Debug|x86 {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Release|Any CPU.ActiveCfg = Release|Any CPU {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Release|Any CPU.Build.0 = Release|Any CPU {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Release|x64.ActiveCfg = Release|x64 {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Release|x64.Build.0 = Release|x64 + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Release|x86.ActiveCfg = Release|x86 + {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Release|x86.Build.0 = Release|x86 + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Checked|Any CPU.ActiveCfg = Release|Any CPU + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Checked|Any CPU.Build.0 = Release|Any CPU + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Checked|x64.ActiveCfg = Release|x64 + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Checked|x64.Build.0 = Release|x64 + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Checked|x86.ActiveCfg = Release|Any CPU + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Checked|x86.Build.0 = Release|Any CPU {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Debug|Any CPU.Build.0 = Debug|Any CPU {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Debug|x64.ActiveCfg = Debug|x64 {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Debug|x64.Build.0 = Debug|x64 + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Debug|x86.ActiveCfg = Debug|Any CPU + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Debug|x86.Build.0 = Debug|Any CPU {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Release|Any CPU.ActiveCfg = Release|Any CPU {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Release|Any CPU.Build.0 = Release|Any CPU {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Release|x64.ActiveCfg = Release|x64 {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Release|x64.Build.0 = Release|x64 + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Release|x86.ActiveCfg = Release|Any CPU + {E2A577E5-7AF3-49B3-BA78-7071B75ED64B}.Release|x86.Build.0 = Release|Any CPU + {4E9512BA-F963-472A-B689-37D4D32456F3}.Checked|Any CPU.ActiveCfg = Checked|x86 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Checked|x64.ActiveCfg = Checked|x64 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Checked|x64.Build.0 = Checked|x64 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Checked|x86.ActiveCfg = Checked|x86 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Checked|x86.Build.0 = Checked|x86 {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|Any CPU.ActiveCfg = Debug|x64 {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|Any CPU.Build.0 = Debug|x64 {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x64.ActiveCfg = Debug|x64 {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x64.Build.0 = Debug|x64 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x86.ActiveCfg = Debug|x86 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x86.Build.0 = Debug|x86 {4E9512BA-F963-472A-B689-37D4D32456F3}.Release|Any CPU.ActiveCfg = Release|Any CPU {4E9512BA-F963-472A-B689-37D4D32456F3}.Release|Any CPU.Build.0 = Release|Any CPU {4E9512BA-F963-472A-B689-37D4D32456F3}.Release|x64.ActiveCfg = Release|Any CPU {4E9512BA-F963-472A-B689-37D4D32456F3}.Release|x64.Build.0 = Release|Any CPU + {4E9512BA-F963-472A-B689-37D4D32456F3}.Release|x86.ActiveCfg = Release|x86 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Release|x86.Build.0 = Release|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Checked|Any CPU.ActiveCfg = Checked|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Checked|x64.ActiveCfg = Checked|x64 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Checked|x64.Build.0 = Checked|x64 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Checked|x86.ActiveCfg = Checked|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Checked|x86.Build.0 = Checked|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Debug|Any CPU.ActiveCfg = Debug|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Debug|x64.ActiveCfg = Debug|x64 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Debug|x64.Build.0 = Debug|x64 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Debug|x86.ActiveCfg = Debug|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Debug|x86.Build.0 = Debug|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Release|Any CPU.ActiveCfg = Release|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Release|x64.ActiveCfg = Release|x64 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Release|x64.Build.0 = Release|x64 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Release|x86.ActiveCfg = Release|x86 + {F9CC5645-9E5D-41EE-ACD3-120F661DDA51}.Release|x86.Build.0 = Release|x86 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/coreclr/tools/r2rdump/TextDumper.cs b/src/coreclr/tools/r2rdump/TextDumper.cs index 0e062b88508f9..7ca2b58c77dcd 100644 --- a/src/coreclr/tools/r2rdump/TextDumper.cs +++ b/src/coreclr/tools/r2rdump/TextDumper.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; +using System.Runtime.CompilerServices; using System.Reflection.PortableExecutable; using System.Text; @@ -18,8 +19,6 @@ namespace R2RDump { class TextDumper : Dumper { - private const int GuidByteSize = 16; - public TextDumper(ReadyToRunReader r2r, TextWriter writer, Disassembler disassembler, DumpOptions options) : base(r2r, writer, disassembler, options) { @@ -90,14 +89,8 @@ internal override void DumpHeader(bool dumpSections) int assemblyIndex = 0; foreach (string assemblyName in _r2r.ManifestReferenceAssemblies.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key)) { - string dividerName = $@"Component Assembly [{assemblyIndex}]: {assemblyName}"; - if (_r2r.ReadyToRunHeader.Sections.TryGetValue(ReadyToRunSectionType.ManifestAssemblyMvids, out ReadyToRunSection mvidSection)) - { - int mvidOffset = _r2r.GetOffset(mvidSection.RelativeVirtualAddress) + GuidByteSize * assemblyIndex; - Guid mvid = new Guid(new ReadOnlySpan(_r2r.Image, mvidOffset, GuidByteSize)); - dividerName += $@" - MVID {mvid:b}"; - } - WriteDivider(dividerName); + Guid mvid = _r2r.GetAssemblyMvid(assemblyIndex); + WriteDivider($@"Component Assembly [{assemblyIndex}]: {assemblyName} - MVID {mvid:b}"); ReadyToRunCoreHeader assemblyHeader = _r2r.ReadyToRunAssemblyHeaders[assemblyIndex]; foreach (ReadyToRunSection section in NormalizedSections(assemblyHeader)) { @@ -513,12 +506,10 @@ internal override void DumpSectionContents(ReadyToRunSection section) _writer.WriteLine("Composite executable: {0}", ownerCompositeExecutable.ToEscapedString()); break; case ReadyToRunSectionType.ManifestAssemblyMvids: - int mvidOffset = _r2r.GetOffset(section.RelativeVirtualAddress); - int mvidCount = section.Size / GuidByteSize; + int mvidCount = section.Size / ReadyToRunReader.GuidByteSize; for (int mvidIndex = 0; mvidIndex < mvidCount; mvidIndex++) { - Guid mvid = new Guid(new Span(_r2r.Image, mvidOffset + GuidByteSize * mvidIndex, GuidByteSize)); - _writer.WriteLine("MVID[{0}] = {1:b}", mvidIndex, mvid); + _writer.WriteLine("MVID[{0}] = {1:b}", mvidIndex, _r2r.GetAssemblyMvid(mvidIndex)); } break; default: