OSDN Git Service

[ObjectYAML] Support for DWARF debug_info section
[android-x86/external-llvm.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           bool 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 }