1 //===- yaml2dwarf - Convert YAML to DWARF binary data ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
11 /// \brief The DWARF component of yaml2obj.
13 //===----------------------------------------------------------------------===//
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"
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));
32 void writeVariableSizedInteger(uint64_t Integer, size_t Size, raw_ostream &OS,
33 bool IsLittleEndian) {
35 writeInteger((uint64_t)Integer, OS, IsLittleEndian);
37 writeInteger((uint32_t)Integer, OS, IsLittleEndian);
39 writeInteger((uint16_t)Integer, OS, IsLittleEndian);
41 writeInteger((uint8_t)Integer, OS, IsLittleEndian);
43 assert(false && "Invalid integer write size.");
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);
52 void yaml2debug_str(raw_ostream &OS, const DWARFYAML::Data &DI) {
53 for (auto Str : DI.DebugStrings) {
54 OS.write(Str.data(), Str.size());
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);
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);
82 auto HeaderSize = OS.tell() - HeaderStart;
83 auto FirstDescriptor = alignTo(HeaderSize, Range.AddrSize * 2);
84 ZeroFillBytes(OS, FirstDescriptor - HeaderSize);
86 for (auto Descriptor : Range.Descriptors) {
87 writeVariableSizedInteger(Descriptor.Address, Range.AddrSize, OS,
89 writeVariableSizedInteger(Descriptor.Length, Range.AddrSize, OS,
92 ZeroFillBytes(OS, Range.AddrSize * 2);
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);
105 writeInteger((uint32_t)Entry.Descriptor, OS, IsLittleEndian);
106 OS.write(Entry.Name.data(), Entry.Name.size());
111 void yaml2debug_info(raw_ostream &OS, const DWARFYAML::Data &DI) {
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);
119 auto FirstAbbrevCode = CU.Entries[0].AbbrCode;
121 for (auto Entry : CU.Entries) {
122 encodeULEB128(Entry.AbbrCode, OS);
123 if (Entry.AbbrCode == 0u)
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];
130 auto FormVal = Entry.Values.begin();
131 auto AbbrForm = Abbrev.Attributes.begin();
133 FormVal != Entry.Values.end() && AbbrForm != Abbrev.Attributes.end();
134 ++FormVal, ++AbbrForm) {
135 dwarf::Form Form = AbbrForm->Form;
139 case dwarf::DW_FORM_addr:
140 writeVariableSizedInteger(FormVal->Value, CU.AddrSize, OS,
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,
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());
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());
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());
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());
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);
182 case dwarf::DW_FORM_data2:
183 case dwarf::DW_FORM_ref2:
184 writeInteger((uint16_t)FormVal->Value, OS, DI.IsLittleEndian);
186 case dwarf::DW_FORM_data4:
187 case dwarf::DW_FORM_ref4:
188 writeInteger((uint32_t)FormVal->Value, OS, DI.IsLittleEndian);
190 case dwarf::DW_FORM_data8:
191 case dwarf::DW_FORM_ref8:
192 writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
194 case dwarf::DW_FORM_sdata:
195 encodeSLEB128(FormVal->Value, OS);
197 case dwarf::DW_FORM_udata:
198 case dwarf::DW_FORM_ref_udata:
199 encodeULEB128(FormVal->Value, OS);
201 case dwarf::DW_FORM_string:
202 OS.write(FormVal->CStr.data(), FormVal->CStr.size());
205 case dwarf::DW_FORM_indirect:
206 encodeULEB128(FormVal->Value, OS);
208 Form = static_cast<dwarf::Form>((uint64_t)FormVal->Value);
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);
221 case dwarf::DW_FORM_ref_sig8:
222 writeInteger((uint64_t)FormVal->Value, OS, DI.IsLittleEndian);
224 case dwarf::DW_FORM_GNU_addr_index:
225 case dwarf::DW_FORM_GNU_str_index:
226 encodeULEB128(FormVal->Value, OS);
237 void yaml2FileEntry(raw_ostream &OS, const DWARFYAML::File &File) {
238 OS.write(File.Name.data(), File.Name.size());
240 encodeULEB128(File.DirIdx, OS);
241 encodeULEB128(File.ModTime, OS);
242 encodeULEB128(File.Length, OS);
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;
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);
264 for (auto OpcodeLength : LineTable.StandardOpcodeLengths)
265 writeInteger((uint8_t)OpcodeLength, OS, DI.IsLittleEndian);
267 for (auto IncludeDir : LineTable.IncludeDirs) {
268 OS.write(IncludeDir.data(), IncludeDir.size());
273 for (auto File : LineTable.Files)
274 yaml2FileEntry(OS, File);
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,
288 case dwarf::DW_LNE_define_file:
289 yaml2FileEntry(OS, Op.FileEntry);
291 case dwarf::DW_LNE_end_sequence:
294 for (auto OpByte : Op.UnknownOpcodeData)
295 writeInteger((uint8_t)OpByte, OS, DI.IsLittleEndian);
297 } else if (Op.Opcode < LineTable.OpcodeBase) {
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:
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);
314 case dwarf::DW_LNS_advance_line:
315 encodeSLEB128(Op.SData, OS);
318 case dwarf::DW_LNS_fixed_advance_pc:
319 writeInteger((uint16_t)Op.Data, OS, DI.IsLittleEndian);
323 for (auto OpData : Op.StandardOpcodeData) {
324 encodeULEB128(OpData, OS);