11db9f3b2SDimitry Andric //===- DwarfStreamer.cpp --------------------------------------------------===//
21db9f3b2SDimitry Andric //
31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61db9f3b2SDimitry Andric //
71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===//
81db9f3b2SDimitry Andric
91db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFStreamer.h"
101db9f3b2SDimitry Andric #include "llvm/CodeGen/NonRelocatableStringpool.h"
111db9f3b2SDimitry Andric #include "llvm/DWARFLinker/Classic/DWARFLinkerCompileUnit.h"
121db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFContext.h"
131db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
141db9f3b2SDimitry Andric #include "llvm/MC/MCAsmBackend.h"
151db9f3b2SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
161db9f3b2SDimitry Andric #include "llvm/MC/MCDwarf.h"
171db9f3b2SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
181db9f3b2SDimitry Andric #include "llvm/MC/MCSection.h"
191db9f3b2SDimitry Andric #include "llvm/MC/MCStreamer.h"
201db9f3b2SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
211db9f3b2SDimitry Andric #include "llvm/MC/MCTargetOptions.h"
221db9f3b2SDimitry Andric #include "llvm/MC/MCTargetOptionsCommandFlags.h"
231db9f3b2SDimitry Andric #include "llvm/MC/TargetRegistry.h"
241db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h"
251db9f3b2SDimitry Andric #include "llvm/Support/LEB128.h"
261db9f3b2SDimitry Andric #include "llvm/Target/TargetOptions.h"
271db9f3b2SDimitry Andric #include "llvm/TargetParser/Triple.h"
281db9f3b2SDimitry Andric
291db9f3b2SDimitry Andric using namespace llvm;
301db9f3b2SDimitry Andric using namespace dwarf_linker;
311db9f3b2SDimitry Andric using namespace dwarf_linker::classic;
321db9f3b2SDimitry Andric
createStreamer(const Triple & TheTriple,DWARFLinkerBase::OutputFileType FileType,raw_pwrite_stream & OutFile,DWARFLinkerBase::TranslatorFuncTy Translator,DWARFLinkerBase::MessageHandlerTy Warning)33*7a6dacacSDimitry Andric Expected<std::unique_ptr<DwarfStreamer>> DwarfStreamer::createStreamer(
34*7a6dacacSDimitry Andric const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType,
35*7a6dacacSDimitry Andric raw_pwrite_stream &OutFile, DWARFLinkerBase::TranslatorFuncTy Translator,
36*7a6dacacSDimitry Andric DWARFLinkerBase::MessageHandlerTy Warning) {
37*7a6dacacSDimitry Andric std::unique_ptr<DwarfStreamer> Streamer =
38*7a6dacacSDimitry Andric std::make_unique<DwarfStreamer>(FileType, OutFile, Translator, Warning);
39*7a6dacacSDimitry Andric if (Error Err = Streamer->init(TheTriple, "__DWARF"))
40*7a6dacacSDimitry Andric return std::move(Err);
41*7a6dacacSDimitry Andric
42*7a6dacacSDimitry Andric return std::move(Streamer);
43*7a6dacacSDimitry Andric }
44*7a6dacacSDimitry Andric
init(Triple TheTriple,StringRef Swift5ReflectionSegmentName)451db9f3b2SDimitry Andric Error DwarfStreamer::init(Triple TheTriple,
461db9f3b2SDimitry Andric StringRef Swift5ReflectionSegmentName) {
471db9f3b2SDimitry Andric std::string ErrorStr;
481db9f3b2SDimitry Andric std::string TripleName;
491db9f3b2SDimitry Andric
501db9f3b2SDimitry Andric // Get the target.
511db9f3b2SDimitry Andric const Target *TheTarget =
521db9f3b2SDimitry Andric TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
531db9f3b2SDimitry Andric if (!TheTarget)
541db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, ErrorStr.c_str());
551db9f3b2SDimitry Andric
561db9f3b2SDimitry Andric TripleName = TheTriple.getTriple();
571db9f3b2SDimitry Andric
581db9f3b2SDimitry Andric // Create all the MC Objects.
591db9f3b2SDimitry Andric MRI.reset(TheTarget->createMCRegInfo(TripleName));
601db9f3b2SDimitry Andric if (!MRI)
611db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
621db9f3b2SDimitry Andric "no register info for target %s",
631db9f3b2SDimitry Andric TripleName.c_str());
641db9f3b2SDimitry Andric
651db9f3b2SDimitry Andric MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
661db9f3b2SDimitry Andric MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
671db9f3b2SDimitry Andric if (!MAI)
681db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
691db9f3b2SDimitry Andric "no asm info for target %s", TripleName.c_str());
701db9f3b2SDimitry Andric
711db9f3b2SDimitry Andric MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
721db9f3b2SDimitry Andric if (!MSTI)
731db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
741db9f3b2SDimitry Andric "no subtarget info for target %s",
751db9f3b2SDimitry Andric TripleName.c_str());
761db9f3b2SDimitry Andric
771db9f3b2SDimitry Andric MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
781db9f3b2SDimitry Andric nullptr, true, Swift5ReflectionSegmentName));
791db9f3b2SDimitry Andric MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
801db9f3b2SDimitry Andric MC->setObjectFileInfo(MOFI.get());
811db9f3b2SDimitry Andric
821db9f3b2SDimitry Andric MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
831db9f3b2SDimitry Andric if (!MAB)
841db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
851db9f3b2SDimitry Andric "no asm backend for target %s",
861db9f3b2SDimitry Andric TripleName.c_str());
871db9f3b2SDimitry Andric
881db9f3b2SDimitry Andric MII.reset(TheTarget->createMCInstrInfo());
891db9f3b2SDimitry Andric if (!MII)
901db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
911db9f3b2SDimitry Andric "no instr info info for target %s",
921db9f3b2SDimitry Andric TripleName.c_str());
931db9f3b2SDimitry Andric
941db9f3b2SDimitry Andric MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
951db9f3b2SDimitry Andric if (!MCE)
961db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
971db9f3b2SDimitry Andric "no code emitter for target %s",
981db9f3b2SDimitry Andric TripleName.c_str());
991db9f3b2SDimitry Andric
1001db9f3b2SDimitry Andric switch (OutFileType) {
1011db9f3b2SDimitry Andric case DWARFLinker::OutputFileType::Assembly: {
1021db9f3b2SDimitry Andric MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
1031db9f3b2SDimitry Andric *MAI, *MII, *MRI);
1041db9f3b2SDimitry Andric MS = TheTarget->createAsmStreamer(
1051db9f3b2SDimitry Andric *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
1061db9f3b2SDimitry Andric std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
1071db9f3b2SDimitry Andric true);
1081db9f3b2SDimitry Andric break;
1091db9f3b2SDimitry Andric }
1101db9f3b2SDimitry Andric case DWARFLinker::OutputFileType::Object: {
1111db9f3b2SDimitry Andric MS = TheTarget->createMCObjectStreamer(
1121db9f3b2SDimitry Andric TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
1131db9f3b2SDimitry Andric MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
1141db9f3b2SDimitry Andric *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
1151db9f3b2SDimitry Andric /*DWARFMustBeAtTheEnd*/ false);
1161db9f3b2SDimitry Andric break;
1171db9f3b2SDimitry Andric }
1181db9f3b2SDimitry Andric }
1191db9f3b2SDimitry Andric
1201db9f3b2SDimitry Andric if (!MS)
1211db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
1221db9f3b2SDimitry Andric "no object streamer for target %s",
1231db9f3b2SDimitry Andric TripleName.c_str());
1241db9f3b2SDimitry Andric
1251db9f3b2SDimitry Andric // Finally create the AsmPrinter we'll use to emit the DIEs.
1261db9f3b2SDimitry Andric TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
1271db9f3b2SDimitry Andric std::nullopt));
1281db9f3b2SDimitry Andric if (!TM)
1291db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
1301db9f3b2SDimitry Andric "no target machine for target %s",
1311db9f3b2SDimitry Andric TripleName.c_str());
1321db9f3b2SDimitry Andric
1331db9f3b2SDimitry Andric Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
1341db9f3b2SDimitry Andric if (!Asm)
1351db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument,
1361db9f3b2SDimitry Andric "no asm printer for target %s",
1371db9f3b2SDimitry Andric TripleName.c_str());
1381db9f3b2SDimitry Andric Asm->setDwarfUsesRelocationsAcrossSections(false);
1391db9f3b2SDimitry Andric
1401db9f3b2SDimitry Andric RangesSectionSize = 0;
1411db9f3b2SDimitry Andric RngListsSectionSize = 0;
1421db9f3b2SDimitry Andric LocSectionSize = 0;
1431db9f3b2SDimitry Andric LocListsSectionSize = 0;
1441db9f3b2SDimitry Andric LineSectionSize = 0;
1451db9f3b2SDimitry Andric FrameSectionSize = 0;
1461db9f3b2SDimitry Andric DebugInfoSectionSize = 0;
1471db9f3b2SDimitry Andric MacInfoSectionSize = 0;
1481db9f3b2SDimitry Andric MacroSectionSize = 0;
1491db9f3b2SDimitry Andric
1501db9f3b2SDimitry Andric return Error::success();
1511db9f3b2SDimitry Andric }
1521db9f3b2SDimitry Andric
finish()1531db9f3b2SDimitry Andric void DwarfStreamer::finish() { MS->finish(); }
1541db9f3b2SDimitry Andric
switchToDebugInfoSection(unsigned DwarfVersion)1551db9f3b2SDimitry Andric void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
1561db9f3b2SDimitry Andric MS->switchSection(MOFI->getDwarfInfoSection());
1571db9f3b2SDimitry Andric MC->setDwarfVersion(DwarfVersion);
1581db9f3b2SDimitry Andric }
1591db9f3b2SDimitry Andric
1601db9f3b2SDimitry Andric /// Emit the compilation unit header for \p Unit in the debug_info section.
1611db9f3b2SDimitry Andric ///
1621db9f3b2SDimitry Andric /// A Dwarf 4 section header is encoded as:
1631db9f3b2SDimitry Andric /// uint32_t Unit length (omitting this field)
1641db9f3b2SDimitry Andric /// uint16_t Version
1651db9f3b2SDimitry Andric /// uint32_t Abbreviation table offset
1661db9f3b2SDimitry Andric /// uint8_t Address size
1671db9f3b2SDimitry Andric /// Leading to a total of 11 bytes.
1681db9f3b2SDimitry Andric ///
1691db9f3b2SDimitry Andric /// A Dwarf 5 section header is encoded as:
1701db9f3b2SDimitry Andric /// uint32_t Unit length (omitting this field)
1711db9f3b2SDimitry Andric /// uint16_t Version
1721db9f3b2SDimitry Andric /// uint8_t Unit type
1731db9f3b2SDimitry Andric /// uint8_t Address size
1741db9f3b2SDimitry Andric /// uint32_t Abbreviation table offset
1751db9f3b2SDimitry Andric /// Leading to a total of 12 bytes.
emitCompileUnitHeader(CompileUnit & Unit,unsigned DwarfVersion)1761db9f3b2SDimitry Andric void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,
1771db9f3b2SDimitry Andric unsigned DwarfVersion) {
1781db9f3b2SDimitry Andric switchToDebugInfoSection(DwarfVersion);
1791db9f3b2SDimitry Andric
1801db9f3b2SDimitry Andric /// The start of the unit within its section.
1811db9f3b2SDimitry Andric Unit.setLabelBegin(Asm->createTempSymbol("cu_begin"));
1821db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(Unit.getLabelBegin());
1831db9f3b2SDimitry Andric
1841db9f3b2SDimitry Andric // Emit size of content not including length itself. The size has already
1851db9f3b2SDimitry Andric // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
1861db9f3b2SDimitry Andric // account for the length field.
1871db9f3b2SDimitry Andric Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
1881db9f3b2SDimitry Andric Asm->emitInt16(DwarfVersion);
1891db9f3b2SDimitry Andric
1901db9f3b2SDimitry Andric if (DwarfVersion >= 5) {
1911db9f3b2SDimitry Andric Asm->emitInt8(dwarf::DW_UT_compile);
1921db9f3b2SDimitry Andric Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
1931db9f3b2SDimitry Andric // We share one abbreviations table across all units so it's always at the
1941db9f3b2SDimitry Andric // start of the section.
1951db9f3b2SDimitry Andric Asm->emitInt32(0);
1961db9f3b2SDimitry Andric DebugInfoSectionSize += 12;
1971db9f3b2SDimitry Andric } else {
1981db9f3b2SDimitry Andric // We share one abbreviations table across all units so it's always at the
1991db9f3b2SDimitry Andric // start of the section.
2001db9f3b2SDimitry Andric Asm->emitInt32(0);
2011db9f3b2SDimitry Andric Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
2021db9f3b2SDimitry Andric DebugInfoSectionSize += 11;
2031db9f3b2SDimitry Andric }
2041db9f3b2SDimitry Andric
2051db9f3b2SDimitry Andric // Remember this CU.
2061db9f3b2SDimitry Andric EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});
2071db9f3b2SDimitry Andric }
2081db9f3b2SDimitry Andric
2091db9f3b2SDimitry Andric /// Emit the \p Abbrevs array as the shared abbreviation table
2101db9f3b2SDimitry Andric /// for the linked Dwarf file.
emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> & Abbrevs,unsigned DwarfVersion)2111db9f3b2SDimitry Andric void DwarfStreamer::emitAbbrevs(
2121db9f3b2SDimitry Andric const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
2131db9f3b2SDimitry Andric unsigned DwarfVersion) {
2141db9f3b2SDimitry Andric MS->switchSection(MOFI->getDwarfAbbrevSection());
2151db9f3b2SDimitry Andric MC->setDwarfVersion(DwarfVersion);
2161db9f3b2SDimitry Andric Asm->emitDwarfAbbrevs(Abbrevs);
2171db9f3b2SDimitry Andric }
2181db9f3b2SDimitry Andric
2191db9f3b2SDimitry Andric /// Recursively emit the DIE tree rooted at \p Die.
emitDIE(DIE & Die)2201db9f3b2SDimitry Andric void DwarfStreamer::emitDIE(DIE &Die) {
2211db9f3b2SDimitry Andric MS->switchSection(MOFI->getDwarfInfoSection());
2221db9f3b2SDimitry Andric Asm->emitDwarfDIE(Die);
2231db9f3b2SDimitry Andric DebugInfoSectionSize += Die.getSize();
2241db9f3b2SDimitry Andric }
2251db9f3b2SDimitry Andric
2261db9f3b2SDimitry Andric /// Emit contents of section SecName From Obj.
emitSectionContents(StringRef SecData,DebugSectionKind SecKind)227*7a6dacacSDimitry Andric void DwarfStreamer::emitSectionContents(StringRef SecData,
228*7a6dacacSDimitry Andric DebugSectionKind SecKind) {
229*7a6dacacSDimitry Andric if (SecData.empty())
230*7a6dacacSDimitry Andric return;
2311db9f3b2SDimitry Andric
232*7a6dacacSDimitry Andric if (MCSection *Section = getMCSection(SecKind)) {
2331db9f3b2SDimitry Andric MS->switchSection(Section);
2341db9f3b2SDimitry Andric
2351db9f3b2SDimitry Andric MS->emitBytes(SecData);
2361db9f3b2SDimitry Andric }
2371db9f3b2SDimitry Andric }
2381db9f3b2SDimitry Andric
getMCSection(DebugSectionKind SecKind)239*7a6dacacSDimitry Andric MCSection *DwarfStreamer::getMCSection(DebugSectionKind SecKind) {
240*7a6dacacSDimitry Andric switch (SecKind) {
241*7a6dacacSDimitry Andric case DebugSectionKind::DebugInfo:
242*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfInfoSection();
243*7a6dacacSDimitry Andric case DebugSectionKind::DebugLine:
244*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLineSection();
245*7a6dacacSDimitry Andric case DebugSectionKind::DebugFrame:
246*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfFrameSection();
247*7a6dacacSDimitry Andric case DebugSectionKind::DebugRange:
248*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfRangesSection();
249*7a6dacacSDimitry Andric case DebugSectionKind::DebugRngLists:
250*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfRnglistsSection();
251*7a6dacacSDimitry Andric case DebugSectionKind::DebugLoc:
252*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLocSection();
253*7a6dacacSDimitry Andric case DebugSectionKind::DebugLocLists:
254*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLoclistsSection();
255*7a6dacacSDimitry Andric case DebugSectionKind::DebugARanges:
256*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfARangesSection();
257*7a6dacacSDimitry Andric case DebugSectionKind::DebugAbbrev:
258*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAbbrevSection();
259*7a6dacacSDimitry Andric case DebugSectionKind::DebugMacinfo:
260*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfMacinfoSection();
261*7a6dacacSDimitry Andric case DebugSectionKind::DebugMacro:
262*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfMacroSection();
263*7a6dacacSDimitry Andric case DebugSectionKind::DebugAddr:
264*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAddrSection();
265*7a6dacacSDimitry Andric case DebugSectionKind::DebugStr:
266*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfStrSection();
267*7a6dacacSDimitry Andric case DebugSectionKind::DebugLineStr:
268*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLineStrSection();
269*7a6dacacSDimitry Andric case DebugSectionKind::DebugStrOffsets:
270*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfStrOffSection();
271*7a6dacacSDimitry Andric case DebugSectionKind::DebugPubNames:
272*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfPubNamesSection();
273*7a6dacacSDimitry Andric case DebugSectionKind::DebugPubTypes:
274*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfPubTypesSection();
275*7a6dacacSDimitry Andric case DebugSectionKind::DebugNames:
276*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfDebugNamesSection();
277*7a6dacacSDimitry Andric case DebugSectionKind::AppleNames:
278*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelNamesSection();
279*7a6dacacSDimitry Andric case DebugSectionKind::AppleNamespaces:
280*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelNamespaceSection();
281*7a6dacacSDimitry Andric case DebugSectionKind::AppleObjC:
282*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelObjCSection();
283*7a6dacacSDimitry Andric case DebugSectionKind::AppleTypes:
284*7a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelTypesSection();
285*7a6dacacSDimitry Andric case DebugSectionKind::NumberOfEnumEntries:
286*7a6dacacSDimitry Andric llvm_unreachable("Unknown DebugSectionKind value");
287*7a6dacacSDimitry Andric break;
288*7a6dacacSDimitry Andric }
289*7a6dacacSDimitry Andric
290*7a6dacacSDimitry Andric return nullptr;
291*7a6dacacSDimitry Andric }
292*7a6dacacSDimitry Andric
2931db9f3b2SDimitry Andric /// Emit the debug_str section stored in \p Pool.
emitStrings(const NonRelocatableStringpool & Pool)2941db9f3b2SDimitry Andric void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
2951db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
2961db9f3b2SDimitry Andric std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
2971db9f3b2SDimitry Andric for (auto Entry : Entries) {
2981db9f3b2SDimitry Andric // Emit the string itself.
2991db9f3b2SDimitry Andric Asm->OutStreamer->emitBytes(Entry.getString());
3001db9f3b2SDimitry Andric // Emit a null terminator.
3011db9f3b2SDimitry Andric Asm->emitInt8(0);
3021db9f3b2SDimitry Andric }
3031db9f3b2SDimitry Andric }
3041db9f3b2SDimitry Andric
3051db9f3b2SDimitry Andric /// Emit the debug string offset table described by \p StringOffsets into the
3061db9f3b2SDimitry Andric /// .debug_str_offsets table.
emitStringOffsets(const SmallVector<uint64_t> & StringOffsets,uint16_t TargetDWARFVersion)3071db9f3b2SDimitry Andric void DwarfStreamer::emitStringOffsets(
3081db9f3b2SDimitry Andric const SmallVector<uint64_t> &StringOffsets, uint16_t TargetDWARFVersion) {
3091db9f3b2SDimitry Andric
3101db9f3b2SDimitry Andric if (TargetDWARFVersion < 5 || StringOffsets.empty())
3111db9f3b2SDimitry Andric return;
3121db9f3b2SDimitry Andric
3131db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());
3141db9f3b2SDimitry Andric
3151db9f3b2SDimitry Andric MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugstroff");
3161db9f3b2SDimitry Andric MCSymbol *EndLabel = Asm->createTempSymbol("Edebugstroff");
3171db9f3b2SDimitry Andric
3181db9f3b2SDimitry Andric // Length.
3191db9f3b2SDimitry Andric Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
3201db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(BeginLabel);
3211db9f3b2SDimitry Andric StrOffsetSectionSize += sizeof(uint32_t);
3221db9f3b2SDimitry Andric
3231db9f3b2SDimitry Andric // Version.
3241db9f3b2SDimitry Andric MS->emitInt16(5);
3251db9f3b2SDimitry Andric StrOffsetSectionSize += sizeof(uint16_t);
3261db9f3b2SDimitry Andric
3271db9f3b2SDimitry Andric // Padding.
3281db9f3b2SDimitry Andric MS->emitInt16(0);
3291db9f3b2SDimitry Andric StrOffsetSectionSize += sizeof(uint16_t);
3301db9f3b2SDimitry Andric
3311db9f3b2SDimitry Andric for (auto Off : StringOffsets) {
3321db9f3b2SDimitry Andric Asm->OutStreamer->emitInt32(Off);
3331db9f3b2SDimitry Andric StrOffsetSectionSize += sizeof(uint32_t);
3341db9f3b2SDimitry Andric }
3351db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(EndLabel);
3361db9f3b2SDimitry Andric }
3371db9f3b2SDimitry Andric
3381db9f3b2SDimitry Andric /// Emit the debug_line_str section stored in \p Pool.
emitLineStrings(const NonRelocatableStringpool & Pool)3391db9f3b2SDimitry Andric void DwarfStreamer::emitLineStrings(const NonRelocatableStringpool &Pool) {
3401db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfLineStrSection());
3411db9f3b2SDimitry Andric std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
3421db9f3b2SDimitry Andric for (auto Entry : Entries) {
3431db9f3b2SDimitry Andric // Emit the string itself.
3441db9f3b2SDimitry Andric Asm->OutStreamer->emitBytes(Entry.getString());
3451db9f3b2SDimitry Andric // Emit a null terminator.
3461db9f3b2SDimitry Andric Asm->emitInt8(0);
3471db9f3b2SDimitry Andric }
3481db9f3b2SDimitry Andric }
3491db9f3b2SDimitry Andric
emitDebugNames(DWARF5AccelTable & Table)3501db9f3b2SDimitry Andric void DwarfStreamer::emitDebugNames(DWARF5AccelTable &Table) {
3511db9f3b2SDimitry Andric if (EmittedUnits.empty())
3521db9f3b2SDimitry Andric return;
3531db9f3b2SDimitry Andric
3541db9f3b2SDimitry Andric // Build up data structures needed to emit this section.
3551db9f3b2SDimitry Andric std::vector<std::variant<MCSymbol *, uint64_t>> CompUnits;
3561db9f3b2SDimitry Andric DenseMap<unsigned, unsigned> UniqueIdToCuMap;
3571db9f3b2SDimitry Andric unsigned Id = 0;
3581db9f3b2SDimitry Andric for (auto &CU : EmittedUnits) {
3591db9f3b2SDimitry Andric CompUnits.push_back(CU.LabelBegin);
3601db9f3b2SDimitry Andric // We might be omitting CUs, so we need to remap them.
3611db9f3b2SDimitry Andric UniqueIdToCuMap[CU.ID] = Id++;
3621db9f3b2SDimitry Andric }
3631db9f3b2SDimitry Andric
3641db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
3651db9f3b2SDimitry Andric dwarf::Form Form = DIEInteger::BestForm(/*IsSigned*/ false,
3661db9f3b2SDimitry Andric (uint64_t)UniqueIdToCuMap.size() - 1);
3671db9f3b2SDimitry Andric /// llvm-dwarfutil doesn't support type units + .debug_names right now.
3681db9f3b2SDimitry Andric // FIXME: add support for type units + .debug_names. For now the behavior is
3691db9f3b2SDimitry Andric // unsuported.
3701db9f3b2SDimitry Andric emitDWARF5AccelTable(
3711db9f3b2SDimitry Andric Asm.get(), Table, CompUnits,
3721db9f3b2SDimitry Andric [&](const DWARF5AccelTableData &Entry)
3731db9f3b2SDimitry Andric -> std::optional<DWARF5AccelTable::UnitIndexAndEncoding> {
3741db9f3b2SDimitry Andric if (UniqueIdToCuMap.size() > 1)
3751db9f3b2SDimitry Andric return {{UniqueIdToCuMap[Entry.getUnitID()],
3761db9f3b2SDimitry Andric {dwarf::DW_IDX_compile_unit, Form}}};
3771db9f3b2SDimitry Andric return std::nullopt;
3781db9f3b2SDimitry Andric });
3791db9f3b2SDimitry Andric }
3801db9f3b2SDimitry Andric
emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> & Table)3811db9f3b2SDimitry Andric void DwarfStreamer::emitAppleNamespaces(
3821db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> &Table) {
3831db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
3841db9f3b2SDimitry Andric auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
3851db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(SectionBegin);
3861db9f3b2SDimitry Andric emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
3871db9f3b2SDimitry Andric }
3881db9f3b2SDimitry Andric
emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> & Table)3891db9f3b2SDimitry Andric void DwarfStreamer::emitAppleNames(
3901db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> &Table) {
3911db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
3921db9f3b2SDimitry Andric auto *SectionBegin = Asm->createTempSymbol("names_begin");
3931db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(SectionBegin);
3941db9f3b2SDimitry Andric emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
3951db9f3b2SDimitry Andric }
3961db9f3b2SDimitry Andric
emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> & Table)3971db9f3b2SDimitry Andric void DwarfStreamer::emitAppleObjc(
3981db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticOffsetData> &Table) {
3991db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
4001db9f3b2SDimitry Andric auto *SectionBegin = Asm->createTempSymbol("objc_begin");
4011db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(SectionBegin);
4021db9f3b2SDimitry Andric emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
4031db9f3b2SDimitry Andric }
4041db9f3b2SDimitry Andric
emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> & Table)4051db9f3b2SDimitry Andric void DwarfStreamer::emitAppleTypes(
4061db9f3b2SDimitry Andric AccelTable<AppleAccelTableStaticTypeData> &Table) {
4071db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
4081db9f3b2SDimitry Andric auto *SectionBegin = Asm->createTempSymbol("types_begin");
4091db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(SectionBegin);
4101db9f3b2SDimitry Andric emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
4111db9f3b2SDimitry Andric }
4121db9f3b2SDimitry Andric
4131db9f3b2SDimitry Andric /// Emit the swift_ast section stored in \p Buffers.
emitSwiftAST(StringRef Buffer)4141db9f3b2SDimitry Andric void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
4151db9f3b2SDimitry Andric MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
4161db9f3b2SDimitry Andric SwiftASTSection->setAlignment(Align(32));
4171db9f3b2SDimitry Andric MS->switchSection(SwiftASTSection);
4181db9f3b2SDimitry Andric MS->emitBytes(Buffer);
4191db9f3b2SDimitry Andric }
4201db9f3b2SDimitry Andric
emitSwiftReflectionSection(llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,StringRef Buffer,uint32_t Alignment,uint32_t Size)4211db9f3b2SDimitry Andric void DwarfStreamer::emitSwiftReflectionSection(
4221db9f3b2SDimitry Andric llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
4231db9f3b2SDimitry Andric StringRef Buffer, uint32_t Alignment, uint32_t Size) {
4241db9f3b2SDimitry Andric MCSection *ReflectionSection =
4251db9f3b2SDimitry Andric MOFI->getSwift5ReflectionSection(ReflSectionKind);
4261db9f3b2SDimitry Andric if (ReflectionSection == nullptr)
4271db9f3b2SDimitry Andric return;
4281db9f3b2SDimitry Andric ReflectionSection->setAlignment(Align(Alignment));
4291db9f3b2SDimitry Andric MS->switchSection(ReflectionSection);
4301db9f3b2SDimitry Andric MS->emitBytes(Buffer);
4311db9f3b2SDimitry Andric }
4321db9f3b2SDimitry Andric
emitDwarfDebugArangesTable(const CompileUnit & Unit,const AddressRanges & LinkedRanges)4331db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugArangesTable(
4341db9f3b2SDimitry Andric const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
4351db9f3b2SDimitry Andric unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
4361db9f3b2SDimitry Andric
4371db9f3b2SDimitry Andric // Make .debug_aranges to be current section.
4381db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
4391db9f3b2SDimitry Andric
4401db9f3b2SDimitry Andric // Emit Header.
4411db9f3b2SDimitry Andric MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
4421db9f3b2SDimitry Andric MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
4431db9f3b2SDimitry Andric
4441db9f3b2SDimitry Andric unsigned HeaderSize =
4451db9f3b2SDimitry Andric sizeof(int32_t) + // Size of contents (w/o this field
4461db9f3b2SDimitry Andric sizeof(int16_t) + // DWARF ARange version number
4471db9f3b2SDimitry Andric sizeof(int32_t) + // Offset of CU in the .debug_info section
4481db9f3b2SDimitry Andric sizeof(int8_t) + // Pointer Size (in bytes)
4491db9f3b2SDimitry Andric sizeof(int8_t); // Segment Size (in bytes)
4501db9f3b2SDimitry Andric
4511db9f3b2SDimitry Andric unsigned TupleSize = AddressSize * 2;
4521db9f3b2SDimitry Andric unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
4531db9f3b2SDimitry Andric
4541db9f3b2SDimitry Andric Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
4551db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(BeginLabel);
4561db9f3b2SDimitry Andric Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
4571db9f3b2SDimitry Andric Asm->emitInt32(Unit.getStartOffset()); // Corresponding unit's offset
4581db9f3b2SDimitry Andric Asm->emitInt8(AddressSize); // Address size
4591db9f3b2SDimitry Andric Asm->emitInt8(0); // Segment size
4601db9f3b2SDimitry Andric
4611db9f3b2SDimitry Andric Asm->OutStreamer->emitFill(Padding, 0x0);
4621db9f3b2SDimitry Andric
4631db9f3b2SDimitry Andric // Emit linked ranges.
4641db9f3b2SDimitry Andric for (const AddressRange &Range : LinkedRanges) {
4651db9f3b2SDimitry Andric MS->emitIntValue(Range.start(), AddressSize);
4661db9f3b2SDimitry Andric MS->emitIntValue(Range.end() - Range.start(), AddressSize);
4671db9f3b2SDimitry Andric }
4681db9f3b2SDimitry Andric
4691db9f3b2SDimitry Andric // Emit terminator.
4701db9f3b2SDimitry Andric Asm->OutStreamer->emitIntValue(0, AddressSize);
4711db9f3b2SDimitry Andric Asm->OutStreamer->emitIntValue(0, AddressSize);
4721db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(EndLabel);
4731db9f3b2SDimitry Andric }
4741db9f3b2SDimitry Andric
emitDwarfDebugRangesTableFragment(const CompileUnit & Unit,const AddressRanges & LinkedRanges,PatchLocation Patch)4751db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugRangesTableFragment(
4761db9f3b2SDimitry Andric const CompileUnit &Unit, const AddressRanges &LinkedRanges,
4771db9f3b2SDimitry Andric PatchLocation Patch) {
4781db9f3b2SDimitry Andric Patch.set(RangesSectionSize);
4791db9f3b2SDimitry Andric
4801db9f3b2SDimitry Andric // Make .debug_ranges to be current section.
4811db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
4821db9f3b2SDimitry Andric unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
4831db9f3b2SDimitry Andric
4841db9f3b2SDimitry Andric // Emit ranges.
4851db9f3b2SDimitry Andric uint64_t BaseAddress = 0;
4861db9f3b2SDimitry Andric if (std::optional<uint64_t> LowPC = Unit.getLowPc())
4871db9f3b2SDimitry Andric BaseAddress = *LowPC;
4881db9f3b2SDimitry Andric
4891db9f3b2SDimitry Andric for (const AddressRange &Range : LinkedRanges) {
4901db9f3b2SDimitry Andric MS->emitIntValue(Range.start() - BaseAddress, AddressSize);
4911db9f3b2SDimitry Andric MS->emitIntValue(Range.end() - BaseAddress, AddressSize);
4921db9f3b2SDimitry Andric
4931db9f3b2SDimitry Andric RangesSectionSize += AddressSize;
4941db9f3b2SDimitry Andric RangesSectionSize += AddressSize;
4951db9f3b2SDimitry Andric }
4961db9f3b2SDimitry Andric
4971db9f3b2SDimitry Andric // Add the terminator entry.
4981db9f3b2SDimitry Andric MS->emitIntValue(0, AddressSize);
4991db9f3b2SDimitry Andric MS->emitIntValue(0, AddressSize);
5001db9f3b2SDimitry Andric
5011db9f3b2SDimitry Andric RangesSectionSize += AddressSize;
5021db9f3b2SDimitry Andric RangesSectionSize += AddressSize;
5031db9f3b2SDimitry Andric }
5041db9f3b2SDimitry Andric
5051db9f3b2SDimitry Andric MCSymbol *
emitDwarfDebugRangeListHeader(const CompileUnit & Unit)5061db9f3b2SDimitry Andric DwarfStreamer::emitDwarfDebugRangeListHeader(const CompileUnit &Unit) {
5071db9f3b2SDimitry Andric if (Unit.getOrigUnit().getVersion() < 5)
5081db9f3b2SDimitry Andric return nullptr;
5091db9f3b2SDimitry Andric
5101db9f3b2SDimitry Andric // Make .debug_rnglists to be current section.
5111db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
5121db9f3b2SDimitry Andric
5131db9f3b2SDimitry Andric MCSymbol *BeginLabel = Asm->createTempSymbol("Brnglists");
5141db9f3b2SDimitry Andric MCSymbol *EndLabel = Asm->createTempSymbol("Ernglists");
5151db9f3b2SDimitry Andric unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
5161db9f3b2SDimitry Andric
5171db9f3b2SDimitry Andric // Length
5181db9f3b2SDimitry Andric Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
5191db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(BeginLabel);
5201db9f3b2SDimitry Andric RngListsSectionSize += sizeof(uint32_t);
5211db9f3b2SDimitry Andric
5221db9f3b2SDimitry Andric // Version.
5231db9f3b2SDimitry Andric MS->emitInt16(5);
5241db9f3b2SDimitry Andric RngListsSectionSize += sizeof(uint16_t);
5251db9f3b2SDimitry Andric
5261db9f3b2SDimitry Andric // Address size.
5271db9f3b2SDimitry Andric MS->emitInt8(AddressSize);
5281db9f3b2SDimitry Andric RngListsSectionSize++;
5291db9f3b2SDimitry Andric
5301db9f3b2SDimitry Andric // Seg_size
5311db9f3b2SDimitry Andric MS->emitInt8(0);
5321db9f3b2SDimitry Andric RngListsSectionSize++;
5331db9f3b2SDimitry Andric
5341db9f3b2SDimitry Andric // Offset entry count
5351db9f3b2SDimitry Andric MS->emitInt32(0);
5361db9f3b2SDimitry Andric RngListsSectionSize += sizeof(uint32_t);
5371db9f3b2SDimitry Andric
5381db9f3b2SDimitry Andric return EndLabel;
5391db9f3b2SDimitry Andric }
5401db9f3b2SDimitry Andric
emitDwarfDebugRangeListFragment(const CompileUnit & Unit,const AddressRanges & LinkedRanges,PatchLocation Patch,DebugDieValuePool & AddrPool)5411db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugRangeListFragment(
5421db9f3b2SDimitry Andric const CompileUnit &Unit, const AddressRanges &LinkedRanges,
5431db9f3b2SDimitry Andric PatchLocation Patch, DebugDieValuePool &AddrPool) {
5441db9f3b2SDimitry Andric if (Unit.getOrigUnit().getVersion() < 5) {
5451db9f3b2SDimitry Andric emitDwarfDebugRangesTableFragment(Unit, LinkedRanges, Patch);
5461db9f3b2SDimitry Andric return;
5471db9f3b2SDimitry Andric }
5481db9f3b2SDimitry Andric
5491db9f3b2SDimitry Andric emitDwarfDebugRngListsTableFragment(Unit, LinkedRanges, Patch, AddrPool);
5501db9f3b2SDimitry Andric }
5511db9f3b2SDimitry Andric
emitDwarfDebugRangeListFooter(const CompileUnit & Unit,MCSymbol * EndLabel)5521db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugRangeListFooter(const CompileUnit &Unit,
5531db9f3b2SDimitry Andric MCSymbol *EndLabel) {
5541db9f3b2SDimitry Andric if (Unit.getOrigUnit().getVersion() < 5)
5551db9f3b2SDimitry Andric return;
5561db9f3b2SDimitry Andric
5571db9f3b2SDimitry Andric // Make .debug_rnglists to be current section.
5581db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
5591db9f3b2SDimitry Andric
5601db9f3b2SDimitry Andric if (EndLabel != nullptr)
5611db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(EndLabel);
5621db9f3b2SDimitry Andric }
5631db9f3b2SDimitry Andric
emitDwarfDebugRngListsTableFragment(const CompileUnit & Unit,const AddressRanges & LinkedRanges,PatchLocation Patch,DebugDieValuePool & AddrPool)5641db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugRngListsTableFragment(
5651db9f3b2SDimitry Andric const CompileUnit &Unit, const AddressRanges &LinkedRanges,
5661db9f3b2SDimitry Andric PatchLocation Patch, DebugDieValuePool &AddrPool) {
5671db9f3b2SDimitry Andric Patch.set(RngListsSectionSize);
5681db9f3b2SDimitry Andric
5691db9f3b2SDimitry Andric // Make .debug_rnglists to be current section.
5701db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfRnglistsSection());
5711db9f3b2SDimitry Andric std::optional<uint64_t> BaseAddress;
5721db9f3b2SDimitry Andric
5731db9f3b2SDimitry Andric for (const AddressRange &Range : LinkedRanges) {
5741db9f3b2SDimitry Andric
5751db9f3b2SDimitry Andric if (!BaseAddress) {
5761db9f3b2SDimitry Andric BaseAddress = Range.start();
5771db9f3b2SDimitry Andric
5781db9f3b2SDimitry Andric // Emit base address.
5791db9f3b2SDimitry Andric MS->emitInt8(dwarf::DW_RLE_base_addressx);
5801db9f3b2SDimitry Andric RngListsSectionSize += 1;
5811db9f3b2SDimitry Andric RngListsSectionSize +=
5821db9f3b2SDimitry Andric MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress));
5831db9f3b2SDimitry Andric }
5841db9f3b2SDimitry Andric
5851db9f3b2SDimitry Andric // Emit type of entry.
5861db9f3b2SDimitry Andric MS->emitInt8(dwarf::DW_RLE_offset_pair);
5871db9f3b2SDimitry Andric RngListsSectionSize += 1;
5881db9f3b2SDimitry Andric
5891db9f3b2SDimitry Andric // Emit start offset relative to base address.
5901db9f3b2SDimitry Andric RngListsSectionSize +=
5911db9f3b2SDimitry Andric MS->emitULEB128IntValue(Range.start() - *BaseAddress);
5921db9f3b2SDimitry Andric
5931db9f3b2SDimitry Andric // Emit end offset relative to base address.
5941db9f3b2SDimitry Andric RngListsSectionSize += MS->emitULEB128IntValue(Range.end() - *BaseAddress);
5951db9f3b2SDimitry Andric }
5961db9f3b2SDimitry Andric
5971db9f3b2SDimitry Andric // Emit the terminator entry.
5981db9f3b2SDimitry Andric MS->emitInt8(dwarf::DW_RLE_end_of_list);
5991db9f3b2SDimitry Andric RngListsSectionSize += 1;
6001db9f3b2SDimitry Andric }
6011db9f3b2SDimitry Andric
6021db9f3b2SDimitry Andric /// Emit debug locations(.debug_loc, .debug_loclists) header.
emitDwarfDebugLocListHeader(const CompileUnit & Unit)6031db9f3b2SDimitry Andric MCSymbol *DwarfStreamer::emitDwarfDebugLocListHeader(const CompileUnit &Unit) {
6041db9f3b2SDimitry Andric if (Unit.getOrigUnit().getVersion() < 5)
6051db9f3b2SDimitry Andric return nullptr;
6061db9f3b2SDimitry Andric
6071db9f3b2SDimitry Andric // Make .debug_loclists the current section.
6081db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
6091db9f3b2SDimitry Andric
6101db9f3b2SDimitry Andric MCSymbol *BeginLabel = Asm->createTempSymbol("Bloclists");
6111db9f3b2SDimitry Andric MCSymbol *EndLabel = Asm->createTempSymbol("Eloclists");
6121db9f3b2SDimitry Andric unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
6131db9f3b2SDimitry Andric
6141db9f3b2SDimitry Andric // Length
6151db9f3b2SDimitry Andric Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
6161db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(BeginLabel);
6171db9f3b2SDimitry Andric LocListsSectionSize += sizeof(uint32_t);
6181db9f3b2SDimitry Andric
6191db9f3b2SDimitry Andric // Version.
6201db9f3b2SDimitry Andric MS->emitInt16(5);
6211db9f3b2SDimitry Andric LocListsSectionSize += sizeof(uint16_t);
6221db9f3b2SDimitry Andric
6231db9f3b2SDimitry Andric // Address size.
6241db9f3b2SDimitry Andric MS->emitInt8(AddressSize);
6251db9f3b2SDimitry Andric LocListsSectionSize++;
6261db9f3b2SDimitry Andric
6271db9f3b2SDimitry Andric // Seg_size
6281db9f3b2SDimitry Andric MS->emitInt8(0);
6291db9f3b2SDimitry Andric LocListsSectionSize++;
6301db9f3b2SDimitry Andric
6311db9f3b2SDimitry Andric // Offset entry count
6321db9f3b2SDimitry Andric MS->emitInt32(0);
6331db9f3b2SDimitry Andric LocListsSectionSize += sizeof(uint32_t);
6341db9f3b2SDimitry Andric
6351db9f3b2SDimitry Andric return EndLabel;
6361db9f3b2SDimitry Andric }
6371db9f3b2SDimitry Andric
6381db9f3b2SDimitry Andric /// Emit debug locations(.debug_loc, .debug_loclists) fragment.
emitDwarfDebugLocListFragment(const CompileUnit & Unit,const DWARFLocationExpressionsVector & LinkedLocationExpression,PatchLocation Patch,DebugDieValuePool & AddrPool)6391db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugLocListFragment(
6401db9f3b2SDimitry Andric const CompileUnit &Unit,
6411db9f3b2SDimitry Andric const DWARFLocationExpressionsVector &LinkedLocationExpression,
6421db9f3b2SDimitry Andric PatchLocation Patch, DebugDieValuePool &AddrPool) {
6431db9f3b2SDimitry Andric if (Unit.getOrigUnit().getVersion() < 5) {
6441db9f3b2SDimitry Andric emitDwarfDebugLocTableFragment(Unit, LinkedLocationExpression, Patch);
6451db9f3b2SDimitry Andric return;
6461db9f3b2SDimitry Andric }
6471db9f3b2SDimitry Andric
6481db9f3b2SDimitry Andric emitDwarfDebugLocListsTableFragment(Unit, LinkedLocationExpression, Patch,
6491db9f3b2SDimitry Andric AddrPool);
6501db9f3b2SDimitry Andric }
6511db9f3b2SDimitry Andric
6521db9f3b2SDimitry Andric /// Emit debug locations(.debug_loc, .debug_loclists) footer.
emitDwarfDebugLocListFooter(const CompileUnit & Unit,MCSymbol * EndLabel)6531db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugLocListFooter(const CompileUnit &Unit,
6541db9f3b2SDimitry Andric MCSymbol *EndLabel) {
6551db9f3b2SDimitry Andric if (Unit.getOrigUnit().getVersion() < 5)
6561db9f3b2SDimitry Andric return;
6571db9f3b2SDimitry Andric
6581db9f3b2SDimitry Andric // Make .debug_loclists the current section.
6591db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
6601db9f3b2SDimitry Andric
6611db9f3b2SDimitry Andric if (EndLabel != nullptr)
6621db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(EndLabel);
6631db9f3b2SDimitry Andric }
6641db9f3b2SDimitry Andric
6651db9f3b2SDimitry Andric /// Emit piece of .debug_loc for \p LinkedLocationExpression.
emitDwarfDebugLocTableFragment(const CompileUnit & Unit,const DWARFLocationExpressionsVector & LinkedLocationExpression,PatchLocation Patch)6661db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugLocTableFragment(
6671db9f3b2SDimitry Andric const CompileUnit &Unit,
6681db9f3b2SDimitry Andric const DWARFLocationExpressionsVector &LinkedLocationExpression,
6691db9f3b2SDimitry Andric PatchLocation Patch) {
6701db9f3b2SDimitry Andric Patch.set(LocSectionSize);
6711db9f3b2SDimitry Andric
6721db9f3b2SDimitry Andric // Make .debug_loc to be current section.
6731db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
6741db9f3b2SDimitry Andric unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
6751db9f3b2SDimitry Andric
6761db9f3b2SDimitry Andric // Emit ranges.
6771db9f3b2SDimitry Andric uint64_t BaseAddress = 0;
6781db9f3b2SDimitry Andric if (std::optional<uint64_t> LowPC = Unit.getLowPc())
6791db9f3b2SDimitry Andric BaseAddress = *LowPC;
6801db9f3b2SDimitry Andric
6811db9f3b2SDimitry Andric for (const DWARFLocationExpression &LocExpression :
6821db9f3b2SDimitry Andric LinkedLocationExpression) {
6831db9f3b2SDimitry Andric if (LocExpression.Range) {
6841db9f3b2SDimitry Andric MS->emitIntValue(LocExpression.Range->LowPC - BaseAddress, AddressSize);
6851db9f3b2SDimitry Andric MS->emitIntValue(LocExpression.Range->HighPC - BaseAddress, AddressSize);
6861db9f3b2SDimitry Andric
6871db9f3b2SDimitry Andric LocSectionSize += AddressSize;
6881db9f3b2SDimitry Andric LocSectionSize += AddressSize;
6891db9f3b2SDimitry Andric }
6901db9f3b2SDimitry Andric
6911db9f3b2SDimitry Andric Asm->OutStreamer->emitIntValue(LocExpression.Expr.size(), 2);
6921db9f3b2SDimitry Andric Asm->OutStreamer->emitBytes(StringRef(
6931db9f3b2SDimitry Andric (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
6941db9f3b2SDimitry Andric LocSectionSize += LocExpression.Expr.size() + 2;
6951db9f3b2SDimitry Andric }
6961db9f3b2SDimitry Andric
6971db9f3b2SDimitry Andric // Add the terminator entry.
6981db9f3b2SDimitry Andric MS->emitIntValue(0, AddressSize);
6991db9f3b2SDimitry Andric MS->emitIntValue(0, AddressSize);
7001db9f3b2SDimitry Andric
7011db9f3b2SDimitry Andric LocSectionSize += AddressSize;
7021db9f3b2SDimitry Andric LocSectionSize += AddressSize;
7031db9f3b2SDimitry Andric }
7041db9f3b2SDimitry Andric
7051db9f3b2SDimitry Andric /// Emit .debug_addr header.
emitDwarfDebugAddrsHeader(const CompileUnit & Unit)7061db9f3b2SDimitry Andric MCSymbol *DwarfStreamer::emitDwarfDebugAddrsHeader(const CompileUnit &Unit) {
7071db9f3b2SDimitry Andric
7081db9f3b2SDimitry Andric // Make .debug_addr the current section.
7091db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());
7101db9f3b2SDimitry Andric
7111db9f3b2SDimitry Andric MCSymbol *BeginLabel = Asm->createTempSymbol("Bdebugaddr");
7121db9f3b2SDimitry Andric MCSymbol *EndLabel = Asm->createTempSymbol("Edebugaddr");
7131db9f3b2SDimitry Andric unsigned AddrSize = Unit.getOrigUnit().getAddressByteSize();
7141db9f3b2SDimitry Andric
7151db9f3b2SDimitry Andric // Emit length.
7161db9f3b2SDimitry Andric Asm->emitLabelDifference(EndLabel, BeginLabel, sizeof(uint32_t));
7171db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(BeginLabel);
7181db9f3b2SDimitry Andric AddrSectionSize += sizeof(uint32_t);
7191db9f3b2SDimitry Andric
7201db9f3b2SDimitry Andric // Emit version.
7211db9f3b2SDimitry Andric Asm->emitInt16(5);
7221db9f3b2SDimitry Andric AddrSectionSize += 2;
7231db9f3b2SDimitry Andric
7241db9f3b2SDimitry Andric // Emit address size.
7251db9f3b2SDimitry Andric Asm->emitInt8(AddrSize);
7261db9f3b2SDimitry Andric AddrSectionSize += 1;
7271db9f3b2SDimitry Andric
7281db9f3b2SDimitry Andric // Emit segment size.
7291db9f3b2SDimitry Andric Asm->emitInt8(0);
7301db9f3b2SDimitry Andric AddrSectionSize += 1;
7311db9f3b2SDimitry Andric
7321db9f3b2SDimitry Andric return EndLabel;
7331db9f3b2SDimitry Andric }
7341db9f3b2SDimitry Andric
7351db9f3b2SDimitry Andric /// Emit the .debug_addr addresses stored in \p Addrs.
emitDwarfDebugAddrs(const SmallVector<uint64_t> & Addrs,uint8_t AddrSize)7361db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugAddrs(const SmallVector<uint64_t> &Addrs,
7371db9f3b2SDimitry Andric uint8_t AddrSize) {
7381db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(MOFI->getDwarfAddrSection());
7391db9f3b2SDimitry Andric for (auto Addr : Addrs) {
7401db9f3b2SDimitry Andric Asm->OutStreamer->emitIntValue(Addr, AddrSize);
7411db9f3b2SDimitry Andric AddrSectionSize += AddrSize;
7421db9f3b2SDimitry Andric }
7431db9f3b2SDimitry Andric }
7441db9f3b2SDimitry Andric
7451db9f3b2SDimitry Andric /// Emit .debug_addr footer.
emitDwarfDebugAddrsFooter(const CompileUnit & Unit,MCSymbol * EndLabel)7461db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugAddrsFooter(const CompileUnit &Unit,
7471db9f3b2SDimitry Andric MCSymbol *EndLabel) {
7481db9f3b2SDimitry Andric
7491db9f3b2SDimitry Andric // Make .debug_addr the current section.
7501db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfAddrSection());
7511db9f3b2SDimitry Andric
7521db9f3b2SDimitry Andric if (EndLabel != nullptr)
7531db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(EndLabel);
7541db9f3b2SDimitry Andric }
7551db9f3b2SDimitry Andric
7561db9f3b2SDimitry Andric /// Emit piece of .debug_loclists for \p LinkedLocationExpression.
emitDwarfDebugLocListsTableFragment(const CompileUnit & Unit,const DWARFLocationExpressionsVector & LinkedLocationExpression,PatchLocation Patch,DebugDieValuePool & AddrPool)7571db9f3b2SDimitry Andric void DwarfStreamer::emitDwarfDebugLocListsTableFragment(
7581db9f3b2SDimitry Andric const CompileUnit &Unit,
7591db9f3b2SDimitry Andric const DWARFLocationExpressionsVector &LinkedLocationExpression,
7601db9f3b2SDimitry Andric PatchLocation Patch, DebugDieValuePool &AddrPool) {
7611db9f3b2SDimitry Andric Patch.set(LocListsSectionSize);
7621db9f3b2SDimitry Andric
7631db9f3b2SDimitry Andric // Make .debug_loclists the current section.
7641db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfLoclistsSection());
7651db9f3b2SDimitry Andric std::optional<uint64_t> BaseAddress;
7661db9f3b2SDimitry Andric
7671db9f3b2SDimitry Andric for (const DWARFLocationExpression &LocExpression :
7681db9f3b2SDimitry Andric LinkedLocationExpression) {
7691db9f3b2SDimitry Andric if (LocExpression.Range) {
7701db9f3b2SDimitry Andric
7711db9f3b2SDimitry Andric if (!BaseAddress) {
7721db9f3b2SDimitry Andric
7731db9f3b2SDimitry Andric BaseAddress = LocExpression.Range->LowPC;
7741db9f3b2SDimitry Andric
7751db9f3b2SDimitry Andric // Emit base address.
7761db9f3b2SDimitry Andric MS->emitInt8(dwarf::DW_LLE_base_addressx);
7771db9f3b2SDimitry Andric LocListsSectionSize += 1;
7781db9f3b2SDimitry Andric LocListsSectionSize +=
7791db9f3b2SDimitry Andric MS->emitULEB128IntValue(AddrPool.getValueIndex(*BaseAddress));
7801db9f3b2SDimitry Andric }
7811db9f3b2SDimitry Andric
7821db9f3b2SDimitry Andric // Emit type of entry.
7831db9f3b2SDimitry Andric MS->emitInt8(dwarf::DW_LLE_offset_pair);
7841db9f3b2SDimitry Andric LocListsSectionSize += 1;
7851db9f3b2SDimitry Andric
7861db9f3b2SDimitry Andric // Emit start offset relative to base address.
7871db9f3b2SDimitry Andric LocListsSectionSize +=
7881db9f3b2SDimitry Andric MS->emitULEB128IntValue(LocExpression.Range->LowPC - *BaseAddress);
7891db9f3b2SDimitry Andric
7901db9f3b2SDimitry Andric // Emit end offset relative to base address.
7911db9f3b2SDimitry Andric LocListsSectionSize +=
7921db9f3b2SDimitry Andric MS->emitULEB128IntValue(LocExpression.Range->HighPC - *BaseAddress);
7931db9f3b2SDimitry Andric } else {
7941db9f3b2SDimitry Andric // Emit type of entry.
7951db9f3b2SDimitry Andric MS->emitInt8(dwarf::DW_LLE_default_location);
7961db9f3b2SDimitry Andric LocListsSectionSize += 1;
7971db9f3b2SDimitry Andric }
7981db9f3b2SDimitry Andric
7991db9f3b2SDimitry Andric LocListsSectionSize += MS->emitULEB128IntValue(LocExpression.Expr.size());
8001db9f3b2SDimitry Andric Asm->OutStreamer->emitBytes(StringRef(
8011db9f3b2SDimitry Andric (const char *)LocExpression.Expr.data(), LocExpression.Expr.size()));
8021db9f3b2SDimitry Andric LocListsSectionSize += LocExpression.Expr.size();
8031db9f3b2SDimitry Andric }
8041db9f3b2SDimitry Andric
8051db9f3b2SDimitry Andric // Emit the terminator entry.
8061db9f3b2SDimitry Andric MS->emitInt8(dwarf::DW_LLE_end_of_list);
8071db9f3b2SDimitry Andric LocListsSectionSize += 1;
8081db9f3b2SDimitry Andric }
8091db9f3b2SDimitry Andric
emitLineTableForUnit(const DWARFDebugLine::LineTable & LineTable,const CompileUnit & Unit,OffsetsStringPool & DebugStrPool,OffsetsStringPool & DebugLineStrPool)8101db9f3b2SDimitry Andric void DwarfStreamer::emitLineTableForUnit(
8111db9f3b2SDimitry Andric const DWARFDebugLine::LineTable &LineTable, const CompileUnit &Unit,
8121db9f3b2SDimitry Andric OffsetsStringPool &DebugStrPool, OffsetsStringPool &DebugLineStrPool) {
8131db9f3b2SDimitry Andric // Switch to the section where the table will be emitted into.
8141db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
8151db9f3b2SDimitry Andric
8161db9f3b2SDimitry Andric MCSymbol *LineStartSym = MC->createTempSymbol();
8171db9f3b2SDimitry Andric MCSymbol *LineEndSym = MC->createTempSymbol();
8181db9f3b2SDimitry Andric
8191db9f3b2SDimitry Andric // unit_length.
8201db9f3b2SDimitry Andric if (LineTable.Prologue.FormParams.Format == dwarf::DwarfFormat::DWARF64) {
8211db9f3b2SDimitry Andric MS->emitInt32(dwarf::DW_LENGTH_DWARF64);
8221db9f3b2SDimitry Andric LineSectionSize += 4;
8231db9f3b2SDimitry Andric }
8241db9f3b2SDimitry Andric emitLabelDifference(LineEndSym, LineStartSym,
8251db9f3b2SDimitry Andric LineTable.Prologue.FormParams.Format, LineSectionSize);
8261db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(LineStartSym);
8271db9f3b2SDimitry Andric
8281db9f3b2SDimitry Andric // Emit prologue.
8291db9f3b2SDimitry Andric emitLineTablePrologue(LineTable.Prologue, DebugStrPool, DebugLineStrPool);
8301db9f3b2SDimitry Andric
8311db9f3b2SDimitry Andric // Emit rows.
8321db9f3b2SDimitry Andric emitLineTableRows(LineTable, LineEndSym,
8331db9f3b2SDimitry Andric Unit.getOrigUnit().getAddressByteSize());
8341db9f3b2SDimitry Andric }
8351db9f3b2SDimitry Andric
emitLineTablePrologue(const DWARFDebugLine::Prologue & P,OffsetsStringPool & DebugStrPool,OffsetsStringPool & DebugLineStrPool)8361db9f3b2SDimitry Andric void DwarfStreamer::emitLineTablePrologue(const DWARFDebugLine::Prologue &P,
8371db9f3b2SDimitry Andric OffsetsStringPool &DebugStrPool,
8381db9f3b2SDimitry Andric OffsetsStringPool &DebugLineStrPool) {
8391db9f3b2SDimitry Andric MCSymbol *PrologueStartSym = MC->createTempSymbol();
8401db9f3b2SDimitry Andric MCSymbol *PrologueEndSym = MC->createTempSymbol();
8411db9f3b2SDimitry Andric
8421db9f3b2SDimitry Andric // version (uhalf).
8431db9f3b2SDimitry Andric MS->emitInt16(P.getVersion());
8441db9f3b2SDimitry Andric LineSectionSize += 2;
8451db9f3b2SDimitry Andric if (P.getVersion() == 5) {
8461db9f3b2SDimitry Andric // address_size (ubyte).
8471db9f3b2SDimitry Andric MS->emitInt8(P.getAddressSize());
8481db9f3b2SDimitry Andric LineSectionSize += 1;
8491db9f3b2SDimitry Andric
8501db9f3b2SDimitry Andric // segment_selector_size (ubyte).
8511db9f3b2SDimitry Andric MS->emitInt8(P.SegSelectorSize);
8521db9f3b2SDimitry Andric LineSectionSize += 1;
8531db9f3b2SDimitry Andric }
8541db9f3b2SDimitry Andric
8551db9f3b2SDimitry Andric // header_length.
8561db9f3b2SDimitry Andric emitLabelDifference(PrologueEndSym, PrologueStartSym, P.FormParams.Format,
8571db9f3b2SDimitry Andric LineSectionSize);
8581db9f3b2SDimitry Andric
8591db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(PrologueStartSym);
8601db9f3b2SDimitry Andric emitLineTableProloguePayload(P, DebugStrPool, DebugLineStrPool);
8611db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(PrologueEndSym);
8621db9f3b2SDimitry Andric }
8631db9f3b2SDimitry Andric
emitLineTablePrologueV2IncludeAndFileTable(const DWARFDebugLine::Prologue & P,OffsetsStringPool & DebugStrPool,OffsetsStringPool & DebugLineStrPool)8641db9f3b2SDimitry Andric void DwarfStreamer::emitLineTablePrologueV2IncludeAndFileTable(
8651db9f3b2SDimitry Andric const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
8661db9f3b2SDimitry Andric OffsetsStringPool &DebugLineStrPool) {
8671db9f3b2SDimitry Andric // include_directories (sequence of path names).
8681db9f3b2SDimitry Andric for (const DWARFFormValue &Include : P.IncludeDirectories)
8691db9f3b2SDimitry Andric emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);
8701db9f3b2SDimitry Andric // The last entry is followed by a single null byte.
8711db9f3b2SDimitry Andric MS->emitInt8(0);
8721db9f3b2SDimitry Andric LineSectionSize += 1;
8731db9f3b2SDimitry Andric
8741db9f3b2SDimitry Andric // file_names (sequence of file entries).
8751db9f3b2SDimitry Andric for (const DWARFDebugLine::FileNameEntry &File : P.FileNames) {
8761db9f3b2SDimitry Andric // A null-terminated string containing the full or relative path name of a
8771db9f3b2SDimitry Andric // source file.
8781db9f3b2SDimitry Andric emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);
8791db9f3b2SDimitry Andric // An unsigned LEB128 number representing the directory index of a directory
8801db9f3b2SDimitry Andric // in the include_directories section.
8811db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(File.DirIdx);
8821db9f3b2SDimitry Andric // An unsigned LEB128 number representing the (implementation-defined) time
8831db9f3b2SDimitry Andric // of last modification for the file, or 0 if not available.
8841db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(File.ModTime);
8851db9f3b2SDimitry Andric // An unsigned LEB128 number representing the length in bytes of the file,
8861db9f3b2SDimitry Andric // or 0 if not available.
8871db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(File.Length);
8881db9f3b2SDimitry Andric }
8891db9f3b2SDimitry Andric // The last entry is followed by a single null byte.
8901db9f3b2SDimitry Andric MS->emitInt8(0);
8911db9f3b2SDimitry Andric LineSectionSize += 1;
8921db9f3b2SDimitry Andric }
8931db9f3b2SDimitry Andric
emitLineTablePrologueV5IncludeAndFileTable(const DWARFDebugLine::Prologue & P,OffsetsStringPool & DebugStrPool,OffsetsStringPool & DebugLineStrPool)8941db9f3b2SDimitry Andric void DwarfStreamer::emitLineTablePrologueV5IncludeAndFileTable(
8951db9f3b2SDimitry Andric const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
8961db9f3b2SDimitry Andric OffsetsStringPool &DebugLineStrPool) {
8971db9f3b2SDimitry Andric if (P.IncludeDirectories.empty()) {
8981db9f3b2SDimitry Andric // directory_entry_format_count(ubyte).
8991db9f3b2SDimitry Andric MS->emitInt8(0);
9001db9f3b2SDimitry Andric LineSectionSize += 1;
9011db9f3b2SDimitry Andric } else {
9021db9f3b2SDimitry Andric // directory_entry_format_count(ubyte).
9031db9f3b2SDimitry Andric MS->emitInt8(1);
9041db9f3b2SDimitry Andric LineSectionSize += 1;
9051db9f3b2SDimitry Andric
9061db9f3b2SDimitry Andric // directory_entry_format (sequence of ULEB128 pairs).
9071db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
9081db9f3b2SDimitry Andric LineSectionSize +=
9091db9f3b2SDimitry Andric MS->emitULEB128IntValue(P.IncludeDirectories[0].getForm());
9101db9f3b2SDimitry Andric }
9111db9f3b2SDimitry Andric
9121db9f3b2SDimitry Andric // directories_count (ULEB128).
9131db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(P.IncludeDirectories.size());
9141db9f3b2SDimitry Andric // directories (sequence of directory names).
9151db9f3b2SDimitry Andric for (auto Include : P.IncludeDirectories)
9161db9f3b2SDimitry Andric emitLineTableString(P, Include, DebugStrPool, DebugLineStrPool);
9171db9f3b2SDimitry Andric
9181db9f3b2SDimitry Andric bool HasChecksums = P.ContentTypes.HasMD5;
9191db9f3b2SDimitry Andric bool HasInlineSources = P.ContentTypes.HasSource;
9201db9f3b2SDimitry Andric
9211db9f3b2SDimitry Andric if (P.FileNames.empty()) {
9221db9f3b2SDimitry Andric // file_name_entry_format_count (ubyte).
9231db9f3b2SDimitry Andric MS->emitInt8(0);
9241db9f3b2SDimitry Andric LineSectionSize += 1;
9251db9f3b2SDimitry Andric } else {
9261db9f3b2SDimitry Andric // file_name_entry_format_count (ubyte).
9271db9f3b2SDimitry Andric MS->emitInt8(2 + (HasChecksums ? 1 : 0) + (HasInlineSources ? 1 : 0));
9281db9f3b2SDimitry Andric LineSectionSize += 1;
9291db9f3b2SDimitry Andric
9301db9f3b2SDimitry Andric // file_name_entry_format (sequence of ULEB128 pairs).
9311db9f3b2SDimitry Andric auto StrForm = P.FileNames[0].Name.getForm();
9321db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_path);
9331db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(StrForm);
9341db9f3b2SDimitry Andric
9351db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_directory_index);
9361db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data1);
9371db9f3b2SDimitry Andric
9381db9f3b2SDimitry Andric if (HasChecksums) {
9391db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_MD5);
9401db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_FORM_data16);
9411db9f3b2SDimitry Andric }
9421db9f3b2SDimitry Andric
9431db9f3b2SDimitry Andric if (HasInlineSources) {
9441db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(dwarf::DW_LNCT_LLVM_source);
9451db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(StrForm);
9461db9f3b2SDimitry Andric }
9471db9f3b2SDimitry Andric }
9481db9f3b2SDimitry Andric
9491db9f3b2SDimitry Andric // file_names_count (ULEB128).
9501db9f3b2SDimitry Andric LineSectionSize += MS->emitULEB128IntValue(P.FileNames.size());
9511db9f3b2SDimitry Andric
9521db9f3b2SDimitry Andric // file_names (sequence of file name entries).
9531db9f3b2SDimitry Andric for (auto File : P.FileNames) {
9541db9f3b2SDimitry Andric emitLineTableString(P, File.Name, DebugStrPool, DebugLineStrPool);
9551db9f3b2SDimitry Andric MS->emitInt8(File.DirIdx);
9561db9f3b2SDimitry Andric LineSectionSize += 1;
9571db9f3b2SDimitry Andric if (HasChecksums) {
9581db9f3b2SDimitry Andric MS->emitBinaryData(
9591db9f3b2SDimitry Andric StringRef(reinterpret_cast<const char *>(File.Checksum.data()),
9601db9f3b2SDimitry Andric File.Checksum.size()));
9611db9f3b2SDimitry Andric LineSectionSize += File.Checksum.size();
9621db9f3b2SDimitry Andric }
9631db9f3b2SDimitry Andric if (HasInlineSources)
9641db9f3b2SDimitry Andric emitLineTableString(P, File.Source, DebugStrPool, DebugLineStrPool);
9651db9f3b2SDimitry Andric }
9661db9f3b2SDimitry Andric }
9671db9f3b2SDimitry Andric
emitLineTableString(const DWARFDebugLine::Prologue & P,const DWARFFormValue & String,OffsetsStringPool & DebugStrPool,OffsetsStringPool & DebugLineStrPool)9681db9f3b2SDimitry Andric void DwarfStreamer::emitLineTableString(const DWARFDebugLine::Prologue &P,
9691db9f3b2SDimitry Andric const DWARFFormValue &String,
9701db9f3b2SDimitry Andric OffsetsStringPool &DebugStrPool,
9711db9f3b2SDimitry Andric OffsetsStringPool &DebugLineStrPool) {
9721db9f3b2SDimitry Andric std::optional<const char *> StringVal = dwarf::toString(String);
9731db9f3b2SDimitry Andric if (!StringVal) {
9741db9f3b2SDimitry Andric warn("Cann't read string from line table.");
9751db9f3b2SDimitry Andric return;
9761db9f3b2SDimitry Andric }
9771db9f3b2SDimitry Andric
9781db9f3b2SDimitry Andric switch (String.getForm()) {
9791db9f3b2SDimitry Andric case dwarf::DW_FORM_string: {
9801db9f3b2SDimitry Andric StringRef TranslatedString =
9811db9f3b2SDimitry Andric (Translator) ? Translator(*StringVal) : *StringVal;
9821db9f3b2SDimitry Andric Asm->OutStreamer->emitBytes(TranslatedString.data());
9831db9f3b2SDimitry Andric Asm->emitInt8(0);
9841db9f3b2SDimitry Andric LineSectionSize += TranslatedString.size() + 1;
9851db9f3b2SDimitry Andric } break;
9861db9f3b2SDimitry Andric case dwarf::DW_FORM_strp:
9871db9f3b2SDimitry Andric case dwarf::DW_FORM_line_strp: {
9881db9f3b2SDimitry Andric DwarfStringPoolEntryRef StringRef =
9891db9f3b2SDimitry Andric String.getForm() == dwarf::DW_FORM_strp
9901db9f3b2SDimitry Andric ? DebugStrPool.getEntry(*StringVal)
9911db9f3b2SDimitry Andric : DebugLineStrPool.getEntry(*StringVal);
9921db9f3b2SDimitry Andric
9931db9f3b2SDimitry Andric emitIntOffset(StringRef.getOffset(), P.FormParams.Format, LineSectionSize);
9941db9f3b2SDimitry Andric } break;
9951db9f3b2SDimitry Andric default:
9961db9f3b2SDimitry Andric warn("Unsupported string form inside line table.");
9971db9f3b2SDimitry Andric break;
9981db9f3b2SDimitry Andric };
9991db9f3b2SDimitry Andric }
10001db9f3b2SDimitry Andric
emitLineTableProloguePayload(const DWARFDebugLine::Prologue & P,OffsetsStringPool & DebugStrPool,OffsetsStringPool & DebugLineStrPool)10011db9f3b2SDimitry Andric void DwarfStreamer::emitLineTableProloguePayload(
10021db9f3b2SDimitry Andric const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool,
10031db9f3b2SDimitry Andric OffsetsStringPool &DebugLineStrPool) {
10041db9f3b2SDimitry Andric // minimum_instruction_length (ubyte).
10051db9f3b2SDimitry Andric MS->emitInt8(P.MinInstLength);
10061db9f3b2SDimitry Andric LineSectionSize += 1;
10071db9f3b2SDimitry Andric if (P.FormParams.Version >= 4) {
10081db9f3b2SDimitry Andric // maximum_operations_per_instruction (ubyte).
10091db9f3b2SDimitry Andric MS->emitInt8(P.MaxOpsPerInst);
10101db9f3b2SDimitry Andric LineSectionSize += 1;
10111db9f3b2SDimitry Andric }
10121db9f3b2SDimitry Andric // default_is_stmt (ubyte).
10131db9f3b2SDimitry Andric MS->emitInt8(P.DefaultIsStmt);
10141db9f3b2SDimitry Andric LineSectionSize += 1;
10151db9f3b2SDimitry Andric // line_base (sbyte).
10161db9f3b2SDimitry Andric MS->emitInt8(P.LineBase);
10171db9f3b2SDimitry Andric LineSectionSize += 1;
10181db9f3b2SDimitry Andric // line_range (ubyte).
10191db9f3b2SDimitry Andric MS->emitInt8(P.LineRange);
10201db9f3b2SDimitry Andric LineSectionSize += 1;
10211db9f3b2SDimitry Andric // opcode_base (ubyte).
10221db9f3b2SDimitry Andric MS->emitInt8(P.OpcodeBase);
10231db9f3b2SDimitry Andric LineSectionSize += 1;
10241db9f3b2SDimitry Andric
10251db9f3b2SDimitry Andric // standard_opcode_lengths (array of ubyte).
10261db9f3b2SDimitry Andric for (auto Length : P.StandardOpcodeLengths) {
10271db9f3b2SDimitry Andric MS->emitInt8(Length);
10281db9f3b2SDimitry Andric LineSectionSize += 1;
10291db9f3b2SDimitry Andric }
10301db9f3b2SDimitry Andric
10311db9f3b2SDimitry Andric if (P.FormParams.Version < 5)
10321db9f3b2SDimitry Andric emitLineTablePrologueV2IncludeAndFileTable(P, DebugStrPool,
10331db9f3b2SDimitry Andric DebugLineStrPool);
10341db9f3b2SDimitry Andric else
10351db9f3b2SDimitry Andric emitLineTablePrologueV5IncludeAndFileTable(P, DebugStrPool,
10361db9f3b2SDimitry Andric DebugLineStrPool);
10371db9f3b2SDimitry Andric }
10381db9f3b2SDimitry Andric
emitLineTableRows(const DWARFDebugLine::LineTable & LineTable,MCSymbol * LineEndSym,unsigned AddressByteSize)10391db9f3b2SDimitry Andric void DwarfStreamer::emitLineTableRows(
10401db9f3b2SDimitry Andric const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym,
10411db9f3b2SDimitry Andric unsigned AddressByteSize) {
10421db9f3b2SDimitry Andric
10431db9f3b2SDimitry Andric MCDwarfLineTableParams Params;
10441db9f3b2SDimitry Andric Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase;
10451db9f3b2SDimitry Andric Params.DWARF2LineBase = LineTable.Prologue.LineBase;
10461db9f3b2SDimitry Andric Params.DWARF2LineRange = LineTable.Prologue.LineRange;
10471db9f3b2SDimitry Andric
10481db9f3b2SDimitry Andric SmallString<128> EncodingBuffer;
10491db9f3b2SDimitry Andric
10501db9f3b2SDimitry Andric if (LineTable.Rows.empty()) {
10511db9f3b2SDimitry Andric // We only have the dummy entry, dsymutil emits an entry with a 0
10521db9f3b2SDimitry Andric // address in that case.
10531db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
10541db9f3b2SDimitry Andric EncodingBuffer);
10551db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer);
10561db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size();
10571db9f3b2SDimitry Andric MS->emitLabel(LineEndSym);
10581db9f3b2SDimitry Andric return;
10591db9f3b2SDimitry Andric }
10601db9f3b2SDimitry Andric
10611db9f3b2SDimitry Andric // Line table state machine fields
10621db9f3b2SDimitry Andric unsigned FileNum = 1;
10631db9f3b2SDimitry Andric unsigned LastLine = 1;
10641db9f3b2SDimitry Andric unsigned Column = 0;
10651db9f3b2SDimitry Andric unsigned IsStatement = 1;
10661db9f3b2SDimitry Andric unsigned Isa = 0;
10671db9f3b2SDimitry Andric uint64_t Address = -1ULL;
10681db9f3b2SDimitry Andric
10691db9f3b2SDimitry Andric unsigned RowsSinceLastSequence = 0;
10701db9f3b2SDimitry Andric
10711db9f3b2SDimitry Andric for (const DWARFDebugLine::Row &Row : LineTable.Rows) {
10721db9f3b2SDimitry Andric int64_t AddressDelta;
10731db9f3b2SDimitry Andric if (Address == -1ULL) {
10741db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
10751db9f3b2SDimitry Andric MS->emitULEB128IntValue(AddressByteSize + 1);
10761db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNE_set_address, 1);
10771db9f3b2SDimitry Andric MS->emitIntValue(Row.Address.Address, AddressByteSize);
10781db9f3b2SDimitry Andric LineSectionSize +=
10791db9f3b2SDimitry Andric 2 + AddressByteSize + getULEB128Size(AddressByteSize + 1);
10801db9f3b2SDimitry Andric AddressDelta = 0;
10811db9f3b2SDimitry Andric } else {
10821db9f3b2SDimitry Andric AddressDelta =
10831db9f3b2SDimitry Andric (Row.Address.Address - Address) / LineTable.Prologue.MinInstLength;
10841db9f3b2SDimitry Andric }
10851db9f3b2SDimitry Andric
10861db9f3b2SDimitry Andric // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
10871db9f3b2SDimitry Andric // We should find a way to share this code, but the current compatibility
10881db9f3b2SDimitry Andric // requirement with classic dsymutil makes it hard. Revisit that once this
10891db9f3b2SDimitry Andric // requirement is dropped.
10901db9f3b2SDimitry Andric
10911db9f3b2SDimitry Andric if (FileNum != Row.File) {
10921db9f3b2SDimitry Andric FileNum = Row.File;
10931db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_file, 1);
10941db9f3b2SDimitry Andric MS->emitULEB128IntValue(FileNum);
10951db9f3b2SDimitry Andric LineSectionSize += 1 + getULEB128Size(FileNum);
10961db9f3b2SDimitry Andric }
10971db9f3b2SDimitry Andric if (Column != Row.Column) {
10981db9f3b2SDimitry Andric Column = Row.Column;
10991db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_column, 1);
11001db9f3b2SDimitry Andric MS->emitULEB128IntValue(Column);
11011db9f3b2SDimitry Andric LineSectionSize += 1 + getULEB128Size(Column);
11021db9f3b2SDimitry Andric }
11031db9f3b2SDimitry Andric
11041db9f3b2SDimitry Andric // FIXME: We should handle the discriminator here, but dsymutil doesn't
11051db9f3b2SDimitry Andric // consider it, thus ignore it for now.
11061db9f3b2SDimitry Andric
11071db9f3b2SDimitry Andric if (Isa != Row.Isa) {
11081db9f3b2SDimitry Andric Isa = Row.Isa;
11091db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);
11101db9f3b2SDimitry Andric MS->emitULEB128IntValue(Isa);
11111db9f3b2SDimitry Andric LineSectionSize += 1 + getULEB128Size(Isa);
11121db9f3b2SDimitry Andric }
11131db9f3b2SDimitry Andric if (IsStatement != Row.IsStmt) {
11141db9f3b2SDimitry Andric IsStatement = Row.IsStmt;
11151db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);
11161db9f3b2SDimitry Andric LineSectionSize += 1;
11171db9f3b2SDimitry Andric }
11181db9f3b2SDimitry Andric if (Row.BasicBlock) {
11191db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);
11201db9f3b2SDimitry Andric LineSectionSize += 1;
11211db9f3b2SDimitry Andric }
11221db9f3b2SDimitry Andric
11231db9f3b2SDimitry Andric if (Row.PrologueEnd) {
11241db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
11251db9f3b2SDimitry Andric LineSectionSize += 1;
11261db9f3b2SDimitry Andric }
11271db9f3b2SDimitry Andric
11281db9f3b2SDimitry Andric if (Row.EpilogueBegin) {
11291db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
11301db9f3b2SDimitry Andric LineSectionSize += 1;
11311db9f3b2SDimitry Andric }
11321db9f3b2SDimitry Andric
11331db9f3b2SDimitry Andric int64_t LineDelta = int64_t(Row.Line) - LastLine;
11341db9f3b2SDimitry Andric if (!Row.EndSequence) {
11351db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta,
11361db9f3b2SDimitry Andric EncodingBuffer);
11371db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer);
11381db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size();
11391db9f3b2SDimitry Andric EncodingBuffer.resize(0);
11401db9f3b2SDimitry Andric Address = Row.Address.Address;
11411db9f3b2SDimitry Andric LastLine = Row.Line;
11421db9f3b2SDimitry Andric RowsSinceLastSequence++;
11431db9f3b2SDimitry Andric } else {
11441db9f3b2SDimitry Andric if (LineDelta) {
11451db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);
11461db9f3b2SDimitry Andric MS->emitSLEB128IntValue(LineDelta);
11471db9f3b2SDimitry Andric LineSectionSize += 1 + getSLEB128Size(LineDelta);
11481db9f3b2SDimitry Andric }
11491db9f3b2SDimitry Andric if (AddressDelta) {
11501db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);
11511db9f3b2SDimitry Andric MS->emitULEB128IntValue(AddressDelta);
11521db9f3b2SDimitry Andric LineSectionSize += 1 + getULEB128Size(AddressDelta);
11531db9f3b2SDimitry Andric }
11541db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(),
11551db9f3b2SDimitry Andric 0, EncodingBuffer);
11561db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer);
11571db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size();
11581db9f3b2SDimitry Andric EncodingBuffer.resize(0);
11591db9f3b2SDimitry Andric Address = -1ULL;
11601db9f3b2SDimitry Andric LastLine = FileNum = IsStatement = 1;
11611db9f3b2SDimitry Andric RowsSinceLastSequence = Column = Isa = 0;
11621db9f3b2SDimitry Andric }
11631db9f3b2SDimitry Andric }
11641db9f3b2SDimitry Andric
11651db9f3b2SDimitry Andric if (RowsSinceLastSequence) {
11661db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
11671db9f3b2SDimitry Andric EncodingBuffer);
11681db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer);
11691db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size();
11701db9f3b2SDimitry Andric EncodingBuffer.resize(0);
11711db9f3b2SDimitry Andric }
11721db9f3b2SDimitry Andric
11731db9f3b2SDimitry Andric MS->emitLabel(LineEndSym);
11741db9f3b2SDimitry Andric }
11751db9f3b2SDimitry Andric
emitIntOffset(uint64_t Offset,dwarf::DwarfFormat Format,uint64_t & SectionSize)11761db9f3b2SDimitry Andric void DwarfStreamer::emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format,
11771db9f3b2SDimitry Andric uint64_t &SectionSize) {
11781db9f3b2SDimitry Andric uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);
11791db9f3b2SDimitry Andric MS->emitIntValue(Offset, Size);
11801db9f3b2SDimitry Andric SectionSize += Size;
11811db9f3b2SDimitry Andric }
11821db9f3b2SDimitry Andric
emitLabelDifference(const MCSymbol * Hi,const MCSymbol * Lo,dwarf::DwarfFormat Format,uint64_t & SectionSize)11831db9f3b2SDimitry Andric void DwarfStreamer::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo,
11841db9f3b2SDimitry Andric dwarf::DwarfFormat Format,
11851db9f3b2SDimitry Andric uint64_t &SectionSize) {
11861db9f3b2SDimitry Andric uint8_t Size = dwarf::getDwarfOffsetByteSize(Format);
11871db9f3b2SDimitry Andric Asm->emitLabelDifference(Hi, Lo, Size);
11881db9f3b2SDimitry Andric SectionSize += Size;
11891db9f3b2SDimitry Andric }
11901db9f3b2SDimitry Andric
11911db9f3b2SDimitry Andric /// Emit the pubnames or pubtypes section contribution for \p
11921db9f3b2SDimitry Andric /// Unit into \p Sec. The data is provided in \p Names.
emitPubSectionForUnit(MCSection * Sec,StringRef SecName,const CompileUnit & Unit,const std::vector<CompileUnit::AccelInfo> & Names)11931db9f3b2SDimitry Andric void DwarfStreamer::emitPubSectionForUnit(
11941db9f3b2SDimitry Andric MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
11951db9f3b2SDimitry Andric const std::vector<CompileUnit::AccelInfo> &Names) {
11961db9f3b2SDimitry Andric if (Names.empty())
11971db9f3b2SDimitry Andric return;
11981db9f3b2SDimitry Andric
11991db9f3b2SDimitry Andric // Start the dwarf pubnames section.
12001db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(Sec);
12011db9f3b2SDimitry Andric MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
12021db9f3b2SDimitry Andric MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");
12031db9f3b2SDimitry Andric
12041db9f3b2SDimitry Andric bool HeaderEmitted = false;
12051db9f3b2SDimitry Andric // Emit the pubnames for this compilation unit.
12061db9f3b2SDimitry Andric for (const auto &Name : Names) {
12071db9f3b2SDimitry Andric if (Name.SkipPubSection)
12081db9f3b2SDimitry Andric continue;
12091db9f3b2SDimitry Andric
12101db9f3b2SDimitry Andric if (!HeaderEmitted) {
12111db9f3b2SDimitry Andric // Emit the header.
12121db9f3b2SDimitry Andric Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length
12131db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(BeginLabel);
12141db9f3b2SDimitry Andric Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
12151db9f3b2SDimitry Andric Asm->emitInt32(Unit.getStartOffset()); // Unit offset
12161db9f3b2SDimitry Andric Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
12171db9f3b2SDimitry Andric HeaderEmitted = true;
12181db9f3b2SDimitry Andric }
12191db9f3b2SDimitry Andric Asm->emitInt32(Name.Die->getOffset());
12201db9f3b2SDimitry Andric
12211db9f3b2SDimitry Andric // Emit the string itself.
12221db9f3b2SDimitry Andric Asm->OutStreamer->emitBytes(Name.Name.getString());
12231db9f3b2SDimitry Andric // Emit a null terminator.
12241db9f3b2SDimitry Andric Asm->emitInt8(0);
12251db9f3b2SDimitry Andric }
12261db9f3b2SDimitry Andric
12271db9f3b2SDimitry Andric if (!HeaderEmitted)
12281db9f3b2SDimitry Andric return;
12291db9f3b2SDimitry Andric Asm->emitInt32(0); // End marker.
12301db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(EndLabel);
12311db9f3b2SDimitry Andric }
12321db9f3b2SDimitry Andric
12331db9f3b2SDimitry Andric /// Emit .debug_pubnames for \p Unit.
emitPubNamesForUnit(const CompileUnit & Unit)12341db9f3b2SDimitry Andric void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
12351db9f3b2SDimitry Andric emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
12361db9f3b2SDimitry Andric "names", Unit, Unit.getPubnames());
12371db9f3b2SDimitry Andric }
12381db9f3b2SDimitry Andric
12391db9f3b2SDimitry Andric /// Emit .debug_pubtypes for \p Unit.
emitPubTypesForUnit(const CompileUnit & Unit)12401db9f3b2SDimitry Andric void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
12411db9f3b2SDimitry Andric emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
12421db9f3b2SDimitry Andric "types", Unit, Unit.getPubtypes());
12431db9f3b2SDimitry Andric }
12441db9f3b2SDimitry Andric
12451db9f3b2SDimitry Andric /// Emit a CIE into the debug_frame section.
emitCIE(StringRef CIEBytes)12461db9f3b2SDimitry Andric void DwarfStreamer::emitCIE(StringRef CIEBytes) {
12471db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
12481db9f3b2SDimitry Andric
12491db9f3b2SDimitry Andric MS->emitBytes(CIEBytes);
12501db9f3b2SDimitry Andric FrameSectionSize += CIEBytes.size();
12511db9f3b2SDimitry Andric }
12521db9f3b2SDimitry Andric
12531db9f3b2SDimitry Andric /// Emit a FDE into the debug_frame section. \p FDEBytes
12541db9f3b2SDimitry Andric /// contains the FDE data without the length, CIE offset and address
12551db9f3b2SDimitry Andric /// which will be replaced with the parameter values.
emitFDE(uint32_t CIEOffset,uint32_t AddrSize,uint64_t Address,StringRef FDEBytes)12561db9f3b2SDimitry Andric void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
12571db9f3b2SDimitry Andric uint64_t Address, StringRef FDEBytes) {
12581db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
12591db9f3b2SDimitry Andric
12601db9f3b2SDimitry Andric MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
12611db9f3b2SDimitry Andric MS->emitIntValue(CIEOffset, 4);
12621db9f3b2SDimitry Andric MS->emitIntValue(Address, AddrSize);
12631db9f3b2SDimitry Andric MS->emitBytes(FDEBytes);
12641db9f3b2SDimitry Andric FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
12651db9f3b2SDimitry Andric }
12661db9f3b2SDimitry Andric
emitMacroTables(DWARFContext * Context,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool)12671db9f3b2SDimitry Andric void DwarfStreamer::emitMacroTables(DWARFContext *Context,
12681db9f3b2SDimitry Andric const Offset2UnitMap &UnitMacroMap,
12691db9f3b2SDimitry Andric OffsetsStringPool &StringPool) {
12701db9f3b2SDimitry Andric assert(Context != nullptr && "Empty DWARF context");
12711db9f3b2SDimitry Andric
12721db9f3b2SDimitry Andric // Check for .debug_macinfo table.
12731db9f3b2SDimitry Andric if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) {
12741db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());
12751db9f3b2SDimitry Andric emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize);
12761db9f3b2SDimitry Andric }
12771db9f3b2SDimitry Andric
12781db9f3b2SDimitry Andric // Check for .debug_macro table.
12791db9f3b2SDimitry Andric if (const DWARFDebugMacro *Table = Context->getDebugMacro()) {
12801db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());
12811db9f3b2SDimitry Andric emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize);
12821db9f3b2SDimitry Andric }
12831db9f3b2SDimitry Andric }
12841db9f3b2SDimitry Andric
emitMacroTableImpl(const DWARFDebugMacro * MacroTable,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool,uint64_t & OutOffset)12851db9f3b2SDimitry Andric void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
12861db9f3b2SDimitry Andric const Offset2UnitMap &UnitMacroMap,
12871db9f3b2SDimitry Andric OffsetsStringPool &StringPool,
12881db9f3b2SDimitry Andric uint64_t &OutOffset) {
12891db9f3b2SDimitry Andric bool DefAttributeIsReported = false;
12901db9f3b2SDimitry Andric bool UndefAttributeIsReported = false;
12911db9f3b2SDimitry Andric bool ImportAttributeIsReported = false;
12921db9f3b2SDimitry Andric for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
12931db9f3b2SDimitry Andric Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset);
12941db9f3b2SDimitry Andric if (UnitIt == UnitMacroMap.end()) {
12951db9f3b2SDimitry Andric warn(formatv(
12961db9f3b2SDimitry Andric "couldn`t find compile unit for the macro table with offset = {0:x}",
12971db9f3b2SDimitry Andric List.Offset));
12981db9f3b2SDimitry Andric continue;
12991db9f3b2SDimitry Andric }
13001db9f3b2SDimitry Andric
13011db9f3b2SDimitry Andric // Skip macro table if the unit was not cloned.
13021db9f3b2SDimitry Andric DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();
13031db9f3b2SDimitry Andric if (OutputUnitDIE == nullptr)
13041db9f3b2SDimitry Andric continue;
13051db9f3b2SDimitry Andric
13061db9f3b2SDimitry Andric // Update macro attribute of cloned compile unit with the proper offset to
13071db9f3b2SDimitry Andric // the macro table.
13081db9f3b2SDimitry Andric bool hasDWARFv5Header = false;
13091db9f3b2SDimitry Andric for (auto &V : OutputUnitDIE->values()) {
13101db9f3b2SDimitry Andric if (V.getAttribute() == dwarf::DW_AT_macro_info) {
13111db9f3b2SDimitry Andric V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
13121db9f3b2SDimitry Andric break;
13131db9f3b2SDimitry Andric } else if (V.getAttribute() == dwarf::DW_AT_macros) {
13141db9f3b2SDimitry Andric hasDWARFv5Header = true;
13151db9f3b2SDimitry Andric V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
13161db9f3b2SDimitry Andric break;
13171db9f3b2SDimitry Andric }
13181db9f3b2SDimitry Andric }
13191db9f3b2SDimitry Andric
13201db9f3b2SDimitry Andric // Write DWARFv5 header.
13211db9f3b2SDimitry Andric if (hasDWARFv5Header) {
13221db9f3b2SDimitry Andric // Write header version.
13231db9f3b2SDimitry Andric MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version));
13241db9f3b2SDimitry Andric OutOffset += sizeof(List.Header.Version);
13251db9f3b2SDimitry Andric
13261db9f3b2SDimitry Andric uint8_t Flags = List.Header.Flags;
13271db9f3b2SDimitry Andric
13281db9f3b2SDimitry Andric // Check for OPCODE_OPERANDS_TABLE.
13291db9f3b2SDimitry Andric if (Flags &
13301db9f3b2SDimitry Andric DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
13311db9f3b2SDimitry Andric Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
13321db9f3b2SDimitry Andric warn("opcode_operands_table is not supported yet.");
13331db9f3b2SDimitry Andric }
13341db9f3b2SDimitry Andric
13351db9f3b2SDimitry Andric // Check for DEBUG_LINE_OFFSET.
13361db9f3b2SDimitry Andric std::optional<uint64_t> StmtListOffset;
13371db9f3b2SDimitry Andric if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
13381db9f3b2SDimitry Andric // Get offset to the line table from the cloned compile unit.
13391db9f3b2SDimitry Andric for (auto &V : OutputUnitDIE->values()) {
13401db9f3b2SDimitry Andric if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
13411db9f3b2SDimitry Andric StmtListOffset = V.getDIEInteger().getValue();
13421db9f3b2SDimitry Andric break;
13431db9f3b2SDimitry Andric }
13441db9f3b2SDimitry Andric }
13451db9f3b2SDimitry Andric
13461db9f3b2SDimitry Andric if (!StmtListOffset) {
13471db9f3b2SDimitry Andric Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
13481db9f3b2SDimitry Andric warn("couldn`t find line table for macro table.");
13491db9f3b2SDimitry Andric }
13501db9f3b2SDimitry Andric }
13511db9f3b2SDimitry Andric
13521db9f3b2SDimitry Andric // Write flags.
13531db9f3b2SDimitry Andric MS->emitIntValue(Flags, sizeof(Flags));
13541db9f3b2SDimitry Andric OutOffset += sizeof(Flags);
13551db9f3b2SDimitry Andric
13561db9f3b2SDimitry Andric // Write offset to line table.
13571db9f3b2SDimitry Andric if (StmtListOffset) {
13581db9f3b2SDimitry Andric MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize());
13591db9f3b2SDimitry Andric OutOffset += List.Header.getOffsetByteSize();
13601db9f3b2SDimitry Andric }
13611db9f3b2SDimitry Andric }
13621db9f3b2SDimitry Andric
13631db9f3b2SDimitry Andric // Write macro entries.
13641db9f3b2SDimitry Andric for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
13651db9f3b2SDimitry Andric if (MacroEntry.Type == 0) {
13661db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);
13671db9f3b2SDimitry Andric continue;
13681db9f3b2SDimitry Andric }
13691db9f3b2SDimitry Andric
13701db9f3b2SDimitry Andric uint8_t MacroType = MacroEntry.Type;
13711db9f3b2SDimitry Andric switch (MacroType) {
13721db9f3b2SDimitry Andric default: {
13731db9f3b2SDimitry Andric bool HasVendorSpecificExtension =
13741db9f3b2SDimitry Andric (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) ||
13751db9f3b2SDimitry Andric (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
13761db9f3b2SDimitry Andric MacroType <= dwarf::DW_MACRO_hi_user));
13771db9f3b2SDimitry Andric
13781db9f3b2SDimitry Andric if (HasVendorSpecificExtension) {
13791db9f3b2SDimitry Andric // Write macinfo type.
13801db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1);
13811db9f3b2SDimitry Andric OutOffset++;
13821db9f3b2SDimitry Andric
13831db9f3b2SDimitry Andric // Write vendor extension constant.
13841db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);
13851db9f3b2SDimitry Andric
13861db9f3b2SDimitry Andric // Write vendor extension string.
13871db9f3b2SDimitry Andric StringRef String = MacroEntry.ExtStr;
13881db9f3b2SDimitry Andric MS->emitBytes(String);
13891db9f3b2SDimitry Andric MS->emitIntValue(0, 1);
13901db9f3b2SDimitry Andric OutOffset += String.size() + 1;
13911db9f3b2SDimitry Andric } else
13921db9f3b2SDimitry Andric warn("unknown macro type. skip.");
13931db9f3b2SDimitry Andric } break;
13941db9f3b2SDimitry Andric // debug_macro and debug_macinfo share some common encodings.
13951db9f3b2SDimitry Andric // DW_MACRO_define == DW_MACINFO_define
13961db9f3b2SDimitry Andric // DW_MACRO_undef == DW_MACINFO_undef
13971db9f3b2SDimitry Andric // DW_MACRO_start_file == DW_MACINFO_start_file
13981db9f3b2SDimitry Andric // DW_MACRO_end_file == DW_MACINFO_end_file
13991db9f3b2SDimitry Andric // For readibility/uniformity we are using DW_MACRO_*.
14001db9f3b2SDimitry Andric case dwarf::DW_MACRO_define:
14011db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef: {
14021db9f3b2SDimitry Andric // Write macinfo type.
14031db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1);
14041db9f3b2SDimitry Andric OutOffset++;
14051db9f3b2SDimitry Andric
14061db9f3b2SDimitry Andric // Write source line.
14071db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
14081db9f3b2SDimitry Andric
14091db9f3b2SDimitry Andric // Write macro string.
14101db9f3b2SDimitry Andric StringRef String = MacroEntry.MacroStr;
14111db9f3b2SDimitry Andric MS->emitBytes(String);
14121db9f3b2SDimitry Andric MS->emitIntValue(0, 1);
14131db9f3b2SDimitry Andric OutOffset += String.size() + 1;
14141db9f3b2SDimitry Andric } break;
14151db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strp:
14161db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strp:
14171db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strx:
14181db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strx: {
14191db9f3b2SDimitry Andric assert(UnitIt->second->getOrigUnit().getVersion() >= 5);
14201db9f3b2SDimitry Andric
14211db9f3b2SDimitry Andric // DW_MACRO_*_strx forms are not supported currently.
14221db9f3b2SDimitry Andric // Convert to *_strp.
14231db9f3b2SDimitry Andric switch (MacroType) {
14241db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strx: {
14251db9f3b2SDimitry Andric MacroType = dwarf::DW_MACRO_define_strp;
14261db9f3b2SDimitry Andric if (!DefAttributeIsReported) {
14271db9f3b2SDimitry Andric warn("DW_MACRO_define_strx unsupported yet. Convert to "
14281db9f3b2SDimitry Andric "DW_MACRO_define_strp.");
14291db9f3b2SDimitry Andric DefAttributeIsReported = true;
14301db9f3b2SDimitry Andric }
14311db9f3b2SDimitry Andric } break;
14321db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strx: {
14331db9f3b2SDimitry Andric MacroType = dwarf::DW_MACRO_undef_strp;
14341db9f3b2SDimitry Andric if (!UndefAttributeIsReported) {
14351db9f3b2SDimitry Andric warn("DW_MACRO_undef_strx unsupported yet. Convert to "
14361db9f3b2SDimitry Andric "DW_MACRO_undef_strp.");
14371db9f3b2SDimitry Andric UndefAttributeIsReported = true;
14381db9f3b2SDimitry Andric }
14391db9f3b2SDimitry Andric } break;
14401db9f3b2SDimitry Andric default:
14411db9f3b2SDimitry Andric // Nothing to do.
14421db9f3b2SDimitry Andric break;
14431db9f3b2SDimitry Andric }
14441db9f3b2SDimitry Andric
14451db9f3b2SDimitry Andric // Write macinfo type.
14461db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1);
14471db9f3b2SDimitry Andric OutOffset++;
14481db9f3b2SDimitry Andric
14491db9f3b2SDimitry Andric // Write source line.
14501db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
14511db9f3b2SDimitry Andric
14521db9f3b2SDimitry Andric // Write macro string.
14531db9f3b2SDimitry Andric DwarfStringPoolEntryRef EntryRef =
14541db9f3b2SDimitry Andric StringPool.getEntry(MacroEntry.MacroStr);
14551db9f3b2SDimitry Andric MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize());
14561db9f3b2SDimitry Andric OutOffset += List.Header.getOffsetByteSize();
14571db9f3b2SDimitry Andric break;
14581db9f3b2SDimitry Andric }
14591db9f3b2SDimitry Andric case dwarf::DW_MACRO_start_file: {
14601db9f3b2SDimitry Andric // Write macinfo type.
14611db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1);
14621db9f3b2SDimitry Andric OutOffset++;
14631db9f3b2SDimitry Andric // Write source line.
14641db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
14651db9f3b2SDimitry Andric // Write source file id.
14661db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.File);
14671db9f3b2SDimitry Andric } break;
14681db9f3b2SDimitry Andric case dwarf::DW_MACRO_end_file: {
14691db9f3b2SDimitry Andric // Write macinfo type.
14701db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1);
14711db9f3b2SDimitry Andric OutOffset++;
14721db9f3b2SDimitry Andric } break;
14731db9f3b2SDimitry Andric case dwarf::DW_MACRO_import:
14741db9f3b2SDimitry Andric case dwarf::DW_MACRO_import_sup: {
14751db9f3b2SDimitry Andric if (!ImportAttributeIsReported) {
14761db9f3b2SDimitry Andric warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "
14771db9f3b2SDimitry Andric "remove.");
14781db9f3b2SDimitry Andric ImportAttributeIsReported = true;
14791db9f3b2SDimitry Andric }
14801db9f3b2SDimitry Andric } break;
14811db9f3b2SDimitry Andric }
14821db9f3b2SDimitry Andric }
14831db9f3b2SDimitry Andric }
14841db9f3b2SDimitry Andric }
1485