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