| File: Compiler\ObjectWriter\Dwarf\DwarfLineProgramTableWriter.cs | Web Access |
| Project: src\runtime\src\coreclr\tools\aot\ILCompiler.Compiler\ILCompiler.Compiler.csproj (ILCompiler.Compiler) |
// 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.Buffers.Binary; using System.Collections.Generic; using ILCompiler.DependencyAnalysis; namespace ILCompiler.ObjectWriter { internal sealed class DwarfLineProgramTableWriter : IDisposable { private readonly SectionWriter _lineSectionWriter; private readonly byte _targetPointerSize; private readonly RelocType _codeRelocType; private readonly Dictionary<string, uint> _directoryNameToIndex = new(); private readonly Dictionary<DwarfFileName, uint> _fileNameToIndex = new(); private readonly byte[] _sizeBuffer; public const byte MaximumOperationsPerInstruction = 1; public const sbyte LineBase = -5; public const byte LineRange = 14; public const byte OpCodeBase = 13; private static ReadOnlySpan<byte> StandardOpCodeLengths => [ 0, // DW_LNS_copy 1, // DW_LNS_advance_pc 1, // DW_LNS_advance_line 1, // DW_LNS_set_file 1, // DW_LNS_set_column 0, // DW_LNS_negate_stmt 0, // DW_LNS_set_basic_block 0, // DW_LNS_const_add_pc 1, // DW_LNS_fixed_advance_pc 0, // DW_LNS_set_prologue_end 0, // DW_LNS_set_epilogue_begin 1, // DW_LNS_set_isa ]; public DwarfLineProgramTableWriter( SectionWriter lineSectionWriter, IReadOnlyList<DwarfFileName> fileNames, byte targetPointerSize, byte minimumInstructionLength, RelocType codeRelocType) { _lineSectionWriter = lineSectionWriter; _targetPointerSize = targetPointerSize; _codeRelocType = codeRelocType; // Length _sizeBuffer = new byte[sizeof(uint)]; lineSectionWriter.EmitData(_sizeBuffer); // Version lineSectionWriter.WriteLittleEndian<ushort>(4); // Header Length var headerSizeBuffer = new byte[sizeof(uint)]; lineSectionWriter.EmitData(headerSizeBuffer); var headerStart = lineSectionWriter.Position; lineSectionWriter.WriteByte(minimumInstructionLength); lineSectionWriter.WriteByte(MaximumOperationsPerInstruction); // default_is_stmt lineSectionWriter.WriteByte(1); // line_base lineSectionWriter.WriteByte(unchecked((byte)LineBase)); // line_range lineSectionWriter.WriteByte(LineRange); // opcode_base lineSectionWriter.WriteByte(OpCodeBase); // standard_opcode_lengths foreach (var opcodeLength in StandardOpCodeLengths) { lineSectionWriter.WriteULEB128(opcodeLength); } // Directory names uint directoryIndex = 1; foreach (var fileName in fileNames) { if (fileName.Directory is string directoryName && !string.IsNullOrEmpty(directoryName) && !_directoryNameToIndex.ContainsKey(directoryName)) { lineSectionWriter.WriteUtf8String(directoryName); _directoryNameToIndex.Add(directoryName, directoryIndex); directoryIndex++; } } // Terminate directory list (empty string) lineSectionWriter.WriteByte(0); // File names uint fileNameIndex = 1; foreach (var fileName in fileNames) { directoryIndex = fileName.Directory is string directoryName && !string.IsNullOrEmpty(directoryName) ? _directoryNameToIndex[directoryName] : 0; lineSectionWriter.WriteUtf8String(fileName.Name); lineSectionWriter.WriteULEB128(directoryIndex); lineSectionWriter.WriteULEB128(fileName.Time); lineSectionWriter.WriteULEB128(fileName.Size); _fileNameToIndex[fileName] = fileNameIndex; fileNameIndex++; } // Terminate file name list (empty string) lineSectionWriter.WriteByte(0); // Update header size BinaryPrimitives.WriteInt32LittleEndian(headerSizeBuffer, (int)(lineSectionWriter.Position - headerStart)); } public void Dispose() { // Update size BinaryPrimitives.WriteInt32LittleEndian(_sizeBuffer, (int)(_lineSectionWriter.Position - sizeof(uint))); } public void WriteLineSequence(DwarfLineSequenceWriter lineSequenceWriter) { lineSequenceWriter.Write(_lineSectionWriter, _targetPointerSize, _codeRelocType); } } }