xref: /openbsd-src/gnu/llvm/llvm/lib/DWARFLinker/DWARFStreamer.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
1097a140dSpatrick //===- DwarfStreamer.cpp --------------------------------------------------===//
2097a140dSpatrick //
3097a140dSpatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4097a140dSpatrick // See https://llvm.org/LICENSE.txt for license information.
5097a140dSpatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6097a140dSpatrick //
7097a140dSpatrick //===----------------------------------------------------------------------===//
8097a140dSpatrick 
9097a140dSpatrick #include "llvm/DWARFLinker/DWARFStreamer.h"
10097a140dSpatrick #include "llvm/ADT/Triple.h"
11097a140dSpatrick #include "llvm/CodeGen/NonRelocatableStringpool.h"
12097a140dSpatrick #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
13097a140dSpatrick #include "llvm/DebugInfo/DWARF/DWARFContext.h"
14*d415bd75Srobert #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
15097a140dSpatrick #include "llvm/MC/MCAsmBackend.h"
16097a140dSpatrick #include "llvm/MC/MCCodeEmitter.h"
17097a140dSpatrick #include "llvm/MC/MCDwarf.h"
18097a140dSpatrick #include "llvm/MC/MCObjectWriter.h"
19097a140dSpatrick #include "llvm/MC/MCSection.h"
20097a140dSpatrick #include "llvm/MC/MCStreamer.h"
21097a140dSpatrick #include "llvm/MC/MCSubtargetInfo.h"
22097a140dSpatrick #include "llvm/MC/MCTargetOptions.h"
23097a140dSpatrick #include "llvm/MC/MCTargetOptionsCommandFlags.h"
24*d415bd75Srobert #include "llvm/MC/TargetRegistry.h"
25*d415bd75Srobert #include "llvm/Support/FormatVariadic.h"
26097a140dSpatrick #include "llvm/Support/LEB128.h"
27097a140dSpatrick #include "llvm/Target/TargetOptions.h"
28097a140dSpatrick 
29097a140dSpatrick namespace llvm {
30097a140dSpatrick 
init(Triple TheTriple,StringRef Swift5ReflectionSegmentName)31*d415bd75Srobert bool DwarfStreamer::init(Triple TheTriple,
32*d415bd75Srobert                          StringRef Swift5ReflectionSegmentName) {
33097a140dSpatrick   std::string ErrorStr;
34097a140dSpatrick   std::string TripleName;
35097a140dSpatrick   StringRef Context = "dwarf streamer init";
36097a140dSpatrick 
37097a140dSpatrick   // Get the target.
38097a140dSpatrick   const Target *TheTarget =
39097a140dSpatrick       TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
40097a140dSpatrick   if (!TheTarget)
41097a140dSpatrick     return error(ErrorStr, Context), false;
42097a140dSpatrick   TripleName = TheTriple.getTriple();
43097a140dSpatrick 
44097a140dSpatrick   // Create all the MC Objects.
45097a140dSpatrick   MRI.reset(TheTarget->createMCRegInfo(TripleName));
46097a140dSpatrick   if (!MRI)
47097a140dSpatrick     return error(Twine("no register info for target ") + TripleName, Context),
48097a140dSpatrick            false;
49097a140dSpatrick 
50097a140dSpatrick   MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
51097a140dSpatrick   MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
52097a140dSpatrick   if (!MAI)
53097a140dSpatrick     return error("no asm info for target " + TripleName, Context), false;
54097a140dSpatrick 
55097a140dSpatrick   MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
56097a140dSpatrick   if (!MSTI)
57097a140dSpatrick     return error("no subtarget info for target " + TripleName, Context), false;
58097a140dSpatrick 
59*d415bd75Srobert   MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
60*d415bd75Srobert                          nullptr, true, Swift5ReflectionSegmentName));
61*d415bd75Srobert   MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
6273471bf0Spatrick   MC->setObjectFileInfo(MOFI.get());
6373471bf0Spatrick 
64097a140dSpatrick   MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
65097a140dSpatrick   if (!MAB)
66097a140dSpatrick     return error("no asm backend for target " + TripleName, Context), false;
67097a140dSpatrick 
68097a140dSpatrick   MII.reset(TheTarget->createMCInstrInfo());
69097a140dSpatrick   if (!MII)
70097a140dSpatrick     return error("no instr info info for target " + TripleName, Context), false;
71097a140dSpatrick 
72*d415bd75Srobert   MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
73097a140dSpatrick   if (!MCE)
74097a140dSpatrick     return error("no code emitter for target " + TripleName, Context), false;
75097a140dSpatrick 
76097a140dSpatrick   switch (OutFileType) {
77097a140dSpatrick   case OutputFileType::Assembly: {
78097a140dSpatrick     MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
79097a140dSpatrick                                          *MAI, *MII, *MRI);
80097a140dSpatrick     MS = TheTarget->createAsmStreamer(
81097a140dSpatrick         *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
82097a140dSpatrick         std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
83097a140dSpatrick         true);
84097a140dSpatrick     break;
85097a140dSpatrick   }
86097a140dSpatrick   case OutputFileType::Object: {
87097a140dSpatrick     MS = TheTarget->createMCObjectStreamer(
88097a140dSpatrick         TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
89097a140dSpatrick         MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
90097a140dSpatrick         *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
91097a140dSpatrick         /*DWARFMustBeAtTheEnd*/ false);
92097a140dSpatrick     break;
93097a140dSpatrick   }
94097a140dSpatrick   }
95097a140dSpatrick 
96097a140dSpatrick   if (!MS)
97097a140dSpatrick     return error("no object streamer for target " + TripleName, Context), false;
98097a140dSpatrick 
99097a140dSpatrick   // Finally create the AsmPrinter we'll use to emit the DIEs.
100097a140dSpatrick   TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
101*d415bd75Srobert                                           std::nullopt));
102097a140dSpatrick   if (!TM)
103097a140dSpatrick     return error("no target machine for target " + TripleName, Context), false;
104097a140dSpatrick 
105097a140dSpatrick   Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
106097a140dSpatrick   if (!Asm)
107097a140dSpatrick     return error("no asm printer for target " + TripleName, Context), false;
108*d415bd75Srobert   Asm->setDwarfUsesRelocationsAcrossSections(false);
109097a140dSpatrick 
110097a140dSpatrick   RangesSectionSize = 0;
111097a140dSpatrick   LocSectionSize = 0;
112097a140dSpatrick   LineSectionSize = 0;
113097a140dSpatrick   FrameSectionSize = 0;
114097a140dSpatrick   DebugInfoSectionSize = 0;
115*d415bd75Srobert   MacInfoSectionSize = 0;
116*d415bd75Srobert   MacroSectionSize = 0;
117097a140dSpatrick 
118097a140dSpatrick   return true;
119097a140dSpatrick }
120097a140dSpatrick 
finish()121*d415bd75Srobert void DwarfStreamer::finish() { MS->finish(); }
122097a140dSpatrick 
switchToDebugInfoSection(unsigned DwarfVersion)123097a140dSpatrick void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
124*d415bd75Srobert   MS->switchSection(MOFI->getDwarfInfoSection());
125097a140dSpatrick   MC->setDwarfVersion(DwarfVersion);
126097a140dSpatrick }
127097a140dSpatrick 
128097a140dSpatrick /// Emit the compilation unit header for \p Unit in the debug_info section.
129097a140dSpatrick ///
13073471bf0Spatrick /// A Dwarf 4 section header is encoded as:
131097a140dSpatrick ///  uint32_t   Unit length (omitting this field)
132097a140dSpatrick ///  uint16_t   Version
133097a140dSpatrick ///  uint32_t   Abbreviation table offset
134097a140dSpatrick ///  uint8_t    Address size
135097a140dSpatrick /// Leading to a total of 11 bytes.
13673471bf0Spatrick ///
13773471bf0Spatrick /// A Dwarf 5 section header is encoded as:
13873471bf0Spatrick ///  uint32_t   Unit length (omitting this field)
13973471bf0Spatrick ///  uint16_t   Version
14073471bf0Spatrick ///  uint8_t    Unit type
14173471bf0Spatrick ///  uint8_t    Address size
14273471bf0Spatrick ///  uint32_t   Abbreviation table offset
14373471bf0Spatrick /// Leading to a total of 12 bytes.
emitCompileUnitHeader(CompileUnit & Unit,unsigned DwarfVersion)14473471bf0Spatrick void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,
14573471bf0Spatrick                                           unsigned DwarfVersion) {
14673471bf0Spatrick   switchToDebugInfoSection(DwarfVersion);
147097a140dSpatrick 
148097a140dSpatrick   /// The start of the unit within its section.
149097a140dSpatrick   Unit.setLabelBegin(Asm->createTempSymbol("cu_begin"));
150097a140dSpatrick   Asm->OutStreamer->emitLabel(Unit.getLabelBegin());
151097a140dSpatrick 
152097a140dSpatrick   // Emit size of content not including length itself. The size has already
153097a140dSpatrick   // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
154097a140dSpatrick   // account for the length field.
155097a140dSpatrick   Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
15673471bf0Spatrick   Asm->emitInt16(DwarfVersion);
157097a140dSpatrick 
15873471bf0Spatrick   if (DwarfVersion >= 5) {
15973471bf0Spatrick     Asm->emitInt8(dwarf::DW_UT_compile);
16073471bf0Spatrick     Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
16173471bf0Spatrick     // We share one abbreviations table across all units so it's always at the
16273471bf0Spatrick     // start of the section.
16373471bf0Spatrick     Asm->emitInt32(0);
16473471bf0Spatrick     DebugInfoSectionSize += 12;
16573471bf0Spatrick   } else {
166097a140dSpatrick     // We share one abbreviations table across all units so it's always at the
167097a140dSpatrick     // start of the section.
168097a140dSpatrick     Asm->emitInt32(0);
169097a140dSpatrick     Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
170097a140dSpatrick     DebugInfoSectionSize += 11;
17173471bf0Spatrick   }
172097a140dSpatrick 
173097a140dSpatrick   // Remember this CU.
174097a140dSpatrick   EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});
175097a140dSpatrick }
176097a140dSpatrick 
177097a140dSpatrick /// Emit the \p Abbrevs array as the shared abbreviation table
178097a140dSpatrick /// for the linked Dwarf file.
emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> & Abbrevs,unsigned DwarfVersion)179097a140dSpatrick void DwarfStreamer::emitAbbrevs(
180097a140dSpatrick     const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
181097a140dSpatrick     unsigned DwarfVersion) {
182*d415bd75Srobert   MS->switchSection(MOFI->getDwarfAbbrevSection());
183097a140dSpatrick   MC->setDwarfVersion(DwarfVersion);
184097a140dSpatrick   Asm->emitDwarfAbbrevs(Abbrevs);
185097a140dSpatrick }
186097a140dSpatrick 
187097a140dSpatrick /// Recursively emit the DIE tree rooted at \p Die.
emitDIE(DIE & Die)188097a140dSpatrick void DwarfStreamer::emitDIE(DIE &Die) {
189*d415bd75Srobert   MS->switchSection(MOFI->getDwarfInfoSection());
190097a140dSpatrick   Asm->emitDwarfDIE(Die);
191097a140dSpatrick   DebugInfoSectionSize += Die.getSize();
192097a140dSpatrick }
193097a140dSpatrick 
194097a140dSpatrick /// Emit contents of section SecName From Obj.
emitSectionContents(StringRef SecData,StringRef SecName)195097a140dSpatrick void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) {
196097a140dSpatrick   MCSection *Section =
197097a140dSpatrick       StringSwitch<MCSection *>(SecName)
198097a140dSpatrick           .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
199097a140dSpatrick           .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
200097a140dSpatrick           .Case("debug_ranges",
201097a140dSpatrick                 MC->getObjectFileInfo()->getDwarfRangesSection())
202097a140dSpatrick           .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
203097a140dSpatrick           .Case("debug_aranges",
204097a140dSpatrick                 MC->getObjectFileInfo()->getDwarfARangesSection())
205097a140dSpatrick           .Default(nullptr);
206097a140dSpatrick 
207097a140dSpatrick   if (Section) {
208*d415bd75Srobert     MS->switchSection(Section);
209097a140dSpatrick 
210097a140dSpatrick     MS->emitBytes(SecData);
211097a140dSpatrick   }
212097a140dSpatrick }
213097a140dSpatrick 
214097a140dSpatrick /// Emit DIE containing warnings.
emitPaperTrailWarningsDie(DIE & Die)215097a140dSpatrick void DwarfStreamer::emitPaperTrailWarningsDie(DIE &Die) {
216097a140dSpatrick   switchToDebugInfoSection(/* Version */ 2);
217097a140dSpatrick   auto &Asm = getAsmPrinter();
218097a140dSpatrick   Asm.emitInt32(11 + Die.getSize() - 4);
219097a140dSpatrick   Asm.emitInt16(2);
220097a140dSpatrick   Asm.emitInt32(0);
22173471bf0Spatrick   Asm.emitInt8(MC->getTargetTriple().isArch64Bit() ? 8 : 4);
222097a140dSpatrick   DebugInfoSectionSize += 11;
223097a140dSpatrick   emitDIE(Die);
224097a140dSpatrick }
225097a140dSpatrick 
226097a140dSpatrick /// Emit the debug_str section stored in \p Pool.
emitStrings(const NonRelocatableStringpool & Pool)227097a140dSpatrick void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
228*d415bd75Srobert   Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
229097a140dSpatrick   std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
230097a140dSpatrick   for (auto Entry : Entries) {
231097a140dSpatrick     // Emit the string itself.
232097a140dSpatrick     Asm->OutStreamer->emitBytes(Entry.getString());
233097a140dSpatrick     // Emit a null terminator.
234097a140dSpatrick     Asm->emitInt8(0);
235097a140dSpatrick   }
23673471bf0Spatrick 
23773471bf0Spatrick #if 0
23873471bf0Spatrick   if (DwarfVersion >= 5) {
23973471bf0Spatrick     // Emit an empty string offset section.
240*d415bd75Srobert     Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());
24173471bf0Spatrick     Asm->emitDwarfUnitLength(4, "Length of String Offsets Set");
24273471bf0Spatrick     Asm->emitInt16(DwarfVersion);
24373471bf0Spatrick     Asm->emitInt16(0);
24473471bf0Spatrick   }
24573471bf0Spatrick #endif
246097a140dSpatrick }
247097a140dSpatrick 
emitDebugNames(AccelTable<DWARF5AccelTableStaticData> & Table)248097a140dSpatrick void DwarfStreamer::emitDebugNames(
249097a140dSpatrick     AccelTable<DWARF5AccelTableStaticData> &Table) {
250097a140dSpatrick   if (EmittedUnits.empty())
251097a140dSpatrick     return;
252097a140dSpatrick 
253097a140dSpatrick   // Build up data structures needed to emit this section.
254097a140dSpatrick   std::vector<MCSymbol *> CompUnits;
255097a140dSpatrick   DenseMap<unsigned, size_t> UniqueIdToCuMap;
256097a140dSpatrick   unsigned Id = 0;
257097a140dSpatrick   for (auto &CU : EmittedUnits) {
258097a140dSpatrick     CompUnits.push_back(CU.LabelBegin);
259097a140dSpatrick     // We might be omitting CUs, so we need to remap them.
260097a140dSpatrick     UniqueIdToCuMap[CU.ID] = Id++;
261097a140dSpatrick   }
262097a140dSpatrick 
263*d415bd75Srobert   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
264097a140dSpatrick   emitDWARF5AccelTable(
265097a140dSpatrick       Asm.get(), Table, CompUnits,
266097a140dSpatrick       [&UniqueIdToCuMap](const DWARF5AccelTableStaticData &Entry) {
267097a140dSpatrick         return UniqueIdToCuMap[Entry.getCUIndex()];
268097a140dSpatrick       });
269097a140dSpatrick }
270097a140dSpatrick 
emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> & Table)271097a140dSpatrick void DwarfStreamer::emitAppleNamespaces(
272097a140dSpatrick     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
273*d415bd75Srobert   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
274097a140dSpatrick   auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
275097a140dSpatrick   Asm->OutStreamer->emitLabel(SectionBegin);
276097a140dSpatrick   emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
277097a140dSpatrick }
278097a140dSpatrick 
emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> & Table)279097a140dSpatrick void DwarfStreamer::emitAppleNames(
280097a140dSpatrick     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
281*d415bd75Srobert   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
282097a140dSpatrick   auto *SectionBegin = Asm->createTempSymbol("names_begin");
283097a140dSpatrick   Asm->OutStreamer->emitLabel(SectionBegin);
284097a140dSpatrick   emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
285097a140dSpatrick }
286097a140dSpatrick 
emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> & Table)287097a140dSpatrick void DwarfStreamer::emitAppleObjc(
288097a140dSpatrick     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
289*d415bd75Srobert   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
290097a140dSpatrick   auto *SectionBegin = Asm->createTempSymbol("objc_begin");
291097a140dSpatrick   Asm->OutStreamer->emitLabel(SectionBegin);
292097a140dSpatrick   emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
293097a140dSpatrick }
294097a140dSpatrick 
emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> & Table)295097a140dSpatrick void DwarfStreamer::emitAppleTypes(
296097a140dSpatrick     AccelTable<AppleAccelTableStaticTypeData> &Table) {
297*d415bd75Srobert   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
298097a140dSpatrick   auto *SectionBegin = Asm->createTempSymbol("types_begin");
299097a140dSpatrick   Asm->OutStreamer->emitLabel(SectionBegin);
300097a140dSpatrick   emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
301097a140dSpatrick }
302097a140dSpatrick 
303097a140dSpatrick /// Emit the swift_ast section stored in \p Buffers.
emitSwiftAST(StringRef Buffer)304097a140dSpatrick void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
305097a140dSpatrick   MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
306097a140dSpatrick   SwiftASTSection->setAlignment(Align(32));
307*d415bd75Srobert   MS->switchSection(SwiftASTSection);
308097a140dSpatrick   MS->emitBytes(Buffer);
309097a140dSpatrick }
310097a140dSpatrick 
emitSwiftReflectionSection(llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,StringRef Buffer,uint32_t Alignment,uint32_t Size)311*d415bd75Srobert void DwarfStreamer::emitSwiftReflectionSection(
312*d415bd75Srobert     llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
313*d415bd75Srobert     StringRef Buffer, uint32_t Alignment, uint32_t Size) {
314*d415bd75Srobert   MCSection *ReflectionSection =
315*d415bd75Srobert       MOFI->getSwift5ReflectionSection(ReflSectionKind);
316*d415bd75Srobert   if (ReflectionSection == nullptr)
317*d415bd75Srobert     return;
318*d415bd75Srobert   ReflectionSection->setAlignment(Align(Alignment));
319*d415bd75Srobert   MS->switchSection(ReflectionSection);
320*d415bd75Srobert   MS->emitBytes(Buffer);
321097a140dSpatrick }
322097a140dSpatrick 
emitDwarfDebugArangesTable(const CompileUnit & Unit,const AddressRanges & LinkedRanges)323*d415bd75Srobert void DwarfStreamer::emitDwarfDebugArangesTable(
324*d415bd75Srobert     const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
325097a140dSpatrick   unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
326097a140dSpatrick 
327*d415bd75Srobert   // Make .debug_aranges to be current section.
328*d415bd75Srobert   MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
329097a140dSpatrick 
330*d415bd75Srobert   // Emit Header.
331097a140dSpatrick   MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
332097a140dSpatrick   MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
333097a140dSpatrick 
334097a140dSpatrick   unsigned HeaderSize =
335097a140dSpatrick       sizeof(int32_t) + // Size of contents (w/o this field
336097a140dSpatrick       sizeof(int16_t) + // DWARF ARange version number
337097a140dSpatrick       sizeof(int32_t) + // Offset of CU in the .debug_info section
338097a140dSpatrick       sizeof(int8_t) +  // Pointer Size (in bytes)
339097a140dSpatrick       sizeof(int8_t);   // Segment Size (in bytes)
340097a140dSpatrick 
341097a140dSpatrick   unsigned TupleSize = AddressSize * 2;
342097a140dSpatrick   unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
343097a140dSpatrick 
344097a140dSpatrick   Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
345097a140dSpatrick   Asm->OutStreamer->emitLabel(BeginLabel);
346097a140dSpatrick   Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
347097a140dSpatrick   Asm->emitInt32(Unit.getStartOffset());     // Corresponding unit's offset
348097a140dSpatrick   Asm->emitInt8(AddressSize);                // Address size
349097a140dSpatrick   Asm->emitInt8(0);                          // Segment size
350097a140dSpatrick 
351097a140dSpatrick   Asm->OutStreamer->emitFill(Padding, 0x0);
352097a140dSpatrick 
353*d415bd75Srobert   // Emit linked ranges.
354*d415bd75Srobert   for (const AddressRange &Range : LinkedRanges) {
355*d415bd75Srobert     MS->emitIntValue(Range.start(), AddressSize);
356*d415bd75Srobert     MS->emitIntValue(Range.end() - Range.start(), AddressSize);
357097a140dSpatrick   }
358097a140dSpatrick 
359*d415bd75Srobert   // Emit terminator.
360097a140dSpatrick   Asm->OutStreamer->emitIntValue(0, AddressSize);
361097a140dSpatrick   Asm->OutStreamer->emitIntValue(0, AddressSize);
362097a140dSpatrick   Asm->OutStreamer->emitLabel(EndLabel);
363097a140dSpatrick }
364097a140dSpatrick 
emitDwarfDebugRangesTableFragment(const CompileUnit & Unit,const AddressRanges & LinkedRanges)365*d415bd75Srobert void DwarfStreamer::emitDwarfDebugRangesTableFragment(
366*d415bd75Srobert     const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
367*d415bd75Srobert   unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
368097a140dSpatrick 
369*d415bd75Srobert   // Make .debug_ranges to be current section.
370*d415bd75Srobert   MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
371*d415bd75Srobert 
372*d415bd75Srobert   // Emit ranges.
373*d415bd75Srobert   uint64_t BaseAddress = 0;
374*d415bd75Srobert   if (std::optional<uint64_t> LowPC = Unit.getLowPc())
375*d415bd75Srobert     BaseAddress = *LowPC;
376*d415bd75Srobert 
377*d415bd75Srobert   for (const AddressRange &Range : LinkedRanges) {
378*d415bd75Srobert     MS->emitIntValue(Range.start() - BaseAddress, AddressSize);
379*d415bd75Srobert     MS->emitIntValue(Range.end() - BaseAddress, AddressSize);
380*d415bd75Srobert 
381*d415bd75Srobert     RangesSectionSize += AddressSize;
382*d415bd75Srobert     RangesSectionSize += AddressSize;
383097a140dSpatrick   }
384097a140dSpatrick 
385097a140dSpatrick   // Add the terminator entry.
386097a140dSpatrick   MS->emitIntValue(0, AddressSize);
387097a140dSpatrick   MS->emitIntValue(0, AddressSize);
388*d415bd75Srobert 
389*d415bd75Srobert   RangesSectionSize += AddressSize;
390*d415bd75Srobert   RangesSectionSize += AddressSize;
391*d415bd75Srobert }
392*d415bd75Srobert 
393*d415bd75Srobert /// Emit the debug_aranges contribution of a unit and
394*d415bd75Srobert /// if \p DoDebugRanges is true the debug_range contents for a
395*d415bd75Srobert /// compile_unit level DW_AT_ranges attribute (Which are basically the
396*d415bd75Srobert /// same thing with a different base address).
397*d415bd75Srobert /// Just aggregate all the ranges gathered inside that unit.
emitUnitRangesEntries(CompileUnit & Unit,bool DoDebugRanges)398*d415bd75Srobert void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
399*d415bd75Srobert                                           bool DoDebugRanges) {
400*d415bd75Srobert   const RangesTy &FunctionRanges = Unit.getFunctionRanges();
401*d415bd75Srobert 
402*d415bd75Srobert   // Linked addresses might end up in a different order.
403*d415bd75Srobert   // Build linked address ranges.
404*d415bd75Srobert   AddressRanges LinkedRanges;
405*d415bd75Srobert   for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++)
406*d415bd75Srobert     LinkedRanges.insert(
407*d415bd75Srobert         {FunctionRanges[Idx].first.start() + FunctionRanges[Idx].second,
408*d415bd75Srobert          FunctionRanges[Idx].first.end() + FunctionRanges[Idx].second});
409*d415bd75Srobert 
410*d415bd75Srobert   if (!FunctionRanges.empty())
411*d415bd75Srobert     emitDwarfDebugArangesTable(Unit, LinkedRanges);
412*d415bd75Srobert 
413*d415bd75Srobert   if (DoDebugRanges)
414*d415bd75Srobert     emitDwarfDebugRangesTableFragment(Unit, LinkedRanges);
415097a140dSpatrick }
416097a140dSpatrick 
417097a140dSpatrick /// Emit location lists for \p Unit and update attributes to point to the new
418097a140dSpatrick /// entries.
emitLocationsForUnit(const CompileUnit & Unit,DWARFContext & Dwarf,std::function<void (StringRef,SmallVectorImpl<uint8_t> &)> ProcessExpr)419097a140dSpatrick void DwarfStreamer::emitLocationsForUnit(
420097a140dSpatrick     const CompileUnit &Unit, DWARFContext &Dwarf,
421097a140dSpatrick     std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr) {
422097a140dSpatrick   const auto &Attributes = Unit.getLocationAttributes();
423097a140dSpatrick 
424097a140dSpatrick   if (Attributes.empty())
425097a140dSpatrick     return;
426097a140dSpatrick 
427*d415bd75Srobert   MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
428097a140dSpatrick 
429097a140dSpatrick   unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
430097a140dSpatrick   uint64_t BaseAddressMarker = (AddressSize == 8)
431097a140dSpatrick                                    ? std::numeric_limits<uint64_t>::max()
432097a140dSpatrick                                    : std::numeric_limits<uint32_t>::max();
433097a140dSpatrick   const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
434097a140dSpatrick   DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
435097a140dSpatrick   DWARFUnit &OrigUnit = Unit.getOrigUnit();
436097a140dSpatrick   auto OrigUnitDie = OrigUnit.getUnitDIE(false);
437097a140dSpatrick   int64_t UnitPcOffset = 0;
438*d415bd75Srobert   if (auto OrigLowPc =
439*d415bd75Srobert           dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) {
440*d415bd75Srobert     assert(Unit.getLowPc());
441*d415bd75Srobert     UnitPcOffset = int64_t(*OrigLowPc) - *Unit.getLowPc();
442*d415bd75Srobert   }
443097a140dSpatrick 
444097a140dSpatrick   SmallVector<uint8_t, 32> Buffer;
445097a140dSpatrick   for (const auto &Attr : Attributes) {
446097a140dSpatrick     uint64_t Offset = Attr.first.get();
447097a140dSpatrick     Attr.first.set(LocSectionSize);
448097a140dSpatrick     // This is the quantity to add to the old location address to get
449097a140dSpatrick     // the correct address for the new one.
450097a140dSpatrick     int64_t LocPcOffset = Attr.second + UnitPcOffset;
451097a140dSpatrick     while (Data.isValidOffset(Offset)) {
452097a140dSpatrick       uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
453097a140dSpatrick       uint64_t High = Data.getUnsigned(&Offset, AddressSize);
454097a140dSpatrick       LocSectionSize += 2 * AddressSize;
455097a140dSpatrick       // End of list entry.
456097a140dSpatrick       if (Low == 0 && High == 0) {
457097a140dSpatrick         Asm->OutStreamer->emitIntValue(0, AddressSize);
458097a140dSpatrick         Asm->OutStreamer->emitIntValue(0, AddressSize);
459097a140dSpatrick         break;
460097a140dSpatrick       }
461097a140dSpatrick       // Base address selection entry.
462097a140dSpatrick       if (Low == BaseAddressMarker) {
463097a140dSpatrick         Asm->OutStreamer->emitIntValue(BaseAddressMarker, AddressSize);
464097a140dSpatrick         Asm->OutStreamer->emitIntValue(High + Attr.second, AddressSize);
465097a140dSpatrick         LocPcOffset = 0;
466097a140dSpatrick         continue;
467097a140dSpatrick       }
468097a140dSpatrick       // Location list entry.
469097a140dSpatrick       Asm->OutStreamer->emitIntValue(Low + LocPcOffset, AddressSize);
470097a140dSpatrick       Asm->OutStreamer->emitIntValue(High + LocPcOffset, AddressSize);
471097a140dSpatrick       uint64_t Length = Data.getU16(&Offset);
472097a140dSpatrick       Asm->OutStreamer->emitIntValue(Length, 2);
473097a140dSpatrick       // Copy the bytes into to the buffer, process them, emit them.
474097a140dSpatrick       Buffer.reserve(Length);
475097a140dSpatrick       Buffer.resize(0);
476097a140dSpatrick       StringRef Input = InputSec.Data.substr(Offset, Length);
477097a140dSpatrick       ProcessExpr(Input, Buffer);
478097a140dSpatrick       Asm->OutStreamer->emitBytes(
479097a140dSpatrick           StringRef((const char *)Buffer.data(), Length));
480097a140dSpatrick       Offset += Length;
481097a140dSpatrick       LocSectionSize += Length + 2;
482097a140dSpatrick     }
483097a140dSpatrick   }
484097a140dSpatrick }
485097a140dSpatrick 
emitLineTableForUnit(MCDwarfLineTableParams Params,StringRef PrologueBytes,unsigned MinInstLength,std::vector<DWARFDebugLine::Row> & Rows,unsigned PointerSize)486097a140dSpatrick void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
487097a140dSpatrick                                          StringRef PrologueBytes,
488097a140dSpatrick                                          unsigned MinInstLength,
489097a140dSpatrick                                          std::vector<DWARFDebugLine::Row> &Rows,
490097a140dSpatrick                                          unsigned PointerSize) {
491097a140dSpatrick   // Switch to the section where the table will be emitted into.
492*d415bd75Srobert   MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
493097a140dSpatrick   MCSymbol *LineStartSym = MC->createTempSymbol();
494097a140dSpatrick   MCSymbol *LineEndSym = MC->createTempSymbol();
495097a140dSpatrick 
496097a140dSpatrick   // The first 4 bytes is the total length of the information for this
497097a140dSpatrick   // compilation unit (not including these 4 bytes for the length).
498097a140dSpatrick   Asm->emitLabelDifference(LineEndSym, LineStartSym, 4);
499097a140dSpatrick   Asm->OutStreamer->emitLabel(LineStartSym);
500097a140dSpatrick   // Copy Prologue.
501097a140dSpatrick   MS->emitBytes(PrologueBytes);
502097a140dSpatrick   LineSectionSize += PrologueBytes.size() + 4;
503097a140dSpatrick 
504097a140dSpatrick   SmallString<128> EncodingBuffer;
505097a140dSpatrick   raw_svector_ostream EncodingOS(EncodingBuffer);
506097a140dSpatrick 
507097a140dSpatrick   if (Rows.empty()) {
508097a140dSpatrick     // We only have the dummy entry, dsymutil emits an entry with a 0
509097a140dSpatrick     // address in that case.
510097a140dSpatrick     MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
511097a140dSpatrick                             EncodingOS);
512097a140dSpatrick     MS->emitBytes(EncodingOS.str());
513097a140dSpatrick     LineSectionSize += EncodingBuffer.size();
514097a140dSpatrick     MS->emitLabel(LineEndSym);
515097a140dSpatrick     return;
516097a140dSpatrick   }
517097a140dSpatrick 
518097a140dSpatrick   // Line table state machine fields
519097a140dSpatrick   unsigned FileNum = 1;
520097a140dSpatrick   unsigned LastLine = 1;
521097a140dSpatrick   unsigned Column = 0;
522097a140dSpatrick   unsigned IsStatement = 1;
523097a140dSpatrick   unsigned Isa = 0;
524097a140dSpatrick   uint64_t Address = -1ULL;
525097a140dSpatrick 
526097a140dSpatrick   unsigned RowsSinceLastSequence = 0;
527097a140dSpatrick 
528*d415bd75Srobert   for (DWARFDebugLine::Row &Row : Rows) {
529097a140dSpatrick     int64_t AddressDelta;
530097a140dSpatrick     if (Address == -1ULL) {
531097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
532097a140dSpatrick       MS->emitULEB128IntValue(PointerSize + 1);
533097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNE_set_address, 1);
534097a140dSpatrick       MS->emitIntValue(Row.Address.Address, PointerSize);
535097a140dSpatrick       LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1);
536097a140dSpatrick       AddressDelta = 0;
537097a140dSpatrick     } else {
538097a140dSpatrick       AddressDelta = (Row.Address.Address - Address) / MinInstLength;
539097a140dSpatrick     }
540097a140dSpatrick 
541097a140dSpatrick     // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
542097a140dSpatrick     // We should find a way to share this code, but the current compatibility
543097a140dSpatrick     // requirement with classic dsymutil makes it hard. Revisit that once this
544097a140dSpatrick     // requirement is dropped.
545097a140dSpatrick 
546097a140dSpatrick     if (FileNum != Row.File) {
547097a140dSpatrick       FileNum = Row.File;
548097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_set_file, 1);
549097a140dSpatrick       MS->emitULEB128IntValue(FileNum);
550097a140dSpatrick       LineSectionSize += 1 + getULEB128Size(FileNum);
551097a140dSpatrick     }
552097a140dSpatrick     if (Column != Row.Column) {
553097a140dSpatrick       Column = Row.Column;
554097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_set_column, 1);
555097a140dSpatrick       MS->emitULEB128IntValue(Column);
556097a140dSpatrick       LineSectionSize += 1 + getULEB128Size(Column);
557097a140dSpatrick     }
558097a140dSpatrick 
559097a140dSpatrick     // FIXME: We should handle the discriminator here, but dsymutil doesn't
560097a140dSpatrick     // consider it, thus ignore it for now.
561097a140dSpatrick 
562097a140dSpatrick     if (Isa != Row.Isa) {
563097a140dSpatrick       Isa = Row.Isa;
564097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);
565097a140dSpatrick       MS->emitULEB128IntValue(Isa);
566097a140dSpatrick       LineSectionSize += 1 + getULEB128Size(Isa);
567097a140dSpatrick     }
568097a140dSpatrick     if (IsStatement != Row.IsStmt) {
569097a140dSpatrick       IsStatement = Row.IsStmt;
570097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);
571097a140dSpatrick       LineSectionSize += 1;
572097a140dSpatrick     }
573097a140dSpatrick     if (Row.BasicBlock) {
574097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);
575097a140dSpatrick       LineSectionSize += 1;
576097a140dSpatrick     }
577097a140dSpatrick 
578097a140dSpatrick     if (Row.PrologueEnd) {
579097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
580097a140dSpatrick       LineSectionSize += 1;
581097a140dSpatrick     }
582097a140dSpatrick 
583097a140dSpatrick     if (Row.EpilogueBegin) {
584097a140dSpatrick       MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
585097a140dSpatrick       LineSectionSize += 1;
586097a140dSpatrick     }
587097a140dSpatrick 
588097a140dSpatrick     int64_t LineDelta = int64_t(Row.Line) - LastLine;
589097a140dSpatrick     if (!Row.EndSequence) {
590097a140dSpatrick       MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS);
591097a140dSpatrick       MS->emitBytes(EncodingOS.str());
592097a140dSpatrick       LineSectionSize += EncodingBuffer.size();
593097a140dSpatrick       EncodingBuffer.resize(0);
594097a140dSpatrick       Address = Row.Address.Address;
595097a140dSpatrick       LastLine = Row.Line;
596097a140dSpatrick       RowsSinceLastSequence++;
597097a140dSpatrick     } else {
598097a140dSpatrick       if (LineDelta) {
599097a140dSpatrick         MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);
600097a140dSpatrick         MS->emitSLEB128IntValue(LineDelta);
601097a140dSpatrick         LineSectionSize += 1 + getSLEB128Size(LineDelta);
602097a140dSpatrick       }
603097a140dSpatrick       if (AddressDelta) {
604097a140dSpatrick         MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);
605097a140dSpatrick         MS->emitULEB128IntValue(AddressDelta);
606097a140dSpatrick         LineSectionSize += 1 + getULEB128Size(AddressDelta);
607097a140dSpatrick       }
608097a140dSpatrick       MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(),
609097a140dSpatrick                               0, EncodingOS);
610097a140dSpatrick       MS->emitBytes(EncodingOS.str());
611097a140dSpatrick       LineSectionSize += EncodingBuffer.size();
612097a140dSpatrick       EncodingBuffer.resize(0);
613097a140dSpatrick       Address = -1ULL;
614097a140dSpatrick       LastLine = FileNum = IsStatement = 1;
615097a140dSpatrick       RowsSinceLastSequence = Column = Isa = 0;
616097a140dSpatrick     }
617097a140dSpatrick   }
618097a140dSpatrick 
619097a140dSpatrick   if (RowsSinceLastSequence) {
620097a140dSpatrick     MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
621097a140dSpatrick                             EncodingOS);
622097a140dSpatrick     MS->emitBytes(EncodingOS.str());
623097a140dSpatrick     LineSectionSize += EncodingBuffer.size();
624097a140dSpatrick     EncodingBuffer.resize(0);
625097a140dSpatrick   }
626097a140dSpatrick 
627097a140dSpatrick   MS->emitLabel(LineEndSym);
628097a140dSpatrick }
629097a140dSpatrick 
630097a140dSpatrick /// Copy the debug_line over to the updated binary while unobfuscating the file
631097a140dSpatrick /// names and directories.
translateLineTable(DataExtractor Data,uint64_t Offset)632097a140dSpatrick void DwarfStreamer::translateLineTable(DataExtractor Data, uint64_t Offset) {
633*d415bd75Srobert   MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
634097a140dSpatrick   StringRef Contents = Data.getData();
635097a140dSpatrick 
636097a140dSpatrick   // We have to deconstruct the line table header, because it contains to
637097a140dSpatrick   // length fields that will need to be updated when we change the length of
638097a140dSpatrick   // the files and directories in there.
639097a140dSpatrick   unsigned UnitLength = Data.getU32(&Offset);
640097a140dSpatrick   uint64_t UnitEnd = Offset + UnitLength;
641097a140dSpatrick   MCSymbol *BeginLabel = MC->createTempSymbol();
642097a140dSpatrick   MCSymbol *EndLabel = MC->createTempSymbol();
643097a140dSpatrick   unsigned Version = Data.getU16(&Offset);
644097a140dSpatrick 
645097a140dSpatrick   if (Version > 5) {
646097a140dSpatrick     warn("Unsupported line table version: dropping contents and not "
647097a140dSpatrick          "unobfsucating line table.");
648097a140dSpatrick     return;
649097a140dSpatrick   }
650097a140dSpatrick 
651097a140dSpatrick   Asm->emitLabelDifference(EndLabel, BeginLabel, 4);
652097a140dSpatrick   Asm->OutStreamer->emitLabel(BeginLabel);
653097a140dSpatrick   Asm->emitInt16(Version);
654097a140dSpatrick   LineSectionSize += 6;
655097a140dSpatrick 
656097a140dSpatrick   MCSymbol *HeaderBeginLabel = MC->createTempSymbol();
657097a140dSpatrick   MCSymbol *HeaderEndLabel = MC->createTempSymbol();
658097a140dSpatrick   Asm->emitLabelDifference(HeaderEndLabel, HeaderBeginLabel, 4);
659097a140dSpatrick   Asm->OutStreamer->emitLabel(HeaderBeginLabel);
660097a140dSpatrick   Offset += 4;
661097a140dSpatrick   LineSectionSize += 4;
662097a140dSpatrick 
663097a140dSpatrick   uint64_t AfterHeaderLengthOffset = Offset;
664097a140dSpatrick   // Skip to the directories.
665097a140dSpatrick   Offset += (Version >= 4) ? 5 : 4;
666097a140dSpatrick   unsigned OpcodeBase = Data.getU8(&Offset);
667097a140dSpatrick   Offset += OpcodeBase - 1;
668097a140dSpatrick   Asm->OutStreamer->emitBytes(Contents.slice(AfterHeaderLengthOffset, Offset));
669097a140dSpatrick   LineSectionSize += Offset - AfterHeaderLengthOffset;
670097a140dSpatrick 
671097a140dSpatrick   // Offset points to the first directory.
672097a140dSpatrick   while (const char *Dir = Data.getCStr(&Offset)) {
673097a140dSpatrick     if (Dir[0] == 0)
674097a140dSpatrick       break;
675097a140dSpatrick 
676097a140dSpatrick     StringRef Translated = Translator(Dir);
677097a140dSpatrick     Asm->OutStreamer->emitBytes(Translated);
678097a140dSpatrick     Asm->emitInt8(0);
679097a140dSpatrick     LineSectionSize += Translated.size() + 1;
680097a140dSpatrick   }
681097a140dSpatrick   Asm->emitInt8(0);
682097a140dSpatrick   LineSectionSize += 1;
683097a140dSpatrick 
684097a140dSpatrick   while (const char *File = Data.getCStr(&Offset)) {
685097a140dSpatrick     if (File[0] == 0)
686097a140dSpatrick       break;
687097a140dSpatrick 
688097a140dSpatrick     StringRef Translated = Translator(File);
689097a140dSpatrick     Asm->OutStreamer->emitBytes(Translated);
690097a140dSpatrick     Asm->emitInt8(0);
691097a140dSpatrick     LineSectionSize += Translated.size() + 1;
692097a140dSpatrick 
693097a140dSpatrick     uint64_t OffsetBeforeLEBs = Offset;
694097a140dSpatrick     Asm->emitULEB128(Data.getULEB128(&Offset));
695097a140dSpatrick     Asm->emitULEB128(Data.getULEB128(&Offset));
696097a140dSpatrick     Asm->emitULEB128(Data.getULEB128(&Offset));
697097a140dSpatrick     LineSectionSize += Offset - OffsetBeforeLEBs;
698097a140dSpatrick   }
699097a140dSpatrick   Asm->emitInt8(0);
700097a140dSpatrick   LineSectionSize += 1;
701097a140dSpatrick 
702097a140dSpatrick   Asm->OutStreamer->emitLabel(HeaderEndLabel);
703097a140dSpatrick 
704097a140dSpatrick   // Copy the actual line table program over.
705097a140dSpatrick   Asm->OutStreamer->emitBytes(Contents.slice(Offset, UnitEnd));
706097a140dSpatrick   LineSectionSize += UnitEnd - Offset;
707097a140dSpatrick 
708097a140dSpatrick   Asm->OutStreamer->emitLabel(EndLabel);
709097a140dSpatrick   Offset = UnitEnd;
710097a140dSpatrick }
711097a140dSpatrick 
712097a140dSpatrick /// Emit the pubnames or pubtypes section contribution for \p
713097a140dSpatrick /// 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)714097a140dSpatrick void DwarfStreamer::emitPubSectionForUnit(
715097a140dSpatrick     MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
716097a140dSpatrick     const std::vector<CompileUnit::AccelInfo> &Names) {
717097a140dSpatrick   if (Names.empty())
718097a140dSpatrick     return;
719097a140dSpatrick 
720097a140dSpatrick   // Start the dwarf pubnames section.
721*d415bd75Srobert   Asm->OutStreamer->switchSection(Sec);
722097a140dSpatrick   MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
723097a140dSpatrick   MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");
724097a140dSpatrick 
725097a140dSpatrick   bool HeaderEmitted = false;
726097a140dSpatrick   // Emit the pubnames for this compilation unit.
727097a140dSpatrick   for (const auto &Name : Names) {
728097a140dSpatrick     if (Name.SkipPubSection)
729097a140dSpatrick       continue;
730097a140dSpatrick 
731097a140dSpatrick     if (!HeaderEmitted) {
732097a140dSpatrick       // Emit the header.
733097a140dSpatrick       Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length
734097a140dSpatrick       Asm->OutStreamer->emitLabel(BeginLabel);
735097a140dSpatrick       Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
736097a140dSpatrick       Asm->emitInt32(Unit.getStartOffset());      // Unit offset
737097a140dSpatrick       Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
738097a140dSpatrick       HeaderEmitted = true;
739097a140dSpatrick     }
740097a140dSpatrick     Asm->emitInt32(Name.Die->getOffset());
741097a140dSpatrick 
742097a140dSpatrick     // Emit the string itself.
743097a140dSpatrick     Asm->OutStreamer->emitBytes(Name.Name.getString());
744097a140dSpatrick     // Emit a null terminator.
745097a140dSpatrick     Asm->emitInt8(0);
746097a140dSpatrick   }
747097a140dSpatrick 
748097a140dSpatrick   if (!HeaderEmitted)
749097a140dSpatrick     return;
750097a140dSpatrick   Asm->emitInt32(0); // End marker.
751097a140dSpatrick   Asm->OutStreamer->emitLabel(EndLabel);
752097a140dSpatrick }
753097a140dSpatrick 
754097a140dSpatrick /// Emit .debug_pubnames for \p Unit.
emitPubNamesForUnit(const CompileUnit & Unit)755097a140dSpatrick void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
756097a140dSpatrick   emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
757097a140dSpatrick                         "names", Unit, Unit.getPubnames());
758097a140dSpatrick }
759097a140dSpatrick 
760097a140dSpatrick /// Emit .debug_pubtypes for \p Unit.
emitPubTypesForUnit(const CompileUnit & Unit)761097a140dSpatrick void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
762097a140dSpatrick   emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
763097a140dSpatrick                         "types", Unit, Unit.getPubtypes());
764097a140dSpatrick }
765097a140dSpatrick 
766097a140dSpatrick /// Emit a CIE into the debug_frame section.
emitCIE(StringRef CIEBytes)767097a140dSpatrick void DwarfStreamer::emitCIE(StringRef CIEBytes) {
768*d415bd75Srobert   MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
769097a140dSpatrick 
770097a140dSpatrick   MS->emitBytes(CIEBytes);
771097a140dSpatrick   FrameSectionSize += CIEBytes.size();
772097a140dSpatrick }
773097a140dSpatrick 
774097a140dSpatrick /// Emit a FDE into the debug_frame section. \p FDEBytes
775097a140dSpatrick /// contains the FDE data without the length, CIE offset and address
776097a140dSpatrick /// which will be replaced with the parameter values.
emitFDE(uint32_t CIEOffset,uint32_t AddrSize,uint64_t Address,StringRef FDEBytes)777097a140dSpatrick void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
778*d415bd75Srobert                             uint64_t Address, StringRef FDEBytes) {
779*d415bd75Srobert   MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
780097a140dSpatrick 
781097a140dSpatrick   MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
782097a140dSpatrick   MS->emitIntValue(CIEOffset, 4);
783097a140dSpatrick   MS->emitIntValue(Address, AddrSize);
784097a140dSpatrick   MS->emitBytes(FDEBytes);
785097a140dSpatrick   FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
786097a140dSpatrick }
787097a140dSpatrick 
emitMacroTables(DWARFContext * Context,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool)788*d415bd75Srobert void DwarfStreamer::emitMacroTables(DWARFContext *Context,
789*d415bd75Srobert                                     const Offset2UnitMap &UnitMacroMap,
790*d415bd75Srobert                                     OffsetsStringPool &StringPool) {
791*d415bd75Srobert   assert(Context != nullptr && "Empty DWARF context");
792*d415bd75Srobert 
793*d415bd75Srobert   // Check for .debug_macinfo table.
794*d415bd75Srobert   if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) {
795*d415bd75Srobert     MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());
796*d415bd75Srobert     emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize);
797*d415bd75Srobert   }
798*d415bd75Srobert 
799*d415bd75Srobert   // Check for .debug_macro table.
800*d415bd75Srobert   if (const DWARFDebugMacro *Table = Context->getDebugMacro()) {
801*d415bd75Srobert     MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());
802*d415bd75Srobert     emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize);
803*d415bd75Srobert   }
804*d415bd75Srobert }
805*d415bd75Srobert 
emitMacroTableImpl(const DWARFDebugMacro * MacroTable,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool,uint64_t & OutOffset)806*d415bd75Srobert void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
807*d415bd75Srobert                                        const Offset2UnitMap &UnitMacroMap,
808*d415bd75Srobert                                        OffsetsStringPool &StringPool,
809*d415bd75Srobert                                        uint64_t &OutOffset) {
810*d415bd75Srobert   bool DefAttributeIsReported = false;
811*d415bd75Srobert   bool UndefAttributeIsReported = false;
812*d415bd75Srobert   bool ImportAttributeIsReported = false;
813*d415bd75Srobert   for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
814*d415bd75Srobert     Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset);
815*d415bd75Srobert     if (UnitIt == UnitMacroMap.end()) {
816*d415bd75Srobert       warn(formatv(
817*d415bd75Srobert           "couldn`t find compile unit for the macro table with offset = {0:x}",
818*d415bd75Srobert           List.Offset));
819*d415bd75Srobert       continue;
820*d415bd75Srobert     }
821*d415bd75Srobert 
822*d415bd75Srobert     // Skip macro table if the unit was not cloned.
823*d415bd75Srobert     DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();
824*d415bd75Srobert     if (OutputUnitDIE == nullptr)
825*d415bd75Srobert       continue;
826*d415bd75Srobert 
827*d415bd75Srobert     // Update macro attribute of cloned compile unit with the proper offset to
828*d415bd75Srobert     // the macro table.
829*d415bd75Srobert     bool hasDWARFv5Header = false;
830*d415bd75Srobert     for (auto &V : OutputUnitDIE->values()) {
831*d415bd75Srobert       if (V.getAttribute() == dwarf::DW_AT_macro_info) {
832*d415bd75Srobert         V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
833*d415bd75Srobert         break;
834*d415bd75Srobert       } else if (V.getAttribute() == dwarf::DW_AT_macros) {
835*d415bd75Srobert         hasDWARFv5Header = true;
836*d415bd75Srobert         V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
837*d415bd75Srobert         break;
838*d415bd75Srobert       }
839*d415bd75Srobert     }
840*d415bd75Srobert 
841*d415bd75Srobert     // Write DWARFv5 header.
842*d415bd75Srobert     if (hasDWARFv5Header) {
843*d415bd75Srobert       // Write header version.
844*d415bd75Srobert       MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version));
845*d415bd75Srobert       OutOffset += sizeof(List.Header.Version);
846*d415bd75Srobert 
847*d415bd75Srobert       uint8_t Flags = List.Header.Flags;
848*d415bd75Srobert 
849*d415bd75Srobert       // Check for OPCODE_OPERANDS_TABLE.
850*d415bd75Srobert       if (Flags &
851*d415bd75Srobert           DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
852*d415bd75Srobert         Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
853*d415bd75Srobert         warn("opcode_operands_table is not supported yet.");
854*d415bd75Srobert       }
855*d415bd75Srobert 
856*d415bd75Srobert       // Check for DEBUG_LINE_OFFSET.
857*d415bd75Srobert       std::optional<uint64_t> StmtListOffset;
858*d415bd75Srobert       if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
859*d415bd75Srobert         // Get offset to the line table from the cloned compile unit.
860*d415bd75Srobert         for (auto &V : OutputUnitDIE->values()) {
861*d415bd75Srobert           if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
862*d415bd75Srobert             StmtListOffset = V.getDIEInteger().getValue();
863*d415bd75Srobert             break;
864*d415bd75Srobert           }
865*d415bd75Srobert         }
866*d415bd75Srobert 
867*d415bd75Srobert         if (!StmtListOffset) {
868*d415bd75Srobert           Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
869*d415bd75Srobert           warn("couldn`t find line table for macro table.");
870*d415bd75Srobert         }
871*d415bd75Srobert       }
872*d415bd75Srobert 
873*d415bd75Srobert       // Write flags.
874*d415bd75Srobert       MS->emitIntValue(Flags, sizeof(Flags));
875*d415bd75Srobert       OutOffset += sizeof(Flags);
876*d415bd75Srobert 
877*d415bd75Srobert       // Write offset to line table.
878*d415bd75Srobert       if (StmtListOffset) {
879*d415bd75Srobert         MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize());
880*d415bd75Srobert         OutOffset += List.Header.getOffsetByteSize();
881*d415bd75Srobert       }
882*d415bd75Srobert     }
883*d415bd75Srobert 
884*d415bd75Srobert     // Write macro entries.
885*d415bd75Srobert     for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
886*d415bd75Srobert       if (MacroEntry.Type == 0) {
887*d415bd75Srobert         OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);
888*d415bd75Srobert         continue;
889*d415bd75Srobert       }
890*d415bd75Srobert 
891*d415bd75Srobert       uint8_t MacroType = MacroEntry.Type;
892*d415bd75Srobert       switch (MacroType) {
893*d415bd75Srobert       default: {
894*d415bd75Srobert         bool HasVendorSpecificExtension =
895*d415bd75Srobert             (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) ||
896*d415bd75Srobert             (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
897*d415bd75Srobert                                   MacroType <= dwarf::DW_MACRO_hi_user));
898*d415bd75Srobert 
899*d415bd75Srobert         if (HasVendorSpecificExtension) {
900*d415bd75Srobert           // Write macinfo type.
901*d415bd75Srobert           MS->emitIntValue(MacroType, 1);
902*d415bd75Srobert           OutOffset++;
903*d415bd75Srobert 
904*d415bd75Srobert           // Write vendor extension constant.
905*d415bd75Srobert           OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);
906*d415bd75Srobert 
907*d415bd75Srobert           // Write vendor extension string.
908*d415bd75Srobert           StringRef String = MacroEntry.ExtStr;
909*d415bd75Srobert           MS->emitBytes(String);
910*d415bd75Srobert           MS->emitIntValue(0, 1);
911*d415bd75Srobert           OutOffset += String.size() + 1;
912*d415bd75Srobert         } else
913*d415bd75Srobert           warn("unknown macro type. skip.");
914*d415bd75Srobert       } break;
915*d415bd75Srobert       // debug_macro and debug_macinfo share some common encodings.
916*d415bd75Srobert       // DW_MACRO_define     == DW_MACINFO_define
917*d415bd75Srobert       // DW_MACRO_undef      == DW_MACINFO_undef
918*d415bd75Srobert       // DW_MACRO_start_file == DW_MACINFO_start_file
919*d415bd75Srobert       // DW_MACRO_end_file   == DW_MACINFO_end_file
920*d415bd75Srobert       // For readibility/uniformity we are using DW_MACRO_*.
921*d415bd75Srobert       case dwarf::DW_MACRO_define:
922*d415bd75Srobert       case dwarf::DW_MACRO_undef: {
923*d415bd75Srobert         // Write macinfo type.
924*d415bd75Srobert         MS->emitIntValue(MacroType, 1);
925*d415bd75Srobert         OutOffset++;
926*d415bd75Srobert 
927*d415bd75Srobert         // Write source line.
928*d415bd75Srobert         OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
929*d415bd75Srobert 
930*d415bd75Srobert         // Write macro string.
931*d415bd75Srobert         StringRef String = MacroEntry.MacroStr;
932*d415bd75Srobert         MS->emitBytes(String);
933*d415bd75Srobert         MS->emitIntValue(0, 1);
934*d415bd75Srobert         OutOffset += String.size() + 1;
935*d415bd75Srobert       } break;
936*d415bd75Srobert       case dwarf::DW_MACRO_define_strp:
937*d415bd75Srobert       case dwarf::DW_MACRO_undef_strp:
938*d415bd75Srobert       case dwarf::DW_MACRO_define_strx:
939*d415bd75Srobert       case dwarf::DW_MACRO_undef_strx: {
940*d415bd75Srobert         assert(UnitIt->second->getOrigUnit().getVersion() >= 5);
941*d415bd75Srobert 
942*d415bd75Srobert         // DW_MACRO_*_strx forms are not supported currently.
943*d415bd75Srobert         // Convert to *_strp.
944*d415bd75Srobert         switch (MacroType) {
945*d415bd75Srobert         case dwarf::DW_MACRO_define_strx: {
946*d415bd75Srobert           MacroType = dwarf::DW_MACRO_define_strp;
947*d415bd75Srobert           if (!DefAttributeIsReported) {
948*d415bd75Srobert             warn("DW_MACRO_define_strx unsupported yet. Convert to "
949*d415bd75Srobert                  "DW_MACRO_define_strp.");
950*d415bd75Srobert             DefAttributeIsReported = true;
951*d415bd75Srobert           }
952*d415bd75Srobert         } break;
953*d415bd75Srobert         case dwarf::DW_MACRO_undef_strx: {
954*d415bd75Srobert           MacroType = dwarf::DW_MACRO_undef_strp;
955*d415bd75Srobert           if (!UndefAttributeIsReported) {
956*d415bd75Srobert             warn("DW_MACRO_undef_strx unsupported yet. Convert to "
957*d415bd75Srobert                  "DW_MACRO_undef_strp.");
958*d415bd75Srobert             UndefAttributeIsReported = true;
959*d415bd75Srobert           }
960*d415bd75Srobert         } break;
961*d415bd75Srobert         default:
962*d415bd75Srobert           // Nothing to do.
963*d415bd75Srobert           break;
964*d415bd75Srobert         }
965*d415bd75Srobert 
966*d415bd75Srobert         // Write macinfo type.
967*d415bd75Srobert         MS->emitIntValue(MacroType, 1);
968*d415bd75Srobert         OutOffset++;
969*d415bd75Srobert 
970*d415bd75Srobert         // Write source line.
971*d415bd75Srobert         OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
972*d415bd75Srobert 
973*d415bd75Srobert         // Write macro string.
974*d415bd75Srobert         DwarfStringPoolEntryRef EntryRef =
975*d415bd75Srobert             StringPool.getEntry(MacroEntry.MacroStr);
976*d415bd75Srobert         MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize());
977*d415bd75Srobert         OutOffset += List.Header.getOffsetByteSize();
978*d415bd75Srobert         break;
979*d415bd75Srobert       }
980*d415bd75Srobert       case dwarf::DW_MACRO_start_file: {
981*d415bd75Srobert         // Write macinfo type.
982*d415bd75Srobert         MS->emitIntValue(MacroType, 1);
983*d415bd75Srobert         OutOffset++;
984*d415bd75Srobert         // Write source line.
985*d415bd75Srobert         OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
986*d415bd75Srobert         // Write source file id.
987*d415bd75Srobert         OutOffset += MS->emitULEB128IntValue(MacroEntry.File);
988*d415bd75Srobert       } break;
989*d415bd75Srobert       case dwarf::DW_MACRO_end_file: {
990*d415bd75Srobert         // Write macinfo type.
991*d415bd75Srobert         MS->emitIntValue(MacroType, 1);
992*d415bd75Srobert         OutOffset++;
993*d415bd75Srobert       } break;
994*d415bd75Srobert       case dwarf::DW_MACRO_import:
995*d415bd75Srobert       case dwarf::DW_MACRO_import_sup: {
996*d415bd75Srobert         if (!ImportAttributeIsReported) {
997*d415bd75Srobert           warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "
998*d415bd75Srobert                "remove.");
999*d415bd75Srobert           ImportAttributeIsReported = true;
1000*d415bd75Srobert         }
1001*d415bd75Srobert       } break;
1002*d415bd75Srobert       }
1003*d415bd75Srobert     }
1004*d415bd75Srobert   }
1005*d415bd75Srobert }
1006*d415bd75Srobert 
1007097a140dSpatrick } // namespace llvm
1008