From 573af644b3cd417921fdef261822b61a70764e57 Mon Sep 17 00:00:00 2001 From: Tomas Date: Fri, 13 Nov 2020 00:56:00 +0100 Subject: [PATCH 1/9] Move R2RDump PDB writer code to a separate assembly I have moved the PDB writer code to a new assembly ILCompiler.Diagnostics so that it can be reused by Crossgen2. I have also added an initial trivial implementation of the PerfMap writer. Thanks Tomas --- .../ILCompiler.Diagnostics.csproj | 7 +++ .../ILCompiler.Diagnostics}/ISymNGenWriter.cs | 0 .../aot/ILCompiler.Diagnostics/MethodInfo.cs | 16 +++++++ .../ILCompiler.Diagnostics}/PdbWriter.cs | 18 +------- .../ILCompiler.Diagnostics/PerfMapWriter.cs | 43 +++++++++++++++++++ .../tools/r2rdump/CommandLineOptions.cs | 4 +- src/coreclr/tools/r2rdump/R2RDump.cs | 27 +++++++++--- src/coreclr/tools/r2rdump/R2RDump.csproj | 1 + src/coreclr/tools/r2rdump/R2RDump.sln | 11 ++++- 9 files changed, 104 insertions(+), 23 deletions(-) create mode 100644 src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj rename src/coreclr/tools/{r2rdump => aot/ILCompiler.Diagnostics}/ISymNGenWriter.cs (100%) create mode 100644 src/coreclr/tools/aot/ILCompiler.Diagnostics/MethodInfo.cs rename src/coreclr/tools/{r2rdump => aot/ILCompiler.Diagnostics}/PdbWriter.cs (97%) create mode 100644 src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj new file mode 100644 index 00000000000000..97b11a522cf7ec --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj @@ -0,0 +1,7 @@ + + + + $(NetCoreAppToolCurrent) + + + diff --git a/src/coreclr/tools/r2rdump/ISymNGenWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs similarity index 100% rename from src/coreclr/tools/r2rdump/ISymNGenWriter.cs rename to src/coreclr/tools/aot/ILCompiler.Diagnostics/ISymNGenWriter.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/MethodInfo.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/MethodInfo.cs new file mode 100644 index 00000000000000..0f1b6dec57d750 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/MethodInfo.cs @@ -0,0 +1,16 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace ILCompiler.Diagnostics +{ + public struct MethodInfo + { + public string AssemblyName; + public uint MethodToken; + public uint HotRVA; + public uint HotLength; + public string Name; + public uint ColdRVA; + public uint ColdLength; + } +} diff --git a/src/coreclr/tools/r2rdump/PdbWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs similarity index 97% rename from src/coreclr/tools/r2rdump/PdbWriter.cs rename to src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs index 99216ab6736f81..68386c8d1a4760 100644 --- a/src/coreclr/tools/r2rdump/PdbWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs @@ -10,7 +10,7 @@ using Microsoft.DiaSymReader; -namespace ILCompiler.PdbWriter +namespace ILCompiler.Diagnostics { // NGEN always generates PDBs with public symbols lists (so tools can map IP ranges to // methods). This bitmask indicates what extra info should be added to the PDB @@ -23,20 +23,6 @@ public enum PDBExtraData kPDBLines = 0x00000001, }; - struct MethodInfo - { - public string AssemblyName; - public uint MethodToken; - public uint HotRVA; - public string Name; - public uint ColdRVA; - } - - interface IModuleData - { - IEnumerable Methods { get; } - } - public enum SymChecksumType : byte { None = 0, // indicates no checksum is available @@ -85,7 +71,7 @@ public bool Equals(SymDocument other) } } - class PdbWriter + public class PdbWriter { string _pdbPath; PDBExtraData _pdbExtraData; diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs new file mode 100644 index 00000000000000..4696bc9e2d18ff --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PerfMapWriter.cs @@ -0,0 +1,43 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; + +namespace ILCompiler.Diagnostics +{ + public class PerfMapWriter + { + private TextWriter _writer; + + private PerfMapWriter(TextWriter writer) + { + _writer = writer; + } + + public static void Write(string perfMapFileName, IEnumerable methods) + { + using (TextWriter writer = new StreamWriter(perfMapFileName)) + { + PerfMapWriter perfMapWriter = new PerfMapWriter(writer); + foreach (MethodInfo methodInfo in methods) + { + if (methodInfo.HotRVA != 0 && methodInfo.HotLength != 0) + { + perfMapWriter.WriteLine(methodInfo.Name, methodInfo.HotRVA, methodInfo.HotLength); + } + if (methodInfo.ColdRVA != 0 && methodInfo.ColdLength != 0) + { + perfMapWriter.WriteLine(methodInfo.Name, methodInfo.ColdRVA, methodInfo.ColdLength); + } + } + } + } + + private void WriteLine(string methodName, uint rva, uint length) + { + _writer.WriteLine($@"{rva:X8} {length:X2} {methodName}"); + } + } +} diff --git a/src/coreclr/tools/r2rdump/CommandLineOptions.cs b/src/coreclr/tools/r2rdump/CommandLineOptions.cs index f41ffd43744a85..7ada4e9748ddab 100644 --- a/src/coreclr/tools/r2rdump/CommandLineOptions.cs +++ b/src/coreclr/tools/r2rdump/CommandLineOptions.cs @@ -36,7 +36,9 @@ public static RootCommand RootCommand() command.AddOption(new Option(new[] { "--inlineSignatureBinary", "--isb" }, "Embed binary signature into its textual representation")); command.AddOption(new Option(new[] { "--signatureBinary", "--sb" }, "Append signature binary to its textual representation")); command.AddOption(new Option(new[] { "--create-pdb" }, "Create PDB")); - command.AddOption(new Option(new[] { "--pdb-path" }, "PDB output path for --createpdb")); + 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")); return command; } } diff --git a/src/coreclr/tools/r2rdump/R2RDump.cs b/src/coreclr/tools/r2rdump/R2RDump.cs index 7d465eb36f3e2d..fa732db7aab6ce 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.cs +++ b/src/coreclr/tools/r2rdump/R2RDump.cs @@ -12,13 +12,14 @@ using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; + +using ILCompiler.Diagnostics; using ILCompiler.Reflection.ReadyToRun; -using ILCompiler.PdbWriter; using Internal.Runtime; -using System.Runtime.InteropServices; namespace R2RDump { @@ -51,6 +52,10 @@ public class DumpOptions : IAssemblyResolver public bool CreatePDB { get; set; } public string PdbPath { get; set; } + public bool CreatePerfmap { get; set; } + public string PerfmapPath { get; set; } + + public FileInfo[] Reference { get; set; } public DirectoryInfo[] ReferencePath { get; set; } @@ -360,7 +365,7 @@ private void QueryRuntimeFunction(ReadyToRunReader r2r, IEnumerable quer public void Dump(ReadyToRunReader r2r) { _dumper.Begin(); - bool standardDump = !(_options.EntryPoints || _options.CreatePDB); + bool standardDump = !(_options.EntryPoints || _options.CreatePDB || _options.CreatePerfmap); if (_options.Header && standardDump) { @@ -409,7 +414,17 @@ public void Dump(ReadyToRunReader r2r) pdbPath = Path.GetDirectoryName(r2r.Filename); } var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None); - pdbWriter.WritePDBData(r2r.Filename, ProducePdbWriterMethods(r2r)); + pdbWriter.WritePDBData(r2r.Filename, ProduceDebugInfoMethods(r2r)); + } + + if (_options.CreatePerfmap) + { + string perfmapPath = _options.PerfmapPath; + if (string.IsNullOrEmpty(perfmapPath)) + { + perfmapPath = Path.ChangeExtension(r2r.Filename, ".map"); + PerfMapWriter.Write(perfmapPath, ProduceDebugInfoMethods(r2r)); + } } if (standardDump) @@ -421,16 +436,18 @@ public void Dump(ReadyToRunReader r2r) _dumper.End(); } - IEnumerable ProducePdbWriterMethods(ReadyToRunReader r2r) + IEnumerable ProduceDebugInfoMethods(ReadyToRunReader r2r) { foreach (var method in _dumper.NormalizedMethods()) { MethodInfo mi = new MethodInfo(); mi.Name = method.SignatureString; mi.HotRVA = (uint)method.RuntimeFunctions[0].StartAddress; + mi.HotLength = (uint)method.RuntimeFunctions[0].Size; mi.MethodToken = (uint)MetadataTokens.GetToken(method.ComponentReader.MetadataReader, method.MethodHandle); mi.AssemblyName = method.ComponentReader.MetadataReader.GetString(method.ComponentReader.MetadataReader.GetAssemblyDefinition().Name); mi.ColdRVA = 0; + mi.ColdLength = 0; yield return mi; } diff --git a/src/coreclr/tools/r2rdump/R2RDump.csproj b/src/coreclr/tools/r2rdump/R2RDump.csproj index f80b118cb64d1d..65c929eeb3648f 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.csproj +++ b/src/coreclr/tools/r2rdump/R2RDump.csproj @@ -21,6 +21,7 @@ $(SystemCommandLineVersion) + PreserveNewest diff --git a/src/coreclr/tools/r2rdump/R2RDump.sln b/src/coreclr/tools/r2rdump/R2RDump.sln index 0ba9942f9d0de6..316a22ddc720fe 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.sln +++ b/src/coreclr/tools/r2rdump/R2RDump.sln @@ -1,4 +1,3 @@ - Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 16 VisualStudioVersion = 16.0.29703.146 @@ -7,6 +6,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "R2RDump", "R2RDump.csproj", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Reflection.ReadyToRun", "..\aot\ILCompiler.Reflection.ReadyToRun\ILCompiler.Reflection.ReadyToRun.csproj", "{E2A577E5-7AF3-49B3-BA78-7071B75ED64B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILCompiler.Diagnostics", "..\aot\ILCompiler.Diagnostics\ILCompiler.Diagnostics.csproj", "{4E9512BA-F963-472A-B689-37D4D32456F3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -31,6 +32,14 @@ Global {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 + {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x64.ActiveCfg = Debug|Any CPU + {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x64.Build.0 = Debug|Any CPU + {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 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From ec2e67aad6d7b2fb8ec5fe5582fa6458b9c83c96 Mon Sep 17 00:00:00 2001 From: Tomas Date: Thu, 17 Dec 2020 01:36:19 +0100 Subject: [PATCH 2/9] Initial changes for PDB generation support in Crossgen2 --- .../CodeGen/ReadyToRunObjectWriter.cs | 47 +++++++++++++++++-- .../Compiler/ReadyToRunCodegenCompilation.cs | 28 ++++++++++- .../ReadyToRunCodegenCompilationBuilder.cs | 22 +++++++-- .../ILCompiler.ReadyToRun.csproj | 1 + src/coreclr/tools/aot/crossgen2.sln | 20 ++++++++ .../tools/aot/crossgen2/CommandLineOptions.cs | 4 ++ src/coreclr/tools/aot/crossgen2/Program.cs | 2 + .../aot/crossgen2/Properties/Resources.resx | 8 +++- 8 files changed, 123 insertions(+), 9 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index df25e03107896c..8c3b9e606312d5 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -53,15 +53,27 @@ internal class ReadyToRunObjectWriter /// Set to non-null when the executable generator should output a map file. /// private readonly MapFileBuilder _mapFileBuilder; + /// /// True when the map file builder should emit a textual map file /// private bool _generateMapFile; + /// /// True when the map file builder should emit a CSV formatted map file /// private bool _generateMapCsvFile; + /// + /// True when the map file builder should emit a PDB symbol file (only supported on Windows) + /// + private bool _generatePdbFile; + + /// + /// True when the map file builder should emit a PerfMap file + /// + private bool _generatePerfMapFile; + /// /// If non-zero, the PE file will be laid out such that it can naturally be mapped with a higher alignment than 4KB. /// This is used to support loading via large pages on Linux. @@ -87,7 +99,16 @@ public NodeInfo(ISymbolNode node, int nodeIndex, int symbolIndex) Dictionary _previouslyWrittenNodeNames = new Dictionary(); #endif - public ReadyToRunObjectWriter(string objectFilePath, EcmaModule componentModule, IEnumerable nodes, NodeFactory factory, bool generateMapFile, bool generateMapCsvFile, int customPESectionAlignment) + public ReadyToRunObjectWriter( + string objectFilePath, + EcmaModule componentModule, + IEnumerable nodes, + NodeFactory factory, + bool generateMapFile, + bool generateMapCsvFile, + bool generatePdbFile, + bool generatePerfMapFile, + int customPESectionAlignment) { _objectFilePath = objectFilePath; _componentModule = componentModule; @@ -96,6 +117,8 @@ public ReadyToRunObjectWriter(string objectFilePath, EcmaModule componentModule, _customPESectionAlignment = customPESectionAlignment; _generateMapFile = generateMapFile; _generateMapCsvFile = generateMapCsvFile; + _generatePdbFile = generatePdbFile; + _generatePerfMapFile = generatePerfMapFile; if (generateMapFile || generateMapCsvFile) { @@ -322,10 +345,28 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node r2rPeBuilder.AddObjectData(data, section, name, mapFileBuilder); } - public static void EmitObject(string objectFilePath, EcmaModule componentModule, IEnumerable nodes, NodeFactory factory, bool generateMapFile, bool generateMapCsvFile, int customPESectionAlignment) + public static void EmitObject( + string objectFilePath, + EcmaModule componentModule, + IEnumerable nodes, + NodeFactory factory, + bool generateMapFile, + bool generateMapCsvFile, + bool generatePdbFile, + bool generatePerfMapFile, + int customPESectionAlignment) { Console.WriteLine($@"Emitting R2R PE file: {objectFilePath}"); - ReadyToRunObjectWriter objectWriter = new ReadyToRunObjectWriter(objectFilePath, componentModule, nodes, factory, generateMapFile, generateMapCsvFile, customPESectionAlignment); + ReadyToRunObjectWriter objectWriter = new ReadyToRunObjectWriter( + objectFilePath, + componentModule, + nodes, + factory, + generateMapFile: generateMapFile, + generateMapCsvFile: generateMapCsvFile, + generatePdbFile: generatePdbFile, + generatePerfMapFile: generatePerfMapFile, + customPESectionAlignment); objectWriter.EmitPortableExecutable(); } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 79888b3e89a974..69e0738dbdaf59 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -231,6 +231,8 @@ public sealed class ReadyToRunCodegenCompilation : Compilation private bool _generateMapFile; private bool _generateMapCsvFile; + private bool _generatePdbFile; + private bool _generatePerfMapFile; private ProfileDataManager _profileData; private ReadyToRunFileLayoutOptimizer _fileLayoutOptimizer; @@ -257,6 +259,8 @@ internal ReadyToRunCodegenCompilation( bool resilient, bool generateMapFile, bool generateMapCsvFile, + bool generatePdbFile, + bool generatePerfMapFile, int parallelism, ProfileDataManager profileData, ReadyToRunMethodLayoutAlgorithm methodLayoutAlgorithm, @@ -277,6 +281,8 @@ internal ReadyToRunCodegenCompilation( _parallelism = parallelism; _generateMapFile = generateMapFile; _generateMapCsvFile = generateMapCsvFile; + _generatePdbFile = generatePdbFile; + _generatePerfMapFile = generatePerfMapFile; _customPESectionAlignment = customPESectionAlignment; SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory, verifyTypeAndFieldLayout); _corInfoImpls = new ConditionalWeakTable(); @@ -307,7 +313,16 @@ public override void Compile(string outputFile) using (PerfEventSource.StartStopEvents.EmittingEvents()) { NodeFactory.SetMarkingComplete(); - ReadyToRunObjectWriter.EmitObject(outputFile, componentModule: null, nodes, NodeFactory, _generateMapFile, _generateMapCsvFile, _customPESectionAlignment); + ReadyToRunObjectWriter.EmitObject( + outputFile, + componentModule: null, + nodes, + NodeFactory, + generateMapFile: _generateMapFile, + generateMapCsvFile: _generateMapCsvFile, + generatePdbFile: _generatePdbFile, + generatePerfMapFile: _generatePerfMapFile, + _customPESectionAlignment); CompilationModuleGroup moduleGroup = _nodeFactory.CompilationModuleGroup; if (moduleGroup.IsCompositeBuildMode) @@ -372,7 +387,16 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow } componentGraph.ComputeMarkedNodes(); componentFactory.Header.Add(Internal.Runtime.ReadyToRunSectionType.OwnerCompositeExecutable, ownerExecutableNode, ownerExecutableNode); - ReadyToRunObjectWriter.EmitObject(outputFile, componentModule: inputModule, componentGraph.MarkedNodeList, componentFactory, generateMapFile: false, generateMapCsvFile: false, customPESectionAlignment: 0); + ReadyToRunObjectWriter.EmitObject( + outputFile, + componentModule: inputModule, + componentGraph.MarkedNodeList, + componentFactory, + generateMapFile: false, + generateMapCsvFile: false, + generatePdbFile: false, + generatePerfMapFile: false, + customPESectionAlignment: 0); } public override void WriteDependencyLog(string outputFileName) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index 03ef31b3888e01..30b3889e2ef0b8 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -24,6 +24,8 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder private bool _resilient; private bool _generateMapFile; private bool _generateMapCsvFile; + private bool _generatePdbFile; + private bool _generatePerfMapFile; private int _parallelism; private InstructionSetSupport _instructionSetSupport; private ProfileDataManager _profileData; @@ -133,6 +135,18 @@ public ReadyToRunCodegenCompilationBuilder UseMapCsvFile(bool generateMapCsvFile return this; } + public ReadyToRunCodegenCompilationBuilder UsePdbFile(bool generatePdbFile) + { + _generatePdbFile = generatePdbFile; + return this; + } + + public ReadyToRunCodegenCompilationBuilder UsePerfMapFile(bool generatePerfMapFile) + { + _generatePerfMapFile = generatePerfMapFile; + return this; + } + public ReadyToRunCodegenCompilationBuilder UseParallelism(int parallelism) { _parallelism = parallelism; @@ -245,9 +259,11 @@ public override ICompilation ToCompilation() _inputFiles, _compositeRootPath, _instructionSetSupport, - _resilient, - _generateMapFile, - _generateMapCsvFile, + resilient: _resilient, + generateMapFile: _generateMapFile, + generateMapCsvFile: _generateMapCsvFile, + generatePdbFile: _generatePdbFile, + generatePerfMapFile: _generatePerfMapFile, _parallelism, _profileData, _r2rMethodLayoutAlgorithm, diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 0d8a93f397f630..9058459d10f0f7 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -19,6 +19,7 @@ + diff --git a/src/coreclr/tools/aot/crossgen2.sln b/src/coreclr/tools/aot/crossgen2.sln index e81eae9c024067..aa1a8362184dd7 100644 --- a/src/coreclr/tools/aot/crossgen2.sln +++ b/src/coreclr/tools/aot/crossgen2.sln @@ -12,6 +12,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.TypeSystem.Ready EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.TypeSystem.ReadyToRun.Tests", "ILCompiler.TypeSystem.ReadyToRun.Tests\ILCompiler.TypeSystem.ReadyToRun.Tests.csproj", "{1043373D-8C14-4224-9E2B-75F0DE645E7E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Diagnostics", "ILCompiler.Diagnostics\ILCompiler.Diagnostics.csproj", "{3EACD929-4725-4173-A845-734936BBDF87}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Checked|Any CPU = Checked|Any CPU @@ -103,6 +105,24 @@ Global {1043373D-8C14-4224-9E2B-75F0DE645E7E}.Release|x64.Build.0 = Release|x64 {1043373D-8C14-4224-9E2B-75F0DE645E7E}.Release|x86.ActiveCfg = Release|Any CPU {1043373D-8C14-4224-9E2B-75F0DE645E7E}.Release|x86.Build.0 = Release|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|Any CPU.ActiveCfg = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|Any CPU.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x64.ActiveCfg = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x64.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x86.ActiveCfg = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x86.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x64.ActiveCfg = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x64.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x86.ActiveCfg = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x86.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Release|Any CPU.Build.0 = Release|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Release|x64.ActiveCfg = Release|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Release|x64.Build.0 = Release|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Release|x86.ActiveCfg = Release|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs index ab4afd4b9e1302..2dee86279703cc 100644 --- a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs +++ b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs @@ -46,6 +46,8 @@ internal class CommandLineOptions public bool Resilient; public bool Map; public bool MapCsv; + public bool Pdb; + public bool PerfMap; public int Parallelism; public int CustomPESectionAlignment; public string MethodLayout; @@ -117,6 +119,8 @@ public CommandLineOptions(string[] args) syntax.DefineOption("custom-pe-section-alignment", ref CustomPESectionAlignment, SR.CustomPESectionAlignmentOption); syntax.DefineOption("map", ref Map, SR.MapFileOption); syntax.DefineOption("mapcsv", ref MapCsv, SR.MapCsvFileOption); + syntax.DefineOption("pdb", ref Pdb, SR.PdbFileOption); + syntax.DefineOption("perfmap", ref PerfMap, SR.PerfMapFileOption); 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 e20b25be991282..cee6b0f3b945fe 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -582,6 +582,8 @@ private int Run(string[] args) .UseResilience(_commandLineOptions.Resilient) .UseMapFile(_commandLineOptions.Map) .UseMapCsvFile(_commandLineOptions.MapCsv) + .UsePdbFile(_commandLineOptions.Pdb) + .UsePerfMapFile(_commandLineOptions.PerfMap) .UseParallelism(_commandLineOptions.Parallelism) .UseProfileData(profileDataManager) .FileLayoutAlgorithms(_methodLayout, _fileLayout) diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx index d677fe8d7711e9..cd0bfa75684c52 100644 --- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx +++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx @@ -309,4 +309,10 @@ Warning: -Od overrides other optimization options - \ No newline at end of file + + Generate PDB symbol information file (supported on Windows only) + + + Generate PerfMap symbol information file for use by PerfInfo + + From 20448fc8f4cfbc4c873e8c79242de50372efc4d1 Mon Sep 17 00:00:00 2001 From: Tomas Date: Mon, 11 Jan 2021 17:30:19 +0100 Subject: [PATCH 3/9] Crossgen2 implementation of PDB / Perfmap generator --- src/coreclr/crossgen-corelib.proj | 31 +++---- .../CodeGen/ReadyToRunObjectWriter.cs | 47 +++++++++- .../Compiler/ReadyToRunCodegenCompilation.cs | 10 +++ .../ReadyToRunCodegenCompilationBuilder.cs | 10 ++- .../ObjectWriter/MapFileBuilder.cs | 87 ++++++++++++++++++- .../ObjectWriter/SectionBuilder.cs | 2 +- .../tools/aot/crossgen2/CommandLineOptions.cs | 4 + src/coreclr/tools/aot/crossgen2/Program.cs | 4 +- .../aot/crossgen2/Properties/Resources.resx | 6 ++ 9 files changed, 175 insertions(+), 26 deletions(-) diff --git a/src/coreclr/crossgen-corelib.proj b/src/coreclr/crossgen-corelib.proj index fadc1f514c872f..faebc8d650918e 100644 --- a/src/coreclr/crossgen-corelib.proj +++ b/src/coreclr/crossgen-corelib.proj @@ -8,7 +8,7 @@ AfterTargets="Build"> - false + true $(TargetOS).$(TargetArchitecture).$(Configuration) $([MSBuild]::NormalizeDirectory('$(RepoRoot)', 'artifacts')) @@ -65,27 +65,22 @@ $(CrossGenDllCmd) $(CoreLibInputPath) + + $(CrossGenDllCmd) --pdb --pdb-path:$([MSBuild]::NormalizePath('$(BinDir)', 'PDB')) + + + + $(CrossGenDllCmd) --perf-map --perf-map-path:$(BinDir) + + + call $([MSBuild]::NormalizePath('$(RepoRoot)', 'src', 'coreclr', 'setup_vs_tools.cmd')) && + $(CrossGen1Cmd) /out "$(CoreLibOutputPath)" $(CrossGenDllCmd) "$(CoreLibInputPath)" - - - - $(CrossGen1Cmd) /CreatePerfMap "$(BinDir)" $(CrossGenPerfMapCmd) "$(CoreLibOutputPath)" - - - - $(DotNetCli) $([MSBuild]::NormalizePath('$(BinDir)', 'r2rdump', 'r2rdump.dll')) - $(CrossGenPdbCmd) --create-pdb - $(CrossGenPdbCmd) --pdb-path:$([MSBuild]::NormalizePath('$(BinDir)', 'PDB')) - $(CrossGenPdbCmd) --in:$(CoreLibOutputPath) - - - - call $([MSBuild]::NormalizePath('$(RepoRoot)', 'src', 'coreclr', 'setup_vs_tools.cmd')) && $(VsSetupCmd) $(CrossGen1Cmd) /CreatePdb "$([MSBuild]::NormalizePath('$(BinDir)', 'PDB'))" $(CrossGenPdbCmd) "$(CoreLibOutputPath)" @@ -97,11 +92,11 @@ - + - + diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index 8c3b9e606312d5..24258db6c3ba2f 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -11,6 +11,7 @@ using ILCompiler.DependencyAnalysis.ReadyToRun; using ILCompiler.DependencyAnalysisFramework; +using ILCompiler.Diagnostics; using ILCompiler.PEWriter; using ObjectData = ILCompiler.DependencyAnalysis.ObjectNode.ObjectData; @@ -69,18 +70,27 @@ internal class ReadyToRunObjectWriter /// private bool _generatePdbFile; + /// + /// Explicit specification of the output PDB path + /// + private string _pdbPath; + /// /// True when the map file builder should emit a PerfMap file /// private bool _generatePerfMapFile; + /// + /// Explicit specification of the output PerfMap path + /// + private string _perfMapPath; + /// /// If non-zero, the PE file will be laid out such that it can naturally be mapped with a higher alignment than 4KB. /// This is used to support loading via large pages on Linux. /// private readonly int _customPESectionAlignment; - #if DEBUG private struct NodeInfo { @@ -107,7 +117,9 @@ public ReadyToRunObjectWriter( bool generateMapFile, bool generateMapCsvFile, bool generatePdbFile, + string pdbPath, bool generatePerfMapFile, + string perfMapPath, int customPESectionAlignment) { _objectFilePath = objectFilePath; @@ -118,9 +130,11 @@ public ReadyToRunObjectWriter( _generateMapFile = generateMapFile; _generateMapCsvFile = generateMapCsvFile; _generatePdbFile = generatePdbFile; + _pdbPath = pdbPath; _generatePerfMapFile = generatePerfMapFile; + _perfMapPath = perfMapPath; - if (generateMapFile || generateMapCsvFile) + if (generateMapFile || generateMapCsvFile || generatePdbFile || generatePerfMapFile) { _mapFileBuilder = new MapFileBuilder(); } @@ -232,6 +246,11 @@ public void EmitPortableExecutable() EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section, _mapFileBuilder); lastWrittenObjectNode = node; + + if ((_generatePdbFile || _generatePerfMapFile) && node is MethodWithGCInfo methodNode) + { + _mapFileBuilder.AddMethod(methodNode, nodeContents.DefinedSymbols[0]); + } } r2rPeBuilder.SetCorHeader(_nodeFactory.CopiedCorHeaderNode, _nodeFactory.CopiedCorHeaderNode.Size); @@ -286,6 +305,26 @@ public void EmitPortableExecutable() string mapCsvFileName = Path.ChangeExtension(_objectFilePath, ".map.csv"); _mapFileBuilder.SaveCsv(nodeStatsCsvFileName, mapCsvFileName); } + + if (_generatePdbFile) + { + string path = _pdbPath; + if (string.IsNullOrEmpty(path)) + { + path = Path.GetDirectoryName(_objectFilePath); + } + _mapFileBuilder.SavePdb(path, _objectFilePath); + } + + if (_generatePerfMapFile) + { + string path = _perfMapPath; + if (string.IsNullOrEmpty(path)) + { + path = Path.ChangeExtension(_objectFilePath, ".perf.map"); + } + _mapFileBuilder.SavePerfMap(path); + } } succeeded = true; @@ -353,7 +392,9 @@ public static void EmitObject( bool generateMapFile, bool generateMapCsvFile, bool generatePdbFile, + string pdbPath, bool generatePerfMapFile, + string perfMapPath, int customPESectionAlignment) { Console.WriteLine($@"Emitting R2R PE file: {objectFilePath}"); @@ -365,7 +406,9 @@ public static void EmitObject( generateMapFile: generateMapFile, generateMapCsvFile: generateMapCsvFile, generatePdbFile: generatePdbFile, + pdbPath: pdbPath, generatePerfMapFile: generatePerfMapFile, + perfMapPath: perfMapPath, customPESectionAlignment); objectWriter.EmitPortableExecutable(); } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index 69e0738dbdaf59..a147fa3e45d727 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -232,7 +232,9 @@ public sealed class ReadyToRunCodegenCompilation : Compilation private bool _generateMapFile; private bool _generateMapCsvFile; private bool _generatePdbFile; + private string _pdbPath; private bool _generatePerfMapFile; + private string _perfMapPath; private ProfileDataManager _profileData; private ReadyToRunFileLayoutOptimizer _fileLayoutOptimizer; @@ -260,7 +262,9 @@ internal ReadyToRunCodegenCompilation( bool generateMapFile, bool generateMapCsvFile, bool generatePdbFile, + string pdbPath, bool generatePerfMapFile, + string perfMapPath, int parallelism, ProfileDataManager profileData, ReadyToRunMethodLayoutAlgorithm methodLayoutAlgorithm, @@ -282,7 +286,9 @@ internal ReadyToRunCodegenCompilation( _generateMapFile = generateMapFile; _generateMapCsvFile = generateMapCsvFile; _generatePdbFile = generatePdbFile; + _pdbPath = pdbPath; _generatePerfMapFile = generatePerfMapFile; + _perfMapPath = perfMapPath; _customPESectionAlignment = customPESectionAlignment; SymbolNodeFactory = new ReadyToRunSymbolNodeFactory(nodeFactory, verifyTypeAndFieldLayout); _corInfoImpls = new ConditionalWeakTable(); @@ -321,7 +327,9 @@ public override void Compile(string outputFile) generateMapFile: _generateMapFile, generateMapCsvFile: _generateMapCsvFile, generatePdbFile: _generatePdbFile, + pdbPath: _pdbPath, generatePerfMapFile: _generatePerfMapFile, + perfMapPath: _perfMapPath, _customPESectionAlignment); CompilationModuleGroup moduleGroup = _nodeFactory.CompilationModuleGroup; @@ -395,7 +403,9 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow generateMapFile: false, generateMapCsvFile: false, generatePdbFile: false, + pdbPath: _pdbPath, generatePerfMapFile: false, + perfMapPath: _perfMapPath, 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 30b3889e2ef0b8..acdd53e86a31bf 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -25,7 +25,9 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder private bool _generateMapFile; private bool _generateMapCsvFile; private bool _generatePdbFile; + private string _pdbPath; private bool _generatePerfMapFile; + private string _perfMapPath; private int _parallelism; private InstructionSetSupport _instructionSetSupport; private ProfileDataManager _profileData; @@ -135,15 +137,17 @@ public ReadyToRunCodegenCompilationBuilder UseMapCsvFile(bool generateMapCsvFile return this; } - public ReadyToRunCodegenCompilationBuilder UsePdbFile(bool generatePdbFile) + public ReadyToRunCodegenCompilationBuilder UsePdbFile(bool generatePdbFile, string pdbPath) { _generatePdbFile = generatePdbFile; + _pdbPath = pdbPath; return this; } - public ReadyToRunCodegenCompilationBuilder UsePerfMapFile(bool generatePerfMapFile) + public ReadyToRunCodegenCompilationBuilder UsePerfMapFile(bool generatePerfMapFile, string perfMapPath) { _generatePerfMapFile = generatePerfMapFile; + _perfMapPath = perfMapPath; return this; } @@ -263,7 +267,9 @@ public override ICompilation ToCompilation() generateMapFile: _generateMapFile, generateMapCsvFile: _generateMapCsvFile, generatePdbFile: _generatePdbFile, + pdbPath: _pdbPath, generatePerfMapFile: _generatePerfMapFile, + perfMapPath: _perfMapPath, _parallelism, _profileData, _r2rMethodLayoutAlgorithm, diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs index eb2b9e2a842d02..4f83fd4e457bf6 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs @@ -8,7 +8,16 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; +using System.Reflection.Metadata.Ecma335; +using System.Text; + +using Internal.JitInterface; +using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; + using ILCompiler.DependencyAnalysis; +using ILCompiler.DependencyAnalysis.ReadyToRun; +using ILCompiler.Diagnostics; namespace ILCompiler.PEWriter { @@ -130,6 +139,9 @@ public void AddNode(MapFileNode node) private readonly List _symbols; private readonly List
_sections; + private readonly Dictionary _nodeSymbolMap; + private readonly Dictionary _methodSymbolMap; + private readonly Dictionary _relocCounts; private long _fileSize; @@ -140,12 +152,16 @@ public MapFileBuilder() _symbols = new List(); _sections = new List
(); + _nodeSymbolMap = new Dictionary(); + _methodSymbolMap = new Dictionary(); + _relocCounts = new Dictionary(); } - public void AddNode(MapFileNode node) + public void AddNode(MapFileNode node, ISymbolDefinitionNode symbol) { _nodes.Add(node); + _nodeSymbolMap.Add(symbol, node); } public void AddRelocation(MapFileNode node, RelocType relocType) @@ -165,6 +181,11 @@ public void AddSection(Section section) _sections.Add(section); } + public void AddMethod(MethodWithGCInfo method, ISymbolDefinitionNode symbol) + { + _methodSymbolMap.Add(symbol, method); + } + public void SetFileSize(long fileSize) { _fileSize = fileSize; @@ -205,6 +226,20 @@ public void SaveCsv(string nodeStatsCsvFileName, string mapCsvFileName) } } + public void SavePdb(string pdbPath, string dllFileName) + { + Console.WriteLine("Emitting PDB file: {0}", pdbPath); + + new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, EnumerateMethods()); + } + + public void SavePerfMap(string perfMapFileName) + { + Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); + + PerfMapWriter.Write(perfMapFileName, EnumerateMethods()); + } + private void WriteHeader(StreamWriter writer) { WriteTitle(writer, "Summary Info"); @@ -411,5 +446,55 @@ private void WriteTitle(StreamWriter writer, string title) writer.WriteLine(title); writer.WriteLine(new string('-', title.Length)); } + + private IEnumerable EnumerateMethods() + { + DebugNameFormatter nameFormatter = new DebugNameFormatter(); + TypeNameFormatter typeNameFormatter = new TypeString(); + HashSet emittedMethods = new HashSet(); + foreach (KeyValuePair symbolMethodPair in _methodSymbolMap) + { + EcmaMethod ecmaMethod = symbolMethodPair.Value.Method.GetTypicalMethodDefinition() as EcmaMethod; + if (ecmaMethod != null && emittedMethods.Add(ecmaMethod)) + { + MethodInfo methodInfo = new MethodInfo(); + methodInfo.MethodToken = (uint)MetadataTokens.GetToken(ecmaMethod.Handle); + methodInfo.AssemblyName = ecmaMethod.Module.Assembly.GetName().Name; + methodInfo.Name = FormatMethodName(symbolMethodPair.Value.Method, typeNameFormatter); + MapFileNode node = _nodeSymbolMap[symbolMethodPair.Key]; + Section section = _sections[node.SectionIndex]; + methodInfo.HotRVA = (uint)(section.RVAWhenPlaced + node.Offset); + methodInfo.HotLength = (uint)node.Length; + methodInfo.ColdRVA = 0; + methodInfo.ColdLength = 0; + yield return methodInfo; + } + } + } + + private string FormatMethodName(MethodDesc method, TypeNameFormatter typeNameFormatter) + { + StringBuilder output = new StringBuilder(); + if (!method.Signature.ReturnType.IsVoid) + { + output.Append(typeNameFormatter.FormatName(method.Signature.ReturnType)); + output.Append(" "); + } + output.Append(typeNameFormatter.FormatName(method.OwningType)); + output.Append("::"); + output.Append(method.Name); + output.Append("("); + for (int paramIndex = 0; paramIndex < method.Signature.Length; paramIndex++) + { + if (paramIndex != 0) + { + output.Append(", "); + } + output.Append(typeNameFormatter.FormatName(method.Signature[paramIndex])); + } + output.Append(")"); + return output.ToString(); + } } } +; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs index 6ba8e55636831f..77354483762199 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs @@ -478,7 +478,7 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st if (mapFileBuilder != null) { MapFileNode node = new MapFileNode(sectionIndex, alignedOffset, objectData.Data.Length, name); - mapFileBuilder.AddNode(node); + mapFileBuilder.AddNode(node, objectData.DefinedSymbols[0]); if (objectData.Relocs != null) { foreach (Relocation reloc in objectData.Relocs) diff --git a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs index 2dee86279703cc..910743f709b159 100644 --- a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs +++ b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs @@ -47,7 +47,9 @@ internal class CommandLineOptions public bool Map; public bool MapCsv; public bool Pdb; + public string PdbPath; public bool PerfMap; + public string PerfMapPath; public int Parallelism; public int CustomPESectionAlignment; public string MethodLayout; @@ -120,7 +122,9 @@ public CommandLineOptions(string[] args) syntax.DefineOption("map", ref Map, SR.MapFileOption); syntax.DefineOption("mapcsv", ref MapCsv, SR.MapCsvFileOption); syntax.DefineOption("pdb", ref Pdb, SR.PdbFileOption); + 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("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 cee6b0f3b945fe..35dbcecfe593cf 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -582,8 +582,8 @@ private int Run(string[] args) .UseResilience(_commandLineOptions.Resilient) .UseMapFile(_commandLineOptions.Map) .UseMapCsvFile(_commandLineOptions.MapCsv) - .UsePdbFile(_commandLineOptions.Pdb) - .UsePerfMapFile(_commandLineOptions.PerfMap) + .UsePdbFile(_commandLineOptions.Pdb, _commandLineOptions.PdbPath) + .UsePerfMapFile(_commandLineOptions.PerfMap, _commandLineOptions.PerfMapPath) .UseParallelism(_commandLineOptions.Parallelism) .UseProfileData(profileDataManager) .FileLayoutAlgorithms(_methodLayout, _fileLayout) diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx index cd0bfa75684c52..6b3e6bec1265c6 100644 --- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx +++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx @@ -315,4 +315,10 @@ Generate PerfMap symbol information file for use by PerfInfo + + Explicit specification of the output PDB file path + + + Explicit specification of the PerfMap file path + From a77ab4ca6f26dde56b7f045fedf7c35d7704cb23 Mon Sep 17 00:00:00 2001 From: Tomas Date: Fri, 15 Jan 2021 00:50:25 +0100 Subject: [PATCH 4/9] R2RTest / test build support for PDB production --- .../aot/ILCompiler.Diagnostics/PdbWriter.cs | 19 +++++++---- .../ObjectWriter/MapFileBuilder.cs | 2 +- src/coreclr/tools/r2rtest/BuildOptions.cs | 1 + .../tools/r2rtest/CommandLineOptions.cs | 17 ++++++++-- src/coreclr/tools/r2rtest/Crossgen2Runner.cs | 6 ++++ src/tests/Common/CLRTest.CrossGen.targets | 33 ++++++++++--------- src/tests/build.cmd | 13 +++++++- 7 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs index 68386c8d1a4760..620fb783441830 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs @@ -190,26 +190,33 @@ private void WritePDBDataHelper(string dllPath, IEnumerable methods) throw new NotImplementedException(); } + string dllNameWithoutExtension = Path.GetFileNameWithoutExtension(dllPath); + _pdbFilePath = Path.Combine(_pdbPath, dllNameWithoutExtension + ".pdb"); + string originalDllPath = dllPath; // Currently DiaSymReader does not work properly generating NGEN PDBS unless // the DLL whose PDB is being generated ends in .ni.*. Unfortunately, readyToRun // images do not follow this convention and end up producing bad PDBS. To fix // this (without changing diasymreader.dll which ships indepdendently of .NET Core) - // we copy the file to somethign with this convention before generating the PDB + // we copy the file to something with this convention before generating the PDB // and delete it when we are done. if (!dllPath.EndsWith(".ni.dll", StringComparison.OrdinalIgnoreCase) && !dllPath.EndsWith(".ni.exe", StringComparison.OrdinalIgnoreCase)) { - _tempSourceDllName = Path.Combine(Path.GetDirectoryName(dllPath), Path.GetFileNameWithoutExtension(dllPath) + ".ni" + Path.GetExtension(dllPath)); - File.Copy(dllPath, _tempSourceDllName); + _tempSourceDllName = Path.Combine(Path.GetDirectoryName(dllPath), dllNameWithoutExtension + ".ni" + Path.GetExtension(dllPath)); + File.Copy(dllPath, _tempSourceDllName, overwrite: true); dllPath = _tempSourceDllName; + _pdbFilePath = Path.Combine(_pdbPath, dllNameWithoutExtension + ".ni.pdb"); } - _ngenWriter = CreateNGenWriter(dllPath, _pdbPath + "\\"); + // Delete any preexisting PDB file upfront otherwise CreateNGenWriter silently opens it + File.Delete(_pdbFilePath); + + _ngenWriter = CreateNGenWriter(dllPath, _pdbFilePath); { - // PDB file is now created. Get its path and initialize _pdbFilePath so the PDB file - // can be deleted if we don't make it successfully to the end + // PDB file is now created. Get its path and update _pdbFilePath so the PDB file + // can be deleted if we don't make it successfully to the end. StringBuilder pdbFilePathBuilder = new StringBuilder(); pdbFilePathBuilder.Capacity = 1024; _ngenWriter.QueryPDBNameExW(pdbFilePathBuilder, new IntPtr(pdbFilePathBuilder.Capacity)); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs index 4f83fd4e457bf6..c7b42ffcbfb043 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs @@ -228,7 +228,7 @@ public void SaveCsv(string nodeStatsCsvFileName, string mapCsvFileName) public void SavePdb(string pdbPath, string dllFileName) { - Console.WriteLine("Emitting PDB file: {0}", pdbPath); + Console.WriteLine("Emitting PDB file: {0}", Path.Combine(pdbPath, Path.GetFileNameWithoutExtension(dllFileName) + ".ni.pdb")); new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, EnumerateMethods()); } diff --git a/src/coreclr/tools/r2rtest/BuildOptions.cs b/src/coreclr/tools/r2rtest/BuildOptions.cs index ed72c5c194ab5e..e2e57ca9a42aef 100644 --- a/src/coreclr/tools/r2rtest/BuildOptions.cs +++ b/src/coreclr/tools/r2rtest/BuildOptions.cs @@ -25,6 +25,7 @@ public class BuildOptions public bool NoEtw { get; set; } public bool NoCleanup { get; set; } public bool Map { get; set; } + public bool Pdb { get; set; } public FileInfo PackageList { get; set; } public int DegreeOfParallelism { get; set; } public bool Sequential { get; set; } diff --git a/src/coreclr/tools/r2rtest/CommandLineOptions.cs b/src/coreclr/tools/r2rtest/CommandLineOptions.cs index b778264be5d7f8..86da62ae81bd11 100644 --- a/src/coreclr/tools/r2rtest/CommandLineOptions.cs +++ b/src/coreclr/tools/r2rtest/CommandLineOptions.cs @@ -53,6 +53,7 @@ Command CompileFolder() => NoEtw(), NoCleanup(), Map(), + Pdb(), DegreeOfParallelism(), Sequential(), Framework(), @@ -90,6 +91,7 @@ Command CompileSubtree() => NoEtw(), NoCleanup(), Map(), + Pdb(), DegreeOfParallelism(), Sequential(), Framework(), @@ -119,6 +121,8 @@ Command CompileFramework() => VerifyTypeAndFieldLayout(), NoCrossgen2(), NoCleanup(), + Map(), + Pdb(), Crossgen2Parallelism(), Crossgen2JitPath(), DegreeOfParallelism(), @@ -146,6 +150,8 @@ Command CompileNugetPackages() => PackageList(), Crossgen(), NoCleanup(), + Map(), + Pdb(), DegreeOfParallelism(), CompilationTimeoutMinutes(), ExecutionTimeoutMinutes(), @@ -159,9 +165,11 @@ Command CompileSerp() => InputDirectory(), DegreeOfParallelism(), AspNetPath(), - CompositeScenario() + CompositeScenario(), + Map(), + Pdb(), }, - options => + options => { var compileSerp = new CompileSerpCommand(options); return compileSerp.CompileSerpAssemblies(); @@ -183,7 +191,7 @@ Option CoreRootDirectory() => Option ReferencePath() => new Option(new[] { "--reference-path", "-r" }, "Folder containing assemblies to reference during compilation") - { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly() }; + { Argument = new Argument() { Arity = ArgumentArity.ZeroOrMore }.ExistingOnly() }; Option Crossgen() => new Option(new[] { "--crossgen" }, "Compile the apps using Crossgen in the CORE_ROOT folder"); @@ -218,6 +226,9 @@ Option NoCleanup() => Option Map() => new Option(new[] { "--map" }, "Generate a map file (Crossgen2)"); + Option Pdb() => + new Option(new[] { "--pdb" }, "Generate PDB symbol information (Crossgen2 / Windows only)"); + Option DegreeOfParallelism() => new Option(new[] { "--degree-of-parallelism", "-dop" }, "Override default compilation / execution DOP (default = logical processor count)"); diff --git a/src/coreclr/tools/r2rtest/Crossgen2Runner.cs b/src/coreclr/tools/r2rtest/Crossgen2Runner.cs index 857f62364cccbe..19d13dc2fc6073 100644 --- a/src/coreclr/tools/r2rtest/Crossgen2Runner.cs +++ b/src/coreclr/tools/r2rtest/Crossgen2Runner.cs @@ -86,6 +86,12 @@ protected override IEnumerable BuildCommandLineArguments(IEnumerable$(BashScriptSnippetGen);GetCrossgenBashScript $(BatchScriptSnippetGen);GetCrossgenBatchScript - + + false + Debug;Release;Checked From ff156847b6111f4fe4110d9d08a4f461e755c601 Mon Sep 17 00:00:00 2001 From: Tomas Date: Fri, 15 Jan 2021 23:39:00 +0100 Subject: [PATCH 8/9] Addressing Simon's PR feedback, msbuild project fixes for x86 Based on Simon's suggestion I moved the PDB / PerfMap-specific code to a new file SymbolFileBuilder as I concur that its squatting in the MapFileBuilder was somewhat hacky. Both classes use a new helper class ObjectInfoBuilder that collects the information common to both - I was reluctant to make it a base class of the *FileBuilder's as we'd have to collect all the elements twice. Thanks Tomas --- .../ILCompiler.Diagnostics.csproj | 6 +- .../CodeGen/ReadyToRunObjectWriter.cs | 46 +++- .../ILCompiler.ReadyToRun.csproj | 4 +- .../ObjectWriter/MapFileBuilder.cs | 259 +++--------------- .../ObjectWriter/ObjectInfoBuilder.cs | 230 ++++++++++++++++ .../ObjectWriter/R2RPEBuilder.cs | 12 +- .../ObjectWriter/SectionBuilder.cs | 20 +- .../ObjectWriter/SymbolFileBuilder.cs | 39 +++ src/coreclr/tools/aot/crossgen2.sln | 11 +- src/coreclr/tools/r2rdump/R2RDump.sln | 14 +- 10 files changed, 374 insertions(+), 267 deletions(-) create mode 100644 src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/ObjectInfoBuilder.cs create mode 100644 src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj index 5f270b3e8951fc..8c9419db564aa9 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/ILCompiler.Diagnostics.csproj @@ -1,12 +1,12 @@ - Library ILCompiler.Diagnostics + Library + true $(NetCoreAppToolCurrent) READYTORUN;$(DefineConstants) - false - x64;x86 + x64;x86;arm;arm64 AnyCPU false diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index bab76a267f4a24..e822d20c6f75d4 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -50,11 +50,21 @@ internal class ReadyToRunObjectWriter /// private readonly IEnumerable _nodes; + /// + /// Set to non-null when the executable generator should output a map or symbol file. + /// + private readonly ObjectInfoBuilder _objectInfoBuilder; + /// /// Set to non-null when the executable generator should output a map file. /// private readonly MapFileBuilder _mapFileBuilder; + /// + /// Set to non-null when generating symbol info (PDB / PerfMap). + /// + private readonly SymbolFileBuilder _symbolFileBuilder; + /// /// True when the map file builder should emit a textual map file /// @@ -133,10 +143,23 @@ public ReadyToRunObjectWriter( _pdbPath = pdbPath; _generatePerfMapFile = generatePerfMapFile; _perfMapPath = perfMapPath; - - if (generateMapFile || generateMapCsvFile || generatePdbFile || generatePerfMapFile) + + bool generateMap = (generateMapFile || generateMapCsvFile); + bool generateSymbols = (generatePdbFile || generatePerfMapFile); + + if (generateMap || generateSymbols) { - _mapFileBuilder = new MapFileBuilder(); + _objectInfoBuilder = new ObjectInfoBuilder(); + + if (generateMap) + { + _mapFileBuilder = new MapFileBuilder(_objectInfoBuilder); + } + + if (generateSymbols) + { + _symbolFileBuilder = new SymbolFileBuilder(_objectInfoBuilder); + } } } @@ -244,12 +267,12 @@ public void EmitPortableExecutable() } } - EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section, _mapFileBuilder); + EmitObjectData(r2rPeBuilder, nodeContents, nodeIndex, name, node.Section); lastWrittenObjectNode = node; if ((_generatePdbFile || _generatePerfMapFile) && node is MethodWithGCInfo methodNode) { - _mapFileBuilder.AddMethod(methodNode, nodeContents.DefinedSymbols[0]); + _objectInfoBuilder.AddMethod(methodNode, nodeContents.DefinedSymbols[0]); } } @@ -289,9 +312,9 @@ public void EmitPortableExecutable() } } - if (_mapFileBuilder != null) + if (_objectInfoBuilder != null) { - r2rPeBuilder.AddSections(_mapFileBuilder); + r2rPeBuilder.AddSections(_objectInfoBuilder); if (_generateMapFile) { @@ -313,7 +336,7 @@ public void EmitPortableExecutable() { path = Path.GetDirectoryName(_objectFilePath); } - _mapFileBuilder.SavePdb(path, _objectFilePath); + _symbolFileBuilder.SavePdb(path, _objectFilePath); } if (_generatePerfMapFile) @@ -323,7 +346,7 @@ public void EmitPortableExecutable() { path = Path.GetDirectoryName(_objectFilePath); } - _mapFileBuilder.SavePerfMap(path, _objectFilePath); + _symbolFileBuilder.SavePerfMap(path, _objectFilePath); } } @@ -361,8 +384,7 @@ public void EmitPortableExecutable() /// Logical index of the emitted node for diagnostic purposes /// Textual representation of the ObjecData blob in the map file /// Section to emit the blob into - /// Map file output stream - private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int nodeIndex, string name, ObjectNodeSection section, MapFileBuilder mapFileBuilder) + private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int nodeIndex, string name, ObjectNodeSection section) { #if DEBUG for (int symbolIndex = 0; symbolIndex < data.DefinedSymbols.Length; symbolIndex++) @@ -381,7 +403,7 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node } #endif - r2rPeBuilder.AddObjectData(data, section, name, mapFileBuilder); + r2rPeBuilder.AddObjectData(data, section, name, _objectInfoBuilder); } public static void EmitObject( diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 9058459d10f0f7..9aad5df0044091 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -6,7 +6,7 @@ true READYTORUN;$(DefineConstants) false - x64;x86 + x64;x86;arm;arm64 AnyCPU false @@ -196,6 +196,8 @@ + + diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs index 21d33cbbe2f3c9..8289896c3162c7 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs @@ -21,87 +21,6 @@ namespace ILCompiler.PEWriter { - /// - /// Base class for symbols and nodes in the map file implements common logic - /// for section / offset ordering. - /// - public class MapFileItem - { - public class Comparer : IComparer - { - public readonly static Comparer Instance = new Comparer(); - - public int Compare([AllowNull] MapFileItem x, [AllowNull] MapFileItem y) - { - return (x.SectionIndex != y.SectionIndex ? x.SectionIndex.CompareTo(y.SectionIndex) : x.Offset.CompareTo(y.Offset)); - } - } - - /// - /// Item section index - /// - public readonly int SectionIndex; - - /// - /// Offset relative to section beginning - /// - public readonly int Offset; - - /// - /// Item name - /// - public readonly string Name; - - public MapFileItem(int sectionIndex, int offset, string name) - { - SectionIndex = sectionIndex; - Offset = offset; - Name = name; - } - } - - /// - /// This class represents a single node (contiguous block of data) in the output R2R PE file. - /// - public class MapFileNode : MapFileItem - { - /// - /// Node length (number of bytes). This doesn't include any external alignment - /// applied when concatenating the nodes to form sections. - /// - public readonly int Length; - - /// - /// Number of file-level relocations (.reloc section entries) used by the node. - /// - public int Relocations { get; private set; } - - public MapFileNode(int sectionIndex, int offset, int length, string name) - : base(sectionIndex, offset, name) - { - Length = length; - Relocations = 0; - } - - public void AddRelocation() - { - Relocations++; - } - } - - /// - /// Symbol is a "pointer" into the PE file. Most (but not all) symbols correspond to - /// node beginnings (most nodes have a "start symbol" representing the beginning - /// of the node). - /// - public class MapFileSymbol : MapFileItem - { - public MapFileSymbol(int sectionIndex, int offset, string name) - : base(sectionIndex, offset, name) - { - } - } - /// /// Helper class used to collect information to be output into the map file. /// @@ -127,7 +46,7 @@ public NodeTypeStatistics(string name) Name = name; } - public void AddNode(MapFileNode node) + public void AddNode(ObjectNode node) { Debug.Assert(Name == node.Name); Count++; @@ -135,55 +54,13 @@ public void AddNode(MapFileNode node) } } - private readonly List _nodes; - private readonly List _symbols; - private readonly List
_sections; - - private readonly Dictionary _nodeSymbolMap; - private readonly Dictionary _methodSymbolMap; - - private readonly Dictionary _relocCounts; + private ObjectInfoBuilder _objectInfoBuilder; private long _fileSize; - public MapFileBuilder() - { - _nodes = new List(); - _symbols = new List(); - _sections = new List
(); - - _nodeSymbolMap = new Dictionary(); - _methodSymbolMap = new Dictionary(); - - _relocCounts = new Dictionary(); - } - - public void AddNode(MapFileNode node, ISymbolDefinitionNode symbol) - { - _nodes.Add(node); - _nodeSymbolMap.Add(symbol, node); - } - - public void AddRelocation(MapFileNode node, RelocType relocType) + public MapFileBuilder(ObjectInfoBuilder objectInfoBuilder) { - node.AddRelocation(); - _relocCounts.TryGetValue(relocType, out int relocTypeCount); - _relocCounts[relocType] = relocTypeCount + 1; - } - - public void AddSymbol(MapFileSymbol symbol) - { - _symbols.Add(symbol); - } - - public void AddSection(Section section) - { - _sections.Add(section); - } - - public void AddMethod(MethodWithGCInfo method, ISymbolDefinitionNode symbol) - { - _methodSymbolMap.Add(symbol, method); + _objectInfoBuilder = objectInfoBuilder; } public void SetFileSize(long fileSize) @@ -195,8 +72,7 @@ public void SaveMap(string mapFileName) { Console.WriteLine("Emitting map file: {0}", mapFileName); - _nodes.Sort(MapFileItem.Comparer.Instance); - _symbols.Sort(MapFileItem.Comparer.Instance); + _objectInfoBuilder.Sort(); using (StreamWriter mapWriter = new StreamWriter(mapFileName)) { @@ -212,8 +88,7 @@ public void SaveCsv(string nodeStatsCsvFileName, string mapCsvFileName) { Console.WriteLine("Emitting csv files: {0}, {1}", nodeStatsCsvFileName, mapCsvFileName); - _nodes.Sort(MapFileItem.Comparer.Instance); - _symbols.Sort(MapFileItem.Comparer.Instance); + _objectInfoBuilder.Sort(); using (StreamWriter nodeStatsWriter = new StreamWriter(nodeStatsCsvFileName)) { @@ -226,37 +101,22 @@ public void SaveCsv(string nodeStatsCsvFileName, string mapCsvFileName) } } - public void SavePdb(string pdbPath, string dllFileName) - { - Console.WriteLine("Emitting PDB file: {0}", Path.Combine(pdbPath, Path.GetFileNameWithoutExtension(dllFileName) + ".ni.pdb")); - - new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, EnumerateMethods()); - } - - public void SavePerfMap(string perfMapPath, string dllFileName) - { - string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + ".perf.map"); - Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); - - PerfMapWriter.Write(perfMapFileName, EnumerateMethods()); - } - private void WriteHeader(StreamWriter writer) { WriteTitle(writer, "Summary Info"); writer.WriteLine($"Output file size: {_fileSize,10}"); - writer.WriteLine($"Section count: {_sections.Count,10}"); - writer.WriteLine($"Node count: {_nodes.Count,10}"); - writer.WriteLine($"Symbol count: {_symbols.Count,10}"); - writer.WriteLine($"Relocation count: {_relocCounts.Values.Sum(),10}"); + writer.WriteLine($"Section count: {_objectInfoBuilder.Sections.Count,10}"); + writer.WriteLine($"Node count: {_objectInfoBuilder.Nodes.Count,10}"); + writer.WriteLine($"Symbol count: {_objectInfoBuilder.Symbols.Count,10}"); + writer.WriteLine($"Relocation count: {_objectInfoBuilder.RelocCounts.Values.Sum(),10}"); } private IEnumerable GetNodeTypeStatistics() { List nodeTypeStats = new List(); Dictionary statsNameIndex = new Dictionary(); - foreach (MapFileNode node in _nodes) + foreach (ObjectNode node in _objectInfoBuilder.Nodes) { if (!statsNameIndex.TryGetValue(node.Name, out int statsIndex)) { @@ -304,7 +164,7 @@ private void WriteNodeTypeStatisticsCsv(StreamWriter writer) private void WriteRelocTypeStatistics(StreamWriter writer) { - KeyValuePair[] relocTypeCounts = _relocCounts.ToArray(); + KeyValuePair[] relocTypeCounts = _objectInfoBuilder.RelocCounts.ToArray(); Array.Sort(relocTypeCounts, (a, b) => b.Value.CompareTo(a.Value)); WriteTitle(writer, "Reloc Type Statistics"); @@ -320,13 +180,12 @@ private void WriteRelocTypeStatistics(StreamWriter writer) WriteTitle(writer, "Top Nodes By Relocation Count"); WriteTitle(writer, " COUNT | SYMBOL (NODE)"); - foreach (MapFileNode node in _nodes.Where(node => node.Relocations != 0).OrderByDescending(node => node.Relocations).Take(NumberOfTopNodesByRelocType)) + foreach (ObjectNode node in _objectInfoBuilder.Nodes.Where(node => node.Relocations != 0).OrderByDescending(node => node.Relocations).Take(NumberOfTopNodesByRelocType)) { writer.Write($"{node.Relocations,8} | "); - int symbolIndex = _symbols.BinarySearch(new MapFileSymbol(node.SectionIndex, node.Offset, name: null), MapFileItem.Comparer.Instance); - if (symbolIndex >= 0 && symbolIndex < _symbols.Count && MapFileItem.Comparer.Instance.Compare(_symbols[symbolIndex], node) == 0) + if (_objectInfoBuilder.FindSymbol(node, out int symbolIndex)) { - writer.Write($"{_symbols[symbolIndex].Name}"); + writer.Write($"{_objectInfoBuilder.Symbols[symbolIndex].Name}"); } writer.WriteLine($" ({node.Name})"); } @@ -336,9 +195,9 @@ private void WriteSections(StreamWriter writer) { WriteTitle(writer, "Section Map"); WriteTitle(writer, "INDEX | FILEOFFSET | RVA | END_RVA | LENGTH | NAME"); - for (int sectionIndex = 0; sectionIndex < _sections.Count; sectionIndex++) + for (int sectionIndex = 0; sectionIndex < _objectInfoBuilder.Sections.Count; sectionIndex++) { - Section section = _sections[sectionIndex]; + Section section = _objectInfoBuilder.Sections[sectionIndex]; writer.Write($"{sectionIndex,5} | "); writer.Write($"0x{section.FilePosWhenPlaced:X8} | "); writer.Write($"0x{section.RVAWhenPlaced:X8} | "); @@ -356,13 +215,15 @@ private void WriteMap(StreamWriter writer) int nodeIndex = 0; int symbolIndex = 0; - while (nodeIndex < _nodes.Count || symbolIndex < _symbols.Count) + while (nodeIndex < _objectInfoBuilder.Nodes.Count || symbolIndex < _objectInfoBuilder.Symbols.Count) { - if (nodeIndex >= _nodes.Count || symbolIndex < _symbols.Count && MapFileItem.Comparer.Instance.Compare(_symbols[symbolIndex], _nodes[nodeIndex]) < 0) + if (nodeIndex >= _objectInfoBuilder.Nodes.Count + || symbolIndex < _objectInfoBuilder.Symbols.Count + && ObjectItem.Comparer.Instance.Compare(_objectInfoBuilder.Symbols[symbolIndex], _objectInfoBuilder.Nodes[nodeIndex]) < 0) { // No more nodes or next symbol is below next node - emit symbol - MapFileSymbol symbol = _symbols[symbolIndex++]; - Section section = _sections[symbol.SectionIndex]; + ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; + Section section = _objectInfoBuilder.Sections[symbol.SectionIndex]; writer.Write($"0x{symbol.Offset + section.RVAWhenPlaced:X8} | "); writer.Write(" | "); writer.Write(" | "); @@ -372,16 +233,16 @@ private void WriteMap(StreamWriter writer) else { // Emit node and optionally symbol - MapFileNode node = _nodes[nodeIndex++]; - Section section = _sections[node.SectionIndex]; + ObjectNode node = _objectInfoBuilder.Nodes[nodeIndex++]; + Section section = _objectInfoBuilder.Sections[node.SectionIndex]; writer.Write($"0x{node.Offset + section.RVAWhenPlaced:X8} | "); writer.Write($"0x{node.Length:X6} | "); writer.Write($"{node.Relocations,6} | "); writer.Write($"{GetNameHead(section),-SectionNameHeadLength} | "); - if (symbolIndex < _symbols.Count && MapFileItem.Comparer.Instance.Compare(node, _symbols[symbolIndex]) == 0) + if (symbolIndex < _objectInfoBuilder.Symbols.Count && ObjectItem.Comparer.Instance.Compare(node, _objectInfoBuilder.Symbols[symbolIndex]) == 0) { - MapFileSymbol symbol = _symbols[symbolIndex++]; + ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; writer.Write($"{symbol.Name}"); } writer.WriteLine($" ({node.Name})"); @@ -396,13 +257,15 @@ private void WriteMapCsv(StreamWriter writer) int nodeIndex = 0; int symbolIndex = 0; - while (nodeIndex < _nodes.Count || symbolIndex < _symbols.Count) + while (nodeIndex < _objectInfoBuilder.Nodes.Count || symbolIndex < _objectInfoBuilder.Symbols.Count) { - if (nodeIndex >= _nodes.Count || symbolIndex < _symbols.Count && MapFileItem.Comparer.Instance.Compare(_symbols[symbolIndex], _nodes[nodeIndex]) < 0) + if (nodeIndex >= _objectInfoBuilder.Nodes.Count + || symbolIndex < _objectInfoBuilder.Symbols.Count + && ObjectItem.Comparer.Instance.Compare(_objectInfoBuilder.Symbols[symbolIndex], _objectInfoBuilder.Nodes[nodeIndex]) < 0) { // No more nodes or next symbol is below next node - emit symbol - MapFileSymbol symbol = _symbols[symbolIndex++]; - Section section = _sections[symbol.SectionIndex]; + ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; + Section section = _objectInfoBuilder.Sections[symbol.SectionIndex]; writer.Write($"0x{symbol.Offset + section.RVAWhenPlaced:X8},"); writer.Write(","); writer.Write(","); @@ -413,16 +276,16 @@ private void WriteMapCsv(StreamWriter writer) else { // Emit node and optionally symbol - MapFileNode node = _nodes[nodeIndex++]; - Section section = _sections[node.SectionIndex]; + ObjectNode node = _objectInfoBuilder.Nodes[nodeIndex++]; + Section section = _objectInfoBuilder.Sections[node.SectionIndex]; writer.Write($"0x{node.Offset + section.RVAWhenPlaced:X8},"); writer.Write($"{node.Length},"); writer.Write($"{node.Relocations},"); writer.Write($"{section.Name},"); - if (symbolIndex < _symbols.Count && MapFileItem.Comparer.Instance.Compare(node, _symbols[symbolIndex]) == 0) + if (symbolIndex < _objectInfoBuilder.Symbols.Count && ObjectItem.Comparer.Instance.Compare(node, _objectInfoBuilder.Symbols[symbolIndex]) == 0) { - MapFileSymbol symbol = _symbols[symbolIndex++]; + ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; writer.Write($"{symbol.Name}"); } writer.Write(","); @@ -448,53 +311,5 @@ private void WriteTitle(StreamWriter writer, string title) writer.WriteLine(new string('-', title.Length)); } - private IEnumerable EnumerateMethods() - { - DebugNameFormatter nameFormatter = new DebugNameFormatter(); - TypeNameFormatter typeNameFormatter = new TypeString(); - HashSet emittedMethods = new HashSet(); - foreach (KeyValuePair symbolMethodPair in _methodSymbolMap) - { - EcmaMethod ecmaMethod = symbolMethodPair.Value.Method.GetTypicalMethodDefinition() as EcmaMethod; - if (ecmaMethod != null && emittedMethods.Add(ecmaMethod)) - { - MethodInfo methodInfo = new MethodInfo(); - methodInfo.MethodToken = (uint)MetadataTokens.GetToken(ecmaMethod.Handle); - methodInfo.AssemblyName = ecmaMethod.Module.Assembly.GetName().Name; - methodInfo.Name = FormatMethodName(symbolMethodPair.Value.Method, typeNameFormatter); - MapFileNode node = _nodeSymbolMap[symbolMethodPair.Key]; - Section section = _sections[node.SectionIndex]; - methodInfo.HotRVA = (uint)(section.RVAWhenPlaced + node.Offset); - methodInfo.HotLength = (uint)node.Length; - methodInfo.ColdRVA = 0; - methodInfo.ColdLength = 0; - yield return methodInfo; - } - } - } - - private string FormatMethodName(MethodDesc method, TypeNameFormatter typeNameFormatter) - { - StringBuilder output = new StringBuilder(); - if (!method.Signature.ReturnType.IsVoid) - { - output.Append(typeNameFormatter.FormatName(method.Signature.ReturnType)); - output.Append(" "); - } - output.Append(typeNameFormatter.FormatName(method.OwningType)); - output.Append("::"); - output.Append(method.Name); - output.Append("("); - for (int paramIndex = 0; paramIndex < method.Signature.Length; paramIndex++) - { - if (paramIndex != 0) - { - output.Append(", "); - } - output.Append(typeNameFormatter.FormatName(method.Signature[paramIndex])); - } - output.Append(")"); - return output.ToString(); - } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/ObjectInfoBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/ObjectInfoBuilder.cs new file mode 100644 index 00000000000000..29634dbdc2e947 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/ObjectInfoBuilder.cs @@ -0,0 +1,230 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using System.Reflection.Metadata.Ecma335; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +using Internal.JitInterface; +using Internal.TypeSystem; +using Internal.TypeSystem.Ecma; + +using ILCompiler.DependencyAnalysis; +using ILCompiler.DependencyAnalysis.ReadyToRun; +using ILCompiler.Diagnostics; + +namespace ILCompiler.PEWriter +{ + /// + /// Base class for symbols and nodes in the output file implements common logic + /// for section / offset ordering. + /// + public class ObjectItem + { + public class Comparer : IComparer + { + public readonly static Comparer Instance = new Comparer(); + + public int Compare([AllowNull] ObjectItem x, [AllowNull] ObjectItem y) + { + return (x.SectionIndex != y.SectionIndex ? x.SectionIndex.CompareTo(y.SectionIndex) : x.Offset.CompareTo(y.Offset)); + } + } + + /// + /// Item section index + /// + public readonly int SectionIndex; + + /// + /// Offset relative to section beginning + /// + public readonly int Offset; + + /// + /// Item name + /// + public readonly string Name; + + public ObjectItem(int sectionIndex, int offset, string name) + { + SectionIndex = sectionIndex; + Offset = offset; + Name = name; + } + } + + /// + /// This class represents a single node (contiguous block of data) in the output R2R PE file. + /// + public class ObjectNode : ObjectItem + { + /// + /// Node length (number of bytes). This doesn't include any external alignment + /// applied when concatenating the nodes to form sections. + /// + public readonly int Length; + + /// + /// Number of file-level relocations (.reloc section entries) used by the node. + /// + public int Relocations { get; private set; } + + public ObjectNode(int sectionIndex, int offset, int length, string name) + : base(sectionIndex, offset, name) + { + Length = length; + Relocations = 0; + } + + public void AddRelocation() + { + Relocations++; + } + } + + /// + /// Symbol is a "pointer" into the PE file. Most (but not all) symbols correspond to + /// node beginnings (most nodes have a "start symbol" representing the beginning + /// of the node). + /// + public class ObjectSymbol : ObjectItem + { + public ObjectSymbol(int sectionIndex, int offset, string name) + : base(sectionIndex, offset, name) + { + } + } + + /// + /// Common class used to collect information to use when emitting map files and symbol files. + /// + public class ObjectInfoBuilder + { + private readonly List _nodes; + private readonly List _symbols; + private readonly List
_sections; + + private readonly Dictionary _nodeSymbolMap; + private readonly Dictionary _methodSymbolMap; + + private readonly Dictionary _relocCounts; + + public ObjectInfoBuilder() + { + _nodes = new List(); + _symbols = new List(); + _sections = new List
(); + + _nodeSymbolMap = new Dictionary(); + _methodSymbolMap = new Dictionary(); + + _relocCounts = new Dictionary(); + } + + public void AddNode(ObjectNode node, ISymbolDefinitionNode symbol) + { + _nodes.Add(node); + _nodeSymbolMap.Add(symbol, node); + } + + public void AddRelocation(ObjectNode node, RelocType relocType) + { + node.AddRelocation(); + _relocCounts.TryGetValue(relocType, out int relocTypeCount); + _relocCounts[relocType] = relocTypeCount + 1; + } + + public void AddSymbol(ObjectSymbol symbol) + { + _symbols.Add(symbol); + } + + public void AddSection(Section section) + { + _sections.Add(section); + } + + public void AddMethod(MethodWithGCInfo method, ISymbolDefinitionNode symbol) + { + _methodSymbolMap.Add(symbol, method); + } + + public void Sort() + { + _nodes.Sort(ObjectItem.Comparer.Instance); + _symbols.Sort(ObjectItem.Comparer.Instance); + } + + public bool FindSymbol(ObjectItem item, out int index) + { + index = _symbols.BinarySearch(new ObjectSymbol(item.SectionIndex, item.Offset, name: null), ObjectItem.Comparer.Instance); + bool result = (index >= 0 && index < _symbols.Count && ObjectItem.Comparer.Instance.Compare(_symbols[index], item) == 0); + if (!result) + { + index = -1; + } + return result; + } + + public IEnumerable EnumerateMethods() + { + DebugNameFormatter nameFormatter = new DebugNameFormatter(); + TypeNameFormatter typeNameFormatter = new TypeString(); + HashSet emittedMethods = new HashSet(); + foreach (KeyValuePair symbolMethodPair in _methodSymbolMap) + { + EcmaMethod ecmaMethod = symbolMethodPair.Value.Method.GetTypicalMethodDefinition() as EcmaMethod; + if (ecmaMethod != null && emittedMethods.Add(ecmaMethod)) + { + MethodInfo methodInfo = new MethodInfo(); + methodInfo.MethodToken = (uint)MetadataTokens.GetToken(ecmaMethod.Handle); + methodInfo.AssemblyName = ecmaMethod.Module.Assembly.GetName().Name; + methodInfo.Name = FormatMethodName(symbolMethodPair.Value.Method, typeNameFormatter); + ObjectNode node = _nodeSymbolMap[symbolMethodPair.Key]; + Section section = _sections[node.SectionIndex]; + methodInfo.HotRVA = (uint)(section.RVAWhenPlaced + node.Offset); + methodInfo.HotLength = (uint)node.Length; + methodInfo.ColdRVA = 0; + methodInfo.ColdLength = 0; + yield return methodInfo; + } + } + } + + private string FormatMethodName(MethodDesc method, TypeNameFormatter typeNameFormatter) + { + StringBuilder output = new StringBuilder(); + if (!method.Signature.ReturnType.IsVoid) + { + output.Append(typeNameFormatter.FormatName(method.Signature.ReturnType)); + output.Append(" "); + } + output.Append(typeNameFormatter.FormatName(method.OwningType)); + output.Append("::"); + output.Append(method.Name); + output.Append("("); + for (int paramIndex = 0; paramIndex < method.Signature.Length; paramIndex++) + { + if (paramIndex != 0) + { + output.Append(", "); + } + output.Append(typeNameFormatter.FormatName(method.Signature[paramIndex])); + } + output.Append(")"); + return output.ToString(); + } + + public IReadOnlyList Nodes => _nodes; + public IReadOnlyList
Sections => _sections; + public IReadOnlyList Symbols => _symbols; + + public IReadOnlyDictionary RelocCounts => _relocCounts; + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs index 759fad4ac6fd7f..c93d4c188bff56 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs @@ -241,8 +241,8 @@ public void SetWin32Resources(ISymbolNode symbol, int resourcesSize) /// Object data to emit /// Target section /// Textual name of the object data for diagnostic purposese - /// Optional map file builder to output the data item to - public void AddObjectData(ObjectNode.ObjectData objectData, ObjectNodeSection section, string name, MapFileBuilder mapFileBuilder) + /// Optional object info builder to output the data item to + public void AddObjectData(DependencyAnalysis.ObjectNode.ObjectData objectData, ObjectNodeSection section, string name, ObjectInfoBuilder objectInfoBuilder) { if (_written) { @@ -266,7 +266,7 @@ public void AddObjectData(ObjectNode.ObjectData objectData, ObjectNodeSection se throw new NotImplementedException(); } - _sectionBuilder.AddObjectData(objectData, targetSectionIndex, name, mapFileBuilder); + _sectionBuilder.AddObjectData(objectData, targetSectionIndex, name, objectInfoBuilder); } /// @@ -312,10 +312,10 @@ public void Write(Stream outputStream, int? timeDateStamp) /// /// Fill in map builder section table. /// - /// Map file builder to set up - public void AddSections(MapFileBuilder mapFileBuilder) + /// Object info builder to set up + public void AddSections(ObjectInfoBuilder objectInfoBuilder) { - _sectionBuilder.AddSections(mapFileBuilder); + _sectionBuilder.AddSections(objectInfoBuilder); } /// diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs index 77354483762199..db688de1bcb59e 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs @@ -437,8 +437,8 @@ private NameMangler GetNameMangler() /// Block to add /// Section index /// Node name to emit in the map file - /// Optional map file to emit - public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, string name, MapFileBuilder mapFileBuilder) + /// Optional output info to collect (used for creating maps and symbols) + public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, string name, ObjectInfoBuilder objectInfoBuilder) { Section section = _sections[sectionIndex]; @@ -475,10 +475,10 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st } } - if (mapFileBuilder != null) + if (objectInfoBuilder != null) { - MapFileNode node = new MapFileNode(sectionIndex, alignedOffset, objectData.Data.Length, name); - mapFileBuilder.AddNode(node, objectData.DefinedSymbols[0]); + ObjectNode node = new ObjectNode(sectionIndex, alignedOffset, objectData.Data.Length, name); + objectInfoBuilder.AddNode(node, objectData.DefinedSymbols[0]); if (objectData.Relocs != null) { foreach (Relocation reloc in objectData.Relocs) @@ -486,7 +486,7 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st RelocType fileReloc = Relocation.GetFileRelocationType(reloc.RelocType); if (fileReloc != RelocType.IMAGE_REL_BASED_ABSOLUTE) { - mapFileBuilder.AddRelocation(node, fileReloc); + objectInfoBuilder.AddRelocation(node, fileReloc); } } } @@ -498,12 +498,12 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st { foreach (ISymbolDefinitionNode symbol in objectData.DefinedSymbols) { - if (mapFileBuilder != null) + if (objectInfoBuilder != null) { Utf8StringBuilder sb = new Utf8StringBuilder(); symbol.AppendMangledName(GetNameMangler(), sb); int sectionRelativeOffset = alignedOffset + symbol.Offset; - mapFileBuilder.AddSymbol(new MapFileSymbol(sectionIndex, sectionRelativeOffset, sb.ToString())); + objectInfoBuilder.AddSymbol(new ObjectSymbol(sectionIndex, sectionRelativeOffset, sb.ToString())); } _symbolMap.Add(symbol, new SymbolTarget( sectionIndex: sectionIndex, @@ -551,11 +551,11 @@ public IEnumerable GetSections() return sectionList; } - public void AddSections(MapFileBuilder mapFileBuilder) + public void AddSections(ObjectInfoBuilder objectInfoBuilder) { foreach (Section section in _sections) { - mapFileBuilder.AddSection(section); + objectInfoBuilder.AddSection(section); } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs new file mode 100644 index 00000000000000..a4f209cbe457d4 --- /dev/null +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs @@ -0,0 +1,39 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using ILCompiler.Diagnostics; + +namespace ILCompiler.PEWriter +{ + public class SymbolFileBuilder + { + private readonly ObjectInfoBuilder _objectInfoBuilder; + + public SymbolFileBuilder(ObjectInfoBuilder objectInfoBuilder) + { + _objectInfoBuilder = objectInfoBuilder; + } + + public void SavePdb(string pdbPath, string dllFileName) + { + Console.WriteLine("Emitting PDB file: {0}", Path.Combine(pdbPath, Path.GetFileNameWithoutExtension(dllFileName) + ".ni.pdb")); + + new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, _objectInfoBuilder.EnumerateMethods()); + } + + public void SavePerfMap(string perfMapPath, string dllFileName) + { + string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + ".perf.map"); + Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); + + PerfMapWriter.Write(perfMapFileName, _objectInfoBuilder.EnumerateMethods()); + } + } +} diff --git a/src/coreclr/tools/aot/crossgen2.sln b/src/coreclr/tools/aot/crossgen2.sln index aa1a8362184dd7..cb78b75b95945d 100644 --- a/src/coreclr/tools/aot/crossgen2.sln +++ b/src/coreclr/tools/aot/crossgen2.sln @@ -105,12 +105,11 @@ Global {1043373D-8C14-4224-9E2B-75F0DE645E7E}.Release|x64.Build.0 = Release|x64 {1043373D-8C14-4224-9E2B-75F0DE645E7E}.Release|x86.ActiveCfg = Release|Any CPU {1043373D-8C14-4224-9E2B-75F0DE645E7E}.Release|x86.Build.0 = Release|Any CPU - {3EACD929-4725-4173-A845-734936BBDF87}.Checked|Any CPU.ActiveCfg = Debug|Any CPU - {3EACD929-4725-4173-A845-734936BBDF87}.Checked|Any CPU.Build.0 = Debug|Any CPU - {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x64.ActiveCfg = Debug|Any CPU - {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x64.Build.0 = Debug|Any CPU - {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x86.ActiveCfg = Debug|Any CPU - {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x86.Build.0 = Debug|Any CPU + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|Any CPU.ActiveCfg = Debug|x86 + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x64.ActiveCfg = Debug|x64 + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x64.Build.0 = Debug|x64 + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x86.ActiveCfg = Debug|x86 + {3EACD929-4725-4173-A845-734936BBDF87}.Checked|x86.Build.0 = Debug|x86 {3EACD929-4725-4173-A845-734936BBDF87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3EACD929-4725-4173-A845-734936BBDF87}.Debug|Any CPU.Build.0 = Debug|Any CPU {3EACD929-4725-4173-A845-734936BBDF87}.Debug|x64.ActiveCfg = Debug|Any CPU diff --git a/src/coreclr/tools/r2rdump/R2RDump.sln b/src/coreclr/tools/r2rdump/R2RDump.sln index 316a22ddc720fe..6596a597f104a5 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.sln +++ b/src/coreclr/tools/r2rdump/R2RDump.sln @@ -6,7 +6,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "R2RDump", "R2RDump.csproj", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Reflection.ReadyToRun", "..\aot\ILCompiler.Reflection.ReadyToRun\ILCompiler.Reflection.ReadyToRun.csproj", "{E2A577E5-7AF3-49B3-BA78-7071B75ED64B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILCompiler.Diagnostics", "..\aot\ILCompiler.Diagnostics\ILCompiler.Diagnostics.csproj", "{4E9512BA-F963-472A-B689-37D4D32456F3}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ILCompiler.Diagnostics", "..\aot\ILCompiler.Diagnostics\ILCompiler.Diagnostics.csproj", "{4E9512BA-F963-472A-B689-37D4D32456F3}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -16,8 +16,8 @@ Global Release|x64 = Release|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {00CCF6D0-5905-428E-A2A2-2A6D09D8C257}.Debug|Any CPU.Build.0 = Debug|Any CPU + {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}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -32,10 +32,10 @@ Global {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 - {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x64.ActiveCfg = Debug|Any CPU - {4E9512BA-F963-472A-B689-37D4D32456F3}.Debug|x64.Build.0 = Debug|Any CPU + {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}.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 From e6ee7b05ac173bef27e215b0d380ca643d6b5041 Mon Sep 17 00:00:00 2001 From: Tomas Date: Sat, 16 Jan 2021 00:25:15 +0100 Subject: [PATCH 9/9] Rename ObjectItem/Node/InfoBuilder to Output* to fix ambiguity --- .../CodeGen/ReadyToRunObjectWriter.cs | 16 ++-- .../ILCompiler.ReadyToRun.csproj | 2 +- .../ObjectWriter/MapFileBuilder.cs | 74 +++++++++---------- ...ectInfoBuilder.cs => OutputInfoBuilder.cs} | 54 +++++++------- .../ObjectWriter/R2RPEBuilder.cs | 12 +-- .../ObjectWriter/SectionBuilder.cs | 20 ++--- .../ObjectWriter/SymbolFileBuilder.cs | 10 +-- 7 files changed, 94 insertions(+), 94 deletions(-) rename src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/{ObjectInfoBuilder.cs => OutputInfoBuilder.cs} (81%) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index e822d20c6f75d4..47976ee402a723 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -53,7 +53,7 @@ internal class ReadyToRunObjectWriter /// /// Set to non-null when the executable generator should output a map or symbol file. /// - private readonly ObjectInfoBuilder _objectInfoBuilder; + private readonly OutputInfoBuilder _outputInfoBuilder; /// /// Set to non-null when the executable generator should output a map file. @@ -149,16 +149,16 @@ public ReadyToRunObjectWriter( if (generateMap || generateSymbols) { - _objectInfoBuilder = new ObjectInfoBuilder(); + _outputInfoBuilder = new OutputInfoBuilder(); if (generateMap) { - _mapFileBuilder = new MapFileBuilder(_objectInfoBuilder); + _mapFileBuilder = new MapFileBuilder(_outputInfoBuilder); } if (generateSymbols) { - _symbolFileBuilder = new SymbolFileBuilder(_objectInfoBuilder); + _symbolFileBuilder = new SymbolFileBuilder(_outputInfoBuilder); } } } @@ -272,7 +272,7 @@ public void EmitPortableExecutable() if ((_generatePdbFile || _generatePerfMapFile) && node is MethodWithGCInfo methodNode) { - _objectInfoBuilder.AddMethod(methodNode, nodeContents.DefinedSymbols[0]); + _outputInfoBuilder.AddMethod(methodNode, nodeContents.DefinedSymbols[0]); } } @@ -312,9 +312,9 @@ public void EmitPortableExecutable() } } - if (_objectInfoBuilder != null) + if (_outputInfoBuilder != null) { - r2rPeBuilder.AddSections(_objectInfoBuilder); + r2rPeBuilder.AddSections(_outputInfoBuilder); if (_generateMapFile) { @@ -403,7 +403,7 @@ private void EmitObjectData(R2RPEBuilder r2rPeBuilder, ObjectData data, int node } #endif - r2rPeBuilder.AddObjectData(data, section, name, _objectInfoBuilder); + r2rPeBuilder.AddObjectData(data, section, name, _outputInfoBuilder); } public static void EmitObject( diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index 9aad5df0044091..e6f136eb22377e 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -196,7 +196,7 @@ - + diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs index 8289896c3162c7..726ae5fe079e6d 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/MapFileBuilder.cs @@ -46,7 +46,7 @@ public NodeTypeStatistics(string name) Name = name; } - public void AddNode(ObjectNode node) + public void AddNode(OutputNode node) { Debug.Assert(Name == node.Name); Count++; @@ -54,13 +54,13 @@ public void AddNode(ObjectNode node) } } - private ObjectInfoBuilder _objectInfoBuilder; + private OutputInfoBuilder _outputInfoBuilder; private long _fileSize; - public MapFileBuilder(ObjectInfoBuilder objectInfoBuilder) + public MapFileBuilder(OutputInfoBuilder outputInfoBuilder) { - _objectInfoBuilder = objectInfoBuilder; + _outputInfoBuilder = outputInfoBuilder; } public void SetFileSize(long fileSize) @@ -72,7 +72,7 @@ public void SaveMap(string mapFileName) { Console.WriteLine("Emitting map file: {0}", mapFileName); - _objectInfoBuilder.Sort(); + _outputInfoBuilder.Sort(); using (StreamWriter mapWriter = new StreamWriter(mapFileName)) { @@ -88,7 +88,7 @@ public void SaveCsv(string nodeStatsCsvFileName, string mapCsvFileName) { Console.WriteLine("Emitting csv files: {0}, {1}", nodeStatsCsvFileName, mapCsvFileName); - _objectInfoBuilder.Sort(); + _outputInfoBuilder.Sort(); using (StreamWriter nodeStatsWriter = new StreamWriter(nodeStatsCsvFileName)) { @@ -106,17 +106,17 @@ private void WriteHeader(StreamWriter writer) WriteTitle(writer, "Summary Info"); writer.WriteLine($"Output file size: {_fileSize,10}"); - writer.WriteLine($"Section count: {_objectInfoBuilder.Sections.Count,10}"); - writer.WriteLine($"Node count: {_objectInfoBuilder.Nodes.Count,10}"); - writer.WriteLine($"Symbol count: {_objectInfoBuilder.Symbols.Count,10}"); - writer.WriteLine($"Relocation count: {_objectInfoBuilder.RelocCounts.Values.Sum(),10}"); + writer.WriteLine($"Section count: {_outputInfoBuilder.Sections.Count,10}"); + writer.WriteLine($"Node count: {_outputInfoBuilder.Nodes.Count,10}"); + writer.WriteLine($"Symbol count: {_outputInfoBuilder.Symbols.Count,10}"); + writer.WriteLine($"Relocation count: {_outputInfoBuilder.RelocCounts.Values.Sum(),10}"); } private IEnumerable GetNodeTypeStatistics() { List nodeTypeStats = new List(); Dictionary statsNameIndex = new Dictionary(); - foreach (ObjectNode node in _objectInfoBuilder.Nodes) + foreach (OutputNode node in _outputInfoBuilder.Nodes) { if (!statsNameIndex.TryGetValue(node.Name, out int statsIndex)) { @@ -164,7 +164,7 @@ private void WriteNodeTypeStatisticsCsv(StreamWriter writer) private void WriteRelocTypeStatistics(StreamWriter writer) { - KeyValuePair[] relocTypeCounts = _objectInfoBuilder.RelocCounts.ToArray(); + KeyValuePair[] relocTypeCounts = _outputInfoBuilder.RelocCounts.ToArray(); Array.Sort(relocTypeCounts, (a, b) => b.Value.CompareTo(a.Value)); WriteTitle(writer, "Reloc Type Statistics"); @@ -180,12 +180,12 @@ private void WriteRelocTypeStatistics(StreamWriter writer) WriteTitle(writer, "Top Nodes By Relocation Count"); WriteTitle(writer, " COUNT | SYMBOL (NODE)"); - foreach (ObjectNode node in _objectInfoBuilder.Nodes.Where(node => node.Relocations != 0).OrderByDescending(node => node.Relocations).Take(NumberOfTopNodesByRelocType)) + foreach (OutputNode node in _outputInfoBuilder.Nodes.Where(node => node.Relocations != 0).OrderByDescending(node => node.Relocations).Take(NumberOfTopNodesByRelocType)) { writer.Write($"{node.Relocations,8} | "); - if (_objectInfoBuilder.FindSymbol(node, out int symbolIndex)) + if (_outputInfoBuilder.FindSymbol(node, out int symbolIndex)) { - writer.Write($"{_objectInfoBuilder.Symbols[symbolIndex].Name}"); + writer.Write($"{_outputInfoBuilder.Symbols[symbolIndex].Name}"); } writer.WriteLine($" ({node.Name})"); } @@ -195,9 +195,9 @@ private void WriteSections(StreamWriter writer) { WriteTitle(writer, "Section Map"); WriteTitle(writer, "INDEX | FILEOFFSET | RVA | END_RVA | LENGTH | NAME"); - for (int sectionIndex = 0; sectionIndex < _objectInfoBuilder.Sections.Count; sectionIndex++) + for (int sectionIndex = 0; sectionIndex < _outputInfoBuilder.Sections.Count; sectionIndex++) { - Section section = _objectInfoBuilder.Sections[sectionIndex]; + Section section = _outputInfoBuilder.Sections[sectionIndex]; writer.Write($"{sectionIndex,5} | "); writer.Write($"0x{section.FilePosWhenPlaced:X8} | "); writer.Write($"0x{section.RVAWhenPlaced:X8} | "); @@ -215,15 +215,15 @@ private void WriteMap(StreamWriter writer) int nodeIndex = 0; int symbolIndex = 0; - while (nodeIndex < _objectInfoBuilder.Nodes.Count || symbolIndex < _objectInfoBuilder.Symbols.Count) + while (nodeIndex < _outputInfoBuilder.Nodes.Count || symbolIndex < _outputInfoBuilder.Symbols.Count) { - if (nodeIndex >= _objectInfoBuilder.Nodes.Count - || symbolIndex < _objectInfoBuilder.Symbols.Count - && ObjectItem.Comparer.Instance.Compare(_objectInfoBuilder.Symbols[symbolIndex], _objectInfoBuilder.Nodes[nodeIndex]) < 0) + if (nodeIndex >= _outputInfoBuilder.Nodes.Count + || symbolIndex < _outputInfoBuilder.Symbols.Count + && OutputItem.Comparer.Instance.Compare(_outputInfoBuilder.Symbols[symbolIndex], _outputInfoBuilder.Nodes[nodeIndex]) < 0) { // No more nodes or next symbol is below next node - emit symbol - ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; - Section section = _objectInfoBuilder.Sections[symbol.SectionIndex]; + OutputSymbol symbol = _outputInfoBuilder.Symbols[symbolIndex++]; + Section section = _outputInfoBuilder.Sections[symbol.SectionIndex]; writer.Write($"0x{symbol.Offset + section.RVAWhenPlaced:X8} | "); writer.Write(" | "); writer.Write(" | "); @@ -233,16 +233,16 @@ private void WriteMap(StreamWriter writer) else { // Emit node and optionally symbol - ObjectNode node = _objectInfoBuilder.Nodes[nodeIndex++]; - Section section = _objectInfoBuilder.Sections[node.SectionIndex]; + OutputNode node = _outputInfoBuilder.Nodes[nodeIndex++]; + Section section = _outputInfoBuilder.Sections[node.SectionIndex]; writer.Write($"0x{node.Offset + section.RVAWhenPlaced:X8} | "); writer.Write($"0x{node.Length:X6} | "); writer.Write($"{node.Relocations,6} | "); writer.Write($"{GetNameHead(section),-SectionNameHeadLength} | "); - if (symbolIndex < _objectInfoBuilder.Symbols.Count && ObjectItem.Comparer.Instance.Compare(node, _objectInfoBuilder.Symbols[symbolIndex]) == 0) + if (symbolIndex < _outputInfoBuilder.Symbols.Count && OutputItem.Comparer.Instance.Compare(node, _outputInfoBuilder.Symbols[symbolIndex]) == 0) { - ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; + OutputSymbol symbol = _outputInfoBuilder.Symbols[symbolIndex++]; writer.Write($"{symbol.Name}"); } writer.WriteLine($" ({node.Name})"); @@ -257,15 +257,15 @@ private void WriteMapCsv(StreamWriter writer) int nodeIndex = 0; int symbolIndex = 0; - while (nodeIndex < _objectInfoBuilder.Nodes.Count || symbolIndex < _objectInfoBuilder.Symbols.Count) + while (nodeIndex < _outputInfoBuilder.Nodes.Count || symbolIndex < _outputInfoBuilder.Symbols.Count) { - if (nodeIndex >= _objectInfoBuilder.Nodes.Count - || symbolIndex < _objectInfoBuilder.Symbols.Count - && ObjectItem.Comparer.Instance.Compare(_objectInfoBuilder.Symbols[symbolIndex], _objectInfoBuilder.Nodes[nodeIndex]) < 0) + if (nodeIndex >= _outputInfoBuilder.Nodes.Count + || symbolIndex < _outputInfoBuilder.Symbols.Count + && OutputItem.Comparer.Instance.Compare(_outputInfoBuilder.Symbols[symbolIndex], _outputInfoBuilder.Nodes[nodeIndex]) < 0) { // No more nodes or next symbol is below next node - emit symbol - ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; - Section section = _objectInfoBuilder.Sections[symbol.SectionIndex]; + OutputSymbol symbol = _outputInfoBuilder.Symbols[symbolIndex++]; + Section section = _outputInfoBuilder.Sections[symbol.SectionIndex]; writer.Write($"0x{symbol.Offset + section.RVAWhenPlaced:X8},"); writer.Write(","); writer.Write(","); @@ -276,16 +276,16 @@ private void WriteMapCsv(StreamWriter writer) else { // Emit node and optionally symbol - ObjectNode node = _objectInfoBuilder.Nodes[nodeIndex++]; - Section section = _objectInfoBuilder.Sections[node.SectionIndex]; + OutputNode node = _outputInfoBuilder.Nodes[nodeIndex++]; + Section section = _outputInfoBuilder.Sections[node.SectionIndex]; writer.Write($"0x{node.Offset + section.RVAWhenPlaced:X8},"); writer.Write($"{node.Length},"); writer.Write($"{node.Relocations},"); writer.Write($"{section.Name},"); - if (symbolIndex < _objectInfoBuilder.Symbols.Count && ObjectItem.Comparer.Instance.Compare(node, _objectInfoBuilder.Symbols[symbolIndex]) == 0) + if (symbolIndex < _outputInfoBuilder.Symbols.Count && OutputItem.Comparer.Instance.Compare(node, _outputInfoBuilder.Symbols[symbolIndex]) == 0) { - ObjectSymbol symbol = _objectInfoBuilder.Symbols[symbolIndex++]; + OutputSymbol symbol = _outputInfoBuilder.Symbols[symbolIndex++]; writer.Write($"{symbol.Name}"); } writer.Write(","); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/ObjectInfoBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs similarity index 81% rename from src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/ObjectInfoBuilder.cs rename to src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs index 29634dbdc2e947..00a73721531756 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/ObjectInfoBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/OutputInfoBuilder.cs @@ -24,13 +24,13 @@ namespace ILCompiler.PEWriter /// Base class for symbols and nodes in the output file implements common logic /// for section / offset ordering. /// - public class ObjectItem + public class OutputItem { - public class Comparer : IComparer + public class Comparer : IComparer { public readonly static Comparer Instance = new Comparer(); - public int Compare([AllowNull] ObjectItem x, [AllowNull] ObjectItem y) + public int Compare([AllowNull] OutputItem x, [AllowNull] OutputItem y) { return (x.SectionIndex != y.SectionIndex ? x.SectionIndex.CompareTo(y.SectionIndex) : x.Offset.CompareTo(y.Offset)); } @@ -51,7 +51,7 @@ public int Compare([AllowNull] ObjectItem x, [AllowNull] ObjectItem y) /// public readonly string Name; - public ObjectItem(int sectionIndex, int offset, string name) + public OutputItem(int sectionIndex, int offset, string name) { SectionIndex = sectionIndex; Offset = offset; @@ -62,7 +62,7 @@ public ObjectItem(int sectionIndex, int offset, string name) /// /// This class represents a single node (contiguous block of data) in the output R2R PE file. /// - public class ObjectNode : ObjectItem + public class OutputNode : OutputItem { /// /// Node length (number of bytes). This doesn't include any external alignment @@ -75,7 +75,7 @@ public class ObjectNode : ObjectItem /// public int Relocations { get; private set; } - public ObjectNode(int sectionIndex, int offset, int length, string name) + public OutputNode(int sectionIndex, int offset, int length, string name) : base(sectionIndex, offset, name) { Length = length; @@ -93,9 +93,9 @@ public void AddRelocation() /// node beginnings (most nodes have a "start symbol" representing the beginning /// of the node). /// - public class ObjectSymbol : ObjectItem + public class OutputSymbol : OutputItem { - public ObjectSymbol(int sectionIndex, int offset, string name) + public OutputSymbol(int sectionIndex, int offset, string name) : base(sectionIndex, offset, name) { } @@ -104,43 +104,43 @@ public ObjectSymbol(int sectionIndex, int offset, string name) /// /// Common class used to collect information to use when emitting map files and symbol files. /// - public class ObjectInfoBuilder + public class OutputInfoBuilder { - private readonly List _nodes; - private readonly List _symbols; + private readonly List _nodes; + private readonly List _symbols; private readonly List
_sections; - private readonly Dictionary _nodeSymbolMap; + private readonly Dictionary _nodeSymbolMap; private readonly Dictionary _methodSymbolMap; private readonly Dictionary _relocCounts; - public ObjectInfoBuilder() + public OutputInfoBuilder() { - _nodes = new List(); - _symbols = new List(); + _nodes = new List(); + _symbols = new List(); _sections = new List
(); - _nodeSymbolMap = new Dictionary(); + _nodeSymbolMap = new Dictionary(); _methodSymbolMap = new Dictionary(); _relocCounts = new Dictionary(); } - public void AddNode(ObjectNode node, ISymbolDefinitionNode symbol) + public void AddNode(OutputNode node, ISymbolDefinitionNode symbol) { _nodes.Add(node); _nodeSymbolMap.Add(symbol, node); } - public void AddRelocation(ObjectNode node, RelocType relocType) + public void AddRelocation(OutputNode node, RelocType relocType) { node.AddRelocation(); _relocCounts.TryGetValue(relocType, out int relocTypeCount); _relocCounts[relocType] = relocTypeCount + 1; } - public void AddSymbol(ObjectSymbol symbol) + public void AddSymbol(OutputSymbol symbol) { _symbols.Add(symbol); } @@ -157,14 +157,14 @@ public void AddMethod(MethodWithGCInfo method, ISymbolDefinitionNode symbol) public void Sort() { - _nodes.Sort(ObjectItem.Comparer.Instance); - _symbols.Sort(ObjectItem.Comparer.Instance); + _nodes.Sort(OutputItem.Comparer.Instance); + _symbols.Sort(OutputItem.Comparer.Instance); } - public bool FindSymbol(ObjectItem item, out int index) + public bool FindSymbol(OutputItem item, out int index) { - index = _symbols.BinarySearch(new ObjectSymbol(item.SectionIndex, item.Offset, name: null), ObjectItem.Comparer.Instance); - bool result = (index >= 0 && index < _symbols.Count && ObjectItem.Comparer.Instance.Compare(_symbols[index], item) == 0); + index = _symbols.BinarySearch(new OutputSymbol(item.SectionIndex, item.Offset, name: null), OutputItem.Comparer.Instance); + bool result = (index >= 0 && index < _symbols.Count && OutputItem.Comparer.Instance.Compare(_symbols[index], item) == 0); if (!result) { index = -1; @@ -186,7 +186,7 @@ public IEnumerable EnumerateMethods() methodInfo.MethodToken = (uint)MetadataTokens.GetToken(ecmaMethod.Handle); methodInfo.AssemblyName = ecmaMethod.Module.Assembly.GetName().Name; methodInfo.Name = FormatMethodName(symbolMethodPair.Value.Method, typeNameFormatter); - ObjectNode node = _nodeSymbolMap[symbolMethodPair.Key]; + OutputNode node = _nodeSymbolMap[symbolMethodPair.Key]; Section section = _sections[node.SectionIndex]; methodInfo.HotRVA = (uint)(section.RVAWhenPlaced + node.Offset); methodInfo.HotLength = (uint)node.Length; @@ -221,9 +221,9 @@ private string FormatMethodName(MethodDesc method, TypeNameFormatter typeNameFor return output.ToString(); } - public IReadOnlyList Nodes => _nodes; + public IReadOnlyList Nodes => _nodes; public IReadOnlyList
Sections => _sections; - public IReadOnlyList Symbols => _symbols; + public IReadOnlyList Symbols => _symbols; public IReadOnlyDictionary RelocCounts => _relocCounts; } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs index c93d4c188bff56..3f6764b0e804ba 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs @@ -241,8 +241,8 @@ public void SetWin32Resources(ISymbolNode symbol, int resourcesSize) /// Object data to emit /// Target section /// Textual name of the object data for diagnostic purposese - /// Optional object info builder to output the data item to - public void AddObjectData(DependencyAnalysis.ObjectNode.ObjectData objectData, ObjectNodeSection section, string name, ObjectInfoBuilder objectInfoBuilder) + /// Optional output info builder to output the data item to + public void AddObjectData(DependencyAnalysis.ObjectNode.ObjectData objectData, ObjectNodeSection section, string name, OutputInfoBuilder outputInfoBuilder) { if (_written) { @@ -266,7 +266,7 @@ public void AddObjectData(DependencyAnalysis.ObjectNode.ObjectData objectData, O throw new NotImplementedException(); } - _sectionBuilder.AddObjectData(objectData, targetSectionIndex, name, objectInfoBuilder); + _sectionBuilder.AddObjectData(objectData, targetSectionIndex, name, outputInfoBuilder); } /// @@ -312,10 +312,10 @@ public void Write(Stream outputStream, int? timeDateStamp) /// /// Fill in map builder section table. /// - /// Object info builder to set up - public void AddSections(ObjectInfoBuilder objectInfoBuilder) + /// Object info builder to set up + public void AddSections(OutputInfoBuilder outputInfoBuilder) { - _sectionBuilder.AddSections(objectInfoBuilder); + _sectionBuilder.AddSections(outputInfoBuilder); } /// diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs index db688de1bcb59e..7c3e16b763c0ca 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SectionBuilder.cs @@ -437,8 +437,8 @@ private NameMangler GetNameMangler() /// Block to add /// Section index /// Node name to emit in the map file - /// Optional output info to collect (used for creating maps and symbols) - public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, string name, ObjectInfoBuilder objectInfoBuilder) + /// Optional output info to collect (used for creating maps and symbols) + public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, string name, OutputInfoBuilder outputInfoBuilder) { Section section = _sections[sectionIndex]; @@ -475,10 +475,10 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st } } - if (objectInfoBuilder != null) + if (outputInfoBuilder != null) { - ObjectNode node = new ObjectNode(sectionIndex, alignedOffset, objectData.Data.Length, name); - objectInfoBuilder.AddNode(node, objectData.DefinedSymbols[0]); + var node = new OutputNode(sectionIndex, alignedOffset, objectData.Data.Length, name); + outputInfoBuilder.AddNode(node, objectData.DefinedSymbols[0]); if (objectData.Relocs != null) { foreach (Relocation reloc in objectData.Relocs) @@ -486,7 +486,7 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st RelocType fileReloc = Relocation.GetFileRelocationType(reloc.RelocType); if (fileReloc != RelocType.IMAGE_REL_BASED_ABSOLUTE) { - objectInfoBuilder.AddRelocation(node, fileReloc); + outputInfoBuilder.AddRelocation(node, fileReloc); } } } @@ -498,12 +498,12 @@ public void AddObjectData(ObjectNode.ObjectData objectData, int sectionIndex, st { foreach (ISymbolDefinitionNode symbol in objectData.DefinedSymbols) { - if (objectInfoBuilder != null) + if (outputInfoBuilder != null) { Utf8StringBuilder sb = new Utf8StringBuilder(); symbol.AppendMangledName(GetNameMangler(), sb); int sectionRelativeOffset = alignedOffset + symbol.Offset; - objectInfoBuilder.AddSymbol(new ObjectSymbol(sectionIndex, sectionRelativeOffset, sb.ToString())); + outputInfoBuilder.AddSymbol(new OutputSymbol(sectionIndex, sectionRelativeOffset, sb.ToString())); } _symbolMap.Add(symbol, new SymbolTarget( sectionIndex: sectionIndex, @@ -551,11 +551,11 @@ public IEnumerable GetSections() return sectionList; } - public void AddSections(ObjectInfoBuilder objectInfoBuilder) + public void AddSections(OutputInfoBuilder outputInfoBuilder) { foreach (Section section in _sections) { - objectInfoBuilder.AddSection(section); + outputInfoBuilder.AddSection(section); } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs index a4f209cbe457d4..62eeb0494a9ac9 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs @@ -14,18 +14,18 @@ namespace ILCompiler.PEWriter { public class SymbolFileBuilder { - private readonly ObjectInfoBuilder _objectInfoBuilder; + private readonly OutputInfoBuilder _outputInfoBuilder; - public SymbolFileBuilder(ObjectInfoBuilder objectInfoBuilder) + public SymbolFileBuilder(OutputInfoBuilder outputInfoBuilder) { - _objectInfoBuilder = objectInfoBuilder; + _outputInfoBuilder = outputInfoBuilder; } public void SavePdb(string pdbPath, string dllFileName) { Console.WriteLine("Emitting PDB file: {0}", Path.Combine(pdbPath, Path.GetFileNameWithoutExtension(dllFileName) + ".ni.pdb")); - new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, _objectInfoBuilder.EnumerateMethods()); + new PdbWriter(pdbPath, PDBExtraData.None).WritePDBData(dllFileName, _outputInfoBuilder.EnumerateMethods()); } public void SavePerfMap(string perfMapPath, string dllFileName) @@ -33,7 +33,7 @@ public void SavePerfMap(string perfMapPath, string dllFileName) string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + ".perf.map"); Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); - PerfMapWriter.Write(perfMapFileName, _objectInfoBuilder.EnumerateMethods()); + PerfMapWriter.Write(perfMapFileName, _outputInfoBuilder.EnumerateMethods()); } } }