blob: 4f4a7375eaa5e24d6438adcb7b404fea3f52fb0a [file] [log] [blame]
Daniel Jasper0f778692016-12-08 12:45:29 +00001//===--- unittests/DebugInfo/DWARF/DwarfGenerator.cpp -----------*- C++ -*-===//
Greg Clayton3462a422016-12-08 01:03:48 +00002//
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"
Chandler Carruth9a67b072017-06-06 11:06:56 +000011#include "../lib/CodeGen/AsmPrinter/DwarfStringPool.h"
Greg Clayton3462a422016-12-08 01:03:48 +000012#include "llvm/ADT/Triple.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000013#include "llvm/BinaryFormat/Dwarf.h"
Greg Clayton3462a422016-12-08 01:03:48 +000014#include "llvm/CodeGen/AsmPrinter.h"
15#include "llvm/CodeGen/DIE.h"
Greg Clayton3462a422016-12-08 01:03:48 +000016#include "llvm/DebugInfo/DWARF/DWARFDebugLine.h"
17#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
Greg Clayton3462a422016-12-08 01:03:48 +000018#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"
Peter Collingbournef7b81db2018-05-18 18:26:45 +000025#include "llvm/MC/MCObjectWriter.h"
Greg Clayton3462a422016-12-08 01:03:48 +000026#include "llvm/MC/MCRegisterInfo.h"
27#include "llvm/MC/MCStreamer.h"
28#include "llvm/MC/MCSubtargetInfo.h"
David Blaikie4333f972018-04-11 18:49:37 +000029#include "llvm/MC/MCTargetOptionsCommandFlags.inc"
Greg Clayton3462a422016-12-08 01:03:48 +000030#include "llvm/PassAnalysisSupport.h"
Greg Clayton3462a422016-12-08 01:03:48 +000031#include "llvm/Support/TargetRegistry.h"
32#include "llvm/Support/raw_ostream.h"
Pavel Labathfac87b3d2018-07-26 13:16:06 +000033#include "llvm/Target/TargetLoweringObjectFile.h"
Greg Clayton3462a422016-12-08 01:03:48 +000034#include "llvm/Target/TargetMachine.h"
35#include "llvm/Target/TargetOptions.h"
36
37using namespace llvm;
38using namespace dwarf;
39
40namespace {} // end anonymous namespace
41
42//===----------------------------------------------------------------------===//
43/// dwarfgen::DIE implementation.
44//===----------------------------------------------------------------------===//
45unsigned dwarfgen::DIE::computeSizeAndOffsets(unsigned Offset) {
46 auto &DG = CU->getGenerator();
47 return Die->computeOffsetsAndAbbrevs(DG.getAsmPrinter(), DG.getAbbrevSet(),
48 Offset);
49}
50
51void 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
57void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
58 StringRef String) {
59 auto &DG = CU->getGenerator();
Pavel Labathda3c4fb2018-07-25 16:34:43 +000060 if (Form == DW_FORM_string) {
Greg Clayton3462a422016-12-08 01:03:48 +000061 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
Benjamin Kramereedc4052016-12-09 13:33:41 +000062 new (DG.getAllocator())
63 DIEInlineString(String, DG.getAllocator()));
Pavel Labathda3c4fb2018-07-25 16:34:43 +000064 } else {
Greg Clayton3462a422016-12-08 01:03:48 +000065 Die->addValue(
66 DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
67 DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
68 }
69}
70
71void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form,
72 dwarfgen::DIE &RefDie) {
73 auto &DG = CU->getGenerator();
74 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
75 DIEEntry(*RefDie.Die));
76}
77
78void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form, const void *P,
79 size_t S) {
80 auto &DG = CU->getGenerator();
81 DIEBlock *Block = new (DG.getAllocator()) DIEBlock;
82 for (size_t I = 0; I < S; ++I)
Saleem Abdulrasoolecf13bb2016-12-27 18:35:24 +000083 Block->addValue(
84 DG.getAllocator(), (dwarf::Attribute)0, dwarf::DW_FORM_data1,
85 DIEInteger(
86 (const_cast<uint8_t *>(static_cast<const uint8_t *>(P)))[I]));
Greg Clayton3462a422016-12-08 01:03:48 +000087
88 Block->ComputeSize(DG.getAsmPrinter());
89 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
90 Block);
91}
92
93void dwarfgen::DIE::addAttribute(uint16_t A, dwarf::Form Form) {
94 auto &DG = CU->getGenerator();
95 assert(Form == DW_FORM_flag_present);
96 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
97 DIEInteger(1));
98}
99
100dwarfgen::DIE dwarfgen::DIE::addChild(dwarf::Tag Tag) {
101 auto &DG = CU->getGenerator();
102 return dwarfgen::DIE(CU,
103 &Die->addChild(llvm::DIE::get(DG.getAllocator(), Tag)));
104}
105
106dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() {
107 return dwarfgen::DIE(this, &DU.getUnitDie());
108}
109
110//===----------------------------------------------------------------------===//
James Hendersona3acf992018-05-10 10:51:33 +0000111/// dwarfgen::LineTable implementation.
112//===----------------------------------------------------------------------===//
113DWARFDebugLine::Prologue dwarfgen::LineTable::createBasicPrologue() const {
114 DWARFDebugLine::Prologue P;
115 switch (Version) {
116 case 2:
117 case 3:
118 P.TotalLength = 41;
119 P.PrologueLength = 35;
120 break;
121 case 4:
122 P.TotalLength = 42;
123 P.PrologueLength = 36;
124 break;
125 case 5:
126 P.TotalLength = 47;
127 P.PrologueLength = 39;
128 P.FormParams.AddrSize = AddrSize;
129 break;
130 default:
131 llvm_unreachable("unsupported version");
132 }
133 if (Format == DWARF64) {
134 P.TotalLength += 4;
135 P.FormParams.Format = DWARF64;
136 }
137 P.FormParams.Version = Version;
138 P.MinInstLength = 1;
139 P.MaxOpsPerInst = 1;
140 P.DefaultIsStmt = 1;
141 P.LineBase = -5;
142 P.LineRange = 14;
143 P.OpcodeBase = 13;
144 P.StandardOpcodeLengths = {0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1};
145 P.IncludeDirectories.push_back(DWARFFormValue(DW_FORM_string));
146 P.IncludeDirectories.back().setPValue("a dir");
147 P.FileNames.push_back(DWARFDebugLine::FileNameEntry());
148 P.FileNames.back().Name.setPValue("a file");
149 P.FileNames.back().Name.setForm(DW_FORM_string);
150 return P;
151}
152
153void dwarfgen::LineTable::setPrologue(DWARFDebugLine::Prologue NewPrologue) {
154 Prologue = NewPrologue;
155 CustomPrologue.clear();
156}
157
158void dwarfgen::LineTable::setCustomPrologue(
159 ArrayRef<ValueAndLength> NewPrologue) {
160 Prologue.reset();
161 CustomPrologue = NewPrologue;
162}
163
164void dwarfgen::LineTable::addByte(uint8_t Value) {
165 Contents.push_back({Value, Byte});
166}
167
168void dwarfgen::LineTable::addStandardOpcode(uint8_t Opcode,
169 ArrayRef<ValueAndLength> Operands) {
170 Contents.push_back({Opcode, Byte});
171 Contents.insert(Contents.end(), Operands.begin(), Operands.end());
172}
173
174void dwarfgen::LineTable::addExtendedOpcode(uint64_t Length, uint8_t Opcode,
175 ArrayRef<ValueAndLength> Operands) {
176 Contents.push_back({0, Byte});
177 Contents.push_back({Length, ULEB});
178 Contents.push_back({Opcode, Byte});
179 Contents.insert(Contents.end(), Operands.begin(), Operands.end());
180}
181
182void dwarfgen::LineTable::generate(MCContext &MC, AsmPrinter &Asm) const {
183 MC.setDwarfVersion(Version);
184
185 MCSymbol *EndSymbol = nullptr;
186 if (!CustomPrologue.empty()) {
187 writeData(CustomPrologue, Asm);
188 } else if (!Prologue) {
189 EndSymbol = writeDefaultPrologue(Asm);
190 } else {
191 writePrologue(Asm);
192 }
193
194 writeData(Contents, Asm);
195 if (EndSymbol != nullptr)
196 Asm.OutStreamer->EmitLabel(EndSymbol);
197}
198
199void dwarfgen::LineTable::writeData(ArrayRef<ValueAndLength> Data,
200 AsmPrinter &Asm) const {
201 for (auto Entry : Data) {
202 switch (Entry.Length) {
203 case Byte:
204 case Half:
205 case Long:
206 case Quad:
207 Asm.OutStreamer->EmitIntValue(Entry.Value, Entry.Length);
Roman Lebedeve1b0e292018-05-10 14:16:41 +0000208 continue;
James Hendersona3acf992018-05-10 10:51:33 +0000209 case ULEB:
210 Asm.EmitULEB128(Entry.Value);
Roman Lebedeve1b0e292018-05-10 14:16:41 +0000211 continue;
James Hendersona3acf992018-05-10 10:51:33 +0000212 case SLEB:
213 Asm.EmitSLEB128(Entry.Value);
Roman Lebedeve1b0e292018-05-10 14:16:41 +0000214 continue;
James Hendersona3acf992018-05-10 10:51:33 +0000215 }
Roman Lebedeve1b0e292018-05-10 14:16:41 +0000216 llvm_unreachable("unsupported ValueAndLength Length value");
James Hendersona3acf992018-05-10 10:51:33 +0000217 }
218}
219
220MCSymbol *dwarfgen::LineTable::writeDefaultPrologue(AsmPrinter &Asm) const {
221 MCSymbol *UnitStart = Asm.createTempSymbol("line_unit_start");
222 MCSymbol *UnitEnd = Asm.createTempSymbol("line_unit_end");
223 if (Format == DwarfFormat::DWARF64) {
224 Asm.emitInt32(0xffffffff);
225 Asm.EmitLabelDifference(UnitEnd, UnitStart, 8);
226 } else {
227 Asm.EmitLabelDifference(UnitEnd, UnitStart, 4);
228 }
229 Asm.OutStreamer->EmitLabel(UnitStart);
230 Asm.emitInt16(Version);
231 if (Version == 5) {
232 Asm.emitInt8(AddrSize);
233 Asm.emitInt8(SegSize);
234 }
235
236 MCSymbol *PrologueStart = Asm.createTempSymbol("line_prologue_start");
237 MCSymbol *PrologueEnd = Asm.createTempSymbol("line_prologue_end");
238 Asm.EmitLabelDifference(PrologueEnd, PrologueStart,
239 Format == DwarfFormat::DWARF64 ? 8 : 4);
240 Asm.OutStreamer->EmitLabel(PrologueStart);
241
242 DWARFDebugLine::Prologue DefaultPrologue = createBasicPrologue();
243 writeProloguePayload(DefaultPrologue, Asm);
244 Asm.OutStreamer->EmitLabel(PrologueEnd);
245 return UnitEnd;
246}
247
248void dwarfgen::LineTable::writePrologue(AsmPrinter &Asm) const {
249 if (Format == DwarfFormat::DWARF64) {
250 Asm.emitInt32(0xffffffff);
251 Asm.emitInt64(Prologue->TotalLength);
252 } else {
253 Asm.emitInt32(Prologue->TotalLength);
254 }
255 Asm.emitInt16(Prologue->getVersion());
256 if (Version == 5) {
257 Asm.emitInt8(Prologue->getAddressSize());
258 Asm.emitInt8(Prologue->SegSelectorSize);
259 }
260 if (Format == DwarfFormat::DWARF64)
261 Asm.emitInt64(Prologue->PrologueLength);
262 else
263 Asm.emitInt32(Prologue->PrologueLength);
264
265 writeProloguePayload(*Prologue, Asm);
266}
267
268static void writeCString(StringRef Str, AsmPrinter &Asm) {
269 Asm.OutStreamer->EmitBytes(Str);
270 Asm.emitInt8(0);
271}
272
273static void writeV2IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,
274 AsmPrinter &Asm) {
275 for (auto Include : Prologue.IncludeDirectories) {
276 assert(Include.getAsCString() && "expected a string form for include dir");
277 writeCString(*Include.getAsCString(), Asm);
278 }
279 Asm.emitInt8(0);
280
281 for (auto File : Prologue.FileNames) {
282 assert(File.Name.getAsCString() && "expected a string form for file name");
283 writeCString(*File.Name.getAsCString(), Asm);
284 Asm.EmitULEB128(File.DirIdx);
285 Asm.EmitULEB128(File.ModTime);
286 Asm.EmitULEB128(File.Length);
287 }
288 Asm.emitInt8(0);
289}
290
291static void writeV5IncludeAndFileTable(const DWARFDebugLine::Prologue &Prologue,
292 AsmPrinter &Asm) {
293 Asm.emitInt8(1); // directory_entry_format_count.
294 // TODO: Add support for other content descriptions - we currently only
295 // support a single DW_LNCT_path/DW_FORM_string.
296 Asm.EmitULEB128(DW_LNCT_path);
297 Asm.EmitULEB128(DW_FORM_string);
298 Asm.EmitULEB128(Prologue.IncludeDirectories.size());
299 for (auto Include : Prologue.IncludeDirectories) {
300 assert(Include.getAsCString() && "expected a string form for include dir");
301 writeCString(*Include.getAsCString(), Asm);
302 }
303
304 Asm.emitInt8(1); // file_name_entry_format_count.
305 Asm.EmitULEB128(DW_LNCT_path);
306 Asm.EmitULEB128(DW_FORM_string);
307 Asm.EmitULEB128(Prologue.FileNames.size());
308 for (auto File : Prologue.FileNames) {
309 assert(File.Name.getAsCString() && "expected a string form for file name");
310 writeCString(*File.Name.getAsCString(), Asm);
311 }
312}
313
314void dwarfgen::LineTable::writeProloguePayload(
315 const DWARFDebugLine::Prologue &Prologue, AsmPrinter &Asm) const {
316 Asm.emitInt8(Prologue.MinInstLength);
317 if (Version >= 4)
318 Asm.emitInt8(Prologue.MaxOpsPerInst);
319 Asm.emitInt8(Prologue.DefaultIsStmt);
320 Asm.emitInt8(Prologue.LineBase);
321 Asm.emitInt8(Prologue.LineRange);
322 Asm.emitInt8(Prologue.OpcodeBase);
323 for (auto Length : Prologue.StandardOpcodeLengths) {
324 Asm.emitInt8(Length);
325 }
326
327 if (Version < 5)
328 writeV2IncludeAndFileTable(Prologue, Asm);
329 else
330 writeV5IncludeAndFileTable(Prologue, Asm);
331}
332
333//===----------------------------------------------------------------------===//
Greg Clayton3462a422016-12-08 01:03:48 +0000334/// dwarfgen::Generator implementation.
335//===----------------------------------------------------------------------===//
336
Greg Claytonb9032832016-12-08 16:57:04 +0000337dwarfgen::Generator::Generator()
338 : MAB(nullptr), MCE(nullptr), MS(nullptr), StringPool(nullptr),
339 Abbreviations(Allocator) {}
Greg Clayton3462a422016-12-08 01:03:48 +0000340dwarfgen::Generator::~Generator() = default;
341
342llvm::Expected<std::unique_ptr<dwarfgen::Generator>>
343dwarfgen::Generator::create(Triple TheTriple, uint16_t DwarfVersion) {
344 std::unique_ptr<dwarfgen::Generator> GenUP(new dwarfgen::Generator());
345 llvm::Error error = GenUP->init(TheTriple, DwarfVersion);
346 if (error)
347 return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(error));
348 return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(GenUP));
349}
350
351llvm::Error dwarfgen::Generator::init(Triple TheTriple, uint16_t V) {
352 Version = V;
353 std::string ErrorStr;
354 std::string TripleName;
355
356 // Get the target.
357 const Target *TheTarget =
358 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
359 if (!TheTarget)
360 return make_error<StringError>(ErrorStr, inconvertibleErrorCode());
361
362 TripleName = TheTriple.getTriple();
363
364 // Create all the MC Objects.
365 MRI.reset(TheTarget->createMCRegInfo(TripleName));
366 if (!MRI)
367 return make_error<StringError>(Twine("no register info for target ") +
368 TripleName,
369 inconvertibleErrorCode());
370
371 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName));
372 if (!MAI)
373 return make_error<StringError>("no asm info for target " + TripleName,
374 inconvertibleErrorCode());
375
Alex Bradburyb22f7512018-01-03 08:53:05 +0000376 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
377 if (!MSTI)
378 return make_error<StringError>("no subtarget info for target " + TripleName,
379 inconvertibleErrorCode());
380
David Blaikieeef5c232017-11-27 19:55:16 +0000381 MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
Alex Bradburyb22f7512018-01-03 08:53:05 +0000382 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
Greg Clayton3462a422016-12-08 01:03:48 +0000383 if (!MAB)
384 return make_error<StringError>("no asm backend for target " + TripleName,
385 inconvertibleErrorCode());
386
387 MII.reset(TheTarget->createMCInstrInfo());
388 if (!MII)
389 return make_error<StringError>("no instr info info for target " +
390 TripleName,
391 inconvertibleErrorCode());
392
Pavel Labathfac87b3d2018-07-26 13:16:06 +0000393 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
394 None));
395 if (!TM)
396 return make_error<StringError>("no target machine for target " + TripleName,
397 inconvertibleErrorCode());
398
399 TLOF = TM->getObjFileLowering();
400 MC.reset(new MCContext(MAI.get(), MRI.get(), TLOF));
401 TLOF->Initialize(*MC, *TM);
402
Greg Clayton3462a422016-12-08 01:03:48 +0000403 MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MC);
404 if (!MCE)
405 return make_error<StringError>("no code emitter for target " + TripleName,
406 inconvertibleErrorCode());
407
408 Stream = make_unique<raw_svector_ostream>(FileBytes);
409
Greg Clayton3462a422016-12-08 01:03:48 +0000410 MS = TheTarget->createMCObjectStreamer(
Peter Collingbournef7b81db2018-05-18 18:26:45 +0000411 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB),
412 MAB->createObjectWriter(*Stream), std::unique_ptr<MCCodeEmitter>(MCE),
413 *MSTI, MCOptions.MCRelaxAll, MCOptions.MCIncrementalLinkerCompatible,
Greg Clayton3462a422016-12-08 01:03:48 +0000414 /*DWARFMustBeAtTheEnd*/ false);
415 if (!MS)
416 return make_error<StringError>("no object streamer for target " +
417 TripleName,
418 inconvertibleErrorCode());
419
Greg Clayton3462a422016-12-08 01:03:48 +0000420
Pavel Labathfac87b3d2018-07-26 13:16:06 +0000421 // Finally create the AsmPrinter we'll use to emit the DIEs.
Greg Clayton3462a422016-12-08 01:03:48 +0000422 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
423 if (!Asm)
424 return make_error<StringError>("no asm printer for target " + TripleName,
425 inconvertibleErrorCode());
426
427 // Set the DWARF version correctly on all classes that we use.
428 MC->setDwarfVersion(Version);
429 Asm->setDwarfVersion(Version);
430
Benjamin Kramer9fcb7fe2016-12-09 13:12:30 +0000431 StringPool = llvm::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
Greg Clayton3462a422016-12-08 01:03:48 +0000432
433 return Error::success();
434}
435
436StringRef dwarfgen::Generator::generate() {
437 // Offset from the first CU in the debug info section is 0 initially.
438 unsigned SecOffset = 0;
439
440 // Iterate over each compile unit and set the size and offsets for each
441 // DIE within each compile unit. All offsets are CU relative.
442 for (auto &CU : CompileUnits) {
443 // Set the absolute .debug_info offset for this compile unit.
444 CU->setOffset(SecOffset);
445 // The DIEs contain compile unit relative offsets.
446 unsigned CUOffset = 11;
447 CUOffset = CU->getUnitDIE().computeSizeAndOffsets(CUOffset);
448 // Update our absolute .debug_info offset.
449 SecOffset += CUOffset;
450 CU->setLength(CUOffset - 4);
451 }
Pavel Labathfac87b3d2018-07-26 13:16:06 +0000452 Abbreviations.Emit(Asm.get(), TLOF->getDwarfAbbrevSection());
453 StringPool->emit(*Asm, TLOF->getDwarfStrSection());
454 MS->SwitchSection(TLOF->getDwarfInfoSection());
Greg Clayton3462a422016-12-08 01:03:48 +0000455 for (auto &CU : CompileUnits) {
456 uint16_t Version = CU->getVersion();
457 auto Length = CU->getLength();
458 MC->setDwarfVersion(Version);
459 assert(Length != -1U);
Rafael Espindola4b4d85f2018-03-29 23:32:54 +0000460 Asm->emitInt32(Length);
461 Asm->emitInt16(Version);
Paul Robinsoncddd6042017-02-28 20:24:55 +0000462 if (Version <= 4) {
Rafael Espindola4b4d85f2018-03-29 23:32:54 +0000463 Asm->emitInt32(0);
464 Asm->emitInt8(CU->getAddressSize());
Paul Robinsoncddd6042017-02-28 20:24:55 +0000465 } else {
Rafael Espindola4b4d85f2018-03-29 23:32:54 +0000466 Asm->emitInt8(dwarf::DW_UT_compile);
467 Asm->emitInt8(CU->getAddressSize());
468 Asm->emitInt32(0);
Paul Robinsoncddd6042017-02-28 20:24:55 +0000469 }
Greg Clayton3462a422016-12-08 01:03:48 +0000470 Asm->emitDwarfDIE(*CU->getUnitDIE().Die);
471 }
472
Pavel Labathfac87b3d2018-07-26 13:16:06 +0000473 MS->SwitchSection(TLOF->getDwarfLineSection());
James Hendersona3acf992018-05-10 10:51:33 +0000474 for (auto &LT : LineTables)
475 LT->generate(*MC, *Asm);
476
Greg Clayton3462a422016-12-08 01:03:48 +0000477 MS->Finish();
478 if (FileBytes.empty())
479 return StringRef();
480 return StringRef(FileBytes.data(), FileBytes.size());
481}
482
483bool dwarfgen::Generator::saveFile(StringRef Path) {
484 if (FileBytes.empty())
485 return false;
486 std::error_code EC;
487 raw_fd_ostream Strm(Path, EC, sys::fs::F_None);
488 if (EC)
489 return false;
490 Strm.write(FileBytes.data(), FileBytes.size());
491 Strm.close();
492 return true;
493}
494
495dwarfgen::CompileUnit &dwarfgen::Generator::addCompileUnit() {
James Hendersona3acf992018-05-10 10:51:33 +0000496 CompileUnits.push_back(
497 make_unique<CompileUnit>(*this, Version, Asm->getPointerSize()));
Greg Clayton3462a422016-12-08 01:03:48 +0000498 return *CompileUnits.back();
499}
James Hendersona3acf992018-05-10 10:51:33 +0000500
501dwarfgen::LineTable &dwarfgen::Generator::addLineTable(DwarfFormat Format) {
502 LineTables.push_back(
James Henderson198a87c2018-05-10 14:36:24 +0000503 make_unique<LineTable>(Version, Format, Asm->getPointerSize()));
James Hendersona3acf992018-05-10 10:51:33 +0000504 return *LineTables.back();
505}