From: David Wrighton Date: Tue, 28 Sep 2021 20:51:45 +0000 (-0700) Subject: Add Compiler record to PDB files in Crossgen2 (#59686) X-Git-Tag: accepted/tizen/unified/riscv/20231226.055536~12932 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fcde5f6d2a3bce9d4e0d7c9fe916817c9d6eef5d;p=platform%2Fupstream%2Fdotnet%2Fruntime.git Add Compiler record to PDB files in Crossgen2 (#59686) --- diff --git a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs index 1483cfb..a16d5bf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.Diagnostics/PdbWriter.cs @@ -9,6 +9,7 @@ using System.Reflection.PortableExecutable; using System.Runtime.InteropServices; using System.Text; +using Internal.TypeSystem; using Microsoft.DiaSymReader; namespace ILCompiler.Diagnostics @@ -78,6 +79,7 @@ namespace ILCompiler.Diagnostics string _pdbPath; PDBExtraData _pdbExtraData; + readonly TargetDetails _target; string _pdbFilePath; string _tempSourceDllName; @@ -116,7 +118,7 @@ namespace ILCompiler.Diagnostics [MarshalAs(UnmanagedType.LPWStr)] string pdbPath, [MarshalAs(UnmanagedType.Interface)] out ISymNGenWriter2 ngenPdbWriter); - public PdbWriter(string pdbPath, PDBExtraData pdbExtraData) + public PdbWriter(string pdbPath, PDBExtraData pdbExtraData, TargetDetails target) { SymDocument unknownDocument = new SymDocument(); unknownDocument.Name = "unknown"; @@ -126,6 +128,7 @@ namespace ILCompiler.Diagnostics _symDocuments.Add(unknownDocument); _pdbPath = pdbPath; _pdbExtraData = pdbExtraData; + _target = target; } public void WritePDBData(string dllPath, IEnumerable methods) @@ -227,6 +230,7 @@ namespace ILCompiler.Diagnostics _ngenWriter.OpenModW(originalDllPath, Path.GetFileName(originalDllPath), out _pdbMod); + WriteCompilerVersion(); WriteStringTable(); WriteFileChecksums(); @@ -301,6 +305,24 @@ namespace ILCompiler.Diagnostics DEBUG_S_COFF_SYMBOL_RVA, } + private enum SYM_ENUM : ushort + { + S_COMPILE3 = 0x113c, // Replacement for S_COMPILE2 + } + + private enum CV_CPU_TYPE + { + CV_CFL_PENTIUMIII = 0x07, + CV_CFL_X64 = 0xD0, + CV_CFL_ARMNT = 0xF4, + CV_CFL_ARM64 = 0xF6, + } + + private enum CV_CFL_LANG + { + CV_CFL_MSIL = 0x0F, // Unknown MSIL (LTCG of .NETMODULE) + } + private void WriteStringTable() { _stringTableToOffsetMapping = new Dictionary(); @@ -384,5 +406,111 @@ namespace ILCompiler.Diagnostics byte[] checksumTableArray = checksumStream.ToArray(); _ngenWriter.ModAddSymbols(_pdbMod, checksumTableArray, checksumTableArray.Length); } + + private void WriteCompilerVersion() + { + // The only symbol we write into the DEBUG_S_SYMBOLS stream is the compiler version. + // Other symbols are represented as "public" symbols which are something else entirely. + + MemoryStream symbolStream = new MemoryStream(); + BinaryWriter writer = new BinaryWriter(symbolStream, Encoding.UTF8); + writer.Write(CV_SIGNATURE_C13); + writer.Write((uint)DEBUG_S_SUBSECTION_TYPE.DEBUG_S_SYMBOLS); + long startOfSymbolTablePosition = writer.BaseStream.Position; + writer.Write((uint)0); // Size of actual symbol table. To be filled in later + long startOfSymbolTableOffset = writer.BaseStream.Position; + + { + long startOfCompile3RecordLength = writer.BaseStream.Position; + writer.Write((ushort)0); // Write record length. Fill in later + long startOfCompile3Record = writer.BaseStream.Position; + writer.Write((ushort)SYM_ENUM.S_COMPILE3); + byte iLanguage = (byte)CV_CFL_LANG.CV_CFL_MSIL; + writer.Write(iLanguage); + // Write rest of flags + writer.Write((byte)0); + writer.Write((byte)0); + writer.Write((byte)0); + + switch (_target.Architecture) + { + case TargetArchitecture.ARM: + writer.Write((ushort)CV_CPU_TYPE.CV_CFL_ARMNT); + break; + case TargetArchitecture.ARM64: + writer.Write((ushort)CV_CPU_TYPE.CV_CFL_ARM64); + break; + case TargetArchitecture.X64: + writer.Write((ushort)CV_CPU_TYPE.CV_CFL_X64); + break; + case TargetArchitecture.X86: + writer.Write((ushort)CV_CPU_TYPE.CV_CFL_PENTIUMIII); + break; + default: + throw new Exception("Unknown target architecture"); + } + + writer.Write((ushort)0); // Front end Major Version + writer.Write((ushort)0); // Front end Minor Version + writer.Write((ushort)0); // Front end Build Version + writer.Write((ushort)0); // Front end QFE Version + + Version compilerVersion = null; + foreach (AssemblyFileVersionAttribute versionAttribute in typeof(PdbWriter).Assembly.GetCustomAttributes(typeof(AssemblyFileVersionAttribute), true)) + { + string versionString = versionAttribute.Version; + compilerVersion = new Version(versionString); + } + if (compilerVersion == null) + { + throw new Exception("No AssemblyFileVersionAttribute present"); + } + + writer.Write((ushort)compilerVersion.Major); // Front end Major Version + writer.Write((ushort)compilerVersion.Minor); // Front end Minor Version + writer.Write((ushort)compilerVersion.Build); // Front end Build Version + writer.Write((ushort)compilerVersion.Revision); // Front end QFE Version + + // compiler version string + string informationalVersion = null; + foreach (AssemblyInformationalVersionAttribute versionAttribute in typeof(PdbWriter).Assembly.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), true)) + { + informationalVersion = versionAttribute.InformationalVersion; + } + + if (informationalVersion == null) + { + throw new Exception("No AssemblyInformationalVersionAttribute present"); + } + + string CompilerVersionString = $"Crossgen2 - {informationalVersion}"; + writer.Write(CompilerVersionString.AsSpan()); + writer.Write((byte)0); // Null terminate all strings + + // Must align to the next 4-byte boundary + while ((writer.BaseStream.Position % 4) != 0) + { + writer.Write((byte)0); + } + + // Update Compile3 record size + long currentPosition = writer.BaseStream.Position; + long compile3RecordSize = writer.BaseStream.Position - startOfCompile3Record; + writer.BaseStream.Position = startOfCompile3RecordLength; + writer.Write(checked((ushort)compile3RecordSize)); + writer.Flush(); + writer.BaseStream.Position = currentPosition; + } + + // Update symbol table size + long symbolTableSize = writer.BaseStream.Position - startOfSymbolTableOffset; + writer.BaseStream.Position = startOfSymbolTablePosition; + writer.Write(checked((uint)symbolTableSize)); + writer.Flush(); + + // Write symbol table into pdb file + byte[] symbolTableArray = symbolStream.ToArray(); + _ngenWriter.ModAddSymbols(_pdbMod, symbolTableArray, symbolTableArray.Length); + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index d704579..41bf7f7 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -180,7 +180,7 @@ namespace ILCompiler.DependencyAnalysis if (generateSymbols) { - _symbolFileBuilder = new SymbolFileBuilder(_outputInfoBuilder); + _symbolFileBuilder = new SymbolFileBuilder(_outputInfoBuilder, _nodeFactory.Target); } if (generateProfileFile) @@ -400,7 +400,7 @@ namespace ILCompiler.DependencyAnalysis { path = Path.GetDirectoryName(_objectFilePath); } - _symbolFileBuilder.SavePerfMap(path, _perfMapFormatVersion, _objectFilePath, _nodeFactory.Target); + _symbolFileBuilder.SavePerfMap(path, _perfMapFormatVersion, _objectFilePath); } if (_profileFileBuilder != null) diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs index d46dab2..3065ae3 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/SymbolFileBuilder.cs @@ -16,20 +16,22 @@ namespace ILCompiler.PEWriter public class SymbolFileBuilder { private readonly OutputInfoBuilder _outputInfoBuilder; + private readonly TargetDetails _details; - public SymbolFileBuilder(OutputInfoBuilder outputInfoBuilder) + public SymbolFileBuilder(OutputInfoBuilder outputInfoBuilder, TargetDetails details) { _outputInfoBuilder = outputInfoBuilder; + _details = details; } 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, _outputInfoBuilder.EnumerateMethods()); + new PdbWriter(pdbPath, PDBExtraData.None, _details).WritePDBData(dllFileName, _outputInfoBuilder.EnumerateMethods()); } - public void SavePerfMap(string perfMapPath, int perfMapFormatVersion, string dllFileName, TargetDetails details) + public void SavePerfMap(string perfMapPath, int perfMapFormatVersion, string dllFileName) { string perfMapExtension; if (perfMapFormatVersion == PerfMapWriter.LegacyCrossgen1FormatVersion) @@ -56,7 +58,7 @@ namespace ILCompiler.PEWriter string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + perfMapExtension); Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); - PerfMapWriter.Write(perfMapFileName, perfMapFormatVersion, _outputInfoBuilder.EnumerateMethods(), _outputInfoBuilder.EnumerateInputAssemblies(), details); + PerfMapWriter.Write(perfMapFileName, perfMapFormatVersion, _outputInfoBuilder.EnumerateMethods(), _outputInfoBuilder.EnumerateInputAssemblies(), _details); } } } diff --git a/src/coreclr/tools/r2rdump/R2RDump.cs b/src/coreclr/tools/r2rdump/R2RDump.cs index db9ecd3..8d9d506 100644 --- a/src/coreclr/tools/r2rdump/R2RDump.cs +++ b/src/coreclr/tools/r2rdump/R2RDump.cs @@ -423,7 +423,8 @@ namespace R2RDump { pdbPath = Path.GetDirectoryName(r2r.Filename); } - var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None); + TargetDetails details = new TargetDetails(r2r.TargetArchitecture, r2r.TargetOperatingSystem, TargetAbi.CoreRT); + var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None, details); pdbWriter.WritePDBData(r2r.Filename, ProduceDebugInfoMethods(r2r)); }