1 //===- DwarfStreamer.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/DWARFLinker/DWARFStreamer.h"
10 #include "llvm/ADT/Triple.h"
11 #include "llvm/CodeGen/NonRelocatableStringpool.h"
12 #include "llvm/DWARFLinker/DWARFLinkerCompileUnit.h"
13 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
15 #include "llvm/MC/MCAsmBackend.h"
16 #include "llvm/MC/MCCodeEmitter.h"
17 #include "llvm/MC/MCDwarf.h"
18 #include "llvm/MC/MCObjectWriter.h"
19 #include "llvm/MC/MCSection.h"
20 #include "llvm/MC/MCStreamer.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/MC/MCTargetOptions.h"
23 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
24 #include "llvm/MC/TargetRegistry.h"
25 #include "llvm/Support/FormatVariadic.h"
26 #include "llvm/Support/LEB128.h"
27 #include "llvm/Target/TargetOptions.h"
28 
29 namespace llvm {
30 
init(Triple TheTriple,StringRef Swift5ReflectionSegmentName)31 bool DwarfStreamer::init(Triple TheTriple,
32                          StringRef Swift5ReflectionSegmentName) {
33   std::string ErrorStr;
34   std::string TripleName;
35   StringRef Context = "dwarf streamer init";
36 
37   // Get the target.
38   const Target *TheTarget =
39       TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
40   if (!TheTarget)
41     return error(ErrorStr, Context), false;
42   TripleName = TheTriple.getTriple();
43 
44   // Create all the MC Objects.
45   MRI.reset(TheTarget->createMCRegInfo(TripleName));
46   if (!MRI)
47     return error(Twine("no register info for target ") + TripleName, Context),
48            false;
49 
50   MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
51   MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
52   if (!MAI)
53     return error("no asm info for target " + TripleName, Context), false;
54 
55   MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
56   if (!MSTI)
57     return error("no subtarget info for target " + TripleName, Context), false;
58 
59   MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get(), nullptr,
60                          nullptr, true, Swift5ReflectionSegmentName));
61   MOFI.reset(TheTarget->createMCObjectFileInfo(*MC, /*PIC=*/false, false));
62   MC->setObjectFileInfo(MOFI.get());
63 
64   MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
65   if (!MAB)
66     return error("no asm backend for target " + TripleName, Context), false;
67 
68   MII.reset(TheTarget->createMCInstrInfo());
69   if (!MII)
70     return error("no instr info info for target " + TripleName, Context), false;
71 
72   MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
73   if (!MCE)
74     return error("no code emitter for target " + TripleName, Context), false;
75 
76   switch (OutFileType) {
77   case OutputFileType::Assembly: {
78     MIP = TheTarget->createMCInstPrinter(TheTriple, MAI->getAssemblerDialect(),
79                                          *MAI, *MII, *MRI);
80     MS = TheTarget->createAsmStreamer(
81         *MC, std::make_unique<formatted_raw_ostream>(OutFile), true, true, MIP,
82         std::unique_ptr<MCCodeEmitter>(MCE), std::unique_ptr<MCAsmBackend>(MAB),
83         true);
84     break;
85   }
86   case OutputFileType::Object: {
87     MS = TheTarget->createMCObjectStreamer(
88         TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
89         MAB->createObjectWriter(OutFile), std::unique_ptr<MCCodeEmitter>(MCE),
90         *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
91         /*DWARFMustBeAtTheEnd*/ false);
92     break;
93   }
94   }
95 
96   if (!MS)
97     return error("no object streamer for target " + TripleName, Context), false;
98 
99   // Finally create the AsmPrinter we'll use to emit the DIEs.
100   TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
101                                           std::nullopt));
102   if (!TM)
103     return error("no target machine for target " + TripleName, Context), false;
104 
105   Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
106   if (!Asm)
107     return error("no asm printer for target " + TripleName, Context), false;
108   Asm->setDwarfUsesRelocationsAcrossSections(false);
109 
110   RangesSectionSize = 0;
111   LocSectionSize = 0;
112   LineSectionSize = 0;
113   FrameSectionSize = 0;
114   DebugInfoSectionSize = 0;
115   MacInfoSectionSize = 0;
116   MacroSectionSize = 0;
117 
118   return true;
119 }
120 
finish()121 void DwarfStreamer::finish() { MS->finish(); }
122 
switchToDebugInfoSection(unsigned DwarfVersion)123 void DwarfStreamer::switchToDebugInfoSection(unsigned DwarfVersion) {
124   MS->switchSection(MOFI->getDwarfInfoSection());
125   MC->setDwarfVersion(DwarfVersion);
126 }
127 
128 /// Emit the compilation unit header for \p Unit in the debug_info section.
129 ///
130 /// A Dwarf 4 section header is encoded as:
131 ///  uint32_t   Unit length (omitting this field)
132 ///  uint16_t   Version
133 ///  uint32_t   Abbreviation table offset
134 ///  uint8_t    Address size
135 /// Leading to a total of 11 bytes.
136 ///
137 /// A Dwarf 5 section header is encoded as:
138 ///  uint32_t   Unit length (omitting this field)
139 ///  uint16_t   Version
140 ///  uint8_t    Unit type
141 ///  uint8_t    Address size
142 ///  uint32_t   Abbreviation table offset
143 /// Leading to a total of 12 bytes.
emitCompileUnitHeader(CompileUnit & Unit,unsigned DwarfVersion)144 void DwarfStreamer::emitCompileUnitHeader(CompileUnit &Unit,
145                                           unsigned DwarfVersion) {
146   switchToDebugInfoSection(DwarfVersion);
147 
148   /// The start of the unit within its section.
149   Unit.setLabelBegin(Asm->createTempSymbol("cu_begin"));
150   Asm->OutStreamer->emitLabel(Unit.getLabelBegin());
151 
152   // Emit size of content not including length itself. The size has already
153   // been computed in CompileUnit::computeOffsets(). Subtract 4 to that size to
154   // account for the length field.
155   Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset() - 4);
156   Asm->emitInt16(DwarfVersion);
157 
158   if (DwarfVersion >= 5) {
159     Asm->emitInt8(dwarf::DW_UT_compile);
160     Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
161     // We share one abbreviations table across all units so it's always at the
162     // start of the section.
163     Asm->emitInt32(0);
164     DebugInfoSectionSize += 12;
165   } else {
166     // We share one abbreviations table across all units so it's always at the
167     // start of the section.
168     Asm->emitInt32(0);
169     Asm->emitInt8(Unit.getOrigUnit().getAddressByteSize());
170     DebugInfoSectionSize += 11;
171   }
172 
173   // Remember this CU.
174   EmittedUnits.push_back({Unit.getUniqueID(), Unit.getLabelBegin()});
175 }
176 
177 /// Emit the \p Abbrevs array as the shared abbreviation table
178 /// for the linked Dwarf file.
emitAbbrevs(const std::vector<std::unique_ptr<DIEAbbrev>> & Abbrevs,unsigned DwarfVersion)179 void DwarfStreamer::emitAbbrevs(
180     const std::vector<std::unique_ptr<DIEAbbrev>> &Abbrevs,
181     unsigned DwarfVersion) {
182   MS->switchSection(MOFI->getDwarfAbbrevSection());
183   MC->setDwarfVersion(DwarfVersion);
184   Asm->emitDwarfAbbrevs(Abbrevs);
185 }
186 
187 /// Recursively emit the DIE tree rooted at \p Die.
emitDIE(DIE & Die)188 void DwarfStreamer::emitDIE(DIE &Die) {
189   MS->switchSection(MOFI->getDwarfInfoSection());
190   Asm->emitDwarfDIE(Die);
191   DebugInfoSectionSize += Die.getSize();
192 }
193 
194 /// Emit contents of section SecName From Obj.
emitSectionContents(StringRef SecData,StringRef SecName)195 void DwarfStreamer::emitSectionContents(StringRef SecData, StringRef SecName) {
196   MCSection *Section =
197       StringSwitch<MCSection *>(SecName)
198           .Case("debug_line", MC->getObjectFileInfo()->getDwarfLineSection())
199           .Case("debug_loc", MC->getObjectFileInfo()->getDwarfLocSection())
200           .Case("debug_ranges",
201                 MC->getObjectFileInfo()->getDwarfRangesSection())
202           .Case("debug_frame", MC->getObjectFileInfo()->getDwarfFrameSection())
203           .Case("debug_aranges",
204                 MC->getObjectFileInfo()->getDwarfARangesSection())
205           .Default(nullptr);
206 
207   if (Section) {
208     MS->switchSection(Section);
209 
210     MS->emitBytes(SecData);
211   }
212 }
213 
214 /// Emit DIE containing warnings.
emitPaperTrailWarningsDie(DIE & Die)215 void DwarfStreamer::emitPaperTrailWarningsDie(DIE &Die) {
216   switchToDebugInfoSection(/* Version */ 2);
217   auto &Asm = getAsmPrinter();
218   Asm.emitInt32(11 + Die.getSize() - 4);
219   Asm.emitInt16(2);
220   Asm.emitInt32(0);
221   Asm.emitInt8(MC->getTargetTriple().isArch64Bit() ? 8 : 4);
222   DebugInfoSectionSize += 11;
223   emitDIE(Die);
224 }
225 
226 /// Emit the debug_str section stored in \p Pool.
emitStrings(const NonRelocatableStringpool & Pool)227 void DwarfStreamer::emitStrings(const NonRelocatableStringpool &Pool) {
228   Asm->OutStreamer->switchSection(MOFI->getDwarfStrSection());
229   std::vector<DwarfStringPoolEntryRef> Entries = Pool.getEntriesForEmission();
230   for (auto Entry : Entries) {
231     // Emit the string itself.
232     Asm->OutStreamer->emitBytes(Entry.getString());
233     // Emit a null terminator.
234     Asm->emitInt8(0);
235   }
236 
237 #if 0
238   if (DwarfVersion >= 5) {
239     // Emit an empty string offset section.
240     Asm->OutStreamer->switchSection(MOFI->getDwarfStrOffSection());
241     Asm->emitDwarfUnitLength(4, "Length of String Offsets Set");
242     Asm->emitInt16(DwarfVersion);
243     Asm->emitInt16(0);
244   }
245 #endif
246 }
247 
emitDebugNames(AccelTable<DWARF5AccelTableStaticData> & Table)248 void DwarfStreamer::emitDebugNames(
249     AccelTable<DWARF5AccelTableStaticData> &Table) {
250   if (EmittedUnits.empty())
251     return;
252 
253   // Build up data structures needed to emit this section.
254   std::vector<MCSymbol *> CompUnits;
255   DenseMap<unsigned, size_t> UniqueIdToCuMap;
256   unsigned Id = 0;
257   for (auto &CU : EmittedUnits) {
258     CompUnits.push_back(CU.LabelBegin);
259     // We might be omitting CUs, so we need to remap them.
260     UniqueIdToCuMap[CU.ID] = Id++;
261   }
262 
263   Asm->OutStreamer->switchSection(MOFI->getDwarfDebugNamesSection());
264   emitDWARF5AccelTable(
265       Asm.get(), Table, CompUnits,
266       [&UniqueIdToCuMap](const DWARF5AccelTableStaticData &Entry) {
267         return UniqueIdToCuMap[Entry.getCUIndex()];
268       });
269 }
270 
emitAppleNamespaces(AccelTable<AppleAccelTableStaticOffsetData> & Table)271 void DwarfStreamer::emitAppleNamespaces(
272     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
273   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamespaceSection());
274   auto *SectionBegin = Asm->createTempSymbol("namespac_begin");
275   Asm->OutStreamer->emitLabel(SectionBegin);
276   emitAppleAccelTable(Asm.get(), Table, "namespac", SectionBegin);
277 }
278 
emitAppleNames(AccelTable<AppleAccelTableStaticOffsetData> & Table)279 void DwarfStreamer::emitAppleNames(
280     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
281   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelNamesSection());
282   auto *SectionBegin = Asm->createTempSymbol("names_begin");
283   Asm->OutStreamer->emitLabel(SectionBegin);
284   emitAppleAccelTable(Asm.get(), Table, "names", SectionBegin);
285 }
286 
emitAppleObjc(AccelTable<AppleAccelTableStaticOffsetData> & Table)287 void DwarfStreamer::emitAppleObjc(
288     AccelTable<AppleAccelTableStaticOffsetData> &Table) {
289   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelObjCSection());
290   auto *SectionBegin = Asm->createTempSymbol("objc_begin");
291   Asm->OutStreamer->emitLabel(SectionBegin);
292   emitAppleAccelTable(Asm.get(), Table, "objc", SectionBegin);
293 }
294 
emitAppleTypes(AccelTable<AppleAccelTableStaticTypeData> & Table)295 void DwarfStreamer::emitAppleTypes(
296     AccelTable<AppleAccelTableStaticTypeData> &Table) {
297   Asm->OutStreamer->switchSection(MOFI->getDwarfAccelTypesSection());
298   auto *SectionBegin = Asm->createTempSymbol("types_begin");
299   Asm->OutStreamer->emitLabel(SectionBegin);
300   emitAppleAccelTable(Asm.get(), Table, "types", SectionBegin);
301 }
302 
303 /// Emit the swift_ast section stored in \p Buffers.
emitSwiftAST(StringRef Buffer)304 void DwarfStreamer::emitSwiftAST(StringRef Buffer) {
305   MCSection *SwiftASTSection = MOFI->getDwarfSwiftASTSection();
306   SwiftASTSection->setAlignment(Align(32));
307   MS->switchSection(SwiftASTSection);
308   MS->emitBytes(Buffer);
309 }
310 
emitSwiftReflectionSection(llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,StringRef Buffer,uint32_t Alignment,uint32_t Size)311 void DwarfStreamer::emitSwiftReflectionSection(
312     llvm::binaryformat::Swift5ReflectionSectionKind ReflSectionKind,
313     StringRef Buffer, uint32_t Alignment, uint32_t Size) {
314   MCSection *ReflectionSection =
315       MOFI->getSwift5ReflectionSection(ReflSectionKind);
316   if (ReflectionSection == nullptr)
317     return;
318   ReflectionSection->setAlignment(Align(Alignment));
319   MS->switchSection(ReflectionSection);
320   MS->emitBytes(Buffer);
321 }
322 
emitDwarfDebugArangesTable(const CompileUnit & Unit,const AddressRanges & LinkedRanges)323 void DwarfStreamer::emitDwarfDebugArangesTable(
324     const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
325   unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
326 
327   // Make .debug_aranges to be current section.
328   MS->switchSection(MC->getObjectFileInfo()->getDwarfARangesSection());
329 
330   // Emit Header.
331   MCSymbol *BeginLabel = Asm->createTempSymbol("Barange");
332   MCSymbol *EndLabel = Asm->createTempSymbol("Earange");
333 
334   unsigned HeaderSize =
335       sizeof(int32_t) + // Size of contents (w/o this field
336       sizeof(int16_t) + // DWARF ARange version number
337       sizeof(int32_t) + // Offset of CU in the .debug_info section
338       sizeof(int8_t) +  // Pointer Size (in bytes)
339       sizeof(int8_t);   // Segment Size (in bytes)
340 
341   unsigned TupleSize = AddressSize * 2;
342   unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
343 
344   Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Arange length
345   Asm->OutStreamer->emitLabel(BeginLabel);
346   Asm->emitInt16(dwarf::DW_ARANGES_VERSION); // Version number
347   Asm->emitInt32(Unit.getStartOffset());     // Corresponding unit's offset
348   Asm->emitInt8(AddressSize);                // Address size
349   Asm->emitInt8(0);                          // Segment size
350 
351   Asm->OutStreamer->emitFill(Padding, 0x0);
352 
353   // Emit linked ranges.
354   for (const AddressRange &Range : LinkedRanges) {
355     MS->emitIntValue(Range.start(), AddressSize);
356     MS->emitIntValue(Range.end() - Range.start(), AddressSize);
357   }
358 
359   // Emit terminator.
360   Asm->OutStreamer->emitIntValue(0, AddressSize);
361   Asm->OutStreamer->emitIntValue(0, AddressSize);
362   Asm->OutStreamer->emitLabel(EndLabel);
363 }
364 
emitDwarfDebugRangesTableFragment(const CompileUnit & Unit,const AddressRanges & LinkedRanges)365 void DwarfStreamer::emitDwarfDebugRangesTableFragment(
366     const CompileUnit &Unit, const AddressRanges &LinkedRanges) {
367   unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
368 
369   // Make .debug_ranges to be current section.
370   MS->switchSection(MC->getObjectFileInfo()->getDwarfRangesSection());
371 
372   // Emit ranges.
373   uint64_t BaseAddress = 0;
374   if (std::optional<uint64_t> LowPC = Unit.getLowPc())
375     BaseAddress = *LowPC;
376 
377   for (const AddressRange &Range : LinkedRanges) {
378     MS->emitIntValue(Range.start() - BaseAddress, AddressSize);
379     MS->emitIntValue(Range.end() - BaseAddress, AddressSize);
380 
381     RangesSectionSize += AddressSize;
382     RangesSectionSize += AddressSize;
383   }
384 
385   // Add the terminator entry.
386   MS->emitIntValue(0, AddressSize);
387   MS->emitIntValue(0, AddressSize);
388 
389   RangesSectionSize += AddressSize;
390   RangesSectionSize += AddressSize;
391 }
392 
393 /// Emit the debug_aranges contribution of a unit and
394 /// if \p DoDebugRanges is true the debug_range contents for a
395 /// compile_unit level DW_AT_ranges attribute (Which are basically the
396 /// same thing with a different base address).
397 /// Just aggregate all the ranges gathered inside that unit.
emitUnitRangesEntries(CompileUnit & Unit,bool DoDebugRanges)398 void DwarfStreamer::emitUnitRangesEntries(CompileUnit &Unit,
399                                           bool DoDebugRanges) {
400   const RangesTy &FunctionRanges = Unit.getFunctionRanges();
401 
402   // Linked addresses might end up in a different order.
403   // Build linked address ranges.
404   AddressRanges LinkedRanges;
405   for (size_t Idx = 0; Idx < FunctionRanges.size(); Idx++)
406     LinkedRanges.insert(
407         {FunctionRanges[Idx].first.start() + FunctionRanges[Idx].second,
408          FunctionRanges[Idx].first.end() + FunctionRanges[Idx].second});
409 
410   if (!FunctionRanges.empty())
411     emitDwarfDebugArangesTable(Unit, LinkedRanges);
412 
413   if (DoDebugRanges)
414     emitDwarfDebugRangesTableFragment(Unit, LinkedRanges);
415 }
416 
417 /// Emit location lists for \p Unit and update attributes to point to the new
418 /// entries.
emitLocationsForUnit(const CompileUnit & Unit,DWARFContext & Dwarf,std::function<void (StringRef,SmallVectorImpl<uint8_t> &)> ProcessExpr)419 void DwarfStreamer::emitLocationsForUnit(
420     const CompileUnit &Unit, DWARFContext &Dwarf,
421     std::function<void(StringRef, SmallVectorImpl<uint8_t> &)> ProcessExpr) {
422   const auto &Attributes = Unit.getLocationAttributes();
423 
424   if (Attributes.empty())
425     return;
426 
427   MS->switchSection(MC->getObjectFileInfo()->getDwarfLocSection());
428 
429   unsigned AddressSize = Unit.getOrigUnit().getAddressByteSize();
430   uint64_t BaseAddressMarker = (AddressSize == 8)
431                                    ? std::numeric_limits<uint64_t>::max()
432                                    : std::numeric_limits<uint32_t>::max();
433   const DWARFSection &InputSec = Dwarf.getDWARFObj().getLocSection();
434   DataExtractor Data(InputSec.Data, Dwarf.isLittleEndian(), AddressSize);
435   DWARFUnit &OrigUnit = Unit.getOrigUnit();
436   auto OrigUnitDie = OrigUnit.getUnitDIE(false);
437   int64_t UnitPcOffset = 0;
438   if (auto OrigLowPc =
439           dwarf::toAddress(OrigUnitDie.find(dwarf::DW_AT_low_pc))) {
440     assert(Unit.getLowPc());
441     UnitPcOffset = int64_t(*OrigLowPc) - *Unit.getLowPc();
442   }
443 
444   SmallVector<uint8_t, 32> Buffer;
445   for (const auto &Attr : Attributes) {
446     uint64_t Offset = Attr.first.get();
447     Attr.first.set(LocSectionSize);
448     // This is the quantity to add to the old location address to get
449     // the correct address for the new one.
450     int64_t LocPcOffset = Attr.second + UnitPcOffset;
451     while (Data.isValidOffset(Offset)) {
452       uint64_t Low = Data.getUnsigned(&Offset, AddressSize);
453       uint64_t High = Data.getUnsigned(&Offset, AddressSize);
454       LocSectionSize += 2 * AddressSize;
455       // End of list entry.
456       if (Low == 0 && High == 0) {
457         Asm->OutStreamer->emitIntValue(0, AddressSize);
458         Asm->OutStreamer->emitIntValue(0, AddressSize);
459         break;
460       }
461       // Base address selection entry.
462       if (Low == BaseAddressMarker) {
463         Asm->OutStreamer->emitIntValue(BaseAddressMarker, AddressSize);
464         Asm->OutStreamer->emitIntValue(High + Attr.second, AddressSize);
465         LocPcOffset = 0;
466         continue;
467       }
468       // Location list entry.
469       Asm->OutStreamer->emitIntValue(Low + LocPcOffset, AddressSize);
470       Asm->OutStreamer->emitIntValue(High + LocPcOffset, AddressSize);
471       uint64_t Length = Data.getU16(&Offset);
472       Asm->OutStreamer->emitIntValue(Length, 2);
473       // Copy the bytes into to the buffer, process them, emit them.
474       Buffer.reserve(Length);
475       Buffer.resize(0);
476       StringRef Input = InputSec.Data.substr(Offset, Length);
477       ProcessExpr(Input, Buffer);
478       Asm->OutStreamer->emitBytes(
479           StringRef((const char *)Buffer.data(), Length));
480       Offset += Length;
481       LocSectionSize += Length + 2;
482     }
483   }
484 }
485 
emitLineTableForUnit(MCDwarfLineTableParams Params,StringRef PrologueBytes,unsigned MinInstLength,std::vector<DWARFDebugLine::Row> & Rows,unsigned PointerSize)486 void DwarfStreamer::emitLineTableForUnit(MCDwarfLineTableParams Params,
487                                          StringRef PrologueBytes,
488                                          unsigned MinInstLength,
489                                          std::vector<DWARFDebugLine::Row> &Rows,
490                                          unsigned PointerSize) {
491   // Switch to the section where the table will be emitted into.
492   MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
493   MCSymbol *LineStartSym = MC->createTempSymbol();
494   MCSymbol *LineEndSym = MC->createTempSymbol();
495 
496   // The first 4 bytes is the total length of the information for this
497   // compilation unit (not including these 4 bytes for the length).
498   Asm->emitLabelDifference(LineEndSym, LineStartSym, 4);
499   Asm->OutStreamer->emitLabel(LineStartSym);
500   // Copy Prologue.
501   MS->emitBytes(PrologueBytes);
502   LineSectionSize += PrologueBytes.size() + 4;
503 
504   SmallString<128> EncodingBuffer;
505   raw_svector_ostream EncodingOS(EncodingBuffer);
506 
507   if (Rows.empty()) {
508     // We only have the dummy entry, dsymutil emits an entry with a 0
509     // address in that case.
510     MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
511                             EncodingOS);
512     MS->emitBytes(EncodingOS.str());
513     LineSectionSize += EncodingBuffer.size();
514     MS->emitLabel(LineEndSym);
515     return;
516   }
517 
518   // Line table state machine fields
519   unsigned FileNum = 1;
520   unsigned LastLine = 1;
521   unsigned Column = 0;
522   unsigned IsStatement = 1;
523   unsigned Isa = 0;
524   uint64_t Address = -1ULL;
525 
526   unsigned RowsSinceLastSequence = 0;
527 
528   for (DWARFDebugLine::Row &Row : Rows) {
529     int64_t AddressDelta;
530     if (Address == -1ULL) {
531       MS->emitIntValue(dwarf::DW_LNS_extended_op, 1);
532       MS->emitULEB128IntValue(PointerSize + 1);
533       MS->emitIntValue(dwarf::DW_LNE_set_address, 1);
534       MS->emitIntValue(Row.Address.Address, PointerSize);
535       LineSectionSize += 2 + PointerSize + getULEB128Size(PointerSize + 1);
536       AddressDelta = 0;
537     } else {
538       AddressDelta = (Row.Address.Address - Address) / MinInstLength;
539     }
540 
541     // FIXME: code copied and transformed from MCDwarf.cpp::EmitDwarfLineTable.
542     // We should find a way to share this code, but the current compatibility
543     // requirement with classic dsymutil makes it hard. Revisit that once this
544     // requirement is dropped.
545 
546     if (FileNum != Row.File) {
547       FileNum = Row.File;
548       MS->emitIntValue(dwarf::DW_LNS_set_file, 1);
549       MS->emitULEB128IntValue(FileNum);
550       LineSectionSize += 1 + getULEB128Size(FileNum);
551     }
552     if (Column != Row.Column) {
553       Column = Row.Column;
554       MS->emitIntValue(dwarf::DW_LNS_set_column, 1);
555       MS->emitULEB128IntValue(Column);
556       LineSectionSize += 1 + getULEB128Size(Column);
557     }
558 
559     // FIXME: We should handle the discriminator here, but dsymutil doesn't
560     // consider it, thus ignore it for now.
561 
562     if (Isa != Row.Isa) {
563       Isa = Row.Isa;
564       MS->emitIntValue(dwarf::DW_LNS_set_isa, 1);
565       MS->emitULEB128IntValue(Isa);
566       LineSectionSize += 1 + getULEB128Size(Isa);
567     }
568     if (IsStatement != Row.IsStmt) {
569       IsStatement = Row.IsStmt;
570       MS->emitIntValue(dwarf::DW_LNS_negate_stmt, 1);
571       LineSectionSize += 1;
572     }
573     if (Row.BasicBlock) {
574       MS->emitIntValue(dwarf::DW_LNS_set_basic_block, 1);
575       LineSectionSize += 1;
576     }
577 
578     if (Row.PrologueEnd) {
579       MS->emitIntValue(dwarf::DW_LNS_set_prologue_end, 1);
580       LineSectionSize += 1;
581     }
582 
583     if (Row.EpilogueBegin) {
584       MS->emitIntValue(dwarf::DW_LNS_set_epilogue_begin, 1);
585       LineSectionSize += 1;
586     }
587 
588     int64_t LineDelta = int64_t(Row.Line) - LastLine;
589     if (!Row.EndSequence) {
590       MCDwarfLineAddr::Encode(*MC, Params, LineDelta, AddressDelta, EncodingOS);
591       MS->emitBytes(EncodingOS.str());
592       LineSectionSize += EncodingBuffer.size();
593       EncodingBuffer.resize(0);
594       Address = Row.Address.Address;
595       LastLine = Row.Line;
596       RowsSinceLastSequence++;
597     } else {
598       if (LineDelta) {
599         MS->emitIntValue(dwarf::DW_LNS_advance_line, 1);
600         MS->emitSLEB128IntValue(LineDelta);
601         LineSectionSize += 1 + getSLEB128Size(LineDelta);
602       }
603       if (AddressDelta) {
604         MS->emitIntValue(dwarf::DW_LNS_advance_pc, 1);
605         MS->emitULEB128IntValue(AddressDelta);
606         LineSectionSize += 1 + getULEB128Size(AddressDelta);
607       }
608       MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(),
609                               0, EncodingOS);
610       MS->emitBytes(EncodingOS.str());
611       LineSectionSize += EncodingBuffer.size();
612       EncodingBuffer.resize(0);
613       Address = -1ULL;
614       LastLine = FileNum = IsStatement = 1;
615       RowsSinceLastSequence = Column = Isa = 0;
616     }
617   }
618 
619   if (RowsSinceLastSequence) {
620     MCDwarfLineAddr::Encode(*MC, Params, std::numeric_limits<int64_t>::max(), 0,
621                             EncodingOS);
622     MS->emitBytes(EncodingOS.str());
623     LineSectionSize += EncodingBuffer.size();
624     EncodingBuffer.resize(0);
625   }
626 
627   MS->emitLabel(LineEndSym);
628 }
629 
630 /// Copy the debug_line over to the updated binary while unobfuscating the file
631 /// names and directories.
translateLineTable(DataExtractor Data,uint64_t Offset)632 void DwarfStreamer::translateLineTable(DataExtractor Data, uint64_t Offset) {
633   MS->switchSection(MC->getObjectFileInfo()->getDwarfLineSection());
634   StringRef Contents = Data.getData();
635 
636   // We have to deconstruct the line table header, because it contains to
637   // length fields that will need to be updated when we change the length of
638   // the files and directories in there.
639   unsigned UnitLength = Data.getU32(&Offset);
640   uint64_t UnitEnd = Offset + UnitLength;
641   MCSymbol *BeginLabel = MC->createTempSymbol();
642   MCSymbol *EndLabel = MC->createTempSymbol();
643   unsigned Version = Data.getU16(&Offset);
644 
645   if (Version > 5) {
646     warn("Unsupported line table version: dropping contents and not "
647          "unobfsucating line table.");
648     return;
649   }
650 
651   Asm->emitLabelDifference(EndLabel, BeginLabel, 4);
652   Asm->OutStreamer->emitLabel(BeginLabel);
653   Asm->emitInt16(Version);
654   LineSectionSize += 6;
655 
656   MCSymbol *HeaderBeginLabel = MC->createTempSymbol();
657   MCSymbol *HeaderEndLabel = MC->createTempSymbol();
658   Asm->emitLabelDifference(HeaderEndLabel, HeaderBeginLabel, 4);
659   Asm->OutStreamer->emitLabel(HeaderBeginLabel);
660   Offset += 4;
661   LineSectionSize += 4;
662 
663   uint64_t AfterHeaderLengthOffset = Offset;
664   // Skip to the directories.
665   Offset += (Version >= 4) ? 5 : 4;
666   unsigned OpcodeBase = Data.getU8(&Offset);
667   Offset += OpcodeBase - 1;
668   Asm->OutStreamer->emitBytes(Contents.slice(AfterHeaderLengthOffset, Offset));
669   LineSectionSize += Offset - AfterHeaderLengthOffset;
670 
671   // Offset points to the first directory.
672   while (const char *Dir = Data.getCStr(&Offset)) {
673     if (Dir[0] == 0)
674       break;
675 
676     StringRef Translated = Translator(Dir);
677     Asm->OutStreamer->emitBytes(Translated);
678     Asm->emitInt8(0);
679     LineSectionSize += Translated.size() + 1;
680   }
681   Asm->emitInt8(0);
682   LineSectionSize += 1;
683 
684   while (const char *File = Data.getCStr(&Offset)) {
685     if (File[0] == 0)
686       break;
687 
688     StringRef Translated = Translator(File);
689     Asm->OutStreamer->emitBytes(Translated);
690     Asm->emitInt8(0);
691     LineSectionSize += Translated.size() + 1;
692 
693     uint64_t OffsetBeforeLEBs = Offset;
694     Asm->emitULEB128(Data.getULEB128(&Offset));
695     Asm->emitULEB128(Data.getULEB128(&Offset));
696     Asm->emitULEB128(Data.getULEB128(&Offset));
697     LineSectionSize += Offset - OffsetBeforeLEBs;
698   }
699   Asm->emitInt8(0);
700   LineSectionSize += 1;
701 
702   Asm->OutStreamer->emitLabel(HeaderEndLabel);
703 
704   // Copy the actual line table program over.
705   Asm->OutStreamer->emitBytes(Contents.slice(Offset, UnitEnd));
706   LineSectionSize += UnitEnd - Offset;
707 
708   Asm->OutStreamer->emitLabel(EndLabel);
709   Offset = UnitEnd;
710 }
711 
712 /// Emit the pubnames or pubtypes section contribution for \p
713 /// 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)714 void DwarfStreamer::emitPubSectionForUnit(
715     MCSection *Sec, StringRef SecName, const CompileUnit &Unit,
716     const std::vector<CompileUnit::AccelInfo> &Names) {
717   if (Names.empty())
718     return;
719 
720   // Start the dwarf pubnames section.
721   Asm->OutStreamer->switchSection(Sec);
722   MCSymbol *BeginLabel = Asm->createTempSymbol("pub" + SecName + "_begin");
723   MCSymbol *EndLabel = Asm->createTempSymbol("pub" + SecName + "_end");
724 
725   bool HeaderEmitted = false;
726   // Emit the pubnames for this compilation unit.
727   for (const auto &Name : Names) {
728     if (Name.SkipPubSection)
729       continue;
730 
731     if (!HeaderEmitted) {
732       // Emit the header.
733       Asm->emitLabelDifference(EndLabel, BeginLabel, 4); // Length
734       Asm->OutStreamer->emitLabel(BeginLabel);
735       Asm->emitInt16(dwarf::DW_PUBNAMES_VERSION); // Version
736       Asm->emitInt32(Unit.getStartOffset());      // Unit offset
737       Asm->emitInt32(Unit.getNextUnitOffset() - Unit.getStartOffset()); // Size
738       HeaderEmitted = true;
739     }
740     Asm->emitInt32(Name.Die->getOffset());
741 
742     // Emit the string itself.
743     Asm->OutStreamer->emitBytes(Name.Name.getString());
744     // Emit a null terminator.
745     Asm->emitInt8(0);
746   }
747 
748   if (!HeaderEmitted)
749     return;
750   Asm->emitInt32(0); // End marker.
751   Asm->OutStreamer->emitLabel(EndLabel);
752 }
753 
754 /// Emit .debug_pubnames for \p Unit.
emitPubNamesForUnit(const CompileUnit & Unit)755 void DwarfStreamer::emitPubNamesForUnit(const CompileUnit &Unit) {
756   emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubNamesSection(),
757                         "names", Unit, Unit.getPubnames());
758 }
759 
760 /// Emit .debug_pubtypes for \p Unit.
emitPubTypesForUnit(const CompileUnit & Unit)761 void DwarfStreamer::emitPubTypesForUnit(const CompileUnit &Unit) {
762   emitPubSectionForUnit(MC->getObjectFileInfo()->getDwarfPubTypesSection(),
763                         "types", Unit, Unit.getPubtypes());
764 }
765 
766 /// Emit a CIE into the debug_frame section.
emitCIE(StringRef CIEBytes)767 void DwarfStreamer::emitCIE(StringRef CIEBytes) {
768   MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
769 
770   MS->emitBytes(CIEBytes);
771   FrameSectionSize += CIEBytes.size();
772 }
773 
774 /// Emit a FDE into the debug_frame section. \p FDEBytes
775 /// contains the FDE data without the length, CIE offset and address
776 /// which will be replaced with the parameter values.
emitFDE(uint32_t CIEOffset,uint32_t AddrSize,uint64_t Address,StringRef FDEBytes)777 void DwarfStreamer::emitFDE(uint32_t CIEOffset, uint32_t AddrSize,
778                             uint64_t Address, StringRef FDEBytes) {
779   MS->switchSection(MC->getObjectFileInfo()->getDwarfFrameSection());
780 
781   MS->emitIntValue(FDEBytes.size() + 4 + AddrSize, 4);
782   MS->emitIntValue(CIEOffset, 4);
783   MS->emitIntValue(Address, AddrSize);
784   MS->emitBytes(FDEBytes);
785   FrameSectionSize += FDEBytes.size() + 8 + AddrSize;
786 }
787 
emitMacroTables(DWARFContext * Context,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool)788 void DwarfStreamer::emitMacroTables(DWARFContext *Context,
789                                     const Offset2UnitMap &UnitMacroMap,
790                                     OffsetsStringPool &StringPool) {
791   assert(Context != nullptr && "Empty DWARF context");
792 
793   // Check for .debug_macinfo table.
794   if (const DWARFDebugMacro *Table = Context->getDebugMacinfo()) {
795     MS->switchSection(MC->getObjectFileInfo()->getDwarfMacinfoSection());
796     emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacInfoSectionSize);
797   }
798 
799   // Check for .debug_macro table.
800   if (const DWARFDebugMacro *Table = Context->getDebugMacro()) {
801     MS->switchSection(MC->getObjectFileInfo()->getDwarfMacroSection());
802     emitMacroTableImpl(Table, UnitMacroMap, StringPool, MacroSectionSize);
803   }
804 }
805 
emitMacroTableImpl(const DWARFDebugMacro * MacroTable,const Offset2UnitMap & UnitMacroMap,OffsetsStringPool & StringPool,uint64_t & OutOffset)806 void DwarfStreamer::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
807                                        const Offset2UnitMap &UnitMacroMap,
808                                        OffsetsStringPool &StringPool,
809                                        uint64_t &OutOffset) {
810   bool DefAttributeIsReported = false;
811   bool UndefAttributeIsReported = false;
812   bool ImportAttributeIsReported = false;
813   for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
814     Offset2UnitMap::const_iterator UnitIt = UnitMacroMap.find(List.Offset);
815     if (UnitIt == UnitMacroMap.end()) {
816       warn(formatv(
817           "couldn`t find compile unit for the macro table with offset = {0:x}",
818           List.Offset));
819       continue;
820     }
821 
822     // Skip macro table if the unit was not cloned.
823     DIE *OutputUnitDIE = UnitIt->second->getOutputUnitDIE();
824     if (OutputUnitDIE == nullptr)
825       continue;
826 
827     // Update macro attribute of cloned compile unit with the proper offset to
828     // the macro table.
829     bool hasDWARFv5Header = false;
830     for (auto &V : OutputUnitDIE->values()) {
831       if (V.getAttribute() == dwarf::DW_AT_macro_info) {
832         V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
833         break;
834       } else if (V.getAttribute() == dwarf::DW_AT_macros) {
835         hasDWARFv5Header = true;
836         V = DIEValue(V.getAttribute(), V.getForm(), DIEInteger(OutOffset));
837         break;
838       }
839     }
840 
841     // Write DWARFv5 header.
842     if (hasDWARFv5Header) {
843       // Write header version.
844       MS->emitIntValue(List.Header.Version, sizeof(List.Header.Version));
845       OutOffset += sizeof(List.Header.Version);
846 
847       uint8_t Flags = List.Header.Flags;
848 
849       // Check for OPCODE_OPERANDS_TABLE.
850       if (Flags &
851           DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
852         Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
853         warn("opcode_operands_table is not supported yet.");
854       }
855 
856       // Check for DEBUG_LINE_OFFSET.
857       std::optional<uint64_t> StmtListOffset;
858       if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
859         // Get offset to the line table from the cloned compile unit.
860         for (auto &V : OutputUnitDIE->values()) {
861           if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
862             StmtListOffset = V.getDIEInteger().getValue();
863             break;
864           }
865         }
866 
867         if (!StmtListOffset) {
868           Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
869           warn("couldn`t find line table for macro table.");
870         }
871       }
872 
873       // Write flags.
874       MS->emitIntValue(Flags, sizeof(Flags));
875       OutOffset += sizeof(Flags);
876 
877       // Write offset to line table.
878       if (StmtListOffset) {
879         MS->emitIntValue(*StmtListOffset, List.Header.getOffsetByteSize());
880         OutOffset += List.Header.getOffsetByteSize();
881       }
882     }
883 
884     // Write macro entries.
885     for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
886       if (MacroEntry.Type == 0) {
887         OutOffset += MS->emitULEB128IntValue(MacroEntry.Type);
888         continue;
889       }
890 
891       uint8_t MacroType = MacroEntry.Type;
892       switch (MacroType) {
893       default: {
894         bool HasVendorSpecificExtension =
895             (!hasDWARFv5Header && MacroType == dwarf::DW_MACINFO_vendor_ext) ||
896             (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
897                                   MacroType <= dwarf::DW_MACRO_hi_user));
898 
899         if (HasVendorSpecificExtension) {
900           // Write macinfo type.
901           MS->emitIntValue(MacroType, 1);
902           OutOffset++;
903 
904           // Write vendor extension constant.
905           OutOffset += MS->emitULEB128IntValue(MacroEntry.ExtConstant);
906 
907           // Write vendor extension string.
908           StringRef String = MacroEntry.ExtStr;
909           MS->emitBytes(String);
910           MS->emitIntValue(0, 1);
911           OutOffset += String.size() + 1;
912         } else
913           warn("unknown macro type. skip.");
914       } break;
915       // debug_macro and debug_macinfo share some common encodings.
916       // DW_MACRO_define     == DW_MACINFO_define
917       // DW_MACRO_undef      == DW_MACINFO_undef
918       // DW_MACRO_start_file == DW_MACINFO_start_file
919       // DW_MACRO_end_file   == DW_MACINFO_end_file
920       // For readibility/uniformity we are using DW_MACRO_*.
921       case dwarf::DW_MACRO_define:
922       case dwarf::DW_MACRO_undef: {
923         // Write macinfo type.
924         MS->emitIntValue(MacroType, 1);
925         OutOffset++;
926 
927         // Write source line.
928         OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
929 
930         // Write macro string.
931         StringRef String = MacroEntry.MacroStr;
932         MS->emitBytes(String);
933         MS->emitIntValue(0, 1);
934         OutOffset += String.size() + 1;
935       } break;
936       case dwarf::DW_MACRO_define_strp:
937       case dwarf::DW_MACRO_undef_strp:
938       case dwarf::DW_MACRO_define_strx:
939       case dwarf::DW_MACRO_undef_strx: {
940         assert(UnitIt->second->getOrigUnit().getVersion() >= 5);
941 
942         // DW_MACRO_*_strx forms are not supported currently.
943         // Convert to *_strp.
944         switch (MacroType) {
945         case dwarf::DW_MACRO_define_strx: {
946           MacroType = dwarf::DW_MACRO_define_strp;
947           if (!DefAttributeIsReported) {
948             warn("DW_MACRO_define_strx unsupported yet. Convert to "
949                  "DW_MACRO_define_strp.");
950             DefAttributeIsReported = true;
951           }
952         } break;
953         case dwarf::DW_MACRO_undef_strx: {
954           MacroType = dwarf::DW_MACRO_undef_strp;
955           if (!UndefAttributeIsReported) {
956             warn("DW_MACRO_undef_strx unsupported yet. Convert to "
957                  "DW_MACRO_undef_strp.");
958             UndefAttributeIsReported = true;
959           }
960         } break;
961         default:
962           // Nothing to do.
963           break;
964         }
965 
966         // Write macinfo type.
967         MS->emitIntValue(MacroType, 1);
968         OutOffset++;
969 
970         // Write source line.
971         OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
972 
973         // Write macro string.
974         DwarfStringPoolEntryRef EntryRef =
975             StringPool.getEntry(MacroEntry.MacroStr);
976         MS->emitIntValue(EntryRef.getOffset(), List.Header.getOffsetByteSize());
977         OutOffset += List.Header.getOffsetByteSize();
978         break;
979       }
980       case dwarf::DW_MACRO_start_file: {
981         // Write macinfo type.
982         MS->emitIntValue(MacroType, 1);
983         OutOffset++;
984         // Write source line.
985         OutOffset += MS->emitULEB128IntValue(MacroEntry.Line);
986         // Write source file id.
987         OutOffset += MS->emitULEB128IntValue(MacroEntry.File);
988       } break;
989       case dwarf::DW_MACRO_end_file: {
990         // Write macinfo type.
991         MS->emitIntValue(MacroType, 1);
992         OutOffset++;
993       } break;
994       case dwarf::DW_MACRO_import:
995       case dwarf::DW_MACRO_import_sup: {
996         if (!ImportAttributeIsReported) {
997           warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported yet. "
998                "remove.");
999           ImportAttributeIsReported = true;
1000         }
1001       } break;
1002       }
1003     }
1004   }
1005 }
1006 
1007 } // namespace llvm
1008