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 337a6dacacSDimitry Andric Expected<std::unique_ptr<DwarfStreamer>> DwarfStreamer::createStreamer( 347a6dacacSDimitry Andric const Triple &TheTriple, DWARFLinkerBase::OutputFileType FileType, 35*0fca6ea1SDimitry Andric raw_pwrite_stream &OutFile, DWARFLinkerBase::MessageHandlerTy Warning) { 367a6dacacSDimitry Andric std::unique_ptr<DwarfStreamer> Streamer = 37*0fca6ea1SDimitry Andric std::make_unique<DwarfStreamer>(FileType, OutFile, Warning); 387a6dacacSDimitry Andric if (Error Err = Streamer->init(TheTriple, "__DWARF")) 397a6dacacSDimitry Andric return std::move(Err); 407a6dacacSDimitry Andric 417a6dacacSDimitry Andric return std::move(Streamer); 427a6dacacSDimitry Andric } 437a6dacacSDimitry Andric 441db9f3b2SDimitry Andric Error DwarfStreamer::init(Triple TheTriple, 451db9f3b2SDimitry Andric StringRef Swift5ReflectionSegmentName) { 461db9f3b2SDimitry Andric std::string ErrorStr; 471db9f3b2SDimitry Andric std::string TripleName; 481db9f3b2SDimitry Andric 491db9f3b2SDimitry Andric // Get the target. 501db9f3b2SDimitry Andric const Target *TheTarget = 511db9f3b2SDimitry Andric TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr); 521db9f3b2SDimitry Andric if (!TheTarget) 531db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, ErrorStr.c_str()); 541db9f3b2SDimitry Andric 551db9f3b2SDimitry Andric TripleName = TheTriple.getTriple(); 561db9f3b2SDimitry Andric 571db9f3b2SDimitry Andric // Create all the MC Objects. 581db9f3b2SDimitry Andric MRI.reset(TheTarget->createMCRegInfo(TripleName)); 591db9f3b2SDimitry Andric if (!MRI) 601db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 611db9f3b2SDimitry Andric "no register info for target %s", 621db9f3b2SDimitry Andric TripleName.c_str()); 631db9f3b2SDimitry Andric 641db9f3b2SDimitry Andric MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags(); 65*0fca6ea1SDimitry Andric MCOptions.AsmVerbose = true; 66*0fca6ea1SDimitry Andric MCOptions.MCUseDwarfDirectory = MCTargetOptions::EnableDwarfDirectory; 671db9f3b2SDimitry Andric MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions)); 681db9f3b2SDimitry Andric if (!MAI) 691db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 701db9f3b2SDimitry Andric "no asm info for target %s", TripleName.c_str()); 711db9f3b2SDimitry Andric 721db9f3b2SDimitry Andric MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", "")); 731db9f3b2SDimitry Andric if (!MSTI) 741db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 751db9f3b2SDimitry Andric "no subtarget info for target %s", 761db9f3b2SDimitry Andric TripleName.c_str()); 771db9f3b2SDimitry Andric 781db9f3b2SDimitry Andric MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr, 791db9f3b2SDimitry Andric nullptr, true, Swift5ReflectionSegmentName)); 801db9f3b2SDimitry Andric MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false)); 811db9f3b2SDimitry Andric MC->setObjectFileInfo(MOFI.get()); 821db9f3b2SDimitry Andric 831db9f3b2SDimitry Andric MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions); 841db9f3b2SDimitry Andric if (!MAB) 851db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 861db9f3b2SDimitry Andric "no asm backend for target %s", 871db9f3b2SDimitry Andric TripleName.c_str()); 881db9f3b2SDimitry Andric 891db9f3b2SDimitry Andric MII.reset(TheTarget->createMCInstrInfo()); 901db9f3b2SDimitry Andric if (!MII) 911db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 921db9f3b2SDimitry Andric "no instr info info for target %s", 931db9f3b2SDimitry Andric TripleName.c_str()); 941db9f3b2SDimitry Andric 951db9f3b2SDimitry Andric MCE = TheTarget->createMCCodeEmitter(*MII, *MC); 961db9f3b2SDimitry Andric if (!MCE) 971db9f3b2SDimitry Andric return createStringError(std::errc::invalid_argument, 981db9f3b2SDimitry Andric "no code emitter for target %s", 991db9f3b2SDimitry Andric TripleName.c_str()); 1001db9f3b2SDimitry Andric 1011db9f3b2SDimitry Andric switch (OutFileType) { 1021db9f3b2SDimitry Andric case DWARFLinker::OutputFileType::Assembly: { 1031db9f3b2SDimitry Andric MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(), 1041db9f3b2SDimitry Andric *MAI, *MII, *MRI); 1051db9f3b2SDimitry Andric MS = TheTarget->createAsmStreamer( 106*0fca6ea1SDimitry Andric *MC, std::make_unique<formatted_raw_ostream>(OutFile), MIP, 107*0fca6ea1SDimitry Andric std::unique_ptr<MCCodeEmitter>(MCE), 108*0fca6ea1SDimitry Andric std::unique_ptr<MCAsmBackend>(MAB)); 1091db9f3b2SDimitry Andric break; 1101db9f3b2SDimitry Andric } 1111db9f3b2SDimitry Andric case DWARFLinker::OutputFileType::Object: { 1121db9f3b2SDimitry Andric MS = TheTarget->createMCObjectStreamer( 1131db9f3b2SDimitry Andric TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB), 1141db9f3b2SDimitry Andric MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE), 115*0fca6ea1SDimitry Andric *MSTI); 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 1531db9f3b2SDimitry Andric void DwarfStreamer::finish() { MS->finish(); } 1541db9f3b2SDimitry Andric 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. 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. 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. 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. 2277a6dacacSDimitry Andric void DwarfStreamer::emitSectionContents(StringRef SecData, 2287a6dacacSDimitry Andric DebugSectionKind SecKind) { 2297a6dacacSDimitry Andric if (SecData.empty()) 2307a6dacacSDimitry Andric return; 2311db9f3b2SDimitry Andric 2327a6dacacSDimitry Andric if (MCSection *Section = getMCSection(SecKind)) { 2331db9f3b2SDimitry Andric MS->switchSection(Section); 2341db9f3b2SDimitry Andric 2351db9f3b2SDimitry Andric MS->emitBytes(SecData); 2361db9f3b2SDimitry Andric } 2371db9f3b2SDimitry Andric } 2381db9f3b2SDimitry Andric 2397a6dacacSDimitry Andric MCSection *DwarfStreamer::getMCSection(DebugSectionKind SecKind) { 2407a6dacacSDimitry Andric switch (SecKind) { 2417a6dacacSDimitry Andric case DebugSectionKind::DebugInfo: 2427a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfInfoSection(); 2437a6dacacSDimitry Andric case DebugSectionKind::DebugLine: 2447a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLineSection(); 2457a6dacacSDimitry Andric case DebugSectionKind::DebugFrame: 2467a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfFrameSection(); 2477a6dacacSDimitry Andric case DebugSectionKind::DebugRange: 2487a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfRangesSection(); 2497a6dacacSDimitry Andric case DebugSectionKind::DebugRngLists: 2507a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfRnglistsSection(); 2517a6dacacSDimitry Andric case DebugSectionKind::DebugLoc: 2527a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLocSection(); 2537a6dacacSDimitry Andric case DebugSectionKind::DebugLocLists: 2547a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLoclistsSection(); 2557a6dacacSDimitry Andric case DebugSectionKind::DebugARanges: 2567a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfARangesSection(); 2577a6dacacSDimitry Andric case DebugSectionKind::DebugAbbrev: 2587a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAbbrevSection(); 2597a6dacacSDimitry Andric case DebugSectionKind::DebugMacinfo: 2607a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfMacinfoSection(); 2617a6dacacSDimitry Andric case DebugSectionKind::DebugMacro: 2627a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfMacroSection(); 2637a6dacacSDimitry Andric case DebugSectionKind::DebugAddr: 2647a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAddrSection(); 2657a6dacacSDimitry Andric case DebugSectionKind::DebugStr: 2667a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfStrSection(); 2677a6dacacSDimitry Andric case DebugSectionKind::DebugLineStr: 2687a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfLineStrSection(); 2697a6dacacSDimitry Andric case DebugSectionKind::DebugStrOffsets: 2707a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfStrOffSection(); 2717a6dacacSDimitry Andric case DebugSectionKind::DebugPubNames: 2727a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfPubNamesSection(); 2737a6dacacSDimitry Andric case DebugSectionKind::DebugPubTypes: 2747a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfPubTypesSection(); 2757a6dacacSDimitry Andric case DebugSectionKind::DebugNames: 2767a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfDebugNamesSection(); 2777a6dacacSDimitry Andric case DebugSectionKind::AppleNames: 2787a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelNamesSection(); 2797a6dacacSDimitry Andric case DebugSectionKind::AppleNamespaces: 2807a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelNamespaceSection(); 2817a6dacacSDimitry Andric case DebugSectionKind::AppleObjC: 2827a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelObjCSection(); 2837a6dacacSDimitry Andric case DebugSectionKind::AppleTypes: 2847a6dacacSDimitry Andric return MC->getObjectFileInfo()->getDwarfAccelTypesSection(); 2857a6dacacSDimitry Andric case DebugSectionKind::NumberOfEnumEntries: 2867a6dacacSDimitry Andric llvm_unreachable("Unknown DebugSectionKind value"); 2877a6dacacSDimitry Andric break; 2887a6dacacSDimitry Andric } 2897a6dacacSDimitry Andric 2907a6dacacSDimitry Andric return nullptr; 2917a6dacacSDimitry Andric } 2927a6dacacSDimitry Andric 2931db9f3b2SDimitry Andric /// Emit the debug_str section stored in \p 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. 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. 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 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 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 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 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 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. 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 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 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 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 * 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 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 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 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. 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. 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. 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. 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. 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. 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. 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. 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 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 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 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 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 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: { 980*0fca6ea1SDimitry Andric StringRef Str = *StringVal; 981*0fca6ea1SDimitry Andric Asm->OutStreamer->emitBytes(Str.data()); 9821db9f3b2SDimitry Andric Asm->emitInt8(0); 983*0fca6ea1SDimitry Andric LineSectionSize += Str.size() + 1; 9841db9f3b2SDimitry Andric } break; 9851db9f3b2SDimitry Andric case dwarf::DW_FORM_strp: 9861db9f3b2SDimitry Andric case dwarf::DW_FORM_line_strp: { 9871db9f3b2SDimitry Andric DwarfStringPoolEntryRef StringRef = 9881db9f3b2SDimitry Andric String.getForm() == dwarf::DW_FORM_strp 9891db9f3b2SDimitry Andric ? DebugStrPool.getEntry(*StringVal) 9901db9f3b2SDimitry Andric : DebugLineStrPool.getEntry(*StringVal); 9911db9f3b2SDimitry Andric 9921db9f3b2SDimitry Andric emitIntOffset(StringRef.getOffset(), P.FormParams.Format, LineSectionSize); 9931db9f3b2SDimitry Andric } break; 9941db9f3b2SDimitry Andric default: 9951db9f3b2SDimitry Andric warn("Unsupported string form inside line table."); 9961db9f3b2SDimitry Andric break; 9971db9f3b2SDimitry Andric }; 9981db9f3b2SDimitry Andric } 9991db9f3b2SDimitry Andric 10001db9f3b2SDimitry Andric void DwarfStreamer::emitLineTableProloguePayload( 10011db9f3b2SDimitry Andric const DWARFDebugLine::Prologue &P, OffsetsStringPool &DebugStrPool, 10021db9f3b2SDimitry Andric OffsetsStringPool &DebugLineStrPool) { 10031db9f3b2SDimitry Andric // minimum_instruction_length (ubyte). 10041db9f3b2SDimitry Andric MS->emitInt8(P.MinInstLength); 10051db9f3b2SDimitry Andric LineSectionSize += 1; 10061db9f3b2SDimitry Andric if (P.FormParams.Version >= 4) { 10071db9f3b2SDimitry Andric // maximum_operations_per_instruction (ubyte). 10081db9f3b2SDimitry Andric MS->emitInt8(P.MaxOpsPerInst); 10091db9f3b2SDimitry Andric LineSectionSize += 1; 10101db9f3b2SDimitry Andric } 10111db9f3b2SDimitry Andric // default_is_stmt (ubyte). 10121db9f3b2SDimitry Andric MS->emitInt8(P.DefaultIsStmt); 10131db9f3b2SDimitry Andric LineSectionSize += 1; 10141db9f3b2SDimitry Andric // line_base (sbyte). 10151db9f3b2SDimitry Andric MS->emitInt8(P.LineBase); 10161db9f3b2SDimitry Andric LineSectionSize += 1; 10171db9f3b2SDimitry Andric // line_range (ubyte). 10181db9f3b2SDimitry Andric MS->emitInt8(P.LineRange); 10191db9f3b2SDimitry Andric LineSectionSize += 1; 10201db9f3b2SDimitry Andric // opcode_base (ubyte). 10211db9f3b2SDimitry Andric MS->emitInt8(P.OpcodeBase); 10221db9f3b2SDimitry Andric LineSectionSize += 1; 10231db9f3b2SDimitry Andric 10241db9f3b2SDimitry Andric // standard_opcode_lengths (array of ubyte). 10251db9f3b2SDimitry Andric for (auto Length : P.StandardOpcodeLengths) { 10261db9f3b2SDimitry Andric MS->emitInt8(Length); 10271db9f3b2SDimitry Andric LineSectionSize += 1; 10281db9f3b2SDimitry Andric } 10291db9f3b2SDimitry Andric 10301db9f3b2SDimitry Andric if (P.FormParams.Version < 5) 10311db9f3b2SDimitry Andric emitLineTablePrologueV2IncludeAndFileTable(P, DebugStrPool, 10321db9f3b2SDimitry Andric DebugLineStrPool); 10331db9f3b2SDimitry Andric else 10341db9f3b2SDimitry Andric emitLineTablePrologueV5IncludeAndFileTable(P, DebugStrPool, 10351db9f3b2SDimitry Andric DebugLineStrPool); 10361db9f3b2SDimitry Andric } 10371db9f3b2SDimitry Andric 10381db9f3b2SDimitry Andric void DwarfStreamer::emitLineTableRows( 10391db9f3b2SDimitry Andric const DWARFDebugLine::LineTable &LineTable, MCSymbol *LineEndSym, 10401db9f3b2SDimitry Andric unsigned AddressByteSize) { 10411db9f3b2SDimitry Andric 10421db9f3b2SDimitry Andric MCDwarfLineTableParams Params; 10431db9f3b2SDimitry Andric Params.DWARF2LineOpcodeBase = LineTable.Prologue.OpcodeBase; 10441db9f3b2SDimitry Andric Params.DWARF2LineBase = LineTable.Prologue.LineBase; 10451db9f3b2SDimitry Andric Params.DWARF2LineRange = LineTable.Prologue.LineRange; 10461db9f3b2SDimitry Andric 10471db9f3b2SDimitry Andric SmallString<128> EncodingBuffer; 10481db9f3b2SDimitry Andric 10491db9f3b2SDimitry Andric if (LineTable.Rows.empty()) { 10501db9f3b2SDimitry Andric // We only have the dummy entry, dsymutil emits an entry with a 0 10511db9f3b2SDimitry Andric // address in that case. 10521db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, 10531db9f3b2SDimitry Andric EncodingBuffer); 10541db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer); 10551db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size(); 10561db9f3b2SDimitry Andric MS->emitLabel(LineEndSym); 10571db9f3b2SDimitry Andric return; 10581db9f3b2SDimitry Andric } 10591db9f3b2SDimitry Andric 10601db9f3b2SDimitry Andric // Line table state machine fields 10611db9f3b2SDimitry Andric unsigned FileNum = 1; 10621db9f3b2SDimitry Andric unsigned LastLine = 1; 10631db9f3b2SDimitry Andric unsigned Column = 0; 1064*0fca6ea1SDimitry Andric unsigned Discriminator = 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 } 1103*0fca6ea1SDimitry Andric if (Discriminator != Row.Discriminator && 1104*0fca6ea1SDimitry Andric MS->getContext().getDwarfVersion() >= 4) { 1105*0fca6ea1SDimitry Andric Discriminator = Row.Discriminator; 1106*0fca6ea1SDimitry Andric unsigned Size = getULEB128Size(Discriminator); 1107*0fca6ea1SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_extended_op, 1); 1108*0fca6ea1SDimitry Andric MS->emitULEB128IntValue(Size + 1); 1109*0fca6ea1SDimitry Andric MS->emitIntValue(dwarf::DW_LNE_set_discriminator, 1); 1110*0fca6ea1SDimitry Andric MS->emitULEB128IntValue(Discriminator); 1111*0fca6ea1SDimitry Andric LineSectionSize += /* extended op */ 1 + getULEB128Size(Size + 1) + 1112*0fca6ea1SDimitry Andric /* discriminator */ 1 + Size; 1113*0fca6ea1SDimitry Andric } 1114*0fca6ea1SDimitry Andric Discriminator = 0; 11151db9f3b2SDimitry Andric 11161db9f3b2SDimitry Andric if (Isa != Row.Isa) { 11171db9f3b2SDimitry Andric Isa = Row.Isa; 11181db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_isa, 1); 11191db9f3b2SDimitry Andric MS->emitULEB128IntValue(Isa); 11201db9f3b2SDimitry Andric LineSectionSize += 1 + getULEB128Size(Isa); 11211db9f3b2SDimitry Andric } 11221db9f3b2SDimitry Andric if (IsStatement != Row.IsStmt) { 11231db9f3b2SDimitry Andric IsStatement = Row.IsStmt; 11241db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1); 11251db9f3b2SDimitry Andric LineSectionSize += 1; 11261db9f3b2SDimitry Andric } 11271db9f3b2SDimitry Andric if (Row.BasicBlock) { 11281db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1); 11291db9f3b2SDimitry Andric LineSectionSize += 1; 11301db9f3b2SDimitry Andric } 11311db9f3b2SDimitry Andric 11321db9f3b2SDimitry Andric if (Row.PrologueEnd) { 11331db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1); 11341db9f3b2SDimitry Andric LineSectionSize += 1; 11351db9f3b2SDimitry Andric } 11361db9f3b2SDimitry Andric 11371db9f3b2SDimitry Andric if (Row.EpilogueBegin) { 11381db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1); 11391db9f3b2SDimitry Andric LineSectionSize += 1; 11401db9f3b2SDimitry Andric } 11411db9f3b2SDimitry Andric 11421db9f3b2SDimitry Andric int64_t LineDelta = int64_t(Row.Line) - LastLine; 11431db9f3b2SDimitry Andric if (!Row.EndSequence) { 11441db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, LineDelta, AddressDelta, 11451db9f3b2SDimitry Andric EncodingBuffer); 11461db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer); 11471db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size(); 11481db9f3b2SDimitry Andric EncodingBuffer.resize(0); 11491db9f3b2SDimitry Andric Address = Row.Address.Address; 11501db9f3b2SDimitry Andric LastLine = Row.Line; 11511db9f3b2SDimitry Andric RowsSinceLastSequence++; 11521db9f3b2SDimitry Andric } else { 11531db9f3b2SDimitry Andric if (LineDelta) { 11541db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_advance_line, 1); 11551db9f3b2SDimitry Andric MS->emitSLEB128IntValue(LineDelta); 11561db9f3b2SDimitry Andric LineSectionSize += 1 + getSLEB128Size(LineDelta); 11571db9f3b2SDimitry Andric } 11581db9f3b2SDimitry Andric if (AddressDelta) { 11591db9f3b2SDimitry Andric MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1); 11601db9f3b2SDimitry Andric MS->emitULEB128IntValue(AddressDelta); 11611db9f3b2SDimitry Andric LineSectionSize += 1 + getULEB128Size(AddressDelta); 11621db9f3b2SDimitry Andric } 11631db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 11641db9f3b2SDimitry Andric 0, EncodingBuffer); 11651db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer); 11661db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size(); 11671db9f3b2SDimitry Andric EncodingBuffer.resize(0); 11681db9f3b2SDimitry Andric Address = -1ULL; 11691db9f3b2SDimitry Andric LastLine = FileNum = IsStatement = 1; 1170*0fca6ea1SDimitry Andric RowsSinceLastSequence = Column = Discriminator = Isa = 0; 11711db9f3b2SDimitry Andric } 11721db9f3b2SDimitry Andric } 11731db9f3b2SDimitry Andric 11741db9f3b2SDimitry Andric if (RowsSinceLastSequence) { 11751db9f3b2SDimitry Andric MCDwarfLineAddr::encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0, 11761db9f3b2SDimitry Andric EncodingBuffer); 11771db9f3b2SDimitry Andric MS->emitBytes(EncodingBuffer); 11781db9f3b2SDimitry Andric LineSectionSize += EncodingBuffer.size(); 11791db9f3b2SDimitry Andric EncodingBuffer.resize(0); 11801db9f3b2SDimitry Andric } 11811db9f3b2SDimitry Andric 11821db9f3b2SDimitry Andric MS->emitLabel(LineEndSym); 11831db9f3b2SDimitry Andric } 11841db9f3b2SDimitry Andric 11851db9f3b2SDimitry Andric void DwarfStreamer::emitIntOffset(uint64_t Offset, dwarf::DwarfFormat Format, 11861db9f3b2SDimitry Andric uint64_t &SectionSize) { 11871db9f3b2SDimitry Andric uint8_t Size = dwarf::getDwarfOffsetByteSize(Format); 11881db9f3b2SDimitry Andric MS->emitIntValue(Offset, Size); 11891db9f3b2SDimitry Andric SectionSize += Size; 11901db9f3b2SDimitry Andric } 11911db9f3b2SDimitry Andric 11921db9f3b2SDimitry Andric void DwarfStreamer::emitLabelDifference(const MCSymbol *Hi, const MCSymbol *Lo, 11931db9f3b2SDimitry Andric dwarf::DwarfFormat Format, 11941db9f3b2SDimitry Andric uint64_t &SectionSize) { 11951db9f3b2SDimitry Andric uint8_t Size = dwarf::getDwarfOffsetByteSize(Format); 11961db9f3b2SDimitry Andric Asm->emitLabelDifference(Hi, Lo, Size); 11971db9f3b2SDimitry Andric SectionSize += Size; 11981db9f3b2SDimitry Andric } 11991db9f3b2SDimitry Andric 12001db9f3b2SDimitry Andric /// Emit the pubnames or pubtypes section contribution for \p 12011db9f3b2SDimitry Andric /// Unit into \p Sec. The data is provided in \p Names. 12021db9f3b2SDimitry Andric void DwarfStreamer::emitPubSectionForUnit( 12031db9f3b2SDimitry Andric MCSection *Sec, StringRef SecName, const CompileUnit &Unit, 12041db9f3b2SDimitry Andric const std::vector<CompileUnit::AccelInfo> &Names) { 12051db9f3b2SDimitry Andric if (Names.empty()) 12061db9f3b2SDimitry Andric return; 12071db9f3b2SDimitry Andric 12081db9f3b2SDimitry Andric // Start the dwarf pubnames section. 12091db9f3b2SDimitry Andric Asm->OutStreamer->switchSection(Sec); 12101db9f3b2SDimitry Andric MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin"); 12111db9f3b2SDimitry Andric MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end"); 12121db9f3b2SDimitry Andric 12131db9f3b2SDimitry Andric bool HeaderEmitted = false; 12141db9f3b2SDimitry Andric // Emit the pubnames for this compilation unit. 12151db9f3b2SDimitry Andric for (const auto &Name : Names) { 12161db9f3b2SDimitry Andric if (Name.SkipPubSection) 12171db9f3b2SDimitry Andric continue; 12181db9f3b2SDimitry Andric 12191db9f3b2SDimitry Andric if (!HeaderEmitted) { 12201db9f3b2SDimitry Andric // Emit the header. 12211db9f3b2SDimitry Andric Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length 12221db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(BeginLabel); 12231db9f3b2SDimitry Andric Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version 12241db9f3b2SDimitry Andric Asm->emitInt32(Unit.getStartOffset()); // Unit offset 12251db9f3b2SDimitry Andric Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size 12261db9f3b2SDimitry Andric HeaderEmitted = true; 12271db9f3b2SDimitry Andric } 12281db9f3b2SDimitry Andric Asm->emitInt32(Name.Die->getOffset()); 12291db9f3b2SDimitry Andric 12301db9f3b2SDimitry Andric // Emit the string itself. 12311db9f3b2SDimitry Andric Asm->OutStreamer->emitBytes(Name.Name.getString()); 12321db9f3b2SDimitry Andric // Emit a null terminator. 12331db9f3b2SDimitry Andric Asm->emitInt8(0); 12341db9f3b2SDimitry Andric } 12351db9f3b2SDimitry Andric 12361db9f3b2SDimitry Andric if (!HeaderEmitted) 12371db9f3b2SDimitry Andric return; 12381db9f3b2SDimitry Andric Asm->emitInt32(0); // End marker. 12391db9f3b2SDimitry Andric Asm->OutStreamer->emitLabel(EndLabel); 12401db9f3b2SDimitry Andric } 12411db9f3b2SDimitry Andric 12421db9f3b2SDimitry Andric /// Emit .debug_pubnames for \p Unit. 12431db9f3b2SDimitry Andric void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) { 12441db9f3b2SDimitry Andric emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(), 12451db9f3b2SDimitry Andric "names", Unit, Unit.getPubnames()); 12461db9f3b2SDimitry Andric } 12471db9f3b2SDimitry Andric 12481db9f3b2SDimitry Andric /// Emit .debug_pubtypes for \p Unit. 12491db9f3b2SDimitry Andric void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) { 12501db9f3b2SDimitry Andric emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(), 12511db9f3b2SDimitry Andric "types", Unit, Unit.getPubtypes()); 12521db9f3b2SDimitry Andric } 12531db9f3b2SDimitry Andric 12541db9f3b2SDimitry Andric /// Emit a CIE into the debug_frame section. 12551db9f3b2SDimitry Andric void DwarfStreamer::emitCIE(StringRef CIEBytes) { 12561db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); 12571db9f3b2SDimitry Andric 12581db9f3b2SDimitry Andric MS->emitBytes(CIEBytes); 12591db9f3b2SDimitry Andric FrameSectionSize += CIEBytes.size(); 12601db9f3b2SDimitry Andric } 12611db9f3b2SDimitry Andric 12621db9f3b2SDimitry Andric /// Emit a FDE into the debug_frame section. \p FDEBytes 12631db9f3b2SDimitry Andric /// contains the FDE data without the length, CIE offset and address 12641db9f3b2SDimitry Andric /// which will be replaced with the parameter values. 12651db9f3b2SDimitry Andric void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize, 12661db9f3b2SDimitry Andric uint64_t Address, StringRef FDEBytes) { 12671db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection()); 12681db9f3b2SDimitry Andric 12691db9f3b2SDimitry Andric MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4); 12701db9f3b2SDimitry Andric MS->emitIntValue(CIEOffset, 4); 12711db9f3b2SDimitry Andric MS->emitIntValue(Address, AddrSize); 12721db9f3b2SDimitry Andric MS->emitBytes(FDEBytes); 12731db9f3b2SDimitry Andric FrameSectionSize += FDEBytes.size() + 8 + AddrSize; 12741db9f3b2SDimitry Andric } 12751db9f3b2SDimitry Andric 12761db9f3b2SDimitry Andric void DwarfStreamer::emitMacroTables(DWARFContext *Context, 12771db9f3b2SDimitry Andric const Offset2UnitMap &UnitMacroMap, 12781db9f3b2SDimitry Andric OffsetsStringPool &StringPool) { 12791db9f3b2SDimitry Andric assert(Context != nullptr && "Empty DWARF context"); 12801db9f3b2SDimitry Andric 12811db9f3b2SDimitry Andric // Check for .debug_macinfo table. 12821db9f3b2SDimitry Andric if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) { 12831db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection()); 12841db9f3b2SDimitry Andric emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize); 12851db9f3b2SDimitry Andric } 12861db9f3b2SDimitry Andric 12871db9f3b2SDimitry Andric // Check for .debug_macro table. 12881db9f3b2SDimitry Andric if (const DWARFDebugMacro *Table = Context->getDebugMacro()) { 12891db9f3b2SDimitry Andric MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection()); 12901db9f3b2SDimitry Andric emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize); 12911db9f3b2SDimitry Andric } 12921db9f3b2SDimitry Andric } 12931db9f3b2SDimitry Andric 12941db9f3b2SDimitry Andric void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable, 12951db9f3b2SDimitry Andric const Offset2UnitMap &UnitMacroMap, 12961db9f3b2SDimitry Andric OffsetsStringPool &StringPool, 12971db9f3b2SDimitry Andric uint64_t &OutOffset) { 12981db9f3b2SDimitry Andric bool DefAttributeIsReported = false; 12991db9f3b2SDimitry Andric bool UndefAttributeIsReported = false; 13001db9f3b2SDimitry Andric bool ImportAttributeIsReported = false; 13011db9f3b2SDimitry Andric for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) { 13021db9f3b2SDimitry Andric Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset); 13031db9f3b2SDimitry Andric if (UnitIt == UnitMacroMap.end()) { 13041db9f3b2SDimitry Andric warn(formatv( 13051db9f3b2SDimitry Andric "couldn`t find compile unit for the macro table with offset = {0:x}", 13061db9f3b2SDimitry Andric List.Offset)); 13071db9f3b2SDimitry Andric continue; 13081db9f3b2SDimitry Andric } 13091db9f3b2SDimitry Andric 13101db9f3b2SDimitry Andric // Skip macro table if the unit was not cloned. 13111db9f3b2SDimitry Andric DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE(); 13121db9f3b2SDimitry Andric if (OutputUnitDIE == nullptr) 13131db9f3b2SDimitry Andric continue; 13141db9f3b2SDimitry Andric 13151db9f3b2SDimitry Andric // Update macro attribute of cloned compile unit with the proper offset to 13161db9f3b2SDimitry Andric // the macro table. 13171db9f3b2SDimitry Andric bool hasDWARFv5Header = false; 13181db9f3b2SDimitry Andric for (auto &V : OutputUnitDIE->values()) { 13191db9f3b2SDimitry Andric if (V.getAttribute() == dwarf::DW_AT_macro_info) { 13201db9f3b2SDimitry Andric V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset)); 13211db9f3b2SDimitry Andric break; 13221db9f3b2SDimitry Andric } else if (V.getAttribute() == dwarf::DW_AT_macros) { 13231db9f3b2SDimitry Andric hasDWARFv5Header = true; 13241db9f3b2SDimitry Andric V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset)); 13251db9f3b2SDimitry Andric break; 13261db9f3b2SDimitry Andric } 13271db9f3b2SDimitry Andric } 13281db9f3b2SDimitry Andric 13291db9f3b2SDimitry Andric // Write DWARFv5 header. 13301db9f3b2SDimitry Andric if (hasDWARFv5Header) { 13311db9f3b2SDimitry Andric // Write header version. 13321db9f3b2SDimitry Andric MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version)); 13331db9f3b2SDimitry Andric OutOffset += sizeof(List.Header.Version); 13341db9f3b2SDimitry Andric 13351db9f3b2SDimitry Andric uint8_t Flags = List.Header.Flags; 13361db9f3b2SDimitry Andric 13371db9f3b2SDimitry Andric // Check for OPCODE_OPERANDS_TABLE. 13381db9f3b2SDimitry Andric if (Flags & 13391db9f3b2SDimitry Andric DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) { 13401db9f3b2SDimitry Andric Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE; 13411db9f3b2SDimitry Andric warn("opcode_operands_table is not supported yet."); 13421db9f3b2SDimitry Andric } 13431db9f3b2SDimitry Andric 13441db9f3b2SDimitry Andric // Check for DEBUG_LINE_OFFSET. 13451db9f3b2SDimitry Andric std::optional<uint64_t> StmtListOffset; 13461db9f3b2SDimitry Andric if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) { 13471db9f3b2SDimitry Andric // Get offset to the line table from the cloned compile unit. 13481db9f3b2SDimitry Andric for (auto &V : OutputUnitDIE->values()) { 13491db9f3b2SDimitry Andric if (V.getAttribute() == dwarf::DW_AT_stmt_list) { 13501db9f3b2SDimitry Andric StmtListOffset = V.getDIEInteger().getValue(); 13511db9f3b2SDimitry Andric break; 13521db9f3b2SDimitry Andric } 13531db9f3b2SDimitry Andric } 13541db9f3b2SDimitry Andric 13551db9f3b2SDimitry Andric if (!StmtListOffset) { 13561db9f3b2SDimitry Andric Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET; 13571db9f3b2SDimitry Andric warn("couldn`t find line table for macro table."); 13581db9f3b2SDimitry Andric } 13591db9f3b2SDimitry Andric } 13601db9f3b2SDimitry Andric 13611db9f3b2SDimitry Andric // Write flags. 13621db9f3b2SDimitry Andric MS->emitIntValue(Flags, sizeof(Flags)); 13631db9f3b2SDimitry Andric OutOffset += sizeof(Flags); 13641db9f3b2SDimitry Andric 13651db9f3b2SDimitry Andric // Write offset to line table. 13661db9f3b2SDimitry Andric if (StmtListOffset) { 13671db9f3b2SDimitry Andric MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize()); 13681db9f3b2SDimitry Andric OutOffset += List.Header.getOffsetByteSize(); 13691db9f3b2SDimitry Andric } 13701db9f3b2SDimitry Andric } 13711db9f3b2SDimitry Andric 13721db9f3b2SDimitry Andric // Write macro entries. 13731db9f3b2SDimitry Andric for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) { 13741db9f3b2SDimitry Andric if (MacroEntry.Type == 0) { 13751db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Type); 13761db9f3b2SDimitry Andric continue; 13771db9f3b2SDimitry Andric } 13781db9f3b2SDimitry Andric 13791db9f3b2SDimitry Andric uint8_t MacroType = MacroEntry.Type; 13801db9f3b2SDimitry Andric switch (MacroType) { 13811db9f3b2SDimitry Andric default: { 13821db9f3b2SDimitry Andric bool HasVendorSpecificExtension = 13831db9f3b2SDimitry Andric (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) || 13841db9f3b2SDimitry Andric (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user && 13851db9f3b2SDimitry Andric MacroType <= dwarf::DW_MACRO_hi_user)); 13861db9f3b2SDimitry Andric 13871db9f3b2SDimitry Andric if (HasVendorSpecificExtension) { 13881db9f3b2SDimitry Andric // Write macinfo type. 13891db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1); 13901db9f3b2SDimitry Andric OutOffset++; 13911db9f3b2SDimitry Andric 13921db9f3b2SDimitry Andric // Write vendor extension constant. 13931db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant); 13941db9f3b2SDimitry Andric 13951db9f3b2SDimitry Andric // Write vendor extension string. 13961db9f3b2SDimitry Andric StringRef String = MacroEntry.ExtStr; 13971db9f3b2SDimitry Andric MS->emitBytes(String); 13981db9f3b2SDimitry Andric MS->emitIntValue(0, 1); 13991db9f3b2SDimitry Andric OutOffset += String.size() + 1; 14001db9f3b2SDimitry Andric } else 14011db9f3b2SDimitry Andric warn("unknown macro type. skip."); 14021db9f3b2SDimitry Andric } break; 14031db9f3b2SDimitry Andric // debug_macro and debug_macinfo share some common encodings. 14041db9f3b2SDimitry Andric // DW_MACRO_define == DW_MACINFO_define 14051db9f3b2SDimitry Andric // DW_MACRO_undef == DW_MACINFO_undef 14061db9f3b2SDimitry Andric // DW_MACRO_start_file == DW_MACINFO_start_file 14071db9f3b2SDimitry Andric // DW_MACRO_end_file == DW_MACINFO_end_file 14081db9f3b2SDimitry Andric // For readibility/uniformity we are using DW_MACRO_*. 14091db9f3b2SDimitry Andric case dwarf::DW_MACRO_define: 14101db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef: { 14111db9f3b2SDimitry Andric // Write macinfo type. 14121db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1); 14131db9f3b2SDimitry Andric OutOffset++; 14141db9f3b2SDimitry Andric 14151db9f3b2SDimitry Andric // Write source line. 14161db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Line); 14171db9f3b2SDimitry Andric 14181db9f3b2SDimitry Andric // Write macro string. 14191db9f3b2SDimitry Andric StringRef String = MacroEntry.MacroStr; 14201db9f3b2SDimitry Andric MS->emitBytes(String); 14211db9f3b2SDimitry Andric MS->emitIntValue(0, 1); 14221db9f3b2SDimitry Andric OutOffset += String.size() + 1; 14231db9f3b2SDimitry Andric } break; 14241db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strp: 14251db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strp: 14261db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strx: 14271db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strx: { 14281db9f3b2SDimitry Andric assert(UnitIt->second->getOrigUnit().getVersion() >= 5); 14291db9f3b2SDimitry Andric 14301db9f3b2SDimitry Andric // DW_MACRO_*_strx forms are not supported currently. 14311db9f3b2SDimitry Andric // Convert to *_strp. 14321db9f3b2SDimitry Andric switch (MacroType) { 14331db9f3b2SDimitry Andric case dwarf::DW_MACRO_define_strx: { 14341db9f3b2SDimitry Andric MacroType = dwarf::DW_MACRO_define_strp; 14351db9f3b2SDimitry Andric if (!DefAttributeIsReported) { 14361db9f3b2SDimitry Andric warn("DW_MACRO_define_strx unsupported yet. Convert to " 14371db9f3b2SDimitry Andric "DW_MACRO_define_strp."); 14381db9f3b2SDimitry Andric DefAttributeIsReported = true; 14391db9f3b2SDimitry Andric } 14401db9f3b2SDimitry Andric } break; 14411db9f3b2SDimitry Andric case dwarf::DW_MACRO_undef_strx: { 14421db9f3b2SDimitry Andric MacroType = dwarf::DW_MACRO_undef_strp; 14431db9f3b2SDimitry Andric if (!UndefAttributeIsReported) { 14441db9f3b2SDimitry Andric warn("DW_MACRO_undef_strx unsupported yet. Convert to " 14451db9f3b2SDimitry Andric "DW_MACRO_undef_strp."); 14461db9f3b2SDimitry Andric UndefAttributeIsReported = true; 14471db9f3b2SDimitry Andric } 14481db9f3b2SDimitry Andric } break; 14491db9f3b2SDimitry Andric default: 14501db9f3b2SDimitry Andric // Nothing to do. 14511db9f3b2SDimitry Andric break; 14521db9f3b2SDimitry Andric } 14531db9f3b2SDimitry Andric 14541db9f3b2SDimitry Andric // Write macinfo type. 14551db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1); 14561db9f3b2SDimitry Andric OutOffset++; 14571db9f3b2SDimitry Andric 14581db9f3b2SDimitry Andric // Write source line. 14591db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Line); 14601db9f3b2SDimitry Andric 14611db9f3b2SDimitry Andric // Write macro string. 14621db9f3b2SDimitry Andric DwarfStringPoolEntryRef EntryRef = 14631db9f3b2SDimitry Andric StringPool.getEntry(MacroEntry.MacroStr); 14641db9f3b2SDimitry Andric MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize()); 14651db9f3b2SDimitry Andric OutOffset += List.Header.getOffsetByteSize(); 14661db9f3b2SDimitry Andric break; 14671db9f3b2SDimitry Andric } 14681db9f3b2SDimitry Andric case dwarf::DW_MACRO_start_file: { 14691db9f3b2SDimitry Andric // Write macinfo type. 14701db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1); 14711db9f3b2SDimitry Andric OutOffset++; 14721db9f3b2SDimitry Andric // Write source line. 14731db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.Line); 14741db9f3b2SDimitry Andric // Write source file id. 14751db9f3b2SDimitry Andric OutOffset += MS->emitULEB128IntValue(MacroEntry.File); 14761db9f3b2SDimitry Andric } break; 14771db9f3b2SDimitry Andric case dwarf::DW_MACRO_end_file: { 14781db9f3b2SDimitry Andric // Write macinfo type. 14791db9f3b2SDimitry Andric MS->emitIntValue(MacroType, 1); 14801db9f3b2SDimitry Andric OutOffset++; 14811db9f3b2SDimitry Andric } break; 14821db9f3b2SDimitry Andric case dwarf::DW_MACRO_import: 14831db9f3b2SDimitry Andric case dwarf::DW_MACRO_import_sup: { 14841db9f3b2SDimitry Andric if (!ImportAttributeIsReported) { 14851db9f3b2SDimitry Andric warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. " 14861db9f3b2SDimitry Andric "remove."); 14871db9f3b2SDimitry Andric ImportAttributeIsReported = true; 14881db9f3b2SDimitry Andric } 14891db9f3b2SDimitry Andric } break; 14901db9f3b2SDimitry Andric } 14911db9f3b2SDimitry Andric } 14921db9f3b2SDimitry Andric } 14931db9f3b2SDimitry Andric } 1494