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