xref: /llvm-project/llvm/unittests/DebugInfo/DWARF/DwarfGenerator.cpp (revision b8220b986dcc8c5d0c44a125642009d8175fc11d)
1 //===--- unittests/DebugInfo/DWARF/DwarfGenerator.cpp -----------*- C++ -*-===//
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 "DwarfGenerator.h"
10 #include "../lib/CodeGen/AsmPrinter/DwarfStringPool.h"
11 #include "llvm/BinaryFormat/Dwarf.h"
12 #include "llvm/CodeGen/AsmPrinter.h"
13 #include "llvm/CodeGen/DIE.h"
14 #include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
15 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
16 #include "llvm/MC/MCAsmBackend.h"
17 #include "llvm/MC/MCAsmInfo.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCDwarf.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCObjectFileInfo.h"
23 #include "llvm/MC/MCObjectWriter.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCStreamer.h"
26 #include "llvm/MC/MCSubtargetInfo.h"
27 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
28 #include "llvm/MC/TargetRegistry.h"
29 #include "llvm/Pass.h"
30 #include "llvm/Support/FileSystem.h"
31 #include "llvm/Support/LEB128.h"
32 #include "llvm/Support/raw_ostream.h"
33 #include "llvm/Target/TargetLoweringObjectFile.h"
34 #include "llvm/Target/TargetMachine.h"
35 #include "llvm/Target/TargetOptions.h"
36 #include "llvm/TargetParser/Triple.h"
37 
38 using namespace llvm;
39 using namespace dwarf;
40 
41 mc::RegisterMCTargetOptionsFlags MOF;
42 
43 namespace {} // end anonymous namespace
44 
45 //===----------------------------------------------------------------------===//
46 /// dwarfgen::DIE implementation.
47 //===----------------------------------------------------------------------===//
48 unsigned dwarfgen::DIE::computeSizeAndOffsets(unsigned Offset) {
49   auto &DG = CU->getGenerator();
50   return Die->computeOffsetsAndAbbrevs(DG.getAsmPrinter()->getDwarfFormParams(),
51                                        DG.getAbbrevSet(), Offset);
52 }
53 
54 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, uint64_t U) {
55   auto &DG = CU->getGenerator();
56   switch (Form) {
57   case DW_FORM_addrx:
58   case DW_FORM_addrx1:
59   case DW_FORM_addrx2:
60   case DW_FORM_addrx3:
61   case DW_FORM_addrx4:
62     U = DG.getAddressPool().getIndex(U);
63     break;
64   default:
65     break;
66   }
67   Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
68                 DIEInteger(U));
69 }
70 
71 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const MCExpr &Expr) {
72   auto &DG = CU->getGenerator();
73   Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
74                 DIEExpr(&Expr));
75 }
76 
77 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
78                                  StringRef String) {
79   auto &DG = CU->getGenerator();
80   switch (Form) {
81   case DW_FORM_string:
82     Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
83                   new (DG.getAllocator())
84                       DIEInlineString(String, DG.getAllocator()));
85     break;
86 
87   case DW_FORM_strp:
88     Die->addValue(
89         DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
90         DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
91     break;
92 
93   case DW_FORM_GNU_str_index:
94   case DW_FORM_strx:
95   case DW_FORM_strx1:
96   case DW_FORM_strx2:
97   case DW_FORM_strx3:
98   case DW_FORM_strx4:
99     Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
100                   DIEString(DG.getStringPool().getIndexedEntry(
101                       *DG.getAsmPrinter(), String)));
102     break;
103 
104   default:
105     llvm_unreachable("Unhandled form!");
106   }
107 }
108 
109 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
110                                  dwarfgen::DIE &RefDie) {
111   auto &DG = CU->getGenerator();
112   Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
113                 DIEEntry(*RefDie.Die));
114 }
115 
116 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const void *P,
117                                  size_t S) {
118   auto &DG = CU->getGenerator();
119   DIEBlock *Block = new (DG.getAllocator()) DIEBlock;
120   for (size_t I = 0; I < S; ++I)
121     Block->addValue(
122         DG.getAllocator(), (dwarf::Attribute)0, dwarf::DW_FORM_data1,
123         DIEInteger(
124             (const_cast<uint8_t *>(static_cast<const uint8_t *>(P)))[I]));
125 
126   Block->computeSize(DG.getAsmPrinter()->getDwarfFormParams());
127   Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
128                 Block);
129 }
130 
131 void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form) {
132   auto &DG = CU->getGenerator();
133   assert(Form == DW_FORM_flag_present);
134   Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
135                 DIEInteger(1));
136 }
137 
138 void dwarfgen::DIE::addStrOffsetsBaseAttribute() {
139   auto &DG = CU->getGenerator();
140   auto &MC = *DG.getMCContext();
141   AsmPrinter *Asm = DG.getAsmPrinter();
142 
143   const MCSymbol *SectionStart =
144       Asm->getObjFileLowering().getDwarfStrOffSection()->getBeginSymbol();
145 
146   const MCExpr *Expr =
147       MCSymbolRefExpr::create(DG.getStringOffsetsStartSym(), MC);
148 
149   if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())
150     Expr = MCBinaryExpr::createSub(
151         Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);
152 
153   addAttribute(dwarf::DW_AT_str_offsets_base, DW_FORM_sec_offset, *Expr);
154 }
155 
156 // This is currently fixed to be the first address entry after the header.
157 void dwarfgen::DIE::addAddrBaseAttribute() {
158   auto &DG = CU->getGenerator();
159   auto &MC = *DG.getMCContext();
160   AsmPrinter *Asm = DG.getAsmPrinter();
161 
162   const MCSymbol *SectionStart =
163       Asm->getObjFileLowering().getDwarfAddrSection()->getBeginSymbol();
164 
165   const MCExpr *Expr = MCSymbolRefExpr::create(DG.getAddrTableStartSym(), MC);
166 
167   if (!Asm->MAI->doesDwarfUseRelocationsAcrossSections())
168     Expr = MCBinaryExpr::createSub(
169         Expr, MCSymbolRefExpr::create(SectionStart, MC), MC);
170 
171   addAttribute(dwarf::DW_AT_addr_base, DW_FORM_sec_offset, *Expr);
172 }
173 
174 dwarfgen::DIE dwarfgen::DIE::addChild(dwarf::Tag Tag) {
175   auto &DG = CU->getGenerator();
176   return dwarfgen::DIE(CU,
177                        &Die->addChild(llvm::DIE::get(DG.getAllocator(), Tag)));
178 }
179 
180 dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() {
181   return dwarfgen::DIE(this, &DU.getUnitDie());
182 }
183 
184 //===----------------------------------------------------------------------===//
185 /// dwarfgen::LineTable implementation.
186 //===----------------------------------------------------------------------===//
187 DWARFDebugLine::Prologue dwarfgen::LineTable::createBasicPrologue() const {
188   DWARFDebugLine::Prologue P;
189   switch (Version) {
190   case 2:
191   case 3:
192     P.TotalLength = 41;
193     P.PrologueLength = 35;
194     break;
195   case 4:
196     P.TotalLength = 42;
197     P.PrologueLength = 36;
198     break;
199   case 5:
200     P.TotalLength = 50;
201     P.PrologueLength = 42;
202     P.FormParams.AddrSize = AddrSize;
203     break;
204   default:
205     llvm_unreachable("unsupported version");
206   }
207   if (Format == DWARF64) {
208     P.TotalLength += 4;
209     P.FormParams.Format = DWARF64;
210   }
211   P.TotalLength += getContentsSize();
212   P.FormParams.Version = Version;
213   P.MinInstLength = 1;
214   P.MaxOpsPerInst = 1;
215   P.DefaultIsStmt = 1;
216   P.LineBase = -5;
217   P.LineRange = 14;
218   P.OpcodeBase = 13;
219   P.StandardOpcodeLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};
220   P.IncludeDirectories.push_back(
221       DWARFFormValue::createFromPValue(DW_FORM_string, "a dir"));
222   P.FileNames.push_back(DWARFDebugLine::FileNameEntry());
223   P.FileNames.back().Name =
224       DWARFFormValue::createFromPValue(DW_FORM_string, "a file");
225   return P;
226 }
227 
228 void dwarfgen::LineTable::setPrologue(DWARFDebugLine::Prologue NewPrologue) {
229   Prologue = NewPrologue;
230   CustomPrologue.clear();
231 }
232 
233 void dwarfgen::LineTable::setCustomPrologue(
234     ArrayRef<ValueAndLength> NewPrologue) {
235   Prologue.reset();
236   CustomPrologue = NewPrologue;
237 }
238 
239 void dwarfgen::LineTable::addByte(uint8_t Value) {
240   Contents.push_back({Value, Byte});
241 }
242 
243 void dwarfgen::LineTable::addStandardOpcode(uint8_t Opcode,
244                                             ArrayRef<ValueAndLength> Operands) {
245   Contents.push_back({Opcode, Byte});
246   Contents.insert(Contents.end(), Operands.begin(), Operands.end());
247 }
248 
249 void dwarfgen::LineTable::addExtendedOpcode(uint64_t Length, uint8_t Opcode,
250                                             ArrayRef<ValueAndLength> Operands) {
251   Contents.push_back({0, Byte});
252   Contents.push_back({Length, ULEB});
253   Contents.push_back({Opcode, Byte});
254   Contents.insert(Contents.end(), Operands.begin(), Operands.end());
255 }
256 
257 void dwarfgen::LineTable::generate(MCContext &MC, AsmPrinter &Asm) const {
258   MC.setDwarfVersion(Version);
259 
260   MCSymbol *EndSymbol = nullptr;
261   if (!CustomPrologue.empty()) {
262     writeData(CustomPrologue, Asm);
263   } else if (!Prologue) {
264     EndSymbol = writeDefaultPrologue(Asm);
265   } else {
266     writePrologue(Asm);
267   }
268 
269   writeData(Contents, Asm);
270   if (EndSymbol != nullptr)
271     Asm.OutStreamer->emitLabel(EndSymbol);
272 }
273 
274 void dwarfgen::LineTable::writeData(ArrayRef<ValueAndLength> Data,
275                                     AsmPrinter &Asm) const {
276   for (auto Entry : Data) {
277     switch (Entry.Length) {
278     case Byte:
279     case Half:
280     case Long:
281     case Quad:
282       Asm.OutStreamer->emitIntValue(Entry.Value, Entry.Length);
283       continue;
284     case ULEB:
285       Asm.emitULEB128(Entry.Value);
286       continue;
287     case SLEB:
288       Asm.emitSLEB128(Entry.Value);
289       continue;
290     }
291     llvm_unreachable("unsupported ValueAndLength Length value");
292   }
293 }
294 
295 size_t dwarfgen::LineTable::getContentsSize() const {
296   size_t Size = 0;
297   for (auto Entry : Contents) {
298     switch (Entry.Length) {
299     case ULEB:
300       Size += getULEB128Size(Entry.Value);
301       break;
302     case SLEB:
303       Size += getSLEB128Size(Entry.Value);
304       break;
305     default:
306       Size += Entry.Length;
307       break;
308     }
309   }
310   return Size;
311 }
312 
313 MCSymbol *dwarfgen::LineTable::writeDefaultPrologue(AsmPrinter &Asm) const {
314   MCSymbol *UnitStart = Asm.createTempSymbol("line_unit_start");
315   MCSymbol *UnitEnd = Asm.createTempSymbol("line_unit_end");
316   if (Format == DwarfFormat::DWARF64) {
317     Asm.emitInt32((int)dwarf::DW_LENGTH_DWARF64);
318     Asm.emitLabelDifference(UnitEnd, UnitStart, 8);
319   } else {
320     Asm.emitLabelDifference(UnitEnd, UnitStart, 4);
321   }
322   Asm.OutStreamer->emitLabel(UnitStart);
323   Asm.emitInt16(Version);
324   if (Version == 5) {
325     Asm.emitInt8(AddrSize);
326     Asm.emitInt8(SegSize);
327   }
328 
329   MCSymbol *PrologueStart = Asm.createTempSymbol("line_prologue_start");
330   MCSymbol *PrologueEnd = Asm.createTempSymbol("line_prologue_end");
331   Asm.emitLabelDifference(PrologueEnd, PrologueStart,
332                           Format == DwarfFormat::DWARF64 ? 8 : 4);
333   Asm.OutStreamer->emitLabel(PrologueStart);
334 
335   DWARFDebugLine::Prologue DefaultPrologue = createBasicPrologue();
336   writeProloguePayload(DefaultPrologue, Asm);
337   Asm.OutStreamer->emitLabel(PrologueEnd);
338   return UnitEnd;
339 }
340 
341 void dwarfgen::LineTable::writePrologue(AsmPrinter &Asm) const {
342   if (Format == DwarfFormat::DWARF64) {
343     Asm.emitInt32((int)dwarf::DW_LENGTH_DWARF64);
344     Asm.emitInt64(Prologue->TotalLength);
345   } else {
346     Asm.emitInt32(Prologue->TotalLength);
347   }
348   Asm.emitInt16(Prologue->getVersion());
349   if (Version == 5) {
350     Asm.emitInt8(Prologue->getAddressSize());
351     Asm.emitInt8(Prologue->SegSelectorSize);
352   }
353   if (Format == DwarfFormat::DWARF64)
354     Asm.emitInt64(Prologue->PrologueLength);
355   else
356     Asm.emitInt32(Prologue->PrologueLength);
357 
358   writeProloguePayload(*Prologue, Asm);
359 }
360 
361 static void writeCString(StringRef Str, AsmPrinter &Asm) {
362   Asm.OutStreamer->emitBytes(Str);
363   Asm.emitInt8(0);
364 }
365 
366 static void writeV2IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,
367                                        AsmPrinter &Asm) {
368   for (auto Include : Prologue.IncludeDirectories)
369     writeCString(*toString(Include), Asm);
370 
371   Asm.emitInt8(0);
372 
373   for (auto File : Prologue.FileNames) {
374     writeCString(*toString(File.Name), Asm);
375     Asm.emitULEB128(File.DirIdx);
376     Asm.emitULEB128(File.ModTime);
377     Asm.emitULEB128(File.Length);
378   }
379   Asm.emitInt8(0);
380 }
381 
382 static void writeV5IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,
383                                        AsmPrinter &Asm) {
384   Asm.emitInt8(1); // directory_entry_format_count.
385   // TODO: Add support for other content descriptions - we currently only
386   // support a single DW_LNCT_path/DW_FORM_string.
387   Asm.emitULEB128(DW_LNCT_path);
388   Asm.emitULEB128(DW_FORM_string);
389   Asm.emitULEB128(Prologue.IncludeDirectories.size());
390   for (auto Include : Prologue.IncludeDirectories)
391     writeCString(*toString(Include), Asm);
392 
393   Asm.emitInt8(2); // file_name_entry_format_count.
394   Asm.emitULEB128(DW_LNCT_path);
395   Asm.emitULEB128(DW_FORM_string);
396   Asm.emitULEB128(DW_LNCT_directory_index);
397   Asm.emitULEB128(DW_FORM_data1);
398   Asm.emitULEB128(Prologue.FileNames.size());
399   for (auto File : Prologue.FileNames) {
400     writeCString(*toString(File.Name), Asm);
401     Asm.emitInt8(File.DirIdx);
402   }
403 }
404 
405 void dwarfgen::LineTable::writeProloguePayload(
406     const DWARFDebugLine::Prologue &Prologue, AsmPrinter &Asm) const {
407   Asm.emitInt8(Prologue.MinInstLength);
408   if (Version >= 4)
409     Asm.emitInt8(Prologue.MaxOpsPerInst);
410   Asm.emitInt8(Prologue.DefaultIsStmt);
411   Asm.emitInt8(Prologue.LineBase);
412   Asm.emitInt8(Prologue.LineRange);
413   Asm.emitInt8(Prologue.OpcodeBase);
414   for (auto Length : Prologue.StandardOpcodeLengths) {
415     Asm.emitInt8(Length);
416   }
417 
418   if (Version < 5)
419     writeV2IncludeAndFileTable(Prologue, Asm);
420   else
421     writeV5IncludeAndFileTable(Prologue, Asm);
422 }
423 
424 //===----------------------------------------------------------------------===//
425 /// dwarfgen::Generator implementation.
426 //===----------------------------------------------------------------------===//
427 
428 dwarfgen::Generator::Generator()
429     : MAB(nullptr), MCE(nullptr), MS(nullptr), TLOF(nullptr),
430       StringPool(nullptr), Abbreviations(Allocator),
431       StringOffsetsStartSym(nullptr), Version(0) {}
432 dwarfgen::Generator::~Generator() = default;
433 
434 llvm::Expected<std::unique_ptr<dwarfgen::Generator>>
435 dwarfgen::Generator::create(Triple TheTriple, uint16_t DwarfVersion) {
436   std::unique_ptr<dwarfgen::Generator> GenUP(new dwarfgen::Generator());
437   llvm::Error error = GenUP->init(TheTriple, DwarfVersion);
438   if (error)
439     return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(error));
440   return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(GenUP));
441 }
442 
443 llvm::Error dwarfgen::Generator::init(Triple TheTriple, uint16_t V) {
444   Version = V;
445   std::string ErrorStr;
446   std::string TripleName;
447 
448   // Get the target.
449   const Target *TheTarget =
450       TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
451   if (!TheTarget)
452     return make_error<StringError>(ErrorStr, inconvertibleErrorCode());
453 
454   TripleName = TheTriple.getTriple();
455 
456   // Create all the MC Objects.
457   MRI.reset(TheTarget->createMCRegInfo(TripleName));
458   if (!MRI)
459     return make_error<StringError>(Twine("no register info for target ") +
460                                        TripleName,
461                                    inconvertibleErrorCode());
462 
463   MCTargetOptions MCOptions = mc::InitMCTargetOptionsFromFlags();
464   MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName, MCOptions));
465   if (!MAI)
466     return make_error<StringError>("no asm info for target " + TripleName,
467                                    inconvertibleErrorCode());
468 
469   MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
470   if (!MSTI)
471     return make_error<StringError>("no subtarget info for target " + TripleName,
472                                    inconvertibleErrorCode());
473 
474   MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
475   if (!MAB)
476     return make_error<StringError>("no asm backend for target " + TripleName,
477                                    inconvertibleErrorCode());
478 
479   MII.reset(TheTarget->createMCInstrInfo());
480   if (!MII)
481     return make_error<StringError>("no instr info info for target " +
482                                        TripleName,
483                                    inconvertibleErrorCode());
484 
485   TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
486                                           std::nullopt));
487   if (!TM)
488     return make_error<StringError>("no target machine for target " + TripleName,
489                                    inconvertibleErrorCode());
490 
491   MC.reset(new MCContext(TheTriple, MAI.get(), MRI.get(), MSTI.get()));
492   TLOF = TM->getObjFileLowering();
493   TLOF->Initialize(*MC, *TM);
494   MC->setObjectFileInfo(TLOF);
495 
496   MCE = TheTarget->createMCCodeEmitter(*MII, *MC);
497   if (!MCE)
498     return make_error<StringError>("no code emitter for target " + TripleName,
499                                    inconvertibleErrorCode());
500 
501   Stream = std::make_unique<raw_svector_ostream>(FileBytes);
502 
503   MS = TheTarget->createMCObjectStreamer(
504       TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
505       MAB->createObjectWriter(*Stream), std::unique_ptr<MCCodeEmitter>(MCE),
506       *MSTI);
507   if (!MS)
508     return make_error<StringError>("no object streamer for target " +
509                                        TripleName,
510                                    inconvertibleErrorCode());
511 
512 
513   // Finally create the AsmPrinter we'll use to emit the DIEs.
514   Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
515   if (!Asm)
516     return make_error<StringError>("no asm printer for target " + TripleName,
517                                    inconvertibleErrorCode());
518 
519   // Set the DWARF version correctly on all classes that we use.
520   MC->setDwarfVersion(Version);
521   Asm->setDwarfVersion(Version);
522 
523   StringPool = std::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
524   StringOffsetsStartSym = Asm->createTempSymbol("str_offsets_base");
525 
526   AddrTableStartSym = Asm->createTempSymbol("addr_table_base");
527 
528   return Error::success();
529 }
530 
531 unsigned dwarfgen::Generator::DummyAddressPool::getIndex(uint64_t Address) {
532   AddressValues.push_back(Address);
533   return static_cast<unsigned>(AddressValues.size() - 1);
534 }
535 
536 void dwarfgen::Generator::DummyAddressPool::emit(AsmPrinter &Asm,
537                                                  MCSection *AddrSection,
538                                                  MCSymbol *StartSym) {
539   const uint8_t AddrSize = Asm.getPointerSize();
540 
541   // Switch to .debug_addr section
542   Asm.OutStreamer->switchSection(AddrSection);
543 
544   if (Asm.getDwarfVersion() >= 5) {
545     // Emit header
546     Asm.emitDwarfUnitLength(AddrSize * AddressValues.size() + 4,
547                             "Length of contribution");
548     Asm.emitInt16(Asm.getDwarfVersion());
549     Asm.emitInt8(AddrSize);
550     Asm.emitInt8(0);
551   }
552 
553   if (StartSym)
554     Asm.OutStreamer->emitLabel(StartSym);
555 
556   // Emit addresses
557   for (uint64_t Addr : AddressValues)
558     Asm.OutStreamer->emitIntValue(Addr, AddrSize);
559 }
560 
561 StringRef dwarfgen::Generator::generate() {
562   // Offset from the first CU in the debug info section is 0 initially.
563   uint64_t SecOffset = 0;
564 
565   // Iterate over each compile unit and set the size and offsets for each
566   // DIE within each compile unit. All offsets are CU relative.
567   for (auto &CU : CompileUnits) {
568     // Set the absolute .debug_info offset for this compile unit.
569     CU->setOffset(SecOffset);
570     // The DIEs contain compile unit relative offsets and the offset depends
571     // on the Dwarf version.
572     unsigned CUOffset = 4 + // Length
573                         2 + // Version
574                         4 + // Abbreviation offset
575                         1;  // Address size
576     if (Asm->getDwarfVersion() >= 5)
577       CUOffset += 1; // DW_UT_compile tag.
578 
579     CUOffset = CU->getUnitDIE().computeSizeAndOffsets(CUOffset);
580     // Update our absolute .debug_info offset.
581     SecOffset += CUOffset;
582     unsigned CUOffsetUnitLength = 4;
583     CU->setLength(CUOffset - CUOffsetUnitLength);
584   }
585   Abbreviations.Emit(Asm.get(), TLOF->getDwarfAbbrevSection());
586 
587   StringPool->emitStringOffsetsTableHeader(*Asm, TLOF->getDwarfStrOffSection(),
588                                            StringOffsetsStartSym);
589   StringPool->emit(*Asm, TLOF->getDwarfStrSection(),
590                    TLOF->getDwarfStrOffSection());
591 
592   if (Asm->getDwarfVersion() >= 5)
593     AddressPool.emit(*Asm, TLOF->getDwarfAddrSection(), AddrTableStartSym);
594 
595   MS->switchSection(TLOF->getDwarfInfoSection());
596   for (auto &CU : CompileUnits) {
597     uint16_t Version = CU->getVersion();
598     auto Length = CU->getLength();
599     MC->setDwarfVersion(Version);
600     assert(Length != -1U);
601     Asm->emitInt32(Length);
602     Asm->emitInt16(Version);
603     if (Version <= 4) {
604       Asm->emitInt32(0);
605       Asm->emitInt8(CU->getAddressSize());
606     } else {
607       Asm->emitInt8(dwarf::DW_UT_compile);
608       Asm->emitInt8(CU->getAddressSize());
609       Asm->emitInt32(0);
610     }
611     Asm->emitDwarfDIE(*CU->getUnitDIE().Die);
612   }
613 
614   MS->switchSection(TLOF->getDwarfLineSection());
615   for (auto &LT : LineTables)
616     LT->generate(*MC, *Asm);
617 
618   MS->finish();
619   if (FileBytes.empty())
620     return StringRef();
621   return StringRef(FileBytes.data(), FileBytes.size());
622 }
623 
624 bool dwarfgen::Generator::saveFile(StringRef Path) {
625   if (FileBytes.empty())
626     return false;
627   std::error_code EC;
628   raw_fd_ostream Strm(Path, EC, sys::fs::OF_None);
629   if (EC)
630     return false;
631   Strm.write(FileBytes.data(), FileBytes.size());
632   Strm.close();
633   return true;
634 }
635 
636 dwarfgen::CompileUnit &dwarfgen::Generator::addCompileUnit() {
637   CompileUnits.push_back(
638       std::make_unique<CompileUnit>(*this, Version, Asm->getPointerSize()));
639   return *CompileUnits.back();
640 }
641 
642 dwarfgen::LineTable &dwarfgen::Generator::addLineTable(DwarfFormat Format) {
643   LineTables.push_back(
644       std::make_unique<LineTable>(Version, Format, Asm->getPointerSize()));
645   return *LineTables.back();
646 }
647