433 lines · c
1//===- DebugLineSectionEmitter.h --------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H10#define LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H11 12#include "DWARFEmitterImpl.h"13#include "llvm/DWARFLinker/AddressesMap.h"14#include "llvm/DWARFLinker/Parallel/DWARFLinker.h"15#include "llvm/DebugInfo/DWARF/DWARFObject.h"16#include "llvm/MC/MCTargetOptionsCommandFlags.h"17#include "llvm/MC/TargetRegistry.h"18 19namespace llvm {20namespace dwarf_linker {21namespace parallel {22 23/// This class emits specified line table into the .debug_line section.24class DebugLineSectionEmitter {25public:26 DebugLineSectionEmitter(const Triple &TheTriple, DwarfUnit &U)27 : TheTriple(TheTriple), U(U) {}28 29 Error emit(const DWARFDebugLine::LineTable &LineTable) {30 // FIXME: remove dependence on MCDwarfLineAddr::encode.31 // As we reuse MCDwarfLineAddr::encode, we need to create/initialize32 // some MC* classes.33 if (Error Err = init(TheTriple))34 return Err;35 36 // Get descriptor for output .debug_line section.37 SectionDescriptor &OutSection =38 U.getOrCreateSectionDescriptor(DebugSectionKind::DebugLine);39 40 // unit_length.41 OutSection.emitUnitLength(0xBADDEF);42 uint64_t OffsetAfterUnitLength = OutSection.OS.tell();43 44 // Emit prologue.45 emitLineTablePrologue(LineTable.Prologue, OutSection);46 47 // Emit rows.48 emitLineTableRows(LineTable, OutSection);49 uint64_t OffsetAfterEnd = OutSection.OS.tell();50 51 // Update unit length field with actual length value.52 assert(OffsetAfterUnitLength -53 OutSection.getFormParams().getDwarfOffsetByteSize() <54 OffsetAfterUnitLength);55 OutSection.apply(OffsetAfterUnitLength -56 OutSection.getFormParams().getDwarfOffsetByteSize(),57 dwarf::DW_FORM_sec_offset,58 OffsetAfterEnd - OffsetAfterUnitLength);59 60 return Error::success();61 }62 63private:64 Error init(Triple TheTriple) {65 std::string ErrorStr;66 std::string TripleName;67 68 // Get the target.69 const Target *TheTarget =70 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);71 if (!TheTarget)72 return createStringError(std::errc::invalid_argument, ErrorStr.c_str());73 TripleName = TheTriple.getTriple();74 75 // Create all the MC Objects.76 MRI.reset(TheTarget->createMCRegInfo(TheTriple));77 if (!MRI)78 return createStringError(std::errc::invalid_argument,79 "no register info for target %s",80 TripleName.c_str());81 82 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();83 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TheTriple, MCOptions));84 if (!MAI)85 return createStringError(std::errc::invalid_argument,86 "no asm info for target %s", TripleName.c_str());87 88 MSTI.reset(TheTarget->createMCSubtargetInfo(TheTriple, "", ""));89 if (!MSTI)90 return createStringError(std::errc::invalid_argument,91 "no subtarget info for target %s",92 TripleName.c_str());93 94 MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,95 nullptr, true, "__DWARF"));96 97 return Error::success();98 }99 100 void emitLineTablePrologue(const DWARFDebugLine::Prologue &P,101 SectionDescriptor &Section) {102 // version (uhalf).103 Section.emitIntVal(P.getVersion(), 2);104 if (P.getVersion() == 5) {105 // address_size (ubyte).106 Section.emitIntVal(P.getAddressSize(), 1);107 108 // segment_selector_size (ubyte).109 Section.emitIntVal(P.SegSelectorSize, 1);110 }111 112 // header_length.113 Section.emitOffset(0xBADDEF);114 115 uint64_t OffsetAfterPrologueLength = Section.OS.tell();116 emitLineTableProloguePayload(P, Section);117 uint64_t OffsetAfterPrologueEnd = Section.OS.tell();118 119 // Update prologue length field with actual length value.120 Section.apply(OffsetAfterPrologueLength -121 Section.getFormParams().getDwarfOffsetByteSize(),122 dwarf::DW_FORM_sec_offset,123 OffsetAfterPrologueEnd - OffsetAfterPrologueLength);124 }125 126 void127 emitLineTablePrologueV2IncludeAndFileTable(const DWARFDebugLine::Prologue &P,128 SectionDescriptor &Section) {129 // include_directories (sequence of path names).130 for (const DWARFFormValue &Include : P.IncludeDirectories) {131 std::optional<const char *> IncludeStr = dwarf::toString(Include);132 if (!IncludeStr) {133 U.warn("cann't read string from line table.");134 return;135 }136 137 Section.emitString(Include.getForm(), *IncludeStr);138 }139 // The last entry is followed by a single null byte.140 Section.emitIntVal(0, 1);141 142 // file_names (sequence of file entries).143 for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) {144 std::optional<const char *> FileNameStr = dwarf::toString(File.Name);145 if (!FileNameStr) {146 U.warn("cann't read string from line table.");147 return;148 }149 150 // A null-terminated string containing the full or relative path name of a151 // source file.152 Section.emitString(File.Name.getForm(), *FileNameStr);153 154 // An unsigned LEB128 number representing the directory index of a155 // directory in the include_directories section.156 encodeULEB128(File.DirIdx, Section.OS);157 // An unsigned LEB128 number representing the (implementation-defined)158 // time of last modification for the file, or 0 if not available.159 encodeULEB128(File.ModTime, Section.OS);160 // An unsigned LEB128 number representing the length in bytes of the file,161 // or 0 if not available.162 encodeULEB128(File.Length, Section.OS);163 }164 // The last entry is followed by a single null byte.165 Section.emitIntVal(0, 1);166 }167 168 void169 emitLineTablePrologueV5IncludeAndFileTable(const DWARFDebugLine::Prologue &P,170 SectionDescriptor &Section) {171 if (P.IncludeDirectories.empty()) {172 // directory_entry_format_count(ubyte).173 Section.emitIntVal(0, 1);174 } else {175 // directory_entry_format_count(ubyte).176 Section.emitIntVal(1, 1);177 178 // directory_entry_format (sequence of ULEB128 pairs).179 encodeULEB128(dwarf::DW_LNCT_path, Section.OS);180 encodeULEB128(P.IncludeDirectories[0].getForm(), Section.OS);181 }182 183 // directories_count (ULEB128).184 encodeULEB128(P.IncludeDirectories.size(), Section.OS);185 // directories (sequence of directory names).186 for (auto Include : P.IncludeDirectories) {187 std::optional<const char *> IncludeStr = dwarf::toString(Include);188 if (!IncludeStr) {189 U.warn("cann't read string from line table.");190 return;191 }192 193 Section.emitString(Include.getForm(), *IncludeStr);194 }195 196 bool HasChecksums = P.ContentTypes.HasMD5;197 bool HasInlineSources = P.ContentTypes.HasSource;198 199 dwarf::Form FileNameForm = dwarf::DW_FORM_string;200 dwarf::Form LLVMSourceForm = dwarf::DW_FORM_string;201 202 if (P.FileNames.empty()) {203 // file_name_entry_format_count (ubyte).204 Section.emitIntVal(0, 1);205 } else {206 FileNameForm = P.FileNames[0].Name.getForm();207 LLVMSourceForm = P.FileNames[0].Source.getForm();208 209 // file_name_entry_format_count (ubyte).210 Section.emitIntVal(211 2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0), 1);212 213 // file_name_entry_format (sequence of ULEB128 pairs).214 encodeULEB128(dwarf::DW_LNCT_path, Section.OS);215 encodeULEB128(FileNameForm, Section.OS);216 217 encodeULEB128(dwarf::DW_LNCT_directory_index, Section.OS);218 encodeULEB128(dwarf::DW_FORM_udata, Section.OS);219 220 if (HasChecksums) {221 encodeULEB128(dwarf::DW_LNCT_MD5, Section.OS);222 encodeULEB128(dwarf::DW_FORM_data16, Section.OS);223 }224 225 if (HasInlineSources) {226 encodeULEB128(dwarf::DW_LNCT_LLVM_source, Section.OS);227 encodeULEB128(LLVMSourceForm, Section.OS);228 }229 }230 231 // file_names_count (ULEB128).232 encodeULEB128(P.FileNames.size(), Section.OS);233 234 // file_names (sequence of file name entries).235 for (auto File : P.FileNames) {236 std::optional<const char *> FileNameStr = dwarf::toString(File.Name);237 if (!FileNameStr) {238 U.warn("cann't read string from line table.");239 return;240 }241 242 // A null-terminated string containing the full or relative path name of a243 // source file.244 Section.emitString(FileNameForm, *FileNameStr);245 encodeULEB128(File.DirIdx, Section.OS);246 247 if (HasChecksums) {248 assert((File.Checksum.size() == 16) &&249 "checksum size is not equal to 16 bytes.");250 Section.emitBinaryData(251 StringRef(reinterpret_cast<const char *>(File.Checksum.data()),252 File.Checksum.size()));253 }254 255 if (HasInlineSources) {256 std::optional<const char *> FileSourceStr =257 dwarf::toString(File.Source);258 if (!FileSourceStr) {259 U.warn("cann't read string from line table.");260 return;261 }262 263 Section.emitString(LLVMSourceForm, *FileSourceStr);264 }265 }266 }267 268 void emitLineTableProloguePayload(const DWARFDebugLine::Prologue &P,269 SectionDescriptor &Section) {270 // minimum_instruction_length (ubyte).271 Section.emitIntVal(P.MinInstLength, 1);272 if (P.FormParams.Version >= 4) {273 // maximum_operations_per_instruction (ubyte).274 Section.emitIntVal(P.MaxOpsPerInst, 1);275 }276 // default_is_stmt (ubyte).277 Section.emitIntVal(P.DefaultIsStmt, 1);278 // line_base (sbyte).279 Section.emitIntVal(P.LineBase, 1);280 // line_range (ubyte).281 Section.emitIntVal(P.LineRange, 1);282 // opcode_base (ubyte).283 Section.emitIntVal(P.OpcodeBase, 1);284 285 // standard_opcode_lengths (array of ubyte).286 for (auto Length : P.StandardOpcodeLengths)287 Section.emitIntVal(Length, 1);288 289 if (P.FormParams.Version < 5)290 emitLineTablePrologueV2IncludeAndFileTable(P, Section);291 else292 emitLineTablePrologueV5IncludeAndFileTable(P, Section);293 }294 295 void emitLineTableRows(const DWARFDebugLine::LineTable &LineTable,296 SectionDescriptor &Section) {297 298 MCDwarfLineTableParams Params;299 Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;300 Params.DWARF2LineBase = LineTable.Prologue.LineBase;301 Params.DWARF2LineRange = LineTable.Prologue.LineRange;302 303 SmallString<128> EncodingBuffer;304 305 if (LineTable.Rows.empty()) {306 // We only have the dummy entry, dsymutil emits an entry with a 0307 // address in that case.308 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),309 0, EncodingBuffer);310 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());311 return;312 }313 314 // Line table state machine fields315 unsigned FileNum = 1;316 unsigned LastLine = 1;317 unsigned Column = 0;318 unsigned Discriminator = 0;319 unsigned IsStatement = 1;320 unsigned Isa = 0;321 uint64_t Address = -1ULL;322 323 unsigned RowsSinceLastSequence = 0;324 325 for (const DWARFDebugLine::Row &Row : LineTable.Rows) {326 int64_t AddressDelta;327 if (Address == -1ULL) {328 Section.emitIntVal(dwarf::DW_LNS_extended_op, 1);329 encodeULEB128(Section.getFormParams().AddrSize + 1, Section.OS);330 Section.emitIntVal(dwarf::DW_LNE_set_address, 1);331 Section.emitIntVal(Row.Address.Address,332 Section.getFormParams().AddrSize);333 AddressDelta = 0;334 } else {335 AddressDelta =336 (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength;337 }338 339 // FIXME: code copied and transformed from340 // MCDwarf.cpp::EmitDwarfLineTable. We should find a way to share this341 // code, but the current compatibility requirement with classic dsymutil342 // makes it hard. Revisit that once this requirement is dropped.343 344 if (FileNum != Row.File) {345 FileNum = Row.File;346 Section.emitIntVal(dwarf::DW_LNS_set_file, 1);347 encodeULEB128(FileNum, Section.OS);348 }349 if (Column != Row.Column) {350 Column = Row.Column;351 Section.emitIntVal(dwarf::DW_LNS_set_column, 1);352 encodeULEB128(Column, Section.OS);353 }354 if (Discriminator != Row.Discriminator && MC->getDwarfVersion() >= 4) {355 Discriminator = Row.Discriminator;356 unsigned Size = getULEB128Size(Discriminator);357 Section.emitIntVal(dwarf::DW_LNS_extended_op, 1);358 encodeULEB128(Size + 1, Section.OS);359 Section.emitIntVal(dwarf::DW_LNE_set_discriminator, 1);360 encodeULEB128(Discriminator, Section.OS);361 }362 Discriminator = 0;363 364 if (Isa != Row.Isa) {365 Isa = Row.Isa;366 Section.emitIntVal(dwarf::DW_LNS_set_isa, 1);367 encodeULEB128(Isa, Section.OS);368 }369 if (IsStatement != Row.IsStmt) {370 IsStatement = Row.IsStmt;371 Section.emitIntVal(dwarf::DW_LNS_negate_stmt, 1);372 }373 if (Row.BasicBlock)374 Section.emitIntVal(dwarf::DW_LNS_set_basic_block, 1);375 376 if (Row.PrologueEnd)377 Section.emitIntVal(dwarf::DW_LNS_set_prologue_end, 1);378 379 if (Row.EpilogueBegin)380 Section.emitIntVal(dwarf::DW_LNS_set_epilogue_begin, 1);381 382 int64_t LineDelta = int64_t(Row.Line) - LastLine;383 if (!Row.EndSequence) {384 MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,385 EncodingBuffer);386 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());387 EncodingBuffer.resize(0);388 Address = Row.Address.Address;389 LastLine = Row.Line;390 RowsSinceLastSequence++;391 } else {392 if (LineDelta) {393 Section.emitIntVal(dwarf::DW_LNS_advance_line, 1);394 encodeSLEB128(LineDelta, Section.OS);395 }396 if (AddressDelta) {397 Section.emitIntVal(dwarf::DW_LNS_advance_pc, 1);398 encodeULEB128(AddressDelta, Section.OS);399 }400 MCDwarfLineAddr::encode(*MC, Params,401 std::numeric_limits<int64_t>::max(), 0,402 EncodingBuffer);403 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());404 EncodingBuffer.resize(0);405 Address = -1ULL;406 LastLine = FileNum = IsStatement = 1;407 RowsSinceLastSequence = Column = Discriminator = Isa = 0;408 }409 }410 411 if (RowsSinceLastSequence) {412 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),413 0, EncodingBuffer);414 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size());415 EncodingBuffer.resize(0);416 }417 }418 419 Triple TheTriple;420 DwarfUnit &U;421 422 std::unique_ptr<MCRegisterInfo> MRI;423 std::unique_ptr<MCAsmInfo> MAI;424 std::unique_ptr<MCContext> MC;425 std::unique_ptr<MCSubtargetInfo> MSTI;426};427 428} // end of namespace parallel429} // end of namespace dwarf_linker430} // end of namespace llvm431 432#endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H433