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