1 //===- DwarfStreamer.cpp --------------------------------------------------===// 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 #include "llvm/DWARFLinker/Classic/DWARFStreamer.h" 10 #include "llvm/CodeGen/NonRelocatableStringpool.h" 11 #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h" 12 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 13 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h" 14 #include "llvm/MC/MCAsmBackend.h" 15 #include "llvm/MC/MCCodeEmitter.h" 16 #include "llvm/MC/MCDwarf.h" 17 #include "llvm/MC/MCObjectWriter.h" 18 #include "llvm/MC/MCSection.h" 19 #include "llvm/MC/MCStreamer.h" 20 #include "llvm/MC/MCSubtargetInfo.h" 21 #include "llvm/MC/MCTargetOptions.h" 22 #include "llvm/MC/MCTargetOptionsCommandFlags.h" 23 #include "llvm/MC/TargetRegistry.h" 24 #include "llvm/Support/FormatVariadic.h" 25 #include "llvm/Support/LEB128.h" 26 #include "llvm/Target/TargetOptions.h" 27 #include "llvm/TargetParser/Triple.h" 28 29 using namespace llvm; 30 using namespace dwarf_linker; 31 using namespace dwarf_linker::classic; 32 33 Error DwarfStreamer::init(Triple TheTriple, 34 StringRef Swift5ReflectionSegmentName) { 35 std::string ErrorStr; 36 std::string TripleName; 37 38 // Get the target. 39 const Target *TheTarget = 40 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr); 41 if (!TheTarget) 42 return createStringError(std::errc::invalid_argument, ErrorStr.c_str()); 43 44 TripleName = TheTriple.getTriple(); 45 46 // Create all the MC Objects. 47 MRI.reset(TheTarget->createMCRegInfo(TripleName)); 48 if (!MRI) 49 return createStringError(std::errc::invalid_argument, 50 "no register info for target %s", 51 TripleName.c_str()); 52 53 MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); 54 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 55 if (!MAI) 56 return createStringError(std::errc::invalid_argument, 57 "no asm info for target %s", TripleName.c_str()); 58 59 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", "")); 60 if (!MSTI) 61 return createStringError(std::errc::invalid_argument, 62 "no subtarget info for target %s", 63 TripleName.c_str()); 64 65 MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr, 66 nullptr, true, Swift5ReflectionSegmentName)); 67 MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false)); 68 MC->setObjectFileInfo(MOFI.get()); 69 70 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions); 71 if (!MAB) 72 return createStringError(std::errc::invalid_argument, 73 "no asm backend for target %s", 74 TripleName.c_str()); 75 76 MII.reset(TheTarget->createMCInstrInfo()); 77 if (!MII) 78 return createStringError(std::errc::invalid_argument, 79 "no instr info info for target %s", 80 TripleName.c_str()); 81 82 MCE = TheTarget->createMCCodeEmitter(*MII, *MC); 83 if (!MCE) 84 return createStringError(std::errc::invalid_argument, 85 "no code emitter for target %s", 86 TripleName.c_str()); 87 88 switch (OutFileType) { 89 case DWARFLinker::OutputFileType::Assembly: { 90 MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(), 91 *MAI, *MII, *MRI); 92 MS = TheTarget->createAsmStreamer( 93 *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP, 94 std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB), 95 true); 96 break; 97 } 98 case DWARFLinker::OutputFileType::Object: { 99 MS = TheTarget->createMCObjectStreamer( 100 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB), 101 MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE), 102 *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible, 103 /*DWARFMustBeAtTheEnd*/ false); 104 break; 105 } 106 } 107 108 if (!MS) 109 return createStringError(std::errc::invalid_argument, 110 "no object streamer for target %s", 111 TripleName.c_str()); 112 113 // Finally create the AsmPrinter we'll use to emit the DIEs. 114 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(), 115 std::nullopt)); 116 if (!TM) 117 return createStringError(std::errc::invalid_argument, 118 "no target machine for target %s", 119 TripleName.c_str()); 120 121 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS))); 122 if (!Asm) 123 return createStringError(std::errc::invalid_argument, 124 "no asm printer for target %s", 125 TripleName.c_str()); 126 Asm->setDwarfUsesRelocationsAcrossSections(false); 127 128 RangesSectionSize = 0; 129 RngListsSectionSize = 0; 130 LocSectionSize = 0; 131 LocListsSectionSize = 0; 132 LineSectionSize = 0; 133 FrameSectionSize = 0; 134 DebugInfoSectionSize = 0; 135 MacInfoSectionSize = 0; 136 MacroSectionSize = 0; 137 138 return Error::success(); 139 } 140 141 void DwarfStreamer::finish() { MS->finish(); } 142 143 void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) { 144 MS->switchSection(MOFI->getDwarfInfoSection()); 145 MC->setDwarfVersion(DwarfVersion); 146 } 147 148 /// Emit the compilation unit header for \p Unit in the debug_info section. 149 /// 150 /// A Dwarf 4 section header is encoded as: 151 /// uint32_t Unit length (omitting this field) 152 /// uint16_t Version 153 /// uint32_t Abbreviation table offset 154 /// uint8_t Address size 155 /// Leading to a total of 11 bytes. 156 /// 157 /// A Dwarf 5 section header is encoded as: 158 /// uint32_t Unit length (omitting this field) 159 /// uint16_t Version 160 /// uint8_t Unit type 161 /// uint8_t Address size 162 /// uint32_t Abbreviation table offset 163 /// Leading to a total of 12 bytes. 164 void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit, 165 unsigned DwarfVersion) { 166 switchToDebugInfoSection(DwarfVersion); 167 168 /// The start of the unit within its section. 169 Unit.setLabelBegin(Asm->createTempSymbol("cu_begin")); 170 Asm->OutStreamer->emitLabel(Unit.getLabelBegin()); 171 172 // Emit size of content not including length itself. The size has already 173 // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to 174 // account for the length field. 175 Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4); 176 Asm->emitInt16(DwarfVersion); 177 178 if (DwarfVersion >= 5) { 179 Asm->emitInt8(dwarf::DW_UT_compile); 180 Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize()); 181 // We share one abbreviations table across all units so it's always at the 182 // start of the section. 183 Asm->emitInt32(0); 184 DebugInfoSectionSize += 12; 185 } else { 186 // We share one abbreviations table across all units so it's always at the 187 // start of the section. 188 Asm->emitInt32(0); 189 Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize()); 190 DebugInfoSectionSize += 11; 191 } 192 193 // Remember this CU. 194 EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()}); 195 } 196 197 /// Emit the \p Abbrevs array as the shared abbreviation table 198 /// for the linked Dwarf file. 199 void DwarfStreamer::emitAbbrevs( 200 const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs, 201 unsigned DwarfVersion) { 202 MS->switchSection(MOFI->getDwarfAbbrevSection()); 203 MC->setDwarfVersion(DwarfVersion); 204 Asm->emitDwarfAbbrevs(Abbrevs); 205 } 206 207 /// Recursively emit the DIE tree rooted at \p Die. 208 void DwarfStreamer::emitDIE(DIE &Die) { 209 MS->switchSection(MOFI->getDwarfInfoSection()); 210 Asm->emitDwarfDIE(Die); 211 DebugInfoSectionSize += Die.getSize(); 212 } 213 214 /// Emit contents of section SecName From Obj. 215 void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) { 216 MCSection *Section = 217 StringSwitch<MCSection *>(SecName) 218 .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection()) 219 .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection()) 220 .Case("debug_ranges", 221 MC->getObjectFileInfo()->getDwarfRangesSection()) 222 .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection()) 223 .Case("debug_aranges", 224 MC->getObjectFileInfo()->getDwarfARangesSection()) 225 .Case("debug_addr", MC->getObjectFileInfo()->getDwarfAddrSection()) 226 .Case("debug_rnglists", 227 MC->getObjectFileInfo()->getDwarfRnglistsSection()) 228 .Case("debug_loclists", 229 MC->getObjectFileInfo()->getDwarfLoclistsSection()) 230 .Default(nullptr); 231 232 if (Section) { 233 MS->switchSection(Section); 234 235 MS->emitBytes(SecData); 236 } 237 } 238 239 /// Emit the debug_str section stored in \p Pool. 240 void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) { 241 Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection()); 242 std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission(); 243 for (auto Entry : Entries) { 244 // Emit the string itself. 245 Asm->OutStreamer->emitBytes(Entry.getString()); 246 // Emit a null terminator. 247 Asm->emitInt8(0); 248 } 249 } 250 251 /// Emit the debug string offset table described by \p StringOffsets into the 252 /// .debug_str_offsets table. 253 void DwarfStreamer::emitStringOffsets( 254 const SmallVector<uint64_t> &StringOffsets, uint16_t TargetDWARFVersion) { 255 256 if (TargetDWARFVersion < 5 || StringOffsets.empty()) 257 return; 258 259 Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection()); 260 261 MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugstroff"); 262 MCSymbol *EndLabel = Asm->createTempSymbol("Edebugstroff"); 263 264 // Length. 265 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t)); 266 Asm->OutStreamer->emitLabel(BeginLabel); 267 StrOffsetSectionSize += sizeof(uint32_t); 268 269 // Version. 270 MS->emitInt16(5); 271 StrOffsetSectionSize += sizeof(uint16_t); 272 273 // Padding. 274 MS->emitInt16(0); 275 StrOffsetSectionSize += sizeof(uint16_t); 276 277 for (auto Off : StringOffsets) { 278 Asm->OutStreamer->emitInt32(Off); 279 StrOffsetSectionSize += sizeof(uint32_t); 280 } 281 Asm->OutStreamer->emitLabel(EndLabel); 282 } 283 284 /// Emit the debug_line_str section stored in \p Pool. 285 void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) { 286 Asm->OutStreamer->switchSection(MOFI->getDwarfLineStrSection()); 287 std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission(); 288 for (auto Entry : Entries) { 289 // Emit the string itself. 290 Asm->OutStreamer->emitBytes(Entry.getString()); 291 // Emit a null terminator. 292 Asm->emitInt8(0); 293 } 294 } 295 296 void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) { 297 if (EmittedUnits.empty()) 298 return; 299 300 // Build up data structures needed to emit this section. 301 std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits; 302 DenseMap<unsigned, unsigned> UniqueIdToCuMap; 303 unsigned Id = 0; 304 for (auto &CU : EmittedUnits) { 305 CompUnits.push_back(CU.LabelBegin); 306 // We might be omitting CUs, so we need to remap them. 307 UniqueIdToCuMap[CU.ID] = Id++; 308 } 309 310 Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection()); 311 dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false, 312 (uint64_t)UniqueIdToCuMap.size() - 1); 313 /// llvm-dwarfutil doesn't support type units + .debug_names right now. 314 // FIXME: add support for type units + .debug_names. For now the behavior is 315 // unsuported. 316 emitDWARF5AccelTable( 317 Asm.get(), Table, CompUnits, 318 [&](const DWARF5AccelTableData &Entry) 319 -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> { 320 if (UniqueIdToCuMap.size() > 1) 321 return {{UniqueIdToCuMap[Entry.getUnitID()], 322 {dwarf::DW_IDX_compile_unit, Form}}}; 323 return std::nullopt; 324 }); 325 } 326 327 void DwarfStreamer::emitAppleNamespaces( 328 AccelTable<AppleAccelTableStaticOffsetData> &Table) { 329 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection()); 330 auto *SectionBegin = Asm->createTempSymbol("namespac_begin"); 331 Asm->OutStreamer->emitLabel(SectionBegin); 332 emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin); 333 } 334 335 void DwarfStreamer::emitAppleNames( 336 AccelTable<AppleAccelTableStaticOffsetData> &Table) { 337 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection()); 338 auto *SectionBegin = Asm->createTempSymbol("names_begin"); 339 Asm->OutStreamer->emitLabel(SectionBegin); 340 emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin); 341 } 342 343 void DwarfStreamer::emitAppleObjc( 344 AccelTable<AppleAccelTableStaticOffsetData> &Table) { 345 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection()); 346 auto *SectionBegin = Asm->createTempSymbol("objc_begin"); 347 Asm->OutStreamer->emitLabel(SectionBegin); 348 emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin); 349 } 350 351 void DwarfStreamer::emitAppleTypes( 352 AccelTable<AppleAccelTableStaticTypeData> &Table) { 353 Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection()); 354 auto *SectionBegin = Asm->createTempSymbol("types_begin"); 355 Asm->OutStreamer->emitLabel(SectionBegin); 356 emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin); 357 } 358 359 /// Emit the swift_ast section stored in \p Buffers. 360 void DwarfStreamer::emitSwiftAST(StringRef Buffer) { 361 MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection(); 362 SwiftASTSection->setAlignment(Align(32)); 363 MS->switchSection(SwiftASTSection); 364 MS->emitBytes(Buffer); 365 } 366 367 void DwarfStreamer::emitSwiftReflectionSection( 368 llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind, 369 StringRef Buffer, uint32_t Alignment, uint32_t Size) { 370 MCSection *ReflectionSection = 371 MOFI->getSwift5ReflectionSection(ReflSectionKind); 372 if (ReflectionSection == nullptr) 373 return; 374 ReflectionSection->setAlignment(Align(Alignment)); 375 MS->switchSection(ReflectionSection); 376 MS->emitBytes(Buffer); 377 } 378 379 void DwarfStreamer::emitDwarfDebugArangesTable( 380 const CompileUnit &Unit, const AddressRanges &LinkedRanges) { 381 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); 382 383 // Make .debug_aranges to be current section. 384 MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection()); 385 386 // Emit Header. 387 MCSymbol *BeginLabel = Asm->createTempSymbol("Barange"); 388 MCSymbol *EndLabel = Asm->createTempSymbol("Earange"); 389 390 unsigned HeaderSize = 391 sizeof(int32_t) + // Size of contents (w/o this field 392 sizeof(int16_t) + // DWARF ARange version number 393 sizeof(int32_t) + // Offset of CU in the .debug_info section 394 sizeof(int8_t) + // Pointer Size (in bytes) 395 sizeof(int8_t); // Segment Size (in bytes) 396 397 unsigned TupleSize = AddressSize * 2; 398 unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize)); 399 400 Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length 401 Asm->OutStreamer->emitLabel(BeginLabel); 402 Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number 403 Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset 404 Asm->emitInt8(AddressSize); // Address size 405 Asm->emitInt8(0); // Segment size 406 407 Asm->OutStreamer->emitFill(Padding, 0x0); 408 409 // Emit linked ranges. 410 for (const AddressRange &Range : LinkedRanges) { 411 MS->emitIntValue(Range.start(), AddressSize); 412 MS->emitIntValue(Range.end() - Range.start(), AddressSize); 413 } 414 415 // Emit terminator. 416 Asm->OutStreamer->emitIntValue(0, AddressSize); 417 Asm->OutStreamer->emitIntValue(0, AddressSize); 418 Asm->OutStreamer->emitLabel(EndLabel); 419 } 420 421 void DwarfStreamer::emitDwarfDebugRangesTableFragment( 422 const CompileUnit &Unit, const AddressRanges &LinkedRanges, 423 PatchLocation Patch) { 424 Patch.set(RangesSectionSize); 425 426 // Make .debug_ranges to be current section. 427 MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection()); 428 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); 429 430 // Emit ranges. 431 uint64_t BaseAddress = 0; 432 if (std::optional<uint64_t> LowPC = Unit.getLowPc()) 433 BaseAddress = *LowPC; 434 435 for (const AddressRange &Range : LinkedRanges) { 436 MS->emitIntValue(Range.start() - BaseAddress, AddressSize); 437 MS->emitIntValue(Range.end() - BaseAddress, AddressSize); 438 439 RangesSectionSize += AddressSize; 440 RangesSectionSize += AddressSize; 441 } 442 443 // Add the terminator entry. 444 MS->emitIntValue(0, AddressSize); 445 MS->emitIntValue(0, AddressSize); 446 447 RangesSectionSize += AddressSize; 448 RangesSectionSize += AddressSize; 449 } 450 451 MCSymbol * 452 DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) { 453 if (Unit.getOrigUnit().getVersion() < 5) 454 return nullptr; 455 456 // Make .debug_rnglists to be current section. 457 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection()); 458 459 MCSymbol *BeginLabel = Asm->createTempSymbol("Brnglists"); 460 MCSymbol *EndLabel = Asm->createTempSymbol("Ernglists"); 461 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); 462 463 // Length 464 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t)); 465 Asm->OutStreamer->emitLabel(BeginLabel); 466 RngListsSectionSize += sizeof(uint32_t); 467 468 // Version. 469 MS->emitInt16(5); 470 RngListsSectionSize += sizeof(uint16_t); 471 472 // Address size. 473 MS->emitInt8(AddressSize); 474 RngListsSectionSize++; 475 476 // Seg_size 477 MS->emitInt8(0); 478 RngListsSectionSize++; 479 480 // Offset entry count 481 MS->emitInt32(0); 482 RngListsSectionSize += sizeof(uint32_t); 483 484 return EndLabel; 485 } 486 487 void DwarfStreamer::emitDwarfDebugRangeListFragment( 488 const CompileUnit &Unit, const AddressRanges &LinkedRanges, 489 PatchLocation Patch, DebugDieValuePool &AddrPool) { 490 if (Unit.getOrigUnit().getVersion() < 5) { 491 emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch); 492 return; 493 } 494 495 emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch, AddrPool); 496 } 497 498 void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit, 499 MCSymbol *EndLabel) { 500 if (Unit.getOrigUnit().getVersion() < 5) 501 return; 502 503 // Make .debug_rnglists to be current section. 504 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection()); 505 506 if (EndLabel != nullptr) 507 Asm->OutStreamer->emitLabel(EndLabel); 508 } 509 510 void DwarfStreamer::emitDwarfDebugRngListsTableFragment( 511 const CompileUnit &Unit, const AddressRanges &LinkedRanges, 512 PatchLocation Patch, DebugDieValuePool &AddrPool) { 513 Patch.set(RngListsSectionSize); 514 515 // Make .debug_rnglists to be current section. 516 MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection()); 517 std::optional<uint64_t> BaseAddress; 518 519 for (const AddressRange &Range : LinkedRanges) { 520 521 if (!BaseAddress) { 522 BaseAddress = Range.start(); 523 524 // Emit base address. 525 MS->emitInt8(dwarf::DW_RLE_base_addressx); 526 RngListsSectionSize += 1; 527 RngListsSectionSize += 528 MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress)); 529 } 530 531 // Emit type of entry. 532 MS->emitInt8(dwarf::DW_RLE_offset_pair); 533 RngListsSectionSize += 1; 534 535 // Emit start offset relative to base address. 536 RngListsSectionSize += 537 MS->emitULEB128IntValue(Range.start() - *BaseAddress); 538 539 // Emit end offset relative to base address. 540 RngListsSectionSize += MS->emitULEB128IntValue(Range.end() - *BaseAddress); 541 } 542 543 // Emit the terminator entry. 544 MS->emitInt8(dwarf::DW_RLE_end_of_list); 545 RngListsSectionSize += 1; 546 } 547 548 /// Emit debug locations(.debug_loc, .debug_loclists) header. 549 MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) { 550 if (Unit.getOrigUnit().getVersion() < 5) 551 return nullptr; 552 553 // Make .debug_loclists the current section. 554 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection()); 555 556 MCSymbol *BeginLabel = Asm->createTempSymbol("Bloclists"); 557 MCSymbol *EndLabel = Asm->createTempSymbol("Eloclists"); 558 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); 559 560 // Length 561 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t)); 562 Asm->OutStreamer->emitLabel(BeginLabel); 563 LocListsSectionSize += sizeof(uint32_t); 564 565 // Version. 566 MS->emitInt16(5); 567 LocListsSectionSize += sizeof(uint16_t); 568 569 // Address size. 570 MS->emitInt8(AddressSize); 571 LocListsSectionSize++; 572 573 // Seg_size 574 MS->emitInt8(0); 575 LocListsSectionSize++; 576 577 // Offset entry count 578 MS->emitInt32(0); 579 LocListsSectionSize += sizeof(uint32_t); 580 581 return EndLabel; 582 } 583 584 /// Emit debug locations(.debug_loc, .debug_loclists) fragment. 585 void DwarfStreamer::emitDwarfDebugLocListFragment( 586 const CompileUnit &Unit, 587 const DWARFLocationExpressionsVector &LinkedLocationExpression, 588 PatchLocation Patch, DebugDieValuePool &AddrPool) { 589 if (Unit.getOrigUnit().getVersion() < 5) { 590 emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch); 591 return; 592 } 593 594 emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch, 595 AddrPool); 596 } 597 598 /// Emit debug locations(.debug_loc, .debug_loclists) footer. 599 void DwarfStreamer::emitDwarfDebugLocListFooter(const CompileUnit &Unit, 600 MCSymbol *EndLabel) { 601 if (Unit.getOrigUnit().getVersion() < 5) 602 return; 603 604 // Make .debug_loclists the current section. 605 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection()); 606 607 if (EndLabel != nullptr) 608 Asm->OutStreamer->emitLabel(EndLabel); 609 } 610 611 /// Emit piece of .debug_loc for \p LinkedLocationExpression. 612 void DwarfStreamer::emitDwarfDebugLocTableFragment( 613 const CompileUnit &Unit, 614 const DWARFLocationExpressionsVector &LinkedLocationExpression, 615 PatchLocation Patch) { 616 Patch.set(LocSectionSize); 617 618 // Make .debug_loc to be current section. 619 MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection()); 620 unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize(); 621 622 // Emit ranges. 623 uint64_t BaseAddress = 0; 624 if (std::optional<uint64_t> LowPC = Unit.getLowPc()) 625 BaseAddress = *LowPC; 626 627 for (const DWARFLocationExpression &LocExpression : 628 LinkedLocationExpression) { 629 if (LocExpression.Range) { 630 MS->emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize); 631 MS->emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize); 632 633 LocSectionSize += AddressSize; 634 LocSectionSize += AddressSize; 635 } 636 637 Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2); 638 Asm->OutStreamer->emitBytes(StringRef( 639 (const char *)LocExpression.Expr.data(), LocExpression.Expr.size())); 640 LocSectionSize += LocExpression.Expr.size() + 2; 641 } 642 643 // Add the terminator entry. 644 MS->emitIntValue(0, AddressSize); 645 MS->emitIntValue(0, AddressSize); 646 647 LocSectionSize += AddressSize; 648 LocSectionSize += AddressSize; 649 } 650 651 /// Emit .debug_addr header. 652 MCSymbol *DwarfStreamer::emitDwarfDebugAddrsHeader(const CompileUnit &Unit) { 653 654 // Make .debug_addr the current section. 655 MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection()); 656 657 MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugaddr"); 658 MCSymbol *EndLabel = Asm->createTempSymbol("Edebugaddr"); 659 unsigned AddrSize = Unit.getOrigUnit().getAddressByteSize(); 660 661 // Emit length. 662 Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t)); 663 Asm->OutStreamer->emitLabel(BeginLabel); 664 AddrSectionSize += sizeof(uint32_t); 665 666 // Emit version. 667 Asm->emitInt16(5); 668 AddrSectionSize += 2; 669 670 // Emit address size. 671 Asm->emitInt8(AddrSize); 672 AddrSectionSize += 1; 673 674 // Emit segment size. 675 Asm->emitInt8(0); 676 AddrSectionSize += 1; 677 678 return EndLabel; 679 } 680 681 /// Emit the .debug_addr addresses stored in \p Addrs. 682 void DwarfStreamer::emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs, 683 uint8_t AddrSize) { 684 Asm->OutStreamer->switchSection(MOFI->getDwarfAddrSection()); 685 for (auto Addr : Addrs) { 686 Asm->OutStreamer->emitIntValue(Addr, AddrSize); 687 AddrSectionSize += AddrSize; 688 } 689 } 690 691 /// Emit .debug_addr footer. 692 void DwarfStreamer::emitDwarfDebugAddrsFooter(const CompileUnit &Unit, 693 MCSymbol *EndLabel) { 694 695 // Make .debug_addr the current section. 696 MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection()); 697 698 if (EndLabel != nullptr) 699 Asm->OutStreamer->emitLabel(EndLabel); 700 } 701 702 /// Emit piece of .debug_loclists for \p LinkedLocationExpression. 703 void DwarfStreamer::emitDwarfDebugLocListsTableFragment( 704 const CompileUnit &Unit, 705 const DWARFLocationExpressionsVector &LinkedLocationExpression, 706 PatchLocation Patch, DebugDieValuePool &AddrPool) { 707 Patch.set(LocListsSectionSize); 708 709 // Make .debug_loclists the current section. 710 MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection()); 711 std::optional<uint64_t> BaseAddress; 712 713 for (const DWARFLocationExpression &LocExpression : 714 LinkedLocationExpression) { 715 if (LocExpression.Range) { 716 717 if (!BaseAddress) { 718 719 BaseAddress = LocExpression.Range->LowPC; 720 721 // Emit base address. 722 MS->emitInt8(dwarf::DW_LLE_base_addressx); 723 LocListsSectionSize += 1; 724 LocListsSectionSize += 725 MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress)); 726 } 727 728 // Emit type of entry. 729 MS->emitInt8(dwarf::DW_LLE_offset_pair); 730 LocListsSectionSize += 1; 731 732 // Emit start offset relative to base address. 733 LocListsSectionSize += 734 MS->emitULEB128IntValue(LocExpression.Range->LowPC - *BaseAddress); 735 736 // Emit end offset relative to base address. 737 LocListsSectionSize += 738 MS->emitULEB128IntValue(LocExpression.Range->HighPC - *BaseAddress); 739 } else { 740 // Emit type of entry. 741 MS->emitInt8(dwarf::DW_LLE_default_location); 742 LocListsSectionSize += 1; 743 } 744 745 LocListsSectionSize += MS->emitULEB128IntValue(LocExpression.Expr.size()); 746 Asm->OutStreamer->emitBytes(StringRef( 747 (const char *)LocExpression.Expr.data(), LocExpression.Expr.size())); 748 LocListsSectionSize += LocExpression.Expr.size(); 749 } 750 751 // Emit the terminator entry. 752 MS->emitInt8(dwarf::DW_LLE_end_of_list); 753 LocListsSectionSize += 1; 754 } 755 756 void DwarfStreamer::emitLineTableForUnit( 757 const DWARFDebugLine::LineTable &LineTable, const CompileUnit &Unit, 758 OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool) { 759 // Switch to the section where the table will be emitted into. 760 MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection()); 761 762 MCSymbol *LineStartSym = MC->createTempSymbol(); 763 MCSymbol *LineEndSym = MC->createTempSymbol(); 764 765 // unit_length. 766 if (LineTable.Prologue.FormParams.Format == dwarf::DwarfFormat::DWARF64) { 767 MS->emitInt32(dwarf::DW_LENGTH_DWARF64); 768 LineSectionSize += 4; 769 } 770 emitLabelDifference(LineEndSym, LineStartSym, 771 LineTable.Prologue.FormParams.Format, LineSectionSize); 772 Asm->OutStreamer->emitLabel(LineStartSym); 773 774 // Emit prologue. 775 emitLineTablePrologue(LineTable.Prologue, DebugStrPool, DebugLineStrPool); 776 777 // Emit rows. 778 emitLineTableRows(LineTable, LineEndSym, 779 Unit.getOrigUnit().getAddressByteSize()); 780 } 781 782 void DwarfStreamer::emitLineTablePrologue(const DWARFDebugLine::Prologue &P, 783 OffsetsStringPool &DebugStrPool, 784 OffsetsStringPool &DebugLineStrPool) { 785 MCSymbol *PrologueStartSym = MC->createTempSymbol(); 786 MCSymbol *PrologueEndSym = MC->createTempSymbol(); 787 788 // version (uhalf). 789 MS->emitInt16(P.getVersion()); 790 LineSectionSize += 2; 791 if (P.getVersion() == 5) { 792 // address_size (ubyte). 793 MS->emitInt8(P.getAddressSize()); 794 LineSectionSize += 1; 795 796 // segment_selector_size (ubyte). 797 MS->emitInt8(P.SegSelectorSize); 798 LineSectionSize += 1; 799 } 800 801 // header_length. 802 emitLabelDifference(PrologueEndSym, PrologueStartSym, P.FormParams.Format, 803 LineSectionSize); 804 805 Asm->OutStreamer->emitLabel(PrologueStartSym); 806 emitLineTableProloguePayload(P, DebugStrPool, DebugLineStrPool); 807 Asm->OutStreamer->emitLabel(PrologueEndSym); 808 } 809 810 void DwarfStreamer::emitLineTablePrologueV2IncludeAndFileTable( 811 const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, 812 OffsetsStringPool &DebugLineStrPool) { 813 // include_directories (sequence of path names). 814 for (const DWARFFormValue &Include : P.IncludeDirectories) 815 emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool); 816 // The last entry is followed by a single null byte. 817 MS->emitInt8(0); 818 LineSectionSize += 1; 819 820 // file_names (sequence of file entries). 821 for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) { 822 // A null-terminated string containing the full or relative path name of a 823 // source file. 824 emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool); 825 // An unsigned LEB128 number representing the directory index of a directory 826 // in the include_directories section. 827 LineSectionSize += MS->emitULEB128IntValue(File.DirIdx); 828 // An unsigned LEB128 number representing the (implementation-defined) time 829 // of last modification for the file, or 0 if not available. 830 LineSectionSize += MS->emitULEB128IntValue(File.ModTime); 831 // An unsigned LEB128 number representing the length in bytes of the file, 832 // or 0 if not available. 833 LineSectionSize += MS->emitULEB128IntValue(File.Length); 834 } 835 // The last entry is followed by a single null byte. 836 MS->emitInt8(0); 837 LineSectionSize += 1; 838 } 839 840 void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable( 841 const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, 842 OffsetsStringPool &DebugLineStrPool) { 843 if (P.IncludeDirectories.empty()) { 844 // directory_entry_format_count(ubyte). 845 MS->emitInt8(0); 846 LineSectionSize += 1; 847 } else { 848 // directory_entry_format_count(ubyte). 849 MS->emitInt8(1); 850 LineSectionSize += 1; 851 852 // directory_entry_format (sequence of ULEB128 pairs). 853 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path); 854 LineSectionSize += 855 MS->emitULEB128IntValue(P.IncludeDirectories[0].getForm()); 856 } 857 858 // directories_count (ULEB128). 859 LineSectionSize += MS->emitULEB128IntValue(P.IncludeDirectories.size()); 860 // directories (sequence of directory names). 861 for (auto Include : P.IncludeDirectories) 862 emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool); 863 864 bool HasChecksums = P.ContentTypes.HasMD5; 865 bool HasInlineSources = P.ContentTypes.HasSource; 866 867 if (P.FileNames.empty()) { 868 // file_name_entry_format_count (ubyte). 869 MS->emitInt8(0); 870 LineSectionSize += 1; 871 } else { 872 // file_name_entry_format_count (ubyte). 873 MS->emitInt8(2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0)); 874 LineSectionSize += 1; 875 876 // file_name_entry_format (sequence of ULEB128 pairs). 877 auto StrForm = P.FileNames[0].Name.getForm(); 878 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path); 879 LineSectionSize += MS->emitULEB128IntValue(StrForm); 880 881 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index); 882 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data1); 883 884 if (HasChecksums) { 885 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_MD5); 886 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data16); 887 } 888 889 if (HasInlineSources) { 890 LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source); 891 LineSectionSize += MS->emitULEB128IntValue(StrForm); 892 } 893 } 894 895 // file_names_count (ULEB128). 896 LineSectionSize += MS->emitULEB128IntValue(P.FileNames.size()); 897 898 // file_names (sequence of file name entries). 899 for (auto File : P.FileNames) { 900 emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool); 901 MS->emitInt8(File.DirIdx); 902 LineSectionSize += 1; 903 if (HasChecksums) { 904 MS->emitBinaryData( 905 StringRef(reinterpret_cast<const char *>(File.Checksum.data()), 906 File.Checksum.size())); 907 LineSectionSize += File.Checksum.size(); 908 } 909 if (HasInlineSources) 910 emitLineTableString(P, File.Source, DebugStrPool, DebugLineStrPool); 911 } 912 } 913 914 void DwarfStreamer::emitLineTableString(const DWARFDebugLine::Prologue &P, 915 const DWARFFormValue &String, 916 OffsetsStringPool &DebugStrPool, 917 OffsetsStringPool &DebugLineStrPool) { 918 std::optional<const char *> StringVal = dwarf::toString(String); 919 if (!StringVal) { 920 warn("Cann't read string from line table."); 921 return; 922 } 923 924 switch (String.getForm()) { 925 case dwarf::DW_FORM_string: { 926 StringRef TranslatedString = 927 (Translator) ? Translator(*StringVal) : *StringVal; 928 Asm->OutStreamer->emitBytes(TranslatedString.data()); 929 Asm->emitInt8(0); 930 LineSectionSize += TranslatedString.size() + 1; 931 } break; 932 case dwarf::DW_FORM_strp: 933 case dwarf::DW_FORM_line_strp: { 934 DwarfStringPoolEntryRef StringRef = 935 String.getForm() == dwarf::DW_FORM_strp 936 ? DebugStrPool.getEntry(*StringVal) 937 : DebugLineStrPool.getEntry(*StringVal); 938 939 emitIntOffset(StringRef.getOffset(), P.FormParams.Format, LineSectionSize); 940 } break; 941 default: 942 warn("Unsupported string form inside line table."); 943 break; 944 }; 945 } 946 947 void DwarfStreamer::emitLineTableProloguePayload( 948 const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, 949 OffsetsStringPool &DebugLineStrPool) { 950 // minimum_instruction_length (ubyte). 951 MS->emitInt8(P.MinInstLength); 952 LineSectionSize += 1; 953 if (P.FormParams.Version >= 4) { 954 // maximum_operations_per_instruction (ubyte). 955 MS->emitInt8(P.MaxOpsPerInst); 956 LineSectionSize += 1; 957 } 958 // default_is_stmt (ubyte). 959 MS->emitInt8(P.DefaultIsStmt); 960 LineSectionSize += 1; 961 // line_base (sbyte). 962 MS->emitInt8(P.LineBase); 963 LineSectionSize += 1; 964 // line_range (ubyte). 965 MS->emitInt8(P.LineRange); 966 LineSectionSize += 1; 967 // opcode_base (ubyte). 968 MS->emitInt8(P.OpcodeBase); 969 LineSectionSize += 1; 970 971 // standard_opcode_lengths (array of ubyte). 972 for (auto Length : P.StandardOpcodeLengths) { 973 MS->emitInt8(Length); 974 LineSectionSize += 1; 975 } 976 977 if (P.FormParams.Version < 5) 978 emitLineTablePrologueV2IncludeAndFileTable(P, DebugStrPool, 979 DebugLineStrPool); 980 else 981 emitLineTablePrologueV5IncludeAndFileTable(P, DebugStrPool, 982 DebugLineStrPool); 983 } 984 985 void DwarfStreamer::emitLineTableRows( 986 const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym, 987 unsigned AddressByteSize) { 988 989 MCDwarfLineTableParams Params; 990 Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; 991 Params.DWARF2LineBase = LineTable.Prologue.LineBase; 992 Params.DWARF2LineRange = LineTable.Prologue.LineRange; 993 994 SmallString<128> EncodingBuffer; 995 996 if (LineTable.Rows.empty()) { 997 // We only have the dummy entry, dsymutil emits an entry with a 0 998 // address in that case. 999 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, 1000 EncodingBuffer); 1001 MS->emitBytes(EncodingBuffer); 1002 LineSectionSize += EncodingBuffer.size(); 1003 MS->emitLabel(LineEndSym); 1004 return; 1005 } 1006 1007 // Line table state machine fields 1008 unsigned FileNum = 1; 1009 unsigned LastLine = 1; 1010 unsigned Column = 0; 1011 unsigned IsStatement = 1; 1012 unsigned Isa = 0; 1013 uint64_t Address = -1ULL; 1014 1015 unsigned RowsSinceLastSequence = 0; 1016 1017 for (const DWARFDebugLine::Row &Row : LineTable.Rows) { 1018 int64_t AddressDelta; 1019 if (Address == -1ULL) { 1020 MS->emitIntValue(dwarf::DW_LNS_extended_op, 1); 1021 MS->emitULEB128IntValue(AddressByteSize + 1); 1022 MS->emitIntValue(dwarf::DW_LNE_set_address, 1); 1023 MS->emitIntValue(Row.Address.Address, AddressByteSize); 1024 LineSectionSize += 1025 2 + AddressByteSize + getULEB128Size(AddressByteSize + 1); 1026 AddressDelta = 0; 1027 } else { 1028 AddressDelta = 1029 (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength; 1030 } 1031 1032 // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable. 1033 // We should find a way to share this code, but the current compatibility 1034 // requirement with classic dsymutil makes it hard. Revisit that once this 1035 // requirement is dropped. 1036 1037 if (FileNum != Row.File) { 1038 FileNum = Row.File; 1039 MS->emitIntValue(dwarf::DW_LNS_set_file, 1); 1040 MS->emitULEB128IntValue(FileNum); 1041 LineSectionSize += 1 + getULEB128Size(FileNum); 1042 } 1043 if (Column != Row.Column) { 1044 Column = Row.Column; 1045 MS->emitIntValue(dwarf::DW_LNS_set_column, 1); 1046 MS->emitULEB128IntValue(Column); 1047 LineSectionSize += 1 + getULEB128Size(Column); 1048 } 1049 1050 // FIXME: We should handle the discriminator here, but dsymutil doesn't 1051 // consider it, thus ignore it for now. 1052 1053 if (Isa != Row.Isa) { 1054 Isa = Row.Isa; 1055 MS->emitIntValue(dwarf::DW_LNS_set_isa, 1); 1056 MS->emitULEB128IntValue(Isa); 1057 LineSectionSize += 1 + getULEB128Size(Isa); 1058 } 1059 if (IsStatement != Row.IsStmt) { 1060 IsStatement = Row.IsStmt; 1061 MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1); 1062 LineSectionSize += 1; 1063 } 1064 if (Row.BasicBlock) { 1065 MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1); 1066 LineSectionSize += 1; 1067 } 1068 1069 if (Row.PrologueEnd) { 1070 MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1); 1071 LineSectionSize += 1; 1072 } 1073 1074 if (Row.EpilogueBegin) { 1075 MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); 1076 LineSectionSize += 1; 1077 } 1078 1079 int64_t LineDelta = int64_t(Row.Line) - LastLine; 1080 if (!Row.EndSequence) { 1081 MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta, 1082 EncodingBuffer); 1083 MS->emitBytes(EncodingBuffer); 1084 LineSectionSize += EncodingBuffer.size(); 1085 EncodingBuffer.resize(0); 1086 Address = Row.Address.Address; 1087 LastLine = Row.Line; 1088 RowsSinceLastSequence++; 1089 } else { 1090 if (LineDelta) { 1091 MS->emitIntValue(dwarf::DW_LNS_advance_line, 1); 1092 MS->emitSLEB128IntValue(LineDelta); 1093 LineSectionSize += 1 + getSLEB128Size(LineDelta); 1094 } 1095 if (AddressDelta) { 1096 MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1); 1097 MS->emitULEB128IntValue(AddressDelta); 1098 LineSectionSize += 1 + getULEB128Size(AddressDelta); 1099 } 1100 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 1101 0, EncodingBuffer); 1102 MS->emitBytes(EncodingBuffer); 1103 LineSectionSize += EncodingBuffer.size(); 1104 EncodingBuffer.resize(0); 1105 Address = -1ULL; 1106 LastLine = FileNum = IsStatement = 1; 1107 RowsSinceLastSequence = Column = Isa = 0; 1108 } 1109 } 1110 1111 if (RowsSinceLastSequence) { 1112 MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, 1113 EncodingBuffer); 1114 MS->emitBytes(EncodingBuffer); 1115 LineSectionSize += EncodingBuffer.size(); 1116 EncodingBuffer.resize(0); 1117 } 1118 1119 MS->emitLabel(LineEndSym); 1120 } 1121 1122 void DwarfStreamer::emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format, 1123 uint64_t &SectionSize) { 1124 uint8_t Size = dwarf::getDwarfOffsetByteSize(Format); 1125 MS->emitIntValue(Offset, Size); 1126 SectionSize += Size; 1127 } 1128 1129 void DwarfStreamer::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, 1130 dwarf::DwarfFormat Format, 1131 uint64_t &SectionSize) { 1132 uint8_t Size = dwarf::getDwarfOffsetByteSize(Format); 1133 Asm->emitLabelDifference(Hi, Lo, Size); 1134 SectionSize += Size; 1135 } 1136 1137 /// Emit the pubnames or pubtypes section contribution for \p 1138 /// Unit into \p Sec. The data is provided in \p Names. 1139 void DwarfStreamer::emitPubSectionForUnit( 1140 MCSection *Sec, StringRef SecName, const CompileUnit &Unit, 1141 const std::vector<CompileUnit::AccelInfo> &Names) { 1142 if (Names.empty()) 1143 return; 1144 1145 // Start the dwarf pubnames section. 1146 Asm->OutStreamer->switchSection(Sec); 1147 MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin"); 1148 MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end"); 1149 1150 bool HeaderEmitted = false; 1151 // Emit the pubnames for this compilation unit. 1152 for (const auto &Name : Names) { 1153 if (Name.SkipPubSection) 1154 continue; 1155 1156 if (!HeaderEmitted) { 1157 // Emit the header. 1158 Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length 1159 Asm->OutStreamer->emitLabel(BeginLabel); 1160 Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version 1161 Asm->emitInt32(Unit.getStartOffset()); // Unit offset 1162 Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size 1163 HeaderEmitted = true; 1164 } 1165 Asm->emitInt32(Name.Die->getOffset()); 1166 1167 // Emit the string itself. 1168 Asm->OutStreamer->emitBytes(Name.Name.getString()); 1169 // Emit a null terminator. 1170 Asm->emitInt8(0); 1171 } 1172 1173 if (!HeaderEmitted) 1174 return; 1175 Asm->emitInt32(0); // End marker. 1176 Asm->OutStreamer->emitLabel(EndLabel); 1177 } 1178 1179 /// Emit .debug_pubnames for \p Unit. 1180 void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) { 1181 emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(), 1182 "names", Unit, Unit.getPubnames()); 1183 } 1184 1185 /// Emit .debug_pubtypes for \p Unit. 1186 void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) { 1187 emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(), 1188 "types", Unit, Unit.getPubtypes()); 1189 } 1190 1191 /// Emit a CIE into the debug_frame section. 1192 void DwarfStreamer::emitCIE(StringRef CIEBytes) { 1193 MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); 1194 1195 MS->emitBytes(CIEBytes); 1196 FrameSectionSize += CIEBytes.size(); 1197 } 1198 1199 /// Emit a FDE into the debug_frame section. \p FDEBytes 1200 /// contains the FDE data without the length, CIE offset and address 1201 /// which will be replaced with the parameter values. 1202 void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, 1203 uint64_t Address, StringRef FDEBytes) { 1204 MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); 1205 1206 MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4); 1207 MS->emitIntValue(CIEOffset, 4); 1208 MS->emitIntValue(Address, AddrSize); 1209 MS->emitBytes(FDEBytes); 1210 FrameSectionSize += FDEBytes.size() + 8 + AddrSize; 1211 } 1212 1213 void DwarfStreamer::emitMacroTables(DWARFContext *Context, 1214 const Offset2UnitMap &UnitMacroMap, 1215 OffsetsStringPool &StringPool) { 1216 assert(Context != nullptr && "Empty DWARF context"); 1217 1218 // Check for .debug_macinfo table. 1219 if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) { 1220 MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection()); 1221 emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize); 1222 } 1223 1224 // Check for .debug_macro table. 1225 if (const DWARFDebugMacro *Table = Context->getDebugMacro()) { 1226 MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection()); 1227 emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize); 1228 } 1229 } 1230 1231 void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable, 1232 const Offset2UnitMap &UnitMacroMap, 1233 OffsetsStringPool &StringPool, 1234 uint64_t &OutOffset) { 1235 bool DefAttributeIsReported = false; 1236 bool UndefAttributeIsReported = false; 1237 bool ImportAttributeIsReported = false; 1238 for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) { 1239 Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset); 1240 if (UnitIt == UnitMacroMap.end()) { 1241 warn(formatv( 1242 "couldn`t find compile unit for the macro table with offset = {0:x}", 1243 List.Offset)); 1244 continue; 1245 } 1246 1247 // Skip macro table if the unit was not cloned. 1248 DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE(); 1249 if (OutputUnitDIE == nullptr) 1250 continue; 1251 1252 // Update macro attribute of cloned compile unit with the proper offset to 1253 // the macro table. 1254 bool hasDWARFv5Header = false; 1255 for (auto &V : OutputUnitDIE->values()) { 1256 if (V.getAttribute() == dwarf::DW_AT_macro_info) { 1257 V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset)); 1258 break; 1259 } else if (V.getAttribute() == dwarf::DW_AT_macros) { 1260 hasDWARFv5Header = true; 1261 V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset)); 1262 break; 1263 } 1264 } 1265 1266 // Write DWARFv5 header. 1267 if (hasDWARFv5Header) { 1268 // Write header version. 1269 MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version)); 1270 OutOffset += sizeof(List.Header.Version); 1271 1272 uint8_t Flags = List.Header.Flags; 1273 1274 // Check for OPCODE_OPERANDS_TABLE. 1275 if (Flags & 1276 DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) { 1277 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE; 1278 warn("opcode_operands_table is not supported yet."); 1279 } 1280 1281 // Check for DEBUG_LINE_OFFSET. 1282 std::optional<uint64_t> StmtListOffset; 1283 if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) { 1284 // Get offset to the line table from the cloned compile unit. 1285 for (auto &V : OutputUnitDIE->values()) { 1286 if (V.getAttribute() == dwarf::DW_AT_stmt_list) { 1287 StmtListOffset = V.getDIEInteger().getValue(); 1288 break; 1289 } 1290 } 1291 1292 if (!StmtListOffset) { 1293 Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET; 1294 warn("couldn`t find line table for macro table."); 1295 } 1296 } 1297 1298 // Write flags. 1299 MS->emitIntValue(Flags, sizeof(Flags)); 1300 OutOffset += sizeof(Flags); 1301 1302 // Write offset to line table. 1303 if (StmtListOffset) { 1304 MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize()); 1305 OutOffset += List.Header.getOffsetByteSize(); 1306 } 1307 } 1308 1309 // Write macro entries. 1310 for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) { 1311 if (MacroEntry.Type == 0) { 1312 OutOffset += MS->emitULEB128IntValue(MacroEntry.Type); 1313 continue; 1314 } 1315 1316 uint8_t MacroType = MacroEntry.Type; 1317 switch (MacroType) { 1318 default: { 1319 bool HasVendorSpecificExtension = 1320 (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) || 1321 (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user && 1322 MacroType <= dwarf::DW_MACRO_hi_user)); 1323 1324 if (HasVendorSpecificExtension) { 1325 // Write macinfo type. 1326 MS->emitIntValue(MacroType, 1); 1327 OutOffset++; 1328 1329 // Write vendor extension constant. 1330 OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant); 1331 1332 // Write vendor extension string. 1333 StringRef String = MacroEntry.ExtStr; 1334 MS->emitBytes(String); 1335 MS->emitIntValue(0, 1); 1336 OutOffset += String.size() + 1; 1337 } else 1338 warn("unknown macro type. skip."); 1339 } break; 1340 // debug_macro and debug_macinfo share some common encodings. 1341 // DW_MACRO_define == DW_MACINFO_define 1342 // DW_MACRO_undef == DW_MACINFO_undef 1343 // DW_MACRO_start_file == DW_MACINFO_start_file 1344 // DW_MACRO_end_file == DW_MACINFO_end_file 1345 // For readibility/uniformity we are using DW_MACRO_*. 1346 case dwarf::DW_MACRO_define: 1347 case dwarf::DW_MACRO_undef: { 1348 // Write macinfo type. 1349 MS->emitIntValue(MacroType, 1); 1350 OutOffset++; 1351 1352 // Write source line. 1353 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line); 1354 1355 // Write macro string. 1356 StringRef String = MacroEntry.MacroStr; 1357 MS->emitBytes(String); 1358 MS->emitIntValue(0, 1); 1359 OutOffset += String.size() + 1; 1360 } break; 1361 case dwarf::DW_MACRO_define_strp: 1362 case dwarf::DW_MACRO_undef_strp: 1363 case dwarf::DW_MACRO_define_strx: 1364 case dwarf::DW_MACRO_undef_strx: { 1365 assert(UnitIt->second->getOrigUnit().getVersion() >= 5); 1366 1367 // DW_MACRO_*_strx forms are not supported currently. 1368 // Convert to *_strp. 1369 switch (MacroType) { 1370 case dwarf::DW_MACRO_define_strx: { 1371 MacroType = dwarf::DW_MACRO_define_strp; 1372 if (!DefAttributeIsReported) { 1373 warn("DW_MACRO_define_strx unsupported yet. Convert to " 1374 "DW_MACRO_define_strp."); 1375 DefAttributeIsReported = true; 1376 } 1377 } break; 1378 case dwarf::DW_MACRO_undef_strx: { 1379 MacroType = dwarf::DW_MACRO_undef_strp; 1380 if (!UndefAttributeIsReported) { 1381 warn("DW_MACRO_undef_strx unsupported yet. Convert to " 1382 "DW_MACRO_undef_strp."); 1383 UndefAttributeIsReported = true; 1384 } 1385 } break; 1386 default: 1387 // Nothing to do. 1388 break; 1389 } 1390 1391 // Write macinfo type. 1392 MS->emitIntValue(MacroType, 1); 1393 OutOffset++; 1394 1395 // Write source line. 1396 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line); 1397 1398 // Write macro string. 1399 DwarfStringPoolEntryRef EntryRef = 1400 StringPool.getEntry(MacroEntry.MacroStr); 1401 MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize()); 1402 OutOffset += List.Header.getOffsetByteSize(); 1403 break; 1404 } 1405 case dwarf::DW_MACRO_start_file: { 1406 // Write macinfo type. 1407 MS->emitIntValue(MacroType, 1); 1408 OutOffset++; 1409 // Write source line. 1410 OutOffset += MS->emitULEB128IntValue(MacroEntry.Line); 1411 // Write source file id. 1412 OutOffset += MS->emitULEB128IntValue(MacroEntry.File); 1413 } break; 1414 case dwarf::DW_MACRO_end_file: { 1415 // Write macinfo type. 1416 MS->emitIntValue(MacroType, 1); 1417 OutOffset++; 1418 } break; 1419 case dwarf::DW_MACRO_import: 1420 case dwarf::DW_MACRO_import_sup: { 1421 if (!ImportAttributeIsReported) { 1422 warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. " 1423 "remove."); 1424 ImportAttributeIsReported = true; 1425 } 1426 } break; 1427 } 1428 } 1429 } 1430 } 1431