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: DebugLineSectionEmitter(const Triple & TheTriple,DwarfUnit & U)26 DebugLineSectionEmitter(const Triple &TheTriple, DwarfUnit &U) 27 : TheTriple(TheTriple), U(U) {} 28 emit(const DWARFDebugLine::LineTable & LineTable)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: init(Triple TheTriple)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 emitLineTablePrologue(const DWARFDebugLine::Prologue & P,SectionDescriptor & Section)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 emitLineTablePrologueV2IncludeAndFileTable(const DWARFDebugLine::Prologue & P,SectionDescriptor & Section)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 emitLineTablePrologueV5IncludeAndFileTable(const DWARFDebugLine::Prologue & P,SectionDescriptor & Section)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 emitLineTableProloguePayload(const DWARFDebugLine::Prologue & P,SectionDescriptor & Section)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 emitLineTableRows(const DWARFDebugLine::LineTable & LineTable,SectionDescriptor & Section)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 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 from 340 // MCDwarf.cpp::EmitDwarfLineTable. We should find a way to share this 341 // code, but the current compatibility requirement with classic dsymutil 342 // 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 parallel 429 } // end of namespace dwarf_linker 430 } // end of namespace llvm 431 432 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_DEBUGLINESECTIONEMITTER_H 433