brintos

brintos / llvm-project-archived public Read only

0
0
Text · 52.1 KiB · 1c0ddc8 Raw
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