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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H 10 #define LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H 11 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 19 namespace llvm { 20 namespace dwarf_linker { 21 namespace parallel { 22 23 /// This class emits specified line table into the .debug_line section. 24 class DebugLineSectionEmitter { 25 public: 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/initialize 32 // 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 63 private: 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(TripleName)); 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, TripleName, 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(TripleName, "", "")); 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 void 127 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 a 151 // source file. 152 Section.emitString(File.Name.getForm(), *FileNameStr); 153 154 // An unsigned LEB128 number representing the directory index of a 155 // 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 void 169 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 if (P.FileNames.empty()) { 197 // file_name_entry_format_count (ubyte). 198 Section.emitIntVal(0, 1); 199 } else { 200 // file_name_entry_format_count (ubyte). 201 Section.emitIntVal(2 + (P.ContentTypes.HasMD5 ? 1 : 0), 1); 202 203 // file_name_entry_format (sequence of ULEB128 pairs). 204 encodeULEB128(dwarf::DW_LNCT_path, Section.OS); 205 encodeULEB128(P.FileNames[0].Name.getForm(), Section.OS); 206 207 encodeULEB128(dwarf::DW_LNCT_directory_index, Section.OS); 208 encodeULEB128(dwarf::DW_FORM_data1, Section.OS); 209 210 if (P.ContentTypes.HasMD5) { 211 encodeULEB128(dwarf::DW_LNCT_MD5, Section.OS); 212 encodeULEB128(dwarf::DW_FORM_data16, Section.OS); 213 } 214 } 215 216 // file_names_count (ULEB128). 217 encodeULEB128(P.FileNames.size(), Section.OS); 218 219 // file_names (sequence of file name entries). 220 for (auto File : P.FileNames) { 221 std::optional<const char *> FileNameStr = dwarf::toString(File.Name); 222 if (!FileNameStr) { 223 U.warn("cann't read string from line table."); 224 return; 225 } 226 227 // A null-terminated string containing the full or relative path name of a 228 // source file. 229 Section.emitString(File.Name.getForm(), *FileNameStr); 230 Section.emitIntVal(File.DirIdx, 1); 231 232 if (P.ContentTypes.HasMD5) { 233 Section.emitBinaryData( 234 StringRef(reinterpret_cast<const char *>(File.Checksum.data()), 235 File.Checksum.size())); 236 } 237 } 238 } 239 240 void emitLineTableProloguePayload(const DWARFDebugLine::Prologue &P, 241 SectionDescriptor &Section) { 242 // minimum_instruction_length (ubyte). 243 Section.emitIntVal(P.MinInstLength, 1); 244 if (P.FormParams.Version >= 4) { 245 // maximum_operations_per_instruction (ubyte). 246 Section.emitIntVal(P.MaxOpsPerInst, 1); 247 } 248 // default_is_stmt (ubyte). 249 Section.emitIntVal(P.DefaultIsStmt, 1); 250 // line_base (sbyte). 251 Section.emitIntVal(P.LineBase, 1); 252 // line_range (ubyte). 253 Section.emitIntVal(P.LineRange, 1); 254 // opcode_base (ubyte). 255 Section.emitIntVal(P.OpcodeBase, 1); 256 257 // standard_opcode_lengths (array of ubyte). 258 for (auto Length : P.StandardOpcodeLengths) 259 Section.emitIntVal(Length, 1); 260 261 if (P.FormParams.Version < 5) 262 emitLineTablePrologueV2IncludeAndFileTable(P, Section); 263 else 264 emitLineTablePrologueV5IncludeAndFileTable(P, Section); 265 } 266 267 void emitLineTableRows(const DWARFDebugLine::LineTable &LineTable, 268 SectionDescriptor &Section) { 269 270 MCDwarfLineTableParams Params; 271 Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; 272 Params.DWARF2LineBase = LineTable.Prologue.LineBase; 273 Params.DWARF2LineRange = LineTable.Prologue.LineRange; 274 275 SmallString<128> EncodingBuffer; 276 277 if (LineTable.Rows.empty()) { 278 // We only have the dummy entry, dsymutil emits an entry with a 0 279 // address in that case. 280 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 281 0, EncodingBuffer); 282 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size()); 283 return; 284 } 285 286 // Line table state machine fields 287 unsigned FileNum = 1; 288 unsigned LastLine = 1; 289 unsigned Column = 0; 290 unsigned IsStatement = 1; 291 unsigned Isa = 0; 292 uint64_t Address = -1ULL; 293 294 unsigned RowsSinceLastSequence = 0; 295 296 for (const DWARFDebugLine::Row &Row : LineTable.Rows) { 297 int64_t AddressDelta; 298 if (Address == -1ULL) { 299 Section.emitIntVal(dwarf::DW_LNS_extended_op, 1); 300 encodeULEB128(Section.getFormParams().AddrSize + 1, Section.OS); 301 Section.emitIntVal(dwarf::DW_LNE_set_address, 1); 302 Section.emitIntVal(Row.Address.Address, 303 Section.getFormParams().AddrSize); 304 AddressDelta = 0; 305 } else { 306 AddressDelta = 307 (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength; 308 } 309 310 // FIXME: code copied and transformed from 311 // MCDwarf.cpp::EmitDwarfLineTable. We should find a way to share this 312 // code, but the current compatibility requirement with classic dsymutil 313 // makes it hard. Revisit that once this requirement is dropped. 314 315 if (FileNum != Row.File) { 316 FileNum = Row.File; 317 Section.emitIntVal(dwarf::DW_LNS_set_file, 1); 318 encodeULEB128(FileNum, Section.OS); 319 } 320 if (Column != Row.Column) { 321 Column = Row.Column; 322 Section.emitIntVal(dwarf::DW_LNS_set_column, 1); 323 encodeULEB128(Column, Section.OS); 324 } 325 326 // FIXME: We should handle the discriminator here, but dsymutil doesn't 327 // consider it, thus ignore it for now. 328 329 if (Isa != Row.Isa) { 330 Isa = Row.Isa; 331 Section.emitIntVal(dwarf::DW_LNS_set_isa, 1); 332 encodeULEB128(Isa, Section.OS); 333 } 334 if (IsStatement != Row.IsStmt) { 335 IsStatement = Row.IsStmt; 336 Section.emitIntVal(dwarf::DW_LNS_negate_stmt, 1); 337 } 338 if (Row.BasicBlock) 339 Section.emitIntVal(dwarf::DW_LNS_set_basic_block, 1); 340 341 if (Row.PrologueEnd) 342 Section.emitIntVal(dwarf::DW_LNS_set_prologue_end, 1); 343 344 if (Row.EpilogueBegin) 345 Section.emitIntVal(dwarf::DW_LNS_set_epilogue_begin, 1); 346 347 int64_t LineDelta = int64_t(Row.Line) - LastLine; 348 if (!Row.EndSequence) { 349 MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta, 350 EncodingBuffer); 351 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size()); 352 EncodingBuffer.resize(0); 353 Address = Row.Address.Address; 354 LastLine = Row.Line; 355 RowsSinceLastSequence++; 356 } else { 357 if (LineDelta) { 358 Section.emitIntVal(dwarf::DW_LNS_advance_line, 1); 359 encodeSLEB128(LineDelta, Section.OS); 360 } 361 if (AddressDelta) { 362 Section.emitIntVal(dwarf::DW_LNS_advance_pc, 1); 363 encodeULEB128(AddressDelta, Section.OS); 364 } 365 MCDwarfLineAddr::encode(*MC, Params, 366 std::numeric_limits<int64_t>::max(), 0, 367 EncodingBuffer); 368 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size()); 369 EncodingBuffer.resize(0); 370 Address = -1ULL; 371 LastLine = FileNum = IsStatement = 1; 372 RowsSinceLastSequence = Column = Isa = 0; 373 } 374 } 375 376 if (RowsSinceLastSequence) { 377 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 378 0, EncodingBuffer); 379 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size()); 380 EncodingBuffer.resize(0); 381 } 382 } 383 384 Triple TheTriple; 385 DwarfUnit &U; 386 387 std::unique_ptr<MCRegisterInfo> MRI; 388 std::unique_ptr<MCAsmInfo> MAI; 389 std::unique_ptr<MCContext> MC; 390 std::unique_ptr<MCSubtargetInfo> MSTI; 391 }; 392 393 } // end of namespace parallel 394 } // end of namespace dwarf_linker 395 } // end of namespace llvm 396 397 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H 398