]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/yaml2obj/yaml2dwarf.cpp
Vendor import of llvm release_40 branch r292009:
[FreeBSD/FreeBSD.git] / tools / yaml2obj / yaml2dwarf.cpp
1 //===- yaml2dwarf - Convert YAML to DWARF binary data ---------------------===//
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 /// \file
11 /// \brief The DWARF component of yaml2obj.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "llvm/ObjectYAML/DWARFYAML.h"
16 #include "llvm/Support/Error.h"
17 #include "llvm/Support/LEB128.h"
18 #include "llvm/Support/raw_ostream.h"
19 #include "llvm/Support/SwapByteOrder.h"
20
21 #include <algorithm>
22
23 using namespace llvm;
24
25 template <typename T>
26 void writeInteger(T Integer, raw_ostream &OS, bool IsLittleEndian) {
27   if (IsLittleEndian != sys::IsLittleEndianHost)
28     sys::swapByteOrder(Integer);
29   OS.write(reinterpret_cast<char *>(&Integer), sizeof(T));
30 }
31
32 void writeVariableSizedInteger(uint64_t Integer, size_t Size, raw_ostream &OS,
33                                bool IsLittleEndian) {
34   if (8 == Size)
35     writeInteger((uint64_t)Integer, OS, IsLittleEndian);
36   else if (4 == Size)
37     writeInteger((uint32_t)Integer, OS, IsLittleEndian);
38   else if (2 == Size)
39     writeInteger((uint16_t)Integer, OS, IsLittleEndian);
40   else if (1 == Size)
41     writeInteger((uint8_t)Integer, OS, IsLittleEndian);
42   else
43     assert(false && "Invalid integer write size.");
44 }
45
46 void ZeroFillBytes(raw_ostream &OS, size_t Size) {
47   std::vector<uint8_t> FillData;
48   FillData.insert(FillData.begin(), Size, 0);
49   OS.write(reinterpret_cast<char *>(FillData.data()), Size);
50 }
51
52 void yaml2debug_str(raw_ostream &OS, const DWARFYAML::Data &DI) {
53   for (auto Str : DI.DebugStrings) {
54     OS.write(Str.data(), Str.size());
55     OS.write('\0');
56   }
57 }
58
59 void yaml2debug_abbrev(raw_ostream &OS, const DWARFYAML::Data &DI) {
60   for (auto AbbrevDecl : DI.AbbrevDecls) {
61     encodeULEB128(AbbrevDecl.Code, OS);
62     encodeULEB128(AbbrevDecl.Tag, OS);
63     OS.write(AbbrevDecl.Children);
64     for (auto Attr : AbbrevDecl.Attributes) {
65       encodeULEB128(Attr.Attribute, OS);
66       encodeULEB128(Attr.Form, OS);
67     }
68     encodeULEB128(0, OS);
69     encodeULEB128(0, OS);
70   }
71 }
72
73 void yaml2debug_aranges(raw_ostream &OS, const DWARFYAML::Data &DI) {
74   for (auto Range : DI.ARanges) {
75     auto HeaderStart = OS.tell();
76     writeInteger((uint32_t)Range.Length, OS, DI.IsLittleEndian);
77     writeInteger((uint16_t)Range.Version, OS, DI.IsLittleEndian);
78     writeInteger((uint32_t)Range.CuOffset, OS, DI.IsLittleEndian);
79     writeInteger((uint8_t)Range.AddrSize, OS, DI.IsLittleEndian);
80     writeInteger((uint8_t)Range.SegSize, OS, DI.IsLittleEndian);
81
82     auto HeaderSize = OS.tell() - HeaderStart;
83     auto FirstDescriptor = alignTo(HeaderSize, Range.AddrSize * 2);
84     ZeroFillBytes(OS, FirstDescriptor - HeaderSize);
85
86     for (auto Descriptor : Range.Descriptors) {
87       writeVariableSizedInteger(Descriptor.Address, Range.AddrSize, OS,
88                                 DI.IsLittleEndian);
89       writeVariableSizedInteger(Descriptor.Length, Range.AddrSize, OS,
90                                 DI.IsLittleEndian);
91     }
92     ZeroFillBytes(OS, Range.AddrSize * 2);
93   }
94 }
95
96 void yaml2pubsection(raw_ostream &OS, const DWARFYAML::PubSection &Sect,
97                      bool IsLittleEndian) {
98   writeInteger((uint32_t)Sect.Length, OS, IsLittleEndian);
99   writeInteger((uint16_t)Sect.Version, OS, IsLittleEndian);
100   writeInteger((uint32_t)Sect.UnitOffset, OS, IsLittleEndian);
101   writeInteger((uint32_t)Sect.UnitSize, OS, IsLittleEndian);
102   for (auto Entry : Sect.Entries) {
103     writeInteger((uint32_t)Entry.DieOffset, OS, IsLittleEndian);
104     if (Sect.IsGNUStyle)
105       writeInteger((uint32_t)Entry.Descriptor, OS, IsLittleEndian);
106     OS.write(Entry.Name.data(), Entry.Name.size());
107     OS.write('\0');
108   }
109 }
110
111 void yaml2debug_info(raw_ostream &OS, const DWARFYAML::Data &DI) {
112
113   for (auto CU : DI.CompileUnits) {
114     writeInteger((uint32_t)CU.Length, OS, DI.IsLittleEndian);
115     writeInteger((uint16_t)CU.Version, OS, DI.IsLittleEndian);
116     writeInteger((uint32_t)CU.AbbrOffset, OS, DI.IsLittleEndian);
117     writeInteger((uint8_t)CU.AddrSize, OS, DI.IsLittleEndian);
118
119     auto FirstAbbrevCode = CU.Entries[0].AbbrCode;
120
121     for (auto Entry : CU.Entries) {
122       encodeULEB128(Entry.AbbrCode, OS);
123       if (Entry.AbbrCode == 0u)
124         continue;
125       bool Indirect = false;
126       assert(Entry.AbbrCode - FirstAbbrevCode < DI.AbbrevDecls.size() &&
127              "Out of range AbbCode");
128       auto &Abbrev = DI.AbbrevDecls[Entry.AbbrCode - FirstAbbrevCode];
129
130       auto FormVal = Entry.Values.begin();
131       auto AbbrForm = Abbrev.Attributes.begin();
132       for (;
133            FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
134            ++FormVal, ++AbbrForm) {
135         dwarf::Form Form = AbbrForm->Form;
136         do {
137           Indirect = false;
138           switch (Form) {
139           case dwarf::DW_FORM_addr:
140             writeVariableSizedInteger(FormVal->Value, CU.AddrSize, OS,
141                                       DI.IsLittleEndian);
142             break;
143           case dwarf::DW_FORM_ref_addr: {
144             // TODO: Handle DWARF32/DWARF64 after Line Table data is done
145             auto writeSize = CU.Version == 2 ? CU.AddrSize : 4;
146             writeVariableSizedInteger(FormVal->Value, writeSize, OS,
147                                       DI.IsLittleEndian);
148             break;
149           }
150           case dwarf::DW_FORM_exprloc:
151           case dwarf::DW_FORM_block:
152             encodeULEB128(FormVal->BlockData.size(), OS);
153             OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
154                      FormVal->BlockData.size());
155             break;
156           case dwarf::DW_FORM_block1: {
157             auto writeSize = FormVal->BlockData.size();
158             writeInteger((uint8_t)writeSize, OS, DI.IsLittleEndian);
159             OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
160                      FormVal->BlockData.size());
161             break;
162           }
163           case dwarf::DW_FORM_block2: {
164             auto writeSize = FormVal->BlockData.size();
165             writeInteger((uint16_t)writeSize, OS, DI.IsLittleEndian);
166             OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
167                      FormVal->BlockData.size());
168             break;
169           }
170           case dwarf::DW_FORM_block4: {
171             auto writeSize = FormVal->BlockData.size();
172             writeInteger((uint32_t)writeSize, OS, DI.IsLittleEndian);
173             OS.write(reinterpret_cast<char *>(&FormVal->BlockData[0]),
174                      FormVal->BlockData.size());
175             break;
176           }
177           case dwarf::DW_FORM_data1:
178           case dwarf::DW_FORM_ref1:
179           case dwarf::DW_FORM_flag:
180             writeInteger((uint8_t)FormVal->Value, OS, DI.IsLittleEndian);
181             break;
182           case dwarf::DW_FORM_data2:
183           case dwarf::DW_FORM_ref2:
184             writeInteger((uint16_t)FormVal->Value, OS, DI.IsLittleEndian);
185             break;
186           case dwarf::DW_FORM_data4:
187           case dwarf::DW_FORM_ref4:
188             writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
189             break;
190           case dwarf::DW_FORM_data8:
191           case dwarf::DW_FORM_ref8:
192             writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
193             break;
194           case dwarf::DW_FORM_sdata:
195             encodeSLEB128(FormVal->Value, OS);
196             break;
197           case dwarf::DW_FORM_udata:
198           case dwarf::DW_FORM_ref_udata:
199             encodeULEB128(FormVal->Value, OS);
200             break;
201           case dwarf::DW_FORM_string:
202             OS.write(FormVal->CStr.data(), FormVal->CStr.size());
203             OS.write('\0');
204             break;
205           case dwarf::DW_FORM_indirect:
206             encodeULEB128(FormVal->Value, OS);
207             Indirect = true;
208             Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
209             ++FormVal;
210             break;
211           case dwarf::DW_FORM_strp:
212           case dwarf::DW_FORM_sec_offset:
213           case dwarf::DW_FORM_GNU_ref_alt:
214           case dwarf::DW_FORM_GNU_strp_alt:
215           case dwarf::DW_FORM_line_strp:
216           case dwarf::DW_FORM_strp_sup:
217           case dwarf::DW_FORM_ref_sup:
218             // TODO: Handle DWARF32/64
219             writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
220             break;
221           case dwarf::DW_FORM_ref_sig8:
222             writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
223             break;
224           case dwarf::DW_FORM_GNU_addr_index:
225           case dwarf::DW_FORM_GNU_str_index:
226             encodeULEB128(FormVal->Value, OS);
227             break;
228           default:
229             break;
230           }
231         } while (Indirect);
232       }
233     }
234   }
235 }
236
237 void yaml2FileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
238   OS.write(File.Name.data(), File.Name.size());
239   OS.write('\0');
240   encodeULEB128(File.DirIdx, OS);
241   encodeULEB128(File.ModTime, OS);
242   encodeULEB128(File.Length, OS);
243 }
244
245 void yaml2debug_line(raw_ostream &OS, const DWARFYAML::Data &DI) {
246   for (const auto LineTable : DI.DebugLines) {
247     writeInteger((uint32_t)LineTable.TotalLength, OS, DI.IsLittleEndian);
248     uint64_t SizeOfPrologueLength = 4;
249     if (LineTable.TotalLength == UINT32_MAX) {
250       writeInteger((uint64_t)LineTable.TotalLength64, OS, DI.IsLittleEndian);
251       SizeOfPrologueLength = 8;
252     }
253     writeInteger((uint16_t)LineTable.Version, OS, DI.IsLittleEndian);
254     writeVariableSizedInteger(LineTable.PrologueLength, SizeOfPrologueLength,
255                               OS, DI.IsLittleEndian);
256     writeInteger((uint8_t)LineTable.MinInstLength, OS, DI.IsLittleEndian);
257     if (LineTable.Version >= 4)
258       writeInteger((uint8_t)LineTable.MaxOpsPerInst, OS, DI.IsLittleEndian);
259     writeInteger((uint8_t)LineTable.DefaultIsStmt, OS, DI.IsLittleEndian);
260     writeInteger((uint8_t)LineTable.LineBase, OS, DI.IsLittleEndian);
261     writeInteger((uint8_t)LineTable.LineRange, OS, DI.IsLittleEndian);
262     writeInteger((uint8_t)LineTable.OpcodeBase, OS, DI.IsLittleEndian);
263
264     for (auto OpcodeLength : LineTable.StandardOpcodeLengths)
265       writeInteger((uint8_t)OpcodeLength, OS, DI.IsLittleEndian);
266
267     for (auto IncludeDir : LineTable.IncludeDirs) {
268       OS.write(IncludeDir.data(), IncludeDir.size());
269       OS.write('\0');
270     }
271     OS.write('\0');
272
273     for (auto File : LineTable.Files)
274       yaml2FileEntry(OS, File);
275     OS.write('\0');
276
277     for (auto Op : LineTable.Opcodes) {
278       writeInteger((uint8_t)Op.Opcode, OS, DI.IsLittleEndian);
279       if (Op.Opcode == 0) {
280         encodeULEB128(Op.ExtLen, OS);
281         writeInteger((uint8_t)Op.SubOpcode, OS, DI.IsLittleEndian);
282         switch (Op.SubOpcode) {
283         case dwarf::DW_LNE_set_address:
284         case dwarf::DW_LNE_set_discriminator:
285           writeVariableSizedInteger(Op.Data, DI.CompileUnits[0].AddrSize, OS,
286                                     DI.IsLittleEndian);
287           break;
288         case dwarf::DW_LNE_define_file:
289           yaml2FileEntry(OS, Op.FileEntry);
290           break;
291         case dwarf::DW_LNE_end_sequence:
292           break;
293         default:
294           for (auto OpByte : Op.UnknownOpcodeData)
295             writeInteger((uint8_t)OpByte, OS, DI.IsLittleEndian);
296         }
297       } else if (Op.Opcode < LineTable.OpcodeBase) {
298         switch (Op.Opcode) {
299         case dwarf::DW_LNS_copy:
300         case dwarf::DW_LNS_negate_stmt:
301         case dwarf::DW_LNS_set_basic_block:
302         case dwarf::DW_LNS_const_add_pc:
303         case dwarf::DW_LNS_set_prologue_end:
304         case dwarf::DW_LNS_set_epilogue_begin:
305           break;
306
307         case dwarf::DW_LNS_advance_pc:
308         case dwarf::DW_LNS_set_file:
309         case dwarf::DW_LNS_set_column:
310         case dwarf::DW_LNS_set_isa:
311           encodeULEB128(Op.Data, OS);
312           break;
313
314         case dwarf::DW_LNS_advance_line:
315           encodeSLEB128(Op.SData, OS);
316           break;
317
318         case dwarf::DW_LNS_fixed_advance_pc:
319           writeInteger((uint16_t)Op.Data, OS, DI.IsLittleEndian);
320           break;
321
322         default:
323           for (auto OpData : Op.StandardOpcodeData) {
324             encodeULEB128(OpData, OS);
325           }
326         }
327       }
328     }
329   }
330 }