blob: 1e2e960b9dc57463d7e5c9a33460b205a3a44cee [file] [log] [blame]
Chris Bieneman07088c12017-01-12 21:35:21 +00001//===- DWARFEmitter - Convert YAML to DWARF binary data -------------------===//
Chris Bieneman7d7364a2016-12-07 22:30:15 +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/// \file
Chris Bieneman07088c12017-01-12 21:35:21 +000011/// \brief The DWARF component of yaml2obj. Provided as library code for tests.
Chris Bieneman7d7364a2016-12-07 22:30:15 +000012///
13//===----------------------------------------------------------------------===//
14
Chris Bieneman07088c12017-01-12 21:35:21 +000015#include "llvm/ObjectYAML/DWARFEmitter.h"
Chris Bieneman7d7364a2016-12-07 22:30:15 +000016#include "llvm/ObjectYAML/DWARFYAML.h"
17#include "llvm/Support/Error.h"
18#include "llvm/Support/LEB128.h"
19#include "llvm/Support/raw_ostream.h"
Chris Bieneman55de3a22016-12-22 21:58:03 +000020#include "llvm/Support/SwapByteOrder.h"
Chris Bieneman7d7364a2016-12-07 22:30:15 +000021
Chris Bienemane0e451d2016-12-22 22:44:27 +000022#include <algorithm>
23
Chris Bieneman7d7364a2016-12-07 22:30:15 +000024using namespace llvm;
25
Chris Bieneman55de3a22016-12-22 21:58:03 +000026template <typename T>
27void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {
28 if (IsLittleEndian != sys::IsLittleEndianHost)
29 sys::swapByteOrder(Integer);
30 OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));
31}
32
33void writeVariableSizedInteger(uint64_t Integer, size_t Size, raw_ostream &OS,
34 bool IsLittleEndian) {
35 if (8 == Size)
36 writeInteger((uint64_t)Integer, OS, IsLittleEndian);
37 else if (4 == Size)
38 writeInteger((uint32_t)Integer, OS, IsLittleEndian);
39 else if (2 == Size)
40 writeInteger((uint16_t)Integer, OS, IsLittleEndian);
41 else if (1 == Size)
42 writeInteger((uint8_t)Integer, OS, IsLittleEndian);
43 else
44 assert(false && "Invalid integer write size.");
45}
46
Chris Bieneman313b3262016-12-09 00:26:44 +000047void ZeroFillBytes(raw_ostream &OS, size_t Size) {
48 std::vector<uint8_t> FillData;
49 FillData.insert(FillData.begin(), Size, 0);
50 OS.write(reinterpret_cast<char *>(FillData.data()), Size);
51}
52
Chris Bieneman07088c12017-01-12 21:35:21 +000053void DWARFYAML::EmitDebugStr(raw_ostream &OS, const DWARFYAML::Data &DI) {
Chris Bieneman7d7364a2016-12-07 22:30:15 +000054 for (auto Str : DI.DebugStrings) {
55 OS.write(Str.data(), Str.size());
56 OS.write('\0');
57 }
58}
59
Chris Bieneman07088c12017-01-12 21:35:21 +000060void DWARFYAML::EmitDebugAbbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
Chris Bieneman7d7364a2016-12-07 22:30:15 +000061 for (auto AbbrevDecl : DI.AbbrevDecls) {
62 encodeULEB128(AbbrevDecl.Code, OS);
63 encodeULEB128(AbbrevDecl.Tag, OS);
64 OS.write(AbbrevDecl.Children);
65 for (auto Attr : AbbrevDecl.Attributes) {
66 encodeULEB128(Attr.Attribute, OS);
67 encodeULEB128(Attr.Form, OS);
68 }
69 encodeULEB128(0, OS);
70 encodeULEB128(0, OS);
71 }
72}
Chris Bieneman313b3262016-12-09 00:26:44 +000073
Chris Bieneman07088c12017-01-12 21:35:21 +000074void DWARFYAML::EmitDebugAranges(raw_ostream &OS, const DWARFYAML::Data &DI) {
Chris Bieneman313b3262016-12-09 00:26:44 +000075 for (auto Range : DI.ARanges) {
76 auto HeaderStart = OS.tell();
Chris Bieneman55de3a22016-12-22 21:58:03 +000077 writeInteger((uint32_t)Range.Length, OS, DI.IsLittleEndian);
78 writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);
79 writeInteger((uint32_t)Range.CuOffset, OS, DI.IsLittleEndian);
80 writeInteger((uint8_t)Range.AddrSize, OS, DI.IsLittleEndian);
81 writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);
Chris Bieneman313b3262016-12-09 00:26:44 +000082
83 auto HeaderSize = OS.tell() - HeaderStart;
84 auto FirstDescriptor = alignTo(HeaderSize, Range.AddrSize * 2);
85 ZeroFillBytes(OS, FirstDescriptor - HeaderSize);
86
87 for (auto Descriptor : Range.Descriptors) {
Chris Bieneman55de3a22016-12-22 21:58:03 +000088 writeVariableSizedInteger(Descriptor.Address, Range.AddrSize, OS,
89 DI.IsLittleEndian);
90 writeVariableSizedInteger(Descriptor.Length, Range.AddrSize, OS,
91 DI.IsLittleEndian);
Chris Bieneman313b3262016-12-09 00:26:44 +000092 }
93 ZeroFillBytes(OS, Range.AddrSize * 2);
94 }
95}
Chris Bienemand9430942016-12-19 22:22:12 +000096
Chris Bieneman07088c12017-01-12 21:35:21 +000097void DWARFYAML::EmitPubSection(raw_ostream &OS,
98 const DWARFYAML::PubSection &Sect,
99 bool IsLittleEndian) {
Chris Bieneman55de3a22016-12-22 21:58:03 +0000100 writeInteger((uint32_t)Sect.Length, OS, IsLittleEndian);
101 writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);
102 writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);
103 writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);
Chris Bienemand9430942016-12-19 22:22:12 +0000104 for (auto Entry : Sect.Entries) {
Chris Bieneman55de3a22016-12-22 21:58:03 +0000105 writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);
Chris Bienemand9430942016-12-19 22:22:12 +0000106 if (Sect.IsGNUStyle)
Chris Bieneman55de3a22016-12-22 21:58:03 +0000107 writeInteger((uint32_t)Entry.Descriptor, OS, IsLittleEndian);
Chris Bienemand9430942016-12-19 22:22:12 +0000108 OS.write(Entry.Name.data(), Entry.Name.size());
109 OS.write('\0');
110 }
Chris Bienemane0e451d2016-12-22 22:44:27 +0000111}
112
Chris Bieneman07088c12017-01-12 21:35:21 +0000113void DWARFYAML::EmitDebugInfo(raw_ostream &OS, const DWARFYAML::Data &DI) {
Chris Bienemane0e451d2016-12-22 22:44:27 +0000114
115 for (auto CU : DI.CompileUnits) {
116 writeInteger((uint32_t)CU.Length, OS, DI.IsLittleEndian);
117 writeInteger((uint16_t)CU.Version, OS, DI.IsLittleEndian);
118 writeInteger((uint32_t)CU.AbbrOffset, OS, DI.IsLittleEndian);
119 writeInteger((uint8_t)CU.AddrSize, OS, DI.IsLittleEndian);
120
121 auto FirstAbbrevCode = CU.Entries[0].AbbrCode;
122
123 for (auto Entry : CU.Entries) {
124 encodeULEB128(Entry.AbbrCode, OS);
125 if (Entry.AbbrCode == 0u)
126 continue;
127 bool Indirect = false;
128 assert(Entry.AbbrCode - FirstAbbrevCode < DI.AbbrevDecls.size() &&
129 "Out of range AbbCode");
130 auto &Abbrev = DI.AbbrevDecls[Entry.AbbrCode - FirstAbbrevCode];
131
132 auto FormVal = Entry.Values.begin();
133 auto AbbrForm = Abbrev.Attributes.begin();
134 for (;
135 FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
136 ++FormVal, ++AbbrForm) {
137 dwarf::Form Form = AbbrForm->Form;
138 do {
Chris Bieneman7e984682016-12-22 22:58:07 +0000139 Indirect = false;
Chris Bienemane0e451d2016-12-22 22:44:27 +0000140 switch (Form) {
141 case dwarf::DW_FORM_addr:
142 writeVariableSizedInteger(FormVal->Value, CU.AddrSize, OS,
143 DI.IsLittleEndian);
144 break;
145 case dwarf::DW_FORM_ref_addr: {
146 // TODO: Handle DWARF32/DWARF64 after Line Table data is done
147 auto writeSize = CU.Version == 2 ? CU.AddrSize : 4;
148 writeVariableSizedInteger(FormVal->Value, writeSize, OS,
149 DI.IsLittleEndian);
150 break;
151 }
152 case dwarf::DW_FORM_exprloc:
153 case dwarf::DW_FORM_block:
154 encodeULEB128(FormVal->BlockData.size(), OS);
155 OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
156 FormVal->BlockData.size());
157 break;
158 case dwarf::DW_FORM_block1: {
159 auto writeSize = FormVal->BlockData.size();
160 writeInteger((uint8_t)writeSize, OS, DI.IsLittleEndian);
161 OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
162 FormVal->BlockData.size());
163 break;
164 }
165 case dwarf::DW_FORM_block2: {
166 auto writeSize = FormVal->BlockData.size();
167 writeInteger((uint16_t)writeSize, OS, DI.IsLittleEndian);
168 OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
169 FormVal->BlockData.size());
170 break;
171 }
172 case dwarf::DW_FORM_block4: {
173 auto writeSize = FormVal->BlockData.size();
174 writeInteger((uint32_t)writeSize, OS, DI.IsLittleEndian);
175 OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
176 FormVal->BlockData.size());
177 break;
178 }
179 case dwarf::DW_FORM_data1:
180 case dwarf::DW_FORM_ref1:
181 case dwarf::DW_FORM_flag:
182 writeInteger((uint8_t)FormVal->Value, OS, DI.IsLittleEndian);
183 break;
184 case dwarf::DW_FORM_data2:
185 case dwarf::DW_FORM_ref2:
186 writeInteger((uint16_t)FormVal->Value, OS, DI.IsLittleEndian);
187 break;
188 case dwarf::DW_FORM_data4:
189 case dwarf::DW_FORM_ref4:
190 writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
191 break;
192 case dwarf::DW_FORM_data8:
193 case dwarf::DW_FORM_ref8:
194 writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
195 break;
196 case dwarf::DW_FORM_sdata:
197 encodeSLEB128(FormVal->Value, OS);
198 break;
199 case dwarf::DW_FORM_udata:
200 case dwarf::DW_FORM_ref_udata:
201 encodeULEB128(FormVal->Value, OS);
202 break;
203 case dwarf::DW_FORM_string:
204 OS.write(FormVal->CStr.data(), FormVal->CStr.size());
205 OS.write('\0');
206 break;
207 case dwarf::DW_FORM_indirect:
208 encodeULEB128(FormVal->Value, OS);
209 Indirect = true;
210 Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
211 ++FormVal;
212 break;
213 case dwarf::DW_FORM_strp:
214 case dwarf::DW_FORM_sec_offset:
215 case dwarf::DW_FORM_GNU_ref_alt:
216 case dwarf::DW_FORM_GNU_strp_alt:
217 case dwarf::DW_FORM_line_strp:
218 case dwarf::DW_FORM_strp_sup:
219 case dwarf::DW_FORM_ref_sup:
220 // TODO: Handle DWARF32/64
221 writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
222 break;
223 case dwarf::DW_FORM_ref_sig8:
224 writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
225 break;
226 case dwarf::DW_FORM_GNU_addr_index:
227 case dwarf::DW_FORM_GNU_str_index:
228 encodeULEB128(FormVal->Value, OS);
229 break;
230 default:
231 break;
232 }
233 } while (Indirect);
234 }
235 }
236 }
237}
Chris Bieneman1b7200d2017-01-10 06:22:49 +0000238
Chris Bieneman07088c12017-01-12 21:35:21 +0000239void EmitFileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
Chris Bieneman1b7200d2017-01-10 06:22:49 +0000240 OS.write(File.Name.data(), File.Name.size());
241 OS.write('\0');
242 encodeULEB128(File.DirIdx, OS);
243 encodeULEB128(File.ModTime, OS);
244 encodeULEB128(File.Length, OS);
245}
246
Chris Bieneman07088c12017-01-12 21:35:21 +0000247void DWARFYAML::EmitDebugLine(raw_ostream &OS, const DWARFYAML::Data &DI) {
Chris Bieneman1b7200d2017-01-10 06:22:49 +0000248 for (const auto LineTable : DI.DebugLines) {
249 writeInteger((uint32_t)LineTable.TotalLength, OS, DI.IsLittleEndian);
250 uint64_t SizeOfPrologueLength = 4;
251 if (LineTable.TotalLength == UINT32_MAX) {
252 writeInteger((uint64_t)LineTable.TotalLength64, OS, DI.IsLittleEndian);
253 SizeOfPrologueLength = 8;
254 }
255 writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian);
256 writeVariableSizedInteger(LineTable.PrologueLength, SizeOfPrologueLength,
257 OS, DI.IsLittleEndian);
258 writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian);
259 if (LineTable.Version >= 4)
260 writeInteger((uint8_t)LineTable.MaxOpsPerInst, OS, DI.IsLittleEndian);
261 writeInteger((uint8_t)LineTable.DefaultIsStmt, OS, DI.IsLittleEndian);
262 writeInteger((uint8_t)LineTable.LineBase, OS, DI.IsLittleEndian);
263 writeInteger((uint8_t)LineTable.LineRange, OS, DI.IsLittleEndian);
264 writeInteger((uint8_t)LineTable.OpcodeBase, OS, DI.IsLittleEndian);
265
266 for (auto OpcodeLength : LineTable.StandardOpcodeLengths)
267 writeInteger((uint8_t)OpcodeLength, OS, DI.IsLittleEndian);
268
269 for (auto IncludeDir : LineTable.IncludeDirs) {
270 OS.write(IncludeDir.data(), IncludeDir.size());
271 OS.write('\0');
272 }
273 OS.write('\0');
274
275 for (auto File : LineTable.Files)
Chris Bieneman07088c12017-01-12 21:35:21 +0000276 EmitFileEntry(OS, File);
Chris Bieneman1b7200d2017-01-10 06:22:49 +0000277 OS.write('\0');
278
279 for (auto Op : LineTable.Opcodes) {
280 writeInteger((uint8_t)Op.Opcode, OS, DI.IsLittleEndian);
281 if (Op.Opcode == 0) {
282 encodeULEB128(Op.ExtLen, OS);
283 writeInteger((uint8_t)Op.SubOpcode, OS, DI.IsLittleEndian);
284 switch (Op.SubOpcode) {
285 case dwarf::DW_LNE_set_address:
286 case dwarf::DW_LNE_set_discriminator:
287 writeVariableSizedInteger(Op.Data, DI.CompileUnits[0].AddrSize, OS,
288 DI.IsLittleEndian);
289 break;
290 case dwarf::DW_LNE_define_file:
Chris Bieneman07088c12017-01-12 21:35:21 +0000291 EmitFileEntry(OS, Op.FileEntry);
Chris Bieneman1b7200d2017-01-10 06:22:49 +0000292 break;
293 case dwarf::DW_LNE_end_sequence:
294 break;
295 default:
296 for (auto OpByte : Op.UnknownOpcodeData)
297 writeInteger((uint8_t)OpByte, OS, DI.IsLittleEndian);
298 }
299 } else if (Op.Opcode < LineTable.OpcodeBase) {
300 switch (Op.Opcode) {
301 case dwarf::DW_LNS_copy:
302 case dwarf::DW_LNS_negate_stmt:
303 case dwarf::DW_LNS_set_basic_block:
304 case dwarf::DW_LNS_const_add_pc:
305 case dwarf::DW_LNS_set_prologue_end:
306 case dwarf::DW_LNS_set_epilogue_begin:
307 break;
308
309 case dwarf::DW_LNS_advance_pc:
310 case dwarf::DW_LNS_set_file:
311 case dwarf::DW_LNS_set_column:
312 case dwarf::DW_LNS_set_isa:
313 encodeULEB128(Op.Data, OS);
314 break;
315
316 case dwarf::DW_LNS_advance_line:
317 encodeSLEB128(Op.SData, OS);
318 break;
319
320 case dwarf::DW_LNS_fixed_advance_pc:
321 writeInteger((uint16_t)Op.Data, OS, DI.IsLittleEndian);
322 break;
323
324 default:
325 for (auto OpData : Op.StandardOpcodeData) {
326 encodeULEB128(OpData, OS);
327 }
328 }
329 }
330 }
331 }
332}
Chris Bieneman2e752db2017-01-20 19:03:14 +0000333
334typedef void (*EmitFuncType)(raw_ostream &, const DWARFYAML::Data &);
335
336void EmitDebugSectionImpl(
337 const DWARFYAML::Data &DI, EmitFuncType EmitFunc, StringRef Sec,
338 StringMap<std::unique_ptr<MemoryBuffer>> &OutputBuffers) {
339 std::string Data;
340 raw_string_ostream DebugInfoStream(Data);
341 EmitFunc(DebugInfoStream, DI);
342 DebugInfoStream.flush();
343 if (!Data.empty())
344 OutputBuffers[Sec] = MemoryBuffer::getMemBufferCopy(Data);
345}
346
347Expected<StringMap<std::unique_ptr<MemoryBuffer>>>
348DWARFYAML::EmitDebugSections(StringRef YAMLString,
349 bool IsLittleEndian) {
350 StringMap<std::unique_ptr<MemoryBuffer>> DebugSections;
351
352 yaml::Input YIn(YAMLString);
353
354 DWARFYAML::Data DI;
355 DI.IsLittleEndian = IsLittleEndian;
356 YIn >> DI;
357 if (YIn.error())
358 return errorCodeToError(YIn.error());
359
360 EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugInfo, "debug_info",
361 DebugSections);
362 EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugLine, "debug_line",
363 DebugSections);
364 EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugStr, "debug_str",
365 DebugSections);
366 EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugAbbrev, "debug_abbrev",
367 DebugSections);
368 EmitDebugSectionImpl(DI, &DWARFYAML::EmitDebugAranges, "debug_aranges",
369 DebugSections);
370 return std::move(DebugSections);
371}