Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DebugLineSectionEmitter.h
35292 views
//===- DebugLineSectionEmitter.h --------------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H9#define LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H1011#include "DWARFEmitterImpl.h"12#include "llvm/DWARFLinker/AddressesMap.h"13#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"14#include "llvm/DebugInfo/DWARF/DWARFObject.h"15#include "llvm/MC/MCTargetOptionsCommandFlags.h"16#include "llvm/MC/TargetRegistry.h"1718namespace llvm {19namespace dwarf_linker {20namespace parallel {2122/// This class emits specified line table into the .debug_line section.23class DebugLineSectionEmitter {24public:25DebugLineSectionEmitter(const Triple &TheTriple, DwarfUnit &U)26: TheTriple(TheTriple), U(U) {}2728Error emit(const DWARFDebugLine::LineTable &LineTable) {29// FIXME: remove dependence on MCDwarfLineAddr::encode.30// As we reuse MCDwarfLineAddr::encode, we need to create/initialize31// some MC* classes.32if (Error Err = init(TheTriple))33return Err;3435// Get descriptor for output .debug_line section.36SectionDescriptor &OutSection =37U.getOrCreateSectionDescriptor(DebugSectionKind::DebugLine);3839// unit_length.40OutSection.emitUnitLength(0xBADDEF);41uint64_t OffsetAfterUnitLength = OutSection.OS.tell();4243// Emit prologue.44emitLineTablePrologue(LineTable.Prologue, OutSection);4546// Emit rows.47emitLineTableRows(LineTable, OutSection);48uint64_t OffsetAfterEnd = OutSection.OS.tell();4950// Update unit length field with actual length value.51assert(OffsetAfterUnitLength -52OutSection.getFormParams().getDwarfOffsetByteSize() <53OffsetAfterUnitLength);54OutSection.apply(OffsetAfterUnitLength -55OutSection.getFormParams().getDwarfOffsetByteSize(),56dwarf::DW_FORM_sec_offset,57OffsetAfterEnd - OffsetAfterUnitLength);5859return Error::success();60}6162private:63Error init(Triple TheTriple) {64std::string ErrorStr;65std::string TripleName;6667// Get the target.68const Target *TheTarget =69TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);70if (!TheTarget)71return createStringError(std::errc::invalid_argument, ErrorStr.c_str());72TripleName = TheTriple.getTriple();7374// Create all the MC Objects.75MRI.reset(TheTarget->createMCRegInfo(TripleName));76if (!MRI)77return createStringError(std::errc::invalid_argument,78"no register info for target %s",79TripleName.c_str());8081MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();82MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));83if (!MAI)84return createStringError(std::errc::invalid_argument,85"no asm info for target %s", TripleName.c_str());8687MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));88if (!MSTI)89return createStringError(std::errc::invalid_argument,90"no subtarget info for target %s",91TripleName.c_str());9293MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,94nullptr, true, "__DWARF"));9596return Error::success();97}9899void emitLineTablePrologue(const DWARFDebugLine::Prologue &P,100SectionDescriptor &Section) {101// version (uhalf).102Section.emitIntVal(P.getVersion(), 2);103if (P.getVersion() == 5) {104// address_size (ubyte).105Section.emitIntVal(P.getAddressSize(), 1);106107// segment_selector_size (ubyte).108Section.emitIntVal(P.SegSelectorSize, 1);109}110111// header_length.112Section.emitOffset(0xBADDEF);113114uint64_t OffsetAfterPrologueLength = Section.OS.tell();115emitLineTableProloguePayload(P, Section);116uint64_t OffsetAfterPrologueEnd = Section.OS.tell();117118// Update prologue length field with actual length value.119Section.apply(OffsetAfterPrologueLength -120Section.getFormParams().getDwarfOffsetByteSize(),121dwarf::DW_FORM_sec_offset,122OffsetAfterPrologueEnd - OffsetAfterPrologueLength);123}124125void126emitLineTablePrologueV2IncludeAndFileTable(const DWARFDebugLine::Prologue &P,127SectionDescriptor &Section) {128// include_directories (sequence of path names).129for (const DWARFFormValue &Include : P.IncludeDirectories) {130std::optional<const char *> IncludeStr = dwarf::toString(Include);131if (!IncludeStr) {132U.warn("cann't read string from line table.");133return;134}135136Section.emitString(Include.getForm(), *IncludeStr);137}138// The last entry is followed by a single null byte.139Section.emitIntVal(0, 1);140141// file_names (sequence of file entries).142for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) {143std::optional<const char *> FileNameStr = dwarf::toString(File.Name);144if (!FileNameStr) {145U.warn("cann't read string from line table.");146return;147}148149// A null-terminated string containing the full or relative path name of a150// source file.151Section.emitString(File.Name.getForm(), *FileNameStr);152153// An unsigned LEB128 number representing the directory index of a154// directory in the include_directories section.155encodeULEB128(File.DirIdx, Section.OS);156// An unsigned LEB128 number representing the (implementation-defined)157// time of last modification for the file, or 0 if not available.158encodeULEB128(File.ModTime, Section.OS);159// An unsigned LEB128 number representing the length in bytes of the file,160// or 0 if not available.161encodeULEB128(File.Length, Section.OS);162}163// The last entry is followed by a single null byte.164Section.emitIntVal(0, 1);165}166167void168emitLineTablePrologueV5IncludeAndFileTable(const DWARFDebugLine::Prologue &P,169SectionDescriptor &Section) {170if (P.IncludeDirectories.empty()) {171// directory_entry_format_count(ubyte).172Section.emitIntVal(0, 1);173} else {174// directory_entry_format_count(ubyte).175Section.emitIntVal(1, 1);176177// directory_entry_format (sequence of ULEB128 pairs).178encodeULEB128(dwarf::DW_LNCT_path, Section.OS);179encodeULEB128(P.IncludeDirectories[0].getForm(), Section.OS);180}181182// directories_count (ULEB128).183encodeULEB128(P.IncludeDirectories.size(), Section.OS);184// directories (sequence of directory names).185for (auto Include : P.IncludeDirectories) {186std::optional<const char *> IncludeStr = dwarf::toString(Include);187if (!IncludeStr) {188U.warn("cann't read string from line table.");189return;190}191192Section.emitString(Include.getForm(), *IncludeStr);193}194195bool HasChecksums = P.ContentTypes.HasMD5;196bool HasInlineSources = P.ContentTypes.HasSource;197198dwarf::Form FileNameForm = dwarf::DW_FORM_string;199dwarf::Form LLVMSourceForm = dwarf::DW_FORM_string;200201if (P.FileNames.empty()) {202// file_name_entry_format_count (ubyte).203Section.emitIntVal(0, 1);204} else {205FileNameForm = P.FileNames[0].Name.getForm();206LLVMSourceForm = P.FileNames[0].Source.getForm();207208// file_name_entry_format_count (ubyte).209Section.emitIntVal(2102 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0), 1);211212// file_name_entry_format (sequence of ULEB128 pairs).213encodeULEB128(dwarf::DW_LNCT_path, Section.OS);214encodeULEB128(FileNameForm, Section.OS);215216encodeULEB128(dwarf::DW_LNCT_directory_index, Section.OS);217encodeULEB128(dwarf::DW_FORM_data1, Section.OS);218219if (HasChecksums) {220encodeULEB128(dwarf::DW_LNCT_MD5, Section.OS);221encodeULEB128(dwarf::DW_FORM_data16, Section.OS);222}223224if (HasInlineSources) {225encodeULEB128(dwarf::DW_LNCT_LLVM_source, Section.OS);226encodeULEB128(LLVMSourceForm, Section.OS);227}228}229230// file_names_count (ULEB128).231encodeULEB128(P.FileNames.size(), Section.OS);232233// file_names (sequence of file name entries).234for (auto File : P.FileNames) {235std::optional<const char *> FileNameStr = dwarf::toString(File.Name);236if (!FileNameStr) {237U.warn("cann't read string from line table.");238return;239}240241// A null-terminated string containing the full or relative path name of a242// source file.243Section.emitString(FileNameForm, *FileNameStr);244Section.emitIntVal(File.DirIdx, 1);245246if (HasChecksums) {247assert((File.Checksum.size() == 16) &&248"checksum size is not equal to 16 bytes.");249Section.emitBinaryData(250StringRef(reinterpret_cast<const char *>(File.Checksum.data()),251File.Checksum.size()));252}253254if (HasInlineSources) {255std::optional<const char *> FileSourceStr =256dwarf::toString(File.Source);257if (!FileSourceStr) {258U.warn("cann't read string from line table.");259return;260}261262Section.emitString(LLVMSourceForm, *FileSourceStr);263}264}265}266267void emitLineTableProloguePayload(const DWARFDebugLine::Prologue &P,268SectionDescriptor &Section) {269// minimum_instruction_length (ubyte).270Section.emitIntVal(P.MinInstLength, 1);271if (P.FormParams.Version >= 4) {272// maximum_operations_per_instruction (ubyte).273Section.emitIntVal(P.MaxOpsPerInst, 1);274}275// default_is_stmt (ubyte).276Section.emitIntVal(P.DefaultIsStmt, 1);277// line_base (sbyte).278Section.emitIntVal(P.LineBase, 1);279// line_range (ubyte).280Section.emitIntVal(P.LineRange, 1);281// opcode_base (ubyte).282Section.emitIntVal(P.OpcodeBase, 1);283284// standard_opcode_lengths (array of ubyte).285for (auto Length : P.StandardOpcodeLengths)286Section.emitIntVal(Length, 1);287288if (P.FormParams.Version < 5)289emitLineTablePrologueV2IncludeAndFileTable(P, Section);290else291emitLineTablePrologueV5IncludeAndFileTable(P, Section);292}293294void emitLineTableRows(const DWARFDebugLine::LineTable &LineTable,295SectionDescriptor &Section) {296297MCDwarfLineTableParams Params;298Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;299Params.DWARF2LineBase = LineTable.Prologue.LineBase;300Params.DWARF2LineRange = LineTable.Prologue.LineRange;301302SmallString<128> EncodingBuffer;303304if (LineTable.Rows.empty()) {305// We only have the dummy entry, dsymutil emits an entry with a 0306// address in that case.307MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),3080, EncodingBuffer);309Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());310return;311}312313// Line table state machine fields314unsigned FileNum = 1;315unsigned LastLine = 1;316unsigned Column = 0;317unsigned Discriminator = 0;318unsigned IsStatement = 1;319unsigned Isa = 0;320uint64_t Address = -1ULL;321322unsigned RowsSinceLastSequence = 0;323324for (const DWARFDebugLine::Row &Row : LineTable.Rows) {325int64_t AddressDelta;326if (Address == -1ULL) {327Section.emitIntVal(dwarf::DW_LNS_extended_op, 1);328encodeULEB128(Section.getFormParams().AddrSize + 1, Section.OS);329Section.emitIntVal(dwarf::DW_LNE_set_address, 1);330Section.emitIntVal(Row.Address.Address,331Section.getFormParams().AddrSize);332AddressDelta = 0;333} else {334AddressDelta =335(Row.Address.Address - Address) / LineTable.Prologue.MinInstLength;336}337338// FIXME: code copied and transformed from339// MCDwarf.cpp::EmitDwarfLineTable. We should find a way to share this340// code, but the current compatibility requirement with classic dsymutil341// makes it hard. Revisit that once this requirement is dropped.342343if (FileNum != Row.File) {344FileNum = Row.File;345Section.emitIntVal(dwarf::DW_LNS_set_file, 1);346encodeULEB128(FileNum, Section.OS);347}348if (Column != Row.Column) {349Column = Row.Column;350Section.emitIntVal(dwarf::DW_LNS_set_column, 1);351encodeULEB128(Column, Section.OS);352}353if (Discriminator != Row.Discriminator && MC->getDwarfVersion() >= 4) {354Discriminator = Row.Discriminator;355unsigned Size = getULEB128Size(Discriminator);356Section.emitIntVal(dwarf::DW_LNS_extended_op, 1);357encodeULEB128(Size + 1, Section.OS);358Section.emitIntVal(dwarf::DW_LNE_set_discriminator, 1);359encodeULEB128(Discriminator, Section.OS);360}361Discriminator = 0;362363if (Isa != Row.Isa) {364Isa = Row.Isa;365Section.emitIntVal(dwarf::DW_LNS_set_isa, 1);366encodeULEB128(Isa, Section.OS);367}368if (IsStatement != Row.IsStmt) {369IsStatement = Row.IsStmt;370Section.emitIntVal(dwarf::DW_LNS_negate_stmt, 1);371}372if (Row.BasicBlock)373Section.emitIntVal(dwarf::DW_LNS_set_basic_block, 1);374375if (Row.PrologueEnd)376Section.emitIntVal(dwarf::DW_LNS_set_prologue_end, 1);377378if (Row.EpilogueBegin)379Section.emitIntVal(dwarf::DW_LNS_set_epilogue_begin, 1);380381int64_t LineDelta = int64_t(Row.Line) - LastLine;382if (!Row.EndSequence) {383MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,384EncodingBuffer);385Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());386EncodingBuffer.resize(0);387Address = Row.Address.Address;388LastLine = Row.Line;389RowsSinceLastSequence++;390} else {391if (LineDelta) {392Section.emitIntVal(dwarf::DW_LNS_advance_line, 1);393encodeSLEB128(LineDelta, Section.OS);394}395if (AddressDelta) {396Section.emitIntVal(dwarf::DW_LNS_advance_pc, 1);397encodeULEB128(AddressDelta, Section.OS);398}399MCDwarfLineAddr::encode(*MC, Params,400std::numeric_limits<int64_t>::max(), 0,401EncodingBuffer);402Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());403EncodingBuffer.resize(0);404Address = -1ULL;405LastLine = FileNum = IsStatement = 1;406RowsSinceLastSequence = Column = Discriminator = Isa = 0;407}408}409410if (RowsSinceLastSequence) {411MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),4120, EncodingBuffer);413Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());414EncodingBuffer.resize(0);415}416}417418Triple TheTriple;419DwarfUnit &U;420421std::unique_ptr<MCRegisterInfo> MRI;422std::unique_ptr<MCAsmInfo> MAI;423std::unique_ptr<MCContext> MC;424std::unique_ptr<MCSubtargetInfo> MSTI;425};426427} // end of namespace parallel428} // end of namespace dwarf_linker429} // end of namespace llvm430431#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H432433434