blob: dfbdf99195d002eb497f61262578278eb4be084e [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"
25#include "llvm/MC/MCRegisterInfo.h"
26#include "llvm/MC/MCStreamer.h"
27#include "llvm/MC/MCSubtargetInfo.h"
David Blaikie4333f972018-04-11 18:49:37 +000028#include "llvm/MC/MCTargetOptionsCommandFlags.inc"
Greg Clayton3462a422016-12-08 01:03:48 +000029#include "llvm/PassAnalysisSupport.h"
Greg Clayton3462a422016-12-08 01:03:48 +000030#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
35using namespace llvm;
36using namespace dwarf;
37
38namespace {} // end anonymous namespace
39
40//===----------------------------------------------------------------------===//
41/// dwarfgen::DIE implementation.
42//===----------------------------------------------------------------------===//
43unsigned dwarfgen::DIE::computeSizeAndOffsets(unsigned Offset) {
44 auto &DG = CU->getGenerator();
45 return Die->computeOffsetsAndAbbrevs(DG.getAsmPrinter(), DG.getAbbrevSet(),
46 Offset);
47}
48
49void 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
55void 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,
Benjamin Kramereedc4052016-12-09 13:33:41 +000060 new (DG.getAllocator())
61 DIEInlineString(String, DG.getAllocator()));
Greg Clayton3462a422016-12-08 01:03:48 +000062 } else {
63 Die->addValue(
64 DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
65 DIEString(DG.getStringPool().getEntry(*DG.getAsmPrinter(), String)));
66 }
67}
68
69void 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
76void 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)
Saleem Abdulrasoolecf13bb2016-12-27 18:35:24 +000081 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]));
Greg Clayton3462a422016-12-08 01:03:48 +000085
86 Block->ComputeSize(DG.getAsmPrinter());
87 Die->addValue(DG.getAllocator(), static_cast<dwarf::Attribute>(A), Form,
88 Block);
89}
90
91void 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
98dwarfgen::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
104dwarfgen::DIE dwarfgen::CompileUnit::getUnitDIE() {
105 return dwarfgen::DIE(this, &DU.getUnitDie());
106}
107
108//===----------------------------------------------------------------------===//
109/// dwarfgen::Generator implementation.
110//===----------------------------------------------------------------------===//
111
Greg Claytonb9032832016-12-08 16:57:04 +0000112dwarfgen::Generator::Generator()
113 : MAB(nullptr), MCE(nullptr), MS(nullptr), StringPool(nullptr),
114 Abbreviations(Allocator) {}
Greg Clayton3462a422016-12-08 01:03:48 +0000115dwarfgen::Generator::~Generator() = default;
116
117llvm::Expected<std::unique_ptr<dwarfgen::Generator>>
118dwarfgen::Generator::create(Triple TheTriple, uint16_t DwarfVersion) {
119 std::unique_ptr<dwarfgen::Generator> GenUP(new dwarfgen::Generator());
120 llvm::Error error = GenUP->init(TheTriple, DwarfVersion);
121 if (error)
122 return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(error));
123 return Expected<std::unique_ptr<dwarfgen::Generator>>(std::move(GenUP));
124}
125
126llvm::Error dwarfgen::Generator::init(Triple TheTriple, uint16_t V) {
127 Version = V;
128 std::string ErrorStr;
129 std::string TripleName;
130
131 // Get the target.
132 const Target *TheTarget =
133 TargetRegistry::lookupTarget(TripleName, TheTriple, ErrorStr);
134 if (!TheTarget)
135 return make_error<StringError>(ErrorStr, inconvertibleErrorCode());
136
137 TripleName = TheTriple.getTriple();
138
139 // Create all the MC Objects.
140 MRI.reset(TheTarget->createMCRegInfo(TripleName));
141 if (!MRI)
142 return make_error<StringError>(Twine("no register info for target ") +
143 TripleName,
144 inconvertibleErrorCode());
145
146 MAI.reset(TheTarget->createMCAsmInfo(*MRI, TripleName));
147 if (!MAI)
148 return make_error<StringError>("no asm info for target " + TripleName,
149 inconvertibleErrorCode());
150
151 MOFI.reset(new MCObjectFileInfo);
152 MC.reset(new MCContext(MAI.get(), MRI.get(), MOFI.get()));
Rafael Espindola9f929952017-08-02 20:32:26 +0000153 MOFI->InitMCObjectFileInfo(TheTriple, /*PIC*/ false, *MC);
Greg Clayton3462a422016-12-08 01:03:48 +0000154
Alex Bradburyb22f7512018-01-03 08:53:05 +0000155 MSTI.reset(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
156 if (!MSTI)
157 return make_error<StringError>("no subtarget info for target " + TripleName,
158 inconvertibleErrorCode());
159
David Blaikieeef5c232017-11-27 19:55:16 +0000160 MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
Alex Bradburyb22f7512018-01-03 08:53:05 +0000161 MAB = TheTarget->createMCAsmBackend(*MSTI, *MRI, MCOptions);
Greg Clayton3462a422016-12-08 01:03:48 +0000162 if (!MAB)
163 return make_error<StringError>("no asm backend for target " + TripleName,
164 inconvertibleErrorCode());
165
166 MII.reset(TheTarget->createMCInstrInfo());
167 if (!MII)
168 return make_error<StringError>("no instr info info for target " +
169 TripleName,
170 inconvertibleErrorCode());
171
Greg Clayton3462a422016-12-08 01:03:48 +0000172 MCE = TheTarget->createMCCodeEmitter(*MII, *MRI, *MC);
173 if (!MCE)
174 return make_error<StringError>("no code emitter for target " + TripleName,
175 inconvertibleErrorCode());
176
177 Stream = make_unique<raw_svector_ostream>(FileBytes);
178
Greg Clayton3462a422016-12-08 01:03:48 +0000179 MS = TheTarget->createMCObjectStreamer(
Lang Hames2241ffa2017-10-11 23:34:47 +0000180 TheTriple, *MC, std::unique_ptr<MCAsmBackend>(MAB), *Stream,
181 std::unique_ptr<MCCodeEmitter>(MCE), *MSTI, MCOptions.MCRelaxAll,
182 MCOptions.MCIncrementalLinkerCompatible,
Greg Clayton3462a422016-12-08 01:03:48 +0000183 /*DWARFMustBeAtTheEnd*/ false);
184 if (!MS)
185 return make_error<StringError>("no object streamer for target " +
186 TripleName,
187 inconvertibleErrorCode());
188
189 // Finally create the AsmPrinter we'll use to emit the DIEs.
190 TM.reset(TheTarget->createTargetMachine(TripleName, "", "", TargetOptions(),
191 None));
192 if (!TM)
193 return make_error<StringError>("no target machine for target " + TripleName,
194 inconvertibleErrorCode());
195
196 Asm.reset(TheTarget->createAsmPrinter(*TM, std::unique_ptr<MCStreamer>(MS)));
197 if (!Asm)
198 return make_error<StringError>("no asm printer for target " + TripleName,
199 inconvertibleErrorCode());
200
201 // Set the DWARF version correctly on all classes that we use.
202 MC->setDwarfVersion(Version);
203 Asm->setDwarfVersion(Version);
204
Benjamin Kramer9fcb7fe2016-12-09 13:12:30 +0000205 StringPool = llvm::make_unique<DwarfStringPool>(Allocator, *Asm, StringRef());
Greg Clayton3462a422016-12-08 01:03:48 +0000206
207 return Error::success();
208}
209
210StringRef dwarfgen::Generator::generate() {
211 // Offset from the first CU in the debug info section is 0 initially.
212 unsigned SecOffset = 0;
213
214 // Iterate over each compile unit and set the size and offsets for each
215 // DIE within each compile unit. All offsets are CU relative.
216 for (auto &CU : CompileUnits) {
217 // Set the absolute .debug_info offset for this compile unit.
218 CU->setOffset(SecOffset);
219 // The DIEs contain compile unit relative offsets.
220 unsigned CUOffset = 11;
221 CUOffset = CU->getUnitDIE().computeSizeAndOffsets(CUOffset);
222 // Update our absolute .debug_info offset.
223 SecOffset += CUOffset;
224 CU->setLength(CUOffset - 4);
225 }
226 Abbreviations.Emit(Asm.get(), MOFI->getDwarfAbbrevSection());
227 StringPool->emit(*Asm, MOFI->getDwarfStrSection());
228 MS->SwitchSection(MOFI->getDwarfInfoSection());
229 for (auto &CU : CompileUnits) {
230 uint16_t Version = CU->getVersion();
231 auto Length = CU->getLength();
232 MC->setDwarfVersion(Version);
233 assert(Length != -1U);
Rafael Espindola4b4d85f2018-03-29 23:32:54 +0000234 Asm->emitInt32(Length);
235 Asm->emitInt16(Version);
Paul Robinsoncddd6042017-02-28 20:24:55 +0000236 if (Version <= 4) {
Rafael Espindola4b4d85f2018-03-29 23:32:54 +0000237 Asm->emitInt32(0);
238 Asm->emitInt8(CU->getAddressSize());
Paul Robinsoncddd6042017-02-28 20:24:55 +0000239 } else {
Rafael Espindola4b4d85f2018-03-29 23:32:54 +0000240 Asm->emitInt8(dwarf::DW_UT_compile);
241 Asm->emitInt8(CU->getAddressSize());
242 Asm->emitInt32(0);
Paul Robinsoncddd6042017-02-28 20:24:55 +0000243 }
Greg Clayton3462a422016-12-08 01:03:48 +0000244 Asm->emitDwarfDIE(*CU->getUnitDIE().Die);
245 }
246
247 MS->Finish();
248 if (FileBytes.empty())
249 return StringRef();
250 return StringRef(FileBytes.data(), FileBytes.size());
251}
252
253bool dwarfgen::Generator::saveFile(StringRef Path) {
254 if (FileBytes.empty())
255 return false;
256 std::error_code EC;
257 raw_fd_ostream Strm(Path, EC, sys::fs::F_None);
258 if (EC)
259 return false;
260 Strm.write(FileBytes.data(), FileBytes.size());
261 Strm.close();
262 return true;
263}
264
265dwarfgen::CompileUnit &dwarfgen::Generator::addCompileUnit() {
266 CompileUnits.push_back(std::unique_ptr<CompileUnit>(
267 new CompileUnit(*this, Version, Asm->getPointerSize())));
268 return *CompileUnits.back();
269}