Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Classic/DWARFStreamer.cpp
35292 views
//===- DwarfStreamer.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/DWARFLinker/Classic/DWARFStreamer.h"9#include "llvm/CodeGen/NonRelocatableStringpool.h"10#include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h"11#include "llvm/DebugInfo/DWARF/DWARFContext.h"12#include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"13#include "llvm/MC/MCAsmBackend.h"14#include "llvm/MC/MCCodeEmitter.h"15#include "llvm/MC/MCDwarf.h"16#include "llvm/MC/MCObjectWriter.h"17#include "llvm/MC/MCSection.h"18#include "llvm/MC/MCStreamer.h"19#include "llvm/MC/MCSubtargetInfo.h"20#include "llvm/MC/MCTargetOptions.h"21#include "llvm/MC/MCTargetOptionsCommandFlags.h"22#include "llvm/MC/TargetRegistry.h"23#include "llvm/Support/FormatVariadic.h"24#include "llvm/Support/LEB128.h"25#include "llvm/Target/TargetOptions.h"26#include "llvm/TargetParser/Triple.h"2728using namespace llvm;29using namespace dwarf_linker;30using namespace dwarf_linker::classic;3132Expected<std::unique_ptr<DwarfStreamer>> DwarfStreamer::createStreamer(33const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType,34raw_pwrite_stream &OutFile, DWARFLinkerBase::MessageHandlerTy Warning) {35std::unique_ptr<DwarfStreamer> Streamer =36std::make_unique<DwarfStreamer>(FileType, OutFile, Warning);37if (Error Err = Streamer->init(TheTriple, "__DWARF"))38return std::move(Err);3940return std::move(Streamer);41}4243Error DwarfStreamer::init(Triple TheTriple,44StringRef Swift5ReflectionSegmentName) {45std::string ErrorStr;46std::string TripleName;4748// Get the target.49const Target *TheTarget =50TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);51if (!TheTarget)52return createStringError(std::errc::invalid_argument, ErrorStr.c_str());5354TripleName = TheTriple.getTriple();5556// Create all the MC Objects.57MRI.reset(TheTarget->createMCRegInfo(TripleName));58if (!MRI)59return createStringError(std::errc::invalid_argument,60"no register info for target %s",61TripleName.c_str());6263MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();64MCOptions.AsmVerbose = true;65MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory;66MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));67if (!MAI)68return createStringError(std::errc::invalid_argument,69"no asm info for target %s", TripleName.c_str());7071MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));72if (!MSTI)73return createStringError(std::errc::invalid_argument,74"no subtarget info for target %s",75TripleName.c_str());7677MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,78nullptr, true, Swift5ReflectionSegmentName));79MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));80MC->setObjectFileInfo(MOFI.get());8182MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);83if (!MAB)84return createStringError(std::errc::invalid_argument,85"no asm backend for target %s",86TripleName.c_str());8788MII.reset(TheTarget->createMCInstrInfo());89if (!MII)90return createStringError(std::errc::invalid_argument,91"no instr info info for target %s",92TripleName.c_str());9394MCE = TheTarget->createMCCodeEmitter(*MII, *MC);95if (!MCE)96return createStringError(std::errc::invalid_argument,97"no code emitter for target %s",98TripleName.c_str());99100switch (OutFileType) {101case DWARFLinker::OutputFileType::Assembly: {102MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),103*MAI, *MII, *MRI);104MS = TheTarget->createAsmStreamer(105*MC, std::make_unique<formatted_raw_ostream>(OutFile), MIP,106std::unique_ptr<MCCodeEmitter>(MCE),107std::unique_ptr<MCAsmBackend>(MAB));108break;109}110case DWARFLinker::OutputFileType::Object: {111MS = TheTarget->createMCObjectStreamer(112TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),113MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),114*MSTI);115break;116}117}118119if (!MS)120return createStringError(std::errc::invalid_argument,121"no object streamer for target %s",122TripleName.c_str());123124// Finally create the AsmPrinter we'll use to emit the DIEs.125TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),126std::nullopt));127if (!TM)128return createStringError(std::errc::invalid_argument,129"no target machine for target %s",130TripleName.c_str());131132Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));133if (!Asm)134return createStringError(std::errc::invalid_argument,135"no asm printer for target %s",136TripleName.c_str());137Asm->setDwarfUsesRelocationsAcrossSections(false);138139RangesSectionSize = 0;140RngListsSectionSize = 0;141LocSectionSize = 0;142LocListsSectionSize = 0;143LineSectionSize = 0;144FrameSectionSize = 0;145DebugInfoSectionSize = 0;146MacInfoSectionSize = 0;147MacroSectionSize = 0;148149return Error::success();150}151152void DwarfStreamer::finish() { MS->finish(); }153154void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {155MS->switchSection(MOFI->getDwarfInfoSection());156MC->setDwarfVersion(DwarfVersion);157}158159/// Emit the compilation unit header for \p Unit in the debug_info section.160///161/// A Dwarf 4 section header is encoded as:162/// uint32_t Unit length (omitting this field)163/// uint16_t Version164/// uint32_t Abbreviation table offset165/// uint8_t Address size166/// Leading to a total of 11 bytes.167///168/// A Dwarf 5 section header is encoded as:169/// uint32_t Unit length (omitting this field)170/// uint16_t Version171/// uint8_t Unit type172/// uint8_t Address size173/// uint32_t Abbreviation table offset174/// Leading to a total of 12 bytes.175void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,176unsigned DwarfVersion) {177switchToDebugInfoSection(DwarfVersion);178179/// The start of the unit within its section.180Unit.setLabelBegin(Asm->createTempSymbol("cu_begin"));181Asm->OutStreamer->emitLabel(Unit.getLabelBegin());182183// Emit size of content not including length itself. The size has already184// been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to185// account for the length field.186Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);187Asm->emitInt16(DwarfVersion);188189if (DwarfVersion >= 5) {190Asm->emitInt8(dwarf::DW_UT_compile);191Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());192// We share one abbreviations table across all units so it's always at the193// start of the section.194Asm->emitInt32(0);195DebugInfoSectionSize += 12;196} else {197// We share one abbreviations table across all units so it's always at the198// start of the section.199Asm->emitInt32(0);200Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());201DebugInfoSectionSize += 11;202}203204// Remember this CU.205EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});206}207208/// Emit the \p Abbrevs array as the shared abbreviation table209/// for the linked Dwarf file.210void DwarfStreamer::emitAbbrevs(211const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,212unsigned DwarfVersion) {213MS->switchSection(MOFI->getDwarfAbbrevSection());214MC->setDwarfVersion(DwarfVersion);215Asm->emitDwarfAbbrevs(Abbrevs);216}217218/// Recursively emit the DIE tree rooted at \p Die.219void DwarfStreamer::emitDIE(DIE &Die) {220MS->switchSection(MOFI->getDwarfInfoSection());221Asm->emitDwarfDIE(Die);222DebugInfoSectionSize += Die.getSize();223}224225/// Emit contents of section SecName From Obj.226void DwarfStreamer::emitSectionContents(StringRef SecData,227DebugSectionKind SecKind) {228if (SecData.empty())229return;230231if (MCSection *Section = getMCSection(SecKind)) {232MS->switchSection(Section);233234MS->emitBytes(SecData);235}236}237238MCSection *DwarfStreamer::getMCSection(DebugSectionKind SecKind) {239switch (SecKind) {240case DebugSectionKind::DebugInfo:241return MC->getObjectFileInfo()->getDwarfInfoSection();242case DebugSectionKind::DebugLine:243return MC->getObjectFileInfo()->getDwarfLineSection();244case DebugSectionKind::DebugFrame:245return MC->getObjectFileInfo()->getDwarfFrameSection();246case DebugSectionKind::DebugRange:247return MC->getObjectFileInfo()->getDwarfRangesSection();248case DebugSectionKind::DebugRngLists:249return MC->getObjectFileInfo()->getDwarfRnglistsSection();250case DebugSectionKind::DebugLoc:251return MC->getObjectFileInfo()->getDwarfLocSection();252case DebugSectionKind::DebugLocLists:253return MC->getObjectFileInfo()->getDwarfLoclistsSection();254case DebugSectionKind::DebugARanges:255return MC->getObjectFileInfo()->getDwarfARangesSection();256case DebugSectionKind::DebugAbbrev:257return MC->getObjectFileInfo()->getDwarfAbbrevSection();258case DebugSectionKind::DebugMacinfo:259return MC->getObjectFileInfo()->getDwarfMacinfoSection();260case DebugSectionKind::DebugMacro:261return MC->getObjectFileInfo()->getDwarfMacroSection();262case DebugSectionKind::DebugAddr:263return MC->getObjectFileInfo()->getDwarfAddrSection();264case DebugSectionKind::DebugStr:265return MC->getObjectFileInfo()->getDwarfStrSection();266case DebugSectionKind::DebugLineStr:267return MC->getObjectFileInfo()->getDwarfLineStrSection();268case DebugSectionKind::DebugStrOffsets:269return MC->getObjectFileInfo()->getDwarfStrOffSection();270case DebugSectionKind::DebugPubNames:271return MC->getObjectFileInfo()->getDwarfPubNamesSection();272case DebugSectionKind::DebugPubTypes:273return MC->getObjectFileInfo()->getDwarfPubTypesSection();274case DebugSectionKind::DebugNames:275return MC->getObjectFileInfo()->getDwarfDebugNamesSection();276case DebugSectionKind::AppleNames:277return MC->getObjectFileInfo()->getDwarfAccelNamesSection();278case DebugSectionKind::AppleNamespaces:279return MC->getObjectFileInfo()->getDwarfAccelNamespaceSection();280case DebugSectionKind::AppleObjC:281return MC->getObjectFileInfo()->getDwarfAccelObjCSection();282case DebugSectionKind::AppleTypes:283return MC->getObjectFileInfo()->getDwarfAccelTypesSection();284case DebugSectionKind::NumberOfEnumEntries:285llvm_unreachable("Unknown DebugSectionKind value");286break;287}288289return nullptr;290}291292/// Emit the debug_str section stored in \p Pool.293void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {294Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());295std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();296for (auto Entry : Entries) {297// Emit the string itself.298Asm->OutStreamer->emitBytes(Entry.getString());299// Emit a null terminator.300Asm->emitInt8(0);301}302}303304/// Emit the debug string offset table described by \p StringOffsets into the305/// .debug_str_offsets table.306void DwarfStreamer::emitStringOffsets(307const SmallVector<uint64_t> &StringOffsets, uint16_t TargetDWARFVersion) {308309if (TargetDWARFVersion < 5 || StringOffsets.empty())310return;311312Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());313314MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugstroff");315MCSymbol *EndLabel = Asm->createTempSymbol("Edebugstroff");316317// Length.318Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));319Asm->OutStreamer->emitLabel(BeginLabel);320StrOffsetSectionSize += sizeof(uint32_t);321322// Version.323MS->emitInt16(5);324StrOffsetSectionSize += sizeof(uint16_t);325326// Padding.327MS->emitInt16(0);328StrOffsetSectionSize += sizeof(uint16_t);329330for (auto Off : StringOffsets) {331Asm->OutStreamer->emitInt32(Off);332StrOffsetSectionSize += sizeof(uint32_t);333}334Asm->OutStreamer->emitLabel(EndLabel);335}336337/// Emit the debug_line_str section stored in \p Pool.338void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) {339Asm->OutStreamer->switchSection(MOFI->getDwarfLineStrSection());340std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();341for (auto Entry : Entries) {342// Emit the string itself.343Asm->OutStreamer->emitBytes(Entry.getString());344// Emit a null terminator.345Asm->emitInt8(0);346}347}348349void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) {350if (EmittedUnits.empty())351return;352353// Build up data structures needed to emit this section.354std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;355DenseMap<unsigned, unsigned> UniqueIdToCuMap;356unsigned Id = 0;357for (auto &CU : EmittedUnits) {358CompUnits.push_back(CU.LabelBegin);359// We might be omitting CUs, so we need to remap them.360UniqueIdToCuMap[CU.ID] = Id++;361}362363Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());364dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false,365(uint64_t)UniqueIdToCuMap.size() - 1);366/// llvm-dwarfutil doesn't support type units + .debug_names right now.367// FIXME: add support for type units + .debug_names. For now the behavior is368// unsuported.369emitDWARF5AccelTable(370Asm.get(), Table, CompUnits,371[&](const DWARF5AccelTableData &Entry)372-> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {373if (UniqueIdToCuMap.size() > 1)374return {{UniqueIdToCuMap[Entry.getUnitID()],375{dwarf::DW_IDX_compile_unit, Form}}};376return std::nullopt;377});378}379380void DwarfStreamer::emitAppleNamespaces(381AccelTable<AppleAccelTableStaticOffsetData> &Table) {382Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());383auto *SectionBegin = Asm->createTempSymbol("namespac_begin");384Asm->OutStreamer->emitLabel(SectionBegin);385emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);386}387388void DwarfStreamer::emitAppleNames(389AccelTable<AppleAccelTableStaticOffsetData> &Table) {390Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());391auto *SectionBegin = Asm->createTempSymbol("names_begin");392Asm->OutStreamer->emitLabel(SectionBegin);393emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);394}395396void DwarfStreamer::emitAppleObjc(397AccelTable<AppleAccelTableStaticOffsetData> &Table) {398Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());399auto *SectionBegin = Asm->createTempSymbol("objc_begin");400Asm->OutStreamer->emitLabel(SectionBegin);401emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);402}403404void DwarfStreamer::emitAppleTypes(405AccelTable<AppleAccelTableStaticTypeData> &Table) {406Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());407auto *SectionBegin = Asm->createTempSymbol("types_begin");408Asm->OutStreamer->emitLabel(SectionBegin);409emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);410}411412/// Emit the swift_ast section stored in \p Buffers.413void DwarfStreamer::emitSwiftAST(StringRef Buffer) {414MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();415SwiftASTSection->setAlignment(Align(32));416MS->switchSection(SwiftASTSection);417MS->emitBytes(Buffer);418}419420void DwarfStreamer::emitSwiftReflectionSection(421llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,422StringRef Buffer, uint32_t Alignment, uint32_t Size) {423MCSection *ReflectionSection =424MOFI->getSwift5ReflectionSection(ReflSectionKind);425if (ReflectionSection == nullptr)426return;427ReflectionSection->setAlignment(Align(Alignment));428MS->switchSection(ReflectionSection);429MS->emitBytes(Buffer);430}431432void DwarfStreamer::emitDwarfDebugArangesTable(433const CompileUnit &Unit, const AddressRanges &LinkedRanges) {434unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();435436// Make .debug_aranges to be current section.437MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());438439// Emit Header.440MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");441MCSymbol *EndLabel = Asm->createTempSymbol("Earange");442443unsigned HeaderSize =444sizeof(int32_t) + // Size of contents (w/o this field445sizeof(int16_t) + // DWARF ARange version number446sizeof(int32_t) + // Offset of CU in the .debug_info section447sizeof(int8_t) + // Pointer Size (in bytes)448sizeof(int8_t); // Segment Size (in bytes)449450unsigned TupleSize = AddressSize * 2;451unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));452453Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length454Asm->OutStreamer->emitLabel(BeginLabel);455Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number456Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset457Asm->emitInt8(AddressSize); // Address size458Asm->emitInt8(0); // Segment size459460Asm->OutStreamer->emitFill(Padding, 0x0);461462// Emit linked ranges.463for (const AddressRange &Range : LinkedRanges) {464MS->emitIntValue(Range.start(), AddressSize);465MS->emitIntValue(Range.end() - Range.start(), AddressSize);466}467468// Emit terminator.469Asm->OutStreamer->emitIntValue(0, AddressSize);470Asm->OutStreamer->emitIntValue(0, AddressSize);471Asm->OutStreamer->emitLabel(EndLabel);472}473474void DwarfStreamer::emitDwarfDebugRangesTableFragment(475const CompileUnit &Unit, const AddressRanges &LinkedRanges,476PatchLocation Patch) {477Patch.set(RangesSectionSize);478479// Make .debug_ranges to be current section.480MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());481unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();482483// Emit ranges.484uint64_t BaseAddress = 0;485if (std::optional<uint64_t> LowPC = Unit.getLowPc())486BaseAddress = *LowPC;487488for (const AddressRange &Range : LinkedRanges) {489MS->emitIntValue(Range.start() - BaseAddress, AddressSize);490MS->emitIntValue(Range.end() - BaseAddress, AddressSize);491492RangesSectionSize += AddressSize;493RangesSectionSize += AddressSize;494}495496// Add the terminator entry.497MS->emitIntValue(0, AddressSize);498MS->emitIntValue(0, AddressSize);499500RangesSectionSize += AddressSize;501RangesSectionSize += AddressSize;502}503504MCSymbol *505DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) {506if (Unit.getOrigUnit().getVersion() < 5)507return nullptr;508509// Make .debug_rnglists to be current section.510MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());511512MCSymbol *BeginLabel = Asm->createTempSymbol("Brnglists");513MCSymbol *EndLabel = Asm->createTempSymbol("Ernglists");514unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();515516// Length517Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));518Asm->OutStreamer->emitLabel(BeginLabel);519RngListsSectionSize += sizeof(uint32_t);520521// Version.522MS->emitInt16(5);523RngListsSectionSize += sizeof(uint16_t);524525// Address size.526MS->emitInt8(AddressSize);527RngListsSectionSize++;528529// Seg_size530MS->emitInt8(0);531RngListsSectionSize++;532533// Offset entry count534MS->emitInt32(0);535RngListsSectionSize += sizeof(uint32_t);536537return EndLabel;538}539540void DwarfStreamer::emitDwarfDebugRangeListFragment(541const CompileUnit &Unit, const AddressRanges &LinkedRanges,542PatchLocation Patch, DebugDieValuePool &AddrPool) {543if (Unit.getOrigUnit().getVersion() < 5) {544emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch);545return;546}547548emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch, AddrPool);549}550551void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit,552MCSymbol *EndLabel) {553if (Unit.getOrigUnit().getVersion() < 5)554return;555556// Make .debug_rnglists to be current section.557MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());558559if (EndLabel != nullptr)560Asm->OutStreamer->emitLabel(EndLabel);561}562563void DwarfStreamer::emitDwarfDebugRngListsTableFragment(564const CompileUnit &Unit, const AddressRanges &LinkedRanges,565PatchLocation Patch, DebugDieValuePool &AddrPool) {566Patch.set(RngListsSectionSize);567568// Make .debug_rnglists to be current section.569MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());570std::optional<uint64_t> BaseAddress;571572for (const AddressRange &Range : LinkedRanges) {573574if (!BaseAddress) {575BaseAddress = Range.start();576577// Emit base address.578MS->emitInt8(dwarf::DW_RLE_base_addressx);579RngListsSectionSize += 1;580RngListsSectionSize +=581MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress));582}583584// Emit type of entry.585MS->emitInt8(dwarf::DW_RLE_offset_pair);586RngListsSectionSize += 1;587588// Emit start offset relative to base address.589RngListsSectionSize +=590MS->emitULEB128IntValue(Range.start() - *BaseAddress);591592// Emit end offset relative to base address.593RngListsSectionSize += MS->emitULEB128IntValue(Range.end() - *BaseAddress);594}595596// Emit the terminator entry.597MS->emitInt8(dwarf::DW_RLE_end_of_list);598RngListsSectionSize += 1;599}600601/// Emit debug locations(.debug_loc, .debug_loclists) header.602MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) {603if (Unit.getOrigUnit().getVersion() < 5)604return nullptr;605606// Make .debug_loclists the current section.607MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());608609MCSymbol *BeginLabel = Asm->createTempSymbol("Bloclists");610MCSymbol *EndLabel = Asm->createTempSymbol("Eloclists");611unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();612613// Length614Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));615Asm->OutStreamer->emitLabel(BeginLabel);616LocListsSectionSize += sizeof(uint32_t);617618// Version.619MS->emitInt16(5);620LocListsSectionSize += sizeof(uint16_t);621622// Address size.623MS->emitInt8(AddressSize);624LocListsSectionSize++;625626// Seg_size627MS->emitInt8(0);628LocListsSectionSize++;629630// Offset entry count631MS->emitInt32(0);632LocListsSectionSize += sizeof(uint32_t);633634return EndLabel;635}636637/// Emit debug locations(.debug_loc, .debug_loclists) fragment.638void DwarfStreamer::emitDwarfDebugLocListFragment(639const CompileUnit &Unit,640const DWARFLocationExpressionsVector &LinkedLocationExpression,641PatchLocation Patch, DebugDieValuePool &AddrPool) {642if (Unit.getOrigUnit().getVersion() < 5) {643emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch);644return;645}646647emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch,648AddrPool);649}650651/// Emit debug locations(.debug_loc, .debug_loclists) footer.652void DwarfStreamer::emitDwarfDebugLocListFooter(const CompileUnit &Unit,653MCSymbol *EndLabel) {654if (Unit.getOrigUnit().getVersion() < 5)655return;656657// Make .debug_loclists the current section.658MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());659660if (EndLabel != nullptr)661Asm->OutStreamer->emitLabel(EndLabel);662}663664/// Emit piece of .debug_loc for \p LinkedLocationExpression.665void DwarfStreamer::emitDwarfDebugLocTableFragment(666const CompileUnit &Unit,667const DWARFLocationExpressionsVector &LinkedLocationExpression,668PatchLocation Patch) {669Patch.set(LocSectionSize);670671// Make .debug_loc to be current section.672MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());673unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();674675// Emit ranges.676uint64_t BaseAddress = 0;677if (std::optional<uint64_t> LowPC = Unit.getLowPc())678BaseAddress = *LowPC;679680for (const DWARFLocationExpression &LocExpression :681LinkedLocationExpression) {682if (LocExpression.Range) {683MS->emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize);684MS->emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize);685686LocSectionSize += AddressSize;687LocSectionSize += AddressSize;688}689690Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2);691Asm->OutStreamer->emitBytes(StringRef(692(const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));693LocSectionSize += LocExpression.Expr.size() + 2;694}695696// Add the terminator entry.697MS->emitIntValue(0, AddressSize);698MS->emitIntValue(0, AddressSize);699700LocSectionSize += AddressSize;701LocSectionSize += AddressSize;702}703704/// Emit .debug_addr header.705MCSymbol *DwarfStreamer::emitDwarfDebugAddrsHeader(const CompileUnit &Unit) {706707// Make .debug_addr the current section.708MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());709710MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugaddr");711MCSymbol *EndLabel = Asm->createTempSymbol("Edebugaddr");712unsigned AddrSize = Unit.getOrigUnit().getAddressByteSize();713714// Emit length.715Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));716Asm->OutStreamer->emitLabel(BeginLabel);717AddrSectionSize += sizeof(uint32_t);718719// Emit version.720Asm->emitInt16(5);721AddrSectionSize += 2;722723// Emit address size.724Asm->emitInt8(AddrSize);725AddrSectionSize += 1;726727// Emit segment size.728Asm->emitInt8(0);729AddrSectionSize += 1;730731return EndLabel;732}733734/// Emit the .debug_addr addresses stored in \p Addrs.735void DwarfStreamer::emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs,736uint8_t AddrSize) {737Asm->OutStreamer->switchSection(MOFI->getDwarfAddrSection());738for (auto Addr : Addrs) {739Asm->OutStreamer->emitIntValue(Addr, AddrSize);740AddrSectionSize += AddrSize;741}742}743744/// Emit .debug_addr footer.745void DwarfStreamer::emitDwarfDebugAddrsFooter(const CompileUnit &Unit,746MCSymbol *EndLabel) {747748// Make .debug_addr the current section.749MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());750751if (EndLabel != nullptr)752Asm->OutStreamer->emitLabel(EndLabel);753}754755/// Emit piece of .debug_loclists for \p LinkedLocationExpression.756void DwarfStreamer::emitDwarfDebugLocListsTableFragment(757const CompileUnit &Unit,758const DWARFLocationExpressionsVector &LinkedLocationExpression,759PatchLocation Patch, DebugDieValuePool &AddrPool) {760Patch.set(LocListsSectionSize);761762// Make .debug_loclists the current section.763MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());764std::optional<uint64_t> BaseAddress;765766for (const DWARFLocationExpression &LocExpression :767LinkedLocationExpression) {768if (LocExpression.Range) {769770if (!BaseAddress) {771772BaseAddress = LocExpression.Range->LowPC;773774// Emit base address.775MS->emitInt8(dwarf::DW_LLE_base_addressx);776LocListsSectionSize += 1;777LocListsSectionSize +=778MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress));779}780781// Emit type of entry.782MS->emitInt8(dwarf::DW_LLE_offset_pair);783LocListsSectionSize += 1;784785// Emit start offset relative to base address.786LocListsSectionSize +=787MS->emitULEB128IntValue(LocExpression.Range->LowPC - *BaseAddress);788789// Emit end offset relative to base address.790LocListsSectionSize +=791MS->emitULEB128IntValue(LocExpression.Range->HighPC - *BaseAddress);792} else {793// Emit type of entry.794MS->emitInt8(dwarf::DW_LLE_default_location);795LocListsSectionSize += 1;796}797798LocListsSectionSize += MS->emitULEB128IntValue(LocExpression.Expr.size());799Asm->OutStreamer->emitBytes(StringRef(800(const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));801LocListsSectionSize += LocExpression.Expr.size();802}803804// Emit the terminator entry.805MS->emitInt8(dwarf::DW_LLE_end_of_list);806LocListsSectionSize += 1;807}808809void DwarfStreamer::emitLineTableForUnit(810const DWARFDebugLine::LineTable &LineTable, const CompileUnit &Unit,811OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool) {812// Switch to the section where the table will be emitted into.813MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());814815MCSymbol *LineStartSym = MC->createTempSymbol();816MCSymbol *LineEndSym = MC->createTempSymbol();817818// unit_length.819if (LineTable.Prologue.FormParams.Format == dwarf::DwarfFormat::DWARF64) {820MS->emitInt32(dwarf::DW_LENGTH_DWARF64);821LineSectionSize += 4;822}823emitLabelDifference(LineEndSym, LineStartSym,824LineTable.Prologue.FormParams.Format, LineSectionSize);825Asm->OutStreamer->emitLabel(LineStartSym);826827// Emit prologue.828emitLineTablePrologue(LineTable.Prologue, DebugStrPool, DebugLineStrPool);829830// Emit rows.831emitLineTableRows(LineTable, LineEndSym,832Unit.getOrigUnit().getAddressByteSize());833}834835void DwarfStreamer::emitLineTablePrologue(const DWARFDebugLine::Prologue &P,836OffsetsStringPool &DebugStrPool,837OffsetsStringPool &DebugLineStrPool) {838MCSymbol *PrologueStartSym = MC->createTempSymbol();839MCSymbol *PrologueEndSym = MC->createTempSymbol();840841// version (uhalf).842MS->emitInt16(P.getVersion());843LineSectionSize += 2;844if (P.getVersion() == 5) {845// address_size (ubyte).846MS->emitInt8(P.getAddressSize());847LineSectionSize += 1;848849// segment_selector_size (ubyte).850MS->emitInt8(P.SegSelectorSize);851LineSectionSize += 1;852}853854// header_length.855emitLabelDifference(PrologueEndSym, PrologueStartSym, P.FormParams.Format,856LineSectionSize);857858Asm->OutStreamer->emitLabel(PrologueStartSym);859emitLineTableProloguePayload(P, DebugStrPool, DebugLineStrPool);860Asm->OutStreamer->emitLabel(PrologueEndSym);861}862863void DwarfStreamer::emitLineTablePrologueV2IncludeAndFileTable(864const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,865OffsetsStringPool &DebugLineStrPool) {866// include_directories (sequence of path names).867for (const DWARFFormValue &Include : P.IncludeDirectories)868emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);869// The last entry is followed by a single null byte.870MS->emitInt8(0);871LineSectionSize += 1;872873// file_names (sequence of file entries).874for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) {875// A null-terminated string containing the full or relative path name of a876// source file.877emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);878// An unsigned LEB128 number representing the directory index of a directory879// in the include_directories section.880LineSectionSize += MS->emitULEB128IntValue(File.DirIdx);881// An unsigned LEB128 number representing the (implementation-defined) time882// of last modification for the file, or 0 if not available.883LineSectionSize += MS->emitULEB128IntValue(File.ModTime);884// An unsigned LEB128 number representing the length in bytes of the file,885// or 0 if not available.886LineSectionSize += MS->emitULEB128IntValue(File.Length);887}888// The last entry is followed by a single null byte.889MS->emitInt8(0);890LineSectionSize += 1;891}892893void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable(894const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,895OffsetsStringPool &DebugLineStrPool) {896if (P.IncludeDirectories.empty()) {897// directory_entry_format_count(ubyte).898MS->emitInt8(0);899LineSectionSize += 1;900} else {901// directory_entry_format_count(ubyte).902MS->emitInt8(1);903LineSectionSize += 1;904905// directory_entry_format (sequence of ULEB128 pairs).906LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);907LineSectionSize +=908MS->emitULEB128IntValue(P.IncludeDirectories[0].getForm());909}910911// directories_count (ULEB128).912LineSectionSize += MS->emitULEB128IntValue(P.IncludeDirectories.size());913// directories (sequence of directory names).914for (auto Include : P.IncludeDirectories)915emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);916917bool HasChecksums = P.ContentTypes.HasMD5;918bool HasInlineSources = P.ContentTypes.HasSource;919920if (P.FileNames.empty()) {921// file_name_entry_format_count (ubyte).922MS->emitInt8(0);923LineSectionSize += 1;924} else {925// file_name_entry_format_count (ubyte).926MS->emitInt8(2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0));927LineSectionSize += 1;928929// file_name_entry_format (sequence of ULEB128 pairs).930auto StrForm = P.FileNames[0].Name.getForm();931LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);932LineSectionSize += MS->emitULEB128IntValue(StrForm);933934LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);935LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data1);936937if (HasChecksums) {938LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);939LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data16);940}941942if (HasInlineSources) {943LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);944LineSectionSize += MS->emitULEB128IntValue(StrForm);945}946}947948// file_names_count (ULEB128).949LineSectionSize += MS->emitULEB128IntValue(P.FileNames.size());950951// file_names (sequence of file name entries).952for (auto File : P.FileNames) {953emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);954MS->emitInt8(File.DirIdx);955LineSectionSize += 1;956if (HasChecksums) {957MS->emitBinaryData(958StringRef(reinterpret_cast<const char *>(File.Checksum.data()),959File.Checksum.size()));960LineSectionSize += File.Checksum.size();961}962if (HasInlineSources)963emitLineTableString(P, File.Source, DebugStrPool, DebugLineStrPool);964}965}966967void DwarfStreamer::emitLineTableString(const DWARFDebugLine::Prologue &P,968const DWARFFormValue &String,969OffsetsStringPool &DebugStrPool,970OffsetsStringPool &DebugLineStrPool) {971std::optional<const char *> StringVal = dwarf::toString(String);972if (!StringVal) {973warn("Cann't read string from line table.");974return;975}976977switch (String.getForm()) {978case dwarf::DW_FORM_string: {979StringRef Str = *StringVal;980Asm->OutStreamer->emitBytes(Str.data());981Asm->emitInt8(0);982LineSectionSize += Str.size() + 1;983} break;984case dwarf::DW_FORM_strp:985case dwarf::DW_FORM_line_strp: {986DwarfStringPoolEntryRef StringRef =987String.getForm() == dwarf::DW_FORM_strp988? DebugStrPool.getEntry(*StringVal)989: DebugLineStrPool.getEntry(*StringVal);990991emitIntOffset(StringRef.getOffset(), P.FormParams.Format, LineSectionSize);992} break;993default:994warn("Unsupported string form inside line table.");995break;996};997}998999void DwarfStreamer::emitLineTableProloguePayload(1000const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,1001OffsetsStringPool &DebugLineStrPool) {1002// minimum_instruction_length (ubyte).1003MS->emitInt8(P.MinInstLength);1004LineSectionSize += 1;1005if (P.FormParams.Version >= 4) {1006// maximum_operations_per_instruction (ubyte).1007MS->emitInt8(P.MaxOpsPerInst);1008LineSectionSize += 1;1009}1010// default_is_stmt (ubyte).1011MS->emitInt8(P.DefaultIsStmt);1012LineSectionSize += 1;1013// line_base (sbyte).1014MS->emitInt8(P.LineBase);1015LineSectionSize += 1;1016// line_range (ubyte).1017MS->emitInt8(P.LineRange);1018LineSectionSize += 1;1019// opcode_base (ubyte).1020MS->emitInt8(P.OpcodeBase);1021LineSectionSize += 1;10221023// standard_opcode_lengths (array of ubyte).1024for (auto Length : P.StandardOpcodeLengths) {1025MS->emitInt8(Length);1026LineSectionSize += 1;1027}10281029if (P.FormParams.Version < 5)1030emitLineTablePrologueV2IncludeAndFileTable(P, DebugStrPool,1031DebugLineStrPool);1032else1033emitLineTablePrologueV5IncludeAndFileTable(P, DebugStrPool,1034DebugLineStrPool);1035}10361037void DwarfStreamer::emitLineTableRows(1038const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym,1039unsigned AddressByteSize) {10401041MCDwarfLineTableParams Params;1042Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;1043Params.DWARF2LineBase = LineTable.Prologue.LineBase;1044Params.DWARF2LineRange = LineTable.Prologue.LineRange;10451046SmallString<128> EncodingBuffer;10471048if (LineTable.Rows.empty()) {1049// We only have the dummy entry, dsymutil emits an entry with a 01050// address in that case.1051MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,1052EncodingBuffer);1053MS->emitBytes(EncodingBuffer);1054LineSectionSize += EncodingBuffer.size();1055MS->emitLabel(LineEndSym);1056return;1057}10581059// Line table state machine fields1060unsigned FileNum = 1;1061unsigned LastLine = 1;1062unsigned Column = 0;1063unsigned Discriminator = 0;1064unsigned IsStatement = 1;1065unsigned Isa = 0;1066uint64_t Address = -1ULL;10671068unsigned RowsSinceLastSequence = 0;10691070for (const DWARFDebugLine::Row &Row : LineTable.Rows) {1071int64_t AddressDelta;1072if (Address == -1ULL) {1073MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);1074MS->emitULEB128IntValue(AddressByteSize + 1);1075MS->emitIntValue(dwarf::DW_LNE_set_address, 1);1076MS->emitIntValue(Row.Address.Address, AddressByteSize);1077LineSectionSize +=10782 + AddressByteSize + getULEB128Size(AddressByteSize + 1);1079AddressDelta = 0;1080} else {1081AddressDelta =1082(Row.Address.Address - Address) / LineTable.Prologue.MinInstLength;1083}10841085// FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.1086// We should find a way to share this code, but the current compatibility1087// requirement with classic dsymutil makes it hard. Revisit that once this1088// requirement is dropped.10891090if (FileNum != Row.File) {1091FileNum = Row.File;1092MS->emitIntValue(dwarf::DW_LNS_set_file, 1);1093MS->emitULEB128IntValue(FileNum);1094LineSectionSize += 1 + getULEB128Size(FileNum);1095}1096if (Column != Row.Column) {1097Column = Row.Column;1098MS->emitIntValue(dwarf::DW_LNS_set_column, 1);1099MS->emitULEB128IntValue(Column);1100LineSectionSize += 1 + getULEB128Size(Column);1101}1102if (Discriminator != Row.Discriminator &&1103MS->getContext().getDwarfVersion() >= 4) {1104Discriminator = Row.Discriminator;1105unsigned Size = getULEB128Size(Discriminator);1106MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);1107MS->emitULEB128IntValue(Size + 1);1108MS->emitIntValue(dwarf::DW_LNE_set_discriminator, 1);1109MS->emitULEB128IntValue(Discriminator);1110LineSectionSize += /* extended op */ 1 + getULEB128Size(Size + 1) +1111/* discriminator */ 1 + Size;1112}1113Discriminator = 0;11141115if (Isa != Row.Isa) {1116Isa = Row.Isa;1117MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);1118MS->emitULEB128IntValue(Isa);1119LineSectionSize += 1 + getULEB128Size(Isa);1120}1121if (IsStatement != Row.IsStmt) {1122IsStatement = Row.IsStmt;1123MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);1124LineSectionSize += 1;1125}1126if (Row.BasicBlock) {1127MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);1128LineSectionSize += 1;1129}11301131if (Row.PrologueEnd) {1132MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);1133LineSectionSize += 1;1134}11351136if (Row.EpilogueBegin) {1137MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);1138LineSectionSize += 1;1139}11401141int64_t LineDelta = int64_t(Row.Line) - LastLine;1142if (!Row.EndSequence) {1143MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,1144EncodingBuffer);1145MS->emitBytes(EncodingBuffer);1146LineSectionSize += EncodingBuffer.size();1147EncodingBuffer.resize(0);1148Address = Row.Address.Address;1149LastLine = Row.Line;1150RowsSinceLastSequence++;1151} else {1152if (LineDelta) {1153MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);1154MS->emitSLEB128IntValue(LineDelta);1155LineSectionSize += 1 + getSLEB128Size(LineDelta);1156}1157if (AddressDelta) {1158MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);1159MS->emitULEB128IntValue(AddressDelta);1160LineSectionSize += 1 + getULEB128Size(AddressDelta);1161}1162MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),11630, EncodingBuffer);1164MS->emitBytes(EncodingBuffer);1165LineSectionSize += EncodingBuffer.size();1166EncodingBuffer.resize(0);1167Address = -1ULL;1168LastLine = FileNum = IsStatement = 1;1169RowsSinceLastSequence = Column = Discriminator = Isa = 0;1170}1171}11721173if (RowsSinceLastSequence) {1174MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,1175EncodingBuffer);1176MS->emitBytes(EncodingBuffer);1177LineSectionSize += EncodingBuffer.size();1178EncodingBuffer.resize(0);1179}11801181MS->emitLabel(LineEndSym);1182}11831184void DwarfStreamer::emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format,1185uint64_t &SectionSize) {1186uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);1187MS->emitIntValue(Offset, Size);1188SectionSize += Size;1189}11901191void DwarfStreamer::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,1192dwarf::DwarfFormat Format,1193uint64_t &SectionSize) {1194uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);1195Asm->emitLabelDifference(Hi, Lo, Size);1196SectionSize += Size;1197}11981199/// Emit the pubnames or pubtypes section contribution for \p1200/// Unit into \p Sec. The data is provided in \p Names.1201void DwarfStreamer::emitPubSectionForUnit(1202MCSection *Sec, StringRef SecName, const CompileUnit &Unit,1203const std::vector<CompileUnit::AccelInfo> &Names) {1204if (Names.empty())1205return;12061207// Start the dwarf pubnames section.1208Asm->OutStreamer->switchSection(Sec);1209MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");1210MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");12111212bool HeaderEmitted = false;1213// Emit the pubnames for this compilation unit.1214for (const auto &Name : Names) {1215if (Name.SkipPubSection)1216continue;12171218if (!HeaderEmitted) {1219// Emit the header.1220Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length1221Asm->OutStreamer->emitLabel(BeginLabel);1222Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version1223Asm->emitInt32(Unit.getStartOffset()); // Unit offset1224Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size1225HeaderEmitted = true;1226}1227Asm->emitInt32(Name.Die->getOffset());12281229// Emit the string itself.1230Asm->OutStreamer->emitBytes(Name.Name.getString());1231// Emit a null terminator.1232Asm->emitInt8(0);1233}12341235if (!HeaderEmitted)1236return;1237Asm->emitInt32(0); // End marker.1238Asm->OutStreamer->emitLabel(EndLabel);1239}12401241/// Emit .debug_pubnames for \p Unit.1242void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {1243emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),1244"names", Unit, Unit.getPubnames());1245}12461247/// Emit .debug_pubtypes for \p Unit.1248void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {1249emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),1250"types", Unit, Unit.getPubtypes());1251}12521253/// Emit a CIE into the debug_frame section.1254void DwarfStreamer::emitCIE(StringRef CIEBytes) {1255MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());12561257MS->emitBytes(CIEBytes);1258FrameSectionSize += CIEBytes.size();1259}12601261/// Emit a FDE into the debug_frame section. \p FDEBytes1262/// contains the FDE data without the length, CIE offset and address1263/// which will be replaced with the parameter values.1264void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,1265uint64_t Address, StringRef FDEBytes) {1266MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());12671268MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4);1269MS->emitIntValue(CIEOffset, 4);1270MS->emitIntValue(Address, AddrSize);1271MS->emitBytes(FDEBytes);1272FrameSectionSize += FDEBytes.size() + 8 + AddrSize;1273}12741275void DwarfStreamer::emitMacroTables(DWARFContext *Context,1276const Offset2UnitMap &UnitMacroMap,1277OffsetsStringPool &StringPool) {1278assert(Context != nullptr && "Empty DWARF context");12791280// Check for .debug_macinfo table.1281if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) {1282MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());1283emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize);1284}12851286// Check for .debug_macro table.1287if (const DWARFDebugMacro *Table = Context->getDebugMacro()) {1288MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());1289emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize);1290}1291}12921293void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,1294const Offset2UnitMap &UnitMacroMap,1295OffsetsStringPool &StringPool,1296uint64_t &OutOffset) {1297bool DefAttributeIsReported = false;1298bool UndefAttributeIsReported = false;1299bool ImportAttributeIsReported = false;1300for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {1301Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset);1302if (UnitIt == UnitMacroMap.end()) {1303warn(formatv(1304"couldn`t find compile unit for the macro table with offset = {0:x}",1305List.Offset));1306continue;1307}13081309// Skip macro table if the unit was not cloned.1310DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();1311if (OutputUnitDIE == nullptr)1312continue;13131314// Update macro attribute of cloned compile unit with the proper offset to1315// the macro table.1316bool hasDWARFv5Header = false;1317for (auto &V : OutputUnitDIE->values()) {1318if (V.getAttribute() == dwarf::DW_AT_macro_info) {1319V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));1320break;1321} else if (V.getAttribute() == dwarf::DW_AT_macros) {1322hasDWARFv5Header = true;1323V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));1324break;1325}1326}13271328// Write DWARFv5 header.1329if (hasDWARFv5Header) {1330// Write header version.1331MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version));1332OutOffset += sizeof(List.Header.Version);13331334uint8_t Flags = List.Header.Flags;13351336// Check for OPCODE_OPERANDS_TABLE.1337if (Flags &1338DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {1339Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;1340warn("opcode_operands_table is not supported yet.");1341}13421343// Check for DEBUG_LINE_OFFSET.1344std::optional<uint64_t> StmtListOffset;1345if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {1346// Get offset to the line table from the cloned compile unit.1347for (auto &V : OutputUnitDIE->values()) {1348if (V.getAttribute() == dwarf::DW_AT_stmt_list) {1349StmtListOffset = V.getDIEInteger().getValue();1350break;1351}1352}13531354if (!StmtListOffset) {1355Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;1356warn("couldn`t find line table for macro table.");1357}1358}13591360// Write flags.1361MS->emitIntValue(Flags, sizeof(Flags));1362OutOffset += sizeof(Flags);13631364// Write offset to line table.1365if (StmtListOffset) {1366MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize());1367OutOffset += List.Header.getOffsetByteSize();1368}1369}13701371// Write macro entries.1372for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {1373if (MacroEntry.Type == 0) {1374OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);1375continue;1376}13771378uint8_t MacroType = MacroEntry.Type;1379switch (MacroType) {1380default: {1381bool HasVendorSpecificExtension =1382(!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) ||1383(hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&1384MacroType <= dwarf::DW_MACRO_hi_user));13851386if (HasVendorSpecificExtension) {1387// Write macinfo type.1388MS->emitIntValue(MacroType, 1);1389OutOffset++;13901391// Write vendor extension constant.1392OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);13931394// Write vendor extension string.1395StringRef String = MacroEntry.ExtStr;1396MS->emitBytes(String);1397MS->emitIntValue(0, 1);1398OutOffset += String.size() + 1;1399} else1400warn("unknown macro type. skip.");1401} break;1402// debug_macro and debug_macinfo share some common encodings.1403// DW_MACRO_define == DW_MACINFO_define1404// DW_MACRO_undef == DW_MACINFO_undef1405// DW_MACRO_start_file == DW_MACINFO_start_file1406// DW_MACRO_end_file == DW_MACINFO_end_file1407// For readibility/uniformity we are using DW_MACRO_*.1408case dwarf::DW_MACRO_define:1409case dwarf::DW_MACRO_undef: {1410// Write macinfo type.1411MS->emitIntValue(MacroType, 1);1412OutOffset++;14131414// Write source line.1415OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);14161417// Write macro string.1418StringRef String = MacroEntry.MacroStr;1419MS->emitBytes(String);1420MS->emitIntValue(0, 1);1421OutOffset += String.size() + 1;1422} break;1423case dwarf::DW_MACRO_define_strp:1424case dwarf::DW_MACRO_undef_strp:1425case dwarf::DW_MACRO_define_strx:1426case dwarf::DW_MACRO_undef_strx: {1427assert(UnitIt->second->getOrigUnit().getVersion() >= 5);14281429// DW_MACRO_*_strx forms are not supported currently.1430// Convert to *_strp.1431switch (MacroType) {1432case dwarf::DW_MACRO_define_strx: {1433MacroType = dwarf::DW_MACRO_define_strp;1434if (!DefAttributeIsReported) {1435warn("DW_MACRO_define_strx unsupported yet. Convert to "1436"DW_MACRO_define_strp.");1437DefAttributeIsReported = true;1438}1439} break;1440case dwarf::DW_MACRO_undef_strx: {1441MacroType = dwarf::DW_MACRO_undef_strp;1442if (!UndefAttributeIsReported) {1443warn("DW_MACRO_undef_strx unsupported yet. Convert to "1444"DW_MACRO_undef_strp.");1445UndefAttributeIsReported = true;1446}1447} break;1448default:1449// Nothing to do.1450break;1451}14521453// Write macinfo type.1454MS->emitIntValue(MacroType, 1);1455OutOffset++;14561457// Write source line.1458OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);14591460// Write macro string.1461DwarfStringPoolEntryRef EntryRef =1462StringPool.getEntry(MacroEntry.MacroStr);1463MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize());1464OutOffset += List.Header.getOffsetByteSize();1465break;1466}1467case dwarf::DW_MACRO_start_file: {1468// Write macinfo type.1469MS->emitIntValue(MacroType, 1);1470OutOffset++;1471// Write source line.1472OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);1473// Write source file id.1474OutOffset += MS->emitULEB128IntValue(MacroEntry.File);1475} break;1476case dwarf::DW_MACRO_end_file: {1477// Write macinfo type.1478MS->emitIntValue(MacroType, 1);1479OutOffset++;1480} break;1481case dwarf::DW_MACRO_import:1482case dwarf::DW_MACRO_import_sup: {1483if (!ImportAttributeIsReported) {1484warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "1485"remove.");1486ImportAttributeIsReported = true;1487}1488} break;1489}1490}1491}1492}149314941495