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 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_data1, 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 a 243 // source file. 244 Section.emitString(FileNameForm, *FileNameStr); 245 Section.emitIntVal(File.DirIdx, 1); 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 else 292 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 0 307 // 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 fields 315 unsigned FileNum = 1; 316 unsigned LastLine = 1; 317 unsigned Column = 0; 318 unsigned IsStatement = 1; 319 unsigned Isa = 0; 320 uint64_t Address = -1ULL; 321 322 unsigned RowsSinceLastSequence = 0; 323 324 for (const DWARFDebugLine::Row &Row : LineTable.Rows) { 325 int64_t AddressDelta; 326 if (Address == -1ULL) { 327 Section.emitIntVal(dwarf::DW_LNS_extended_op, 1); 328 encodeULEB128(Section.getFormParams().AddrSize + 1, Section.OS); 329 Section.emitIntVal(dwarf::DW_LNE_set_address, 1); 330 Section.emitIntVal(Row.Address.Address, 331 Section.getFormParams().AddrSize); 332 AddressDelta = 0; 333 } else { 334 AddressDelta = 335 (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength; 336 } 337 338 // FIXME: code copied and transformed from 339 // MCDwarf.cpp::EmitDwarfLineTable. We should find a way to share this 340 // code, but the current compatibility requirement with classic dsymutil 341 // makes it hard. Revisit that once this requirement is dropped. 342 343 if (FileNum != Row.File) { 344 FileNum = Row.File; 345 Section.emitIntVal(dwarf::DW_LNS_set_file, 1); 346 encodeULEB128(FileNum, Section.OS); 347 } 348 if (Column != Row.Column) { 349 Column = Row.Column; 350 Section.emitIntVal(dwarf::DW_LNS_set_column, 1); 351 encodeULEB128(Column, Section.OS); 352 } 353 354 // FIXME: We should handle the discriminator here, but dsymutil doesn't 355 // consider it, thus ignore it for now. 356 357 if (Isa != Row.Isa) { 358 Isa = Row.Isa; 359 Section.emitIntVal(dwarf::DW_LNS_set_isa, 1); 360 encodeULEB128(Isa, Section.OS); 361 } 362 if (IsStatement != Row.IsStmt) { 363 IsStatement = Row.IsStmt; 364 Section.emitIntVal(dwarf::DW_LNS_negate_stmt, 1); 365 } 366 if (Row.BasicBlock) 367 Section.emitIntVal(dwarf::DW_LNS_set_basic_block, 1); 368 369 if (Row.PrologueEnd) 370 Section.emitIntVal(dwarf::DW_LNS_set_prologue_end, 1); 371 372 if (Row.EpilogueBegin) 373 Section.emitIntVal(dwarf::DW_LNS_set_epilogue_begin, 1); 374 375 int64_t LineDelta = int64_t(Row.Line) - LastLine; 376 if (!Row.EndSequence) { 377 MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta, 378 EncodingBuffer); 379 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size()); 380 EncodingBuffer.resize(0); 381 Address = Row.Address.Address; 382 LastLine = Row.Line; 383 RowsSinceLastSequence++; 384 } else { 385 if (LineDelta) { 386 Section.emitIntVal(dwarf::DW_LNS_advance_line, 1); 387 encodeSLEB128(LineDelta, Section.OS); 388 } 389 if (AddressDelta) { 390 Section.emitIntVal(dwarf::DW_LNS_advance_pc, 1); 391 encodeULEB128(AddressDelta, Section.OS); 392 } 393 MCDwarfLineAddr::encode(*MC, Params, 394 std::numeric_limits<int64_t>::max(), 0, 395 EncodingBuffer); 396 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size()); 397 EncodingBuffer.resize(0); 398 Address = -1ULL; 399 LastLine = FileNum = IsStatement = 1; 400 RowsSinceLastSequence = Column = Isa = 0; 401 } 402 } 403 404 if (RowsSinceLastSequence) { 405 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 406 0, EncodingBuffer); 407 Section.OS.write(EncodingBuffer.c_str(), EncodingBuffer.size()); 408 EncodingBuffer.resize(0); 409 } 410 } 411 412 Triple TheTriple; 413 DwarfUnit &U; 414 415 std::unique_ptr<MCRegisterInfo> MRI; 416 std::unique_ptr<MCAsmInfo> MAI; 417 std::unique_ptr<MCContext> MC; 418 std::unique_ptr<MCSubtargetInfo> MSTI; 419 }; 420 421 } // end of namespace parallel 422 } // end of namespace dwarf_linker 423 } // end of namespace llvm 424 425 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H 426