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