1 //===--- unittests/DebugInfo/DWARF/DwarfGenerator.cpp -----------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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"
39 using namespace dwarf
;
41 mc::RegisterMCTargetOptionsFlags MOF
;
43 namespace {} // end anonymous namespace
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
);
54 void dwarfgen::DIE::addAttribute(uint16_t A
, dwarf::Form Form
, uint64_t U
) {
55 auto &DG
= CU
->getGenerator();
62 U
= DG
.getAddressPool().getIndex(U
);
67 Die
->addValue(DG
.getAllocator(), static_cast<dwarf::Attribute
>(A
), Form
,
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
,
77 void dwarfgen::DIE::addAttribute(uint16_t A
, dwarf::Form Form
,
79 auto &DG
= CU
->getGenerator();
82 Die
->addValue(DG
.getAllocator(), static_cast<dwarf::Attribute
>(A
), Form
,
83 new (DG
.getAllocator())
84 DIEInlineString(String
, DG
.getAllocator()));
89 DG
.getAllocator(), static_cast<dwarf::Attribute
>(A
), Form
,
90 DIEString(DG
.getStringPool().getEntry(*DG
.getAsmPrinter(), String
)));
93 case DW_FORM_GNU_str_index
:
99 Die
->addValue(DG
.getAllocator(), static_cast<dwarf::Attribute
>(A
), Form
,
100 DIEString(DG
.getStringPool().getIndexedEntry(
101 *DG
.getAsmPrinter(), String
)));
105 llvm_unreachable("Unhandled form!");
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
));
116 void dwarfgen::DIE::addAttribute(uint16_t A
, dwarf::Form Form
, const void *P
,
118 auto &DG
= CU
->getGenerator();
119 DIEBlock
*Block
= new (DG
.getAllocator()) DIEBlock
;
120 for (size_t I
= 0; I
< S
; ++I
)
122 DG
.getAllocator(), (dwarf::Attribute
)0, dwarf::DW_FORM_data1
,
124 (const_cast<uint8_t *>(static_cast<const uint8_t *>(P
)))[I
]));
126 Block
->computeSize(DG
.getAsmPrinter()->getDwarfFormParams());
127 Die
->addValue(DG
.getAllocator(), static_cast<dwarf::Attribute
>(A
), Form
,
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
,
138 void dwarfgen::DIE::addStrOffsetsBaseAttribute() {
139 auto &DG
= CU
->getGenerator();
140 auto &MC
= *DG
.getMCContext();
141 AsmPrinter
*Asm
= DG
.getAsmPrinter();
143 const MCSymbol
*SectionStart
=
144 Asm
->getObjFileLowering().getDwarfStrOffSection()->getBeginSymbol();
147 MCSymbolRefExpr::create(DG
.getStringOffsetsStartSym(), MC
);
149 if (!Asm
->MAI
->doesDwarfUseRelocationsAcrossSections())
150 Expr
= MCBinaryExpr::createSub(
151 Expr
, MCSymbolRefExpr::create(SectionStart
, MC
), MC
);
153 addAttribute(dwarf::DW_AT_str_offsets_base
, DW_FORM_sec_offset
, *Expr
);
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();
162 const MCSymbol
*SectionStart
=
163 Asm
->getObjFileLowering().getDwarfAddrSection()->getBeginSymbol();
165 const MCExpr
*Expr
= MCSymbolRefExpr::create(DG
.getAddrTableStartSym(), MC
);
167 if (!Asm
->MAI
->doesDwarfUseRelocationsAcrossSections())
168 Expr
= MCBinaryExpr::createSub(
169 Expr
, MCSymbolRefExpr::create(SectionStart
, MC
), MC
);
171 addAttribute(dwarf::DW_AT_addr_base
, DW_FORM_sec_offset
, *Expr
);
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
)));
180 dwarfgen::DIE
dwarfgen::CompileUnit::getUnitDIE() {
181 return dwarfgen::DIE(this, &DU
.getUnitDie());
184 //===----------------------------------------------------------------------===//
185 /// dwarfgen::LineTable implementation.
186 //===----------------------------------------------------------------------===//
187 DWARFDebugLine::Prologue
dwarfgen::LineTable::createBasicPrologue() const {
188 DWARFDebugLine::Prologue P
;
193 P
.PrologueLength
= 35;
197 P
.PrologueLength
= 36;
201 P
.PrologueLength
= 42;
202 P
.FormParams
.AddrSize
= AddrSize
;
205 llvm_unreachable("unsupported version");
207 if (Format
== DWARF64
) {
209 P
.FormParams
.Format
= DWARF64
;
211 P
.TotalLength
+= getContentsSize();
212 P
.FormParams
.Version
= Version
;
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");
228 void dwarfgen::LineTable::setPrologue(DWARFDebugLine::Prologue NewPrologue
) {
229 Prologue
= NewPrologue
;
230 CustomPrologue
.clear();
233 void dwarfgen::LineTable::setCustomPrologue(
234 ArrayRef
<ValueAndLength
> NewPrologue
) {
236 CustomPrologue
= NewPrologue
;
239 void dwarfgen::LineTable::addByte(uint8_t Value
) {
240 Contents
.push_back({Value
, Byte
});
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());
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());
257 void dwarfgen::LineTable::generate(MCContext
&MC
, AsmPrinter
&Asm
) const {
258 MC
.setDwarfVersion(Version
);
260 MCSymbol
*EndSymbol
= nullptr;
261 if (!CustomPrologue
.empty()) {
262 writeData(CustomPrologue
, Asm
);
263 } else if (!Prologue
) {
264 EndSymbol
= writeDefaultPrologue(Asm
);
269 writeData(Contents
, Asm
);
270 if (EndSymbol
!= nullptr)
271 Asm
.OutStreamer
->emitLabel(EndSymbol
);
274 void dwarfgen::LineTable::writeData(ArrayRef
<ValueAndLength
> Data
,
275 AsmPrinter
&Asm
) const {
276 for (auto Entry
: Data
) {
277 switch (Entry
.Length
) {
282 Asm
.OutStreamer
->emitIntValue(Entry
.Value
, Entry
.Length
);
285 Asm
.emitULEB128(Entry
.Value
);
288 Asm
.emitSLEB128(Entry
.Value
);
291 llvm_unreachable("unsupported ValueAndLength Length value");
295 size_t dwarfgen::LineTable::getContentsSize() const {
297 for (auto Entry
: Contents
) {
298 switch (Entry
.Length
) {
300 Size
+= getULEB128Size(Entry
.Value
);
303 Size
+= getSLEB128Size(Entry
.Value
);
306 Size
+= Entry
.Length
;
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);
320 Asm
.emitLabelDifference(UnitEnd
, UnitStart
, 4);
322 Asm
.OutStreamer
->emitLabel(UnitStart
);
323 Asm
.emitInt16(Version
);
325 Asm
.emitInt8(AddrSize
);
326 Asm
.emitInt8(SegSize
);
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
);
335 DWARFDebugLine::Prologue DefaultPrologue
= createBasicPrologue();
336 writeProloguePayload(DefaultPrologue
, Asm
);
337 Asm
.OutStreamer
->emitLabel(PrologueEnd
);
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
);
346 Asm
.emitInt32(Prologue
->TotalLength
);
348 Asm
.emitInt16(Prologue
->getVersion());
350 Asm
.emitInt8(Prologue
->getAddressSize());
351 Asm
.emitInt8(Prologue
->SegSelectorSize
);
353 if (Format
== DwarfFormat::DWARF64
)
354 Asm
.emitInt64(Prologue
->PrologueLength
);
356 Asm
.emitInt32(Prologue
->PrologueLength
);
358 writeProloguePayload(*Prologue
, Asm
);
361 static void writeCString(StringRef Str
, AsmPrinter
&Asm
) {
362 Asm
.OutStreamer
->emitBytes(Str
);
366 static void writeV2IncludeAndFileTable(const DWARFDebugLine::Prologue
&Prologue
,
368 for (auto Include
: Prologue
.IncludeDirectories
)
369 writeCString(*toString(Include
), Asm
);
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
);
382 static void writeV5IncludeAndFileTable(const DWARFDebugLine::Prologue
&Prologue
,
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
);
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
);
405 void dwarfgen::LineTable::writeProloguePayload(
406 const DWARFDebugLine::Prologue
&Prologue
, AsmPrinter
&Asm
) const {
407 Asm
.emitInt8(Prologue
.MinInstLength
);
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
);
419 writeV2IncludeAndFileTable(Prologue
, Asm
);
421 writeV5IncludeAndFileTable(Prologue
, Asm
);
424 //===----------------------------------------------------------------------===//
425 /// dwarfgen::Generator implementation.
426 //===----------------------------------------------------------------------===//
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;
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
);
439 return Expected
<std::unique_ptr
<dwarfgen::Generator
>>(std::move(error
));
440 return Expected
<std::unique_ptr
<dwarfgen::Generator
>>(std::move(GenUP
));
443 llvm::Error
dwarfgen::Generator::init(Triple TheTriple
, uint16_t V
) {
445 std::string ErrorStr
;
446 std::string TripleName
;
449 const Target
*TheTarget
=
450 TargetRegistry::lookupTarget(TripleName
, TheTriple
, ErrorStr
);
452 return make_error
<StringError
>(ErrorStr
, inconvertibleErrorCode());
454 TripleName
= TheTriple
.getTriple();
456 // Create all the MC Objects.
457 MRI
.reset(TheTarget
->createMCRegInfo(TripleName
));
459 return make_error
<StringError
>(Twine("no register info for target ") +
461 inconvertibleErrorCode());
463 MCTargetOptions MCOptions
= mc::InitMCTargetOptionsFromFlags();
464 MAI
.reset(TheTarget
->createMCAsmInfo(*MRI
, TripleName
, MCOptions
));
466 return make_error
<StringError
>("no asm info for target " + TripleName
,
467 inconvertibleErrorCode());
469 MSTI
.reset(TheTarget
->createMCSubtargetInfo(TripleName
, "", ""));
471 return make_error
<StringError
>("no subtarget info for target " + TripleName
,
472 inconvertibleErrorCode());
474 MAB
= TheTarget
->createMCAsmBackend(*MSTI
, *MRI
, MCOptions
);
476 return make_error
<StringError
>("no asm backend for target " + TripleName
,
477 inconvertibleErrorCode());
479 MII
.reset(TheTarget
->createMCInstrInfo());
481 return make_error
<StringError
>("no instr info info for target " +
483 inconvertibleErrorCode());
485 TM
.reset(TheTarget
->createTargetMachine(TripleName
, "", "", TargetOptions(),
488 return make_error
<StringError
>("no target machine for target " + TripleName
,
489 inconvertibleErrorCode());
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
);
496 MCE
= TheTarget
->createMCCodeEmitter(*MII
, *MC
);
498 return make_error
<StringError
>("no code emitter for target " + TripleName
,
499 inconvertibleErrorCode());
501 Stream
= std::make_unique
<raw_svector_ostream
>(FileBytes
);
503 MS
= TheTarget
->createMCObjectStreamer(
504 TheTriple
, *MC
, std::unique_ptr
<MCAsmBackend
>(MAB
),
505 MAB
->createObjectWriter(*Stream
), std::unique_ptr
<MCCodeEmitter
>(MCE
),
508 return make_error
<StringError
>("no object streamer for target " +
510 inconvertibleErrorCode());
513 // Finally create the AsmPrinter we'll use to emit the DIEs.
514 Asm
.reset(TheTarget
->createAsmPrinter(*TM
, std::unique_ptr
<MCStreamer
>(MS
)));
516 return make_error
<StringError
>("no asm printer for target " + TripleName
,
517 inconvertibleErrorCode());
519 // Set the DWARF version correctly on all classes that we use.
520 MC
->setDwarfVersion(Version
);
521 Asm
->setDwarfVersion(Version
);
523 StringPool
= std::make_unique
<DwarfStringPool
>(Allocator
, *Asm
, StringRef());
524 StringOffsetsStartSym
= Asm
->createTempSymbol("str_offsets_base");
526 AddrTableStartSym
= Asm
->createTempSymbol("addr_table_base");
528 return Error::success();
531 unsigned dwarfgen::Generator::DummyAddressPool::getIndex(uint64_t Address
) {
532 AddressValues
.push_back(Address
);
533 return static_cast<unsigned>(AddressValues
.size() - 1);
536 void dwarfgen::Generator::DummyAddressPool::emit(AsmPrinter
&Asm
,
537 MCSection
*AddrSection
,
538 MCSymbol
*StartSym
) {
539 const uint8_t AddrSize
= Asm
.getPointerSize();
541 // Switch to .debug_addr section
542 Asm
.OutStreamer
->switchSection(AddrSection
);
544 if (Asm
.getDwarfVersion() >= 5) {
546 Asm
.emitDwarfUnitLength(AddrSize
* AddressValues
.size() + 4,
547 "Length of contribution");
548 Asm
.emitInt16(Asm
.getDwarfVersion());
549 Asm
.emitInt8(AddrSize
);
554 Asm
.OutStreamer
->emitLabel(StartSym
);
557 for (uint64_t Addr
: AddressValues
)
558 Asm
.OutStreamer
->emitIntValue(Addr
, AddrSize
);
561 StringRef
dwarfgen::Generator::generate() {
562 // Offset from the first CU in the debug info section is 0 initially.
563 uint64_t SecOffset
= 0;
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
574 4 + // Abbreviation offset
576 if (Asm
->getDwarfVersion() >= 5)
577 CUOffset
+= 1; // DW_UT_compile tag.
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
);
585 Abbreviations
.Emit(Asm
.get(), TLOF
->getDwarfAbbrevSection());
587 StringPool
->emitStringOffsetsTableHeader(*Asm
, TLOF
->getDwarfStrOffSection(),
588 StringOffsetsStartSym
);
589 StringPool
->emit(*Asm
, TLOF
->getDwarfStrSection(),
590 TLOF
->getDwarfStrOffSection());
592 if (Asm
->getDwarfVersion() >= 5)
593 AddressPool
.emit(*Asm
, TLOF
->getDwarfAddrSection(), AddrTableStartSym
);
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
);
605 Asm
->emitInt8(CU
->getAddressSize());
607 Asm
->emitInt8(dwarf::DW_UT_compile
);
608 Asm
->emitInt8(CU
->getAddressSize());
611 Asm
->emitDwarfDIE(*CU
->getUnitDIE().Die
);
614 MS
->switchSection(TLOF
->getDwarfLineSection());
615 for (auto <
: LineTables
)
616 LT
->generate(*MC
, *Asm
);
619 if (FileBytes
.empty())
621 return StringRef(FileBytes
.data(), FileBytes
.size());
624 bool dwarfgen::Generator::saveFile(StringRef Path
) {
625 if (FileBytes
.empty())
628 raw_fd_ostream
Strm(Path
, EC
, sys::fs::OF_None
);
631 Strm
.write(FileBytes
.data(), FileBytes
.size());
636 dwarfgen::CompileUnit
&dwarfgen::Generator::addCompileUnit() {
637 CompileUnits
.push_back(
638 std::make_unique
<CompileUnit
>(*this, Version
, Asm
->getPointerSize()));
639 return *CompileUnits
.back();
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();