| File: Compiler\DependencyAnalysis\ReadyToRun\DebugDirectoryNode.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.ReadyToRun\ILCompiler.ReadyToRun.csproj (ILCompiler.ReadyToRun) |
// 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.Immutable; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection.PortableExecutable; using Internal.Text; using Internal.TypeSystem; using Internal.TypeSystem.Ecma; namespace ILCompiler.DependencyAnalysis.ReadyToRun { public class DebugDirectoryNode : ObjectNode, ISymbolDefinitionNode { const int ImageDebugDirectorySize = sizeof(int) + // Characteristics sizeof(int) + // TimeDateStamp sizeof(short) + // MajorVersion: sizeof(short) + // MinorVersion sizeof(int) + // Type sizeof(int) + // SizeOfData: sizeof(int) + // AddressOfRawData: sizeof(int); // PointerToRawData private EcmaModule _module; private NativeDebugDirectoryEntryNode _nativeEntry; private PerfMapDebugDirectoryEntryNode _perfMapEntry; private bool _insertDeterministicEntry; public DebugDirectoryNode(EcmaModule sourceModule, string outputFileName, bool shouldAddNiPdb, bool shouldGeneratePerfmap, int perfMapFormatVersion) { _module = sourceModule; _insertDeterministicEntry = sourceModule == null; // Mark module as deterministic if generating composite image string pdbNameRoot = Path.GetFileNameWithoutExtension(outputFileName); if (sourceModule != null) { pdbNameRoot = sourceModule.Assembly.GetName().Name; } if (shouldAddNiPdb) { _nativeEntry = new NativeDebugDirectoryEntryNode(pdbNameRoot + ".ni.pdb"); } if (shouldGeneratePerfmap) { _perfMapEntry = new PerfMapDebugDirectoryEntryNode(pdbNameRoot + ".ni.r2rmap", perfMapFormatVersion); } } public override ObjectNodeSection GetSection(NodeFactory factory) { return ObjectNodeSection.ReadOnlyDataSection; } public override bool IsShareable => false; protected internal override int Phase => (int)ObjectNodePhase.Ordered; public override int ClassCode => (int)ObjectNodeOrder.DebugDirectoryNode; public override bool StaticDependenciesAreComputed => true; public int Offset => 0; public int Size => (GetNumDebugDirectoryEntriesInModule() + (_nativeEntry is not null ? 1 : 0) + (_perfMapEntry is not null ? 1 : 0) + (_insertDeterministicEntry ? 1 : 0)) * ImageDebugDirectorySize; public NativeDebugDirectoryEntryNode PdbEntry => _nativeEntry; public PerfMapDebugDirectoryEntryNode PerfMapEntry => _perfMapEntry; public void AppendMangledName(NameMangler nameMangler, Utf8StringBuilder sb) { sb.Append(nameMangler.CompilationUnitPrefix); string directoryName; if (_module != null) directoryName = _module.Assembly.GetName().Name; else directoryName = "Composite"; sb.Append($"__DebugDirectory_{directoryName}"); } protected override string GetName(NodeFactory factory) => this.GetMangledName(factory.NameMangler); int GetNumDebugDirectoryEntriesInModule() { if (_module == null) return 0; ImmutableArray<DebugDirectoryEntry> entries = _module.PEReader.SafeReadDebugDirectory(); return entries == null ? 0 : entries.Length; } public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) { ObjectDataBuilder builder = new ObjectDataBuilder(factory, relocsOnly); builder.RequireInitialPointerAlignment(); builder.AddSymbol(this); ImmutableArray<DebugDirectoryEntry> entries = ImmutableArray<DebugDirectoryEntry>.Empty; if (_module != null) entries = _module.PEReader.SafeReadDebugDirectory(); int numEntries = GetNumDebugDirectoryEntriesInModule(); // Reuse the module's PDB entry DebugDirectoryEntry pdbEntry = entries.Where(s => s.Type == DebugDirectoryEntryType.CodeView).FirstOrDefault(); // NI PDB entry _nativeEntry?.EmitHeader(ref builder, pdbEntry.Stamp, pdbEntry.MajorVersion); _perfMapEntry?.EmitHeader(ref builder); // If generating a composite image, emit the deterministic marker if (_insertDeterministicEntry) { DeterministicDebugDirectoryEntry.EmitHeader(ref builder); } // Second, copy existing entries from input module for (int i = 0; i < numEntries; i++) { builder.EmitUInt(0 /* Characteristics */); builder.EmitUInt(entries[i].Stamp); builder.EmitUShort(entries[i].MajorVersion); builder.EmitUShort(entries[i].MinorVersion); builder.EmitInt((int)entries[i].Type); builder.EmitInt(entries[i].DataSize); if (entries[i].DataSize == 0) { builder.EmitUInt(0); builder.EmitUInt(0); } else { builder.EmitReloc(factory.DebugDirectoryEntry(_module, i), RelocType.IMAGE_REL_BASED_ADDR32NB); builder.EmitReloc(factory.DebugDirectoryEntry(_module, i), RelocType.IMAGE_REL_FILE_ABSOLUTE); } } Debug.Assert(builder.CountBytes == Size); return builder.ToObjectData(); } public override int CompareToImpl(ISortableNode other, CompilerComparer comparer) { if (_module == null) { if (((DebugDirectoryNode)other)._module == null) return 0; return -1; } else if (((DebugDirectoryNode)other)._module == null) { return 1; } return _module.CompareTo(((DebugDirectoryNode)other)._module); } } }