[TextAPI] Remove a superfluous semicolon, fixing GCC warnings. NFC.
[llvm-core.git] / tools / obj2yaml / dwarf2yaml.cpp
blob1ce6c036e6f5f5a5c7b8136f3731a248c1c2dc20
1 //===------ dwarf2yaml.cpp - obj2yaml conversion tool -----------*- C++ -*-===//
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 //===----------------------------------------------------------------------===//
10 #include "Error.h"
11 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
12 #include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
13 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
14 #include "llvm/ObjectYAML/DWARFYAML.h"
16 #include <algorithm>
18 using namespace llvm;
20 void dumpInitialLength(DataExtractor &Data, uint32_t &Offset,
21 DWARFYAML::InitialLength &InitialLength) {
22 InitialLength.TotalLength = Data.getU32(&Offset);
23 if (InitialLength.isDWARF64())
24 InitialLength.TotalLength64 = Data.getU64(&Offset);
27 void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
28 auto AbbrevSetPtr = DCtx.getDebugAbbrev();
29 if (AbbrevSetPtr) {
30 for (auto AbbrvDeclSet : *AbbrevSetPtr) {
31 for (auto AbbrvDecl : AbbrvDeclSet.second) {
32 DWARFYAML::Abbrev Abbrv;
33 Abbrv.Code = AbbrvDecl.getCode();
34 Abbrv.Tag = AbbrvDecl.getTag();
35 Abbrv.Children = AbbrvDecl.hasChildren() ? dwarf::DW_CHILDREN_yes
36 : dwarf::DW_CHILDREN_no;
37 for (auto Attribute : AbbrvDecl.attributes()) {
38 DWARFYAML::AttributeAbbrev AttAbrv;
39 AttAbrv.Attribute = Attribute.Attr;
40 AttAbrv.Form = Attribute.Form;
41 if (AttAbrv.Form == dwarf::DW_FORM_implicit_const)
42 AttAbrv.Value = Attribute.getImplicitConstValue();
43 Abbrv.Attributes.push_back(AttAbrv);
45 Y.AbbrevDecls.push_back(Abbrv);
51 void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) {
52 StringRef RemainingTable = DCtx.getDWARFObj().getStringSection();
53 while (RemainingTable.size() > 0) {
54 auto SymbolPair = RemainingTable.split('\0');
55 RemainingTable = SymbolPair.second;
56 Y.DebugStrings.push_back(SymbolPair.first);
60 void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
61 DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(),
62 DCtx.isLittleEndian(), 0);
63 uint32_t Offset = 0;
64 DWARFDebugArangeSet Set;
66 while (Set.extract(ArangesData, &Offset)) {
67 DWARFYAML::ARange Range;
68 Range.Length.setLength(Set.getHeader().Length);
69 Range.Version = Set.getHeader().Version;
70 Range.CuOffset = Set.getHeader().CuOffset;
71 Range.AddrSize = Set.getHeader().AddrSize;
72 Range.SegSize = Set.getHeader().SegSize;
73 for (auto Descriptor : Set.descriptors()) {
74 DWARFYAML::ARangeDescriptor Desc;
75 Desc.Address = Descriptor.Address;
76 Desc.Length = Descriptor.Length;
77 Range.Descriptors.push_back(Desc);
79 Y.ARanges.push_back(Range);
83 void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y,
84 DWARFSection Section) {
85 DWARFDataExtractor PubSectionData(DCtx.getDWARFObj(), Section,
86 DCtx.isLittleEndian(), 0);
87 uint32_t Offset = 0;
88 dumpInitialLength(PubSectionData, Offset, Y.Length);
89 Y.Version = PubSectionData.getU16(&Offset);
90 Y.UnitOffset = PubSectionData.getU32(&Offset);
91 Y.UnitSize = PubSectionData.getU32(&Offset);
92 while (Offset < Y.Length.getLength()) {
93 DWARFYAML::PubEntry NewEntry;
94 NewEntry.DieOffset = PubSectionData.getU32(&Offset);
95 if (Y.IsGNUStyle)
96 NewEntry.Descriptor = PubSectionData.getU8(&Offset);
97 NewEntry.Name = PubSectionData.getCStr(&Offset);
98 Y.Entries.push_back(NewEntry);
102 void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) {
103 const DWARFObject &D = DCtx.getDWARFObj();
104 Y.PubNames.IsGNUStyle = false;
105 dumpPubSection(DCtx, Y.PubNames, D.getPubNamesSection());
107 Y.PubTypes.IsGNUStyle = false;
108 dumpPubSection(DCtx, Y.PubTypes, D.getPubTypesSection());
110 Y.GNUPubNames.IsGNUStyle = true;
111 dumpPubSection(DCtx, Y.GNUPubNames, D.getGnuPubNamesSection());
113 Y.GNUPubTypes.IsGNUStyle = true;
114 dumpPubSection(DCtx, Y.GNUPubTypes, D.getGnuPubTypesSection());
117 void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {
118 for (const auto &CU : DCtx.compile_units()) {
119 DWARFYAML::Unit NewUnit;
120 NewUnit.Length.setLength(CU->getLength());
121 NewUnit.Version = CU->getVersion();
122 if(NewUnit.Version >= 5)
123 NewUnit.Type = (dwarf::UnitType)CU->getUnitType();
124 NewUnit.AbbrOffset = CU->getAbbreviations()->getOffset();
125 NewUnit.AddrSize = CU->getAddressByteSize();
126 for (auto DIE : CU->dies()) {
127 DWARFYAML::Entry NewEntry;
128 DataExtractor EntryData = CU->getDebugInfoExtractor();
129 uint32_t offset = DIE.getOffset();
131 assert(EntryData.isValidOffset(offset) && "Invalid DIE Offset");
132 if (!EntryData.isValidOffset(offset))
133 continue;
135 NewEntry.AbbrCode = EntryData.getULEB128(&offset);
137 auto AbbrevDecl = DIE.getAbbreviationDeclarationPtr();
138 if (AbbrevDecl) {
139 for (const auto &AttrSpec : AbbrevDecl->attributes()) {
140 DWARFYAML::FormValue NewValue;
141 NewValue.Value = 0xDEADBEEFDEADBEEF;
142 DWARFDie DIEWrapper(CU.get(), &DIE);
143 auto FormValue = DIEWrapper.find(AttrSpec.Attr);
144 if (!FormValue)
145 return;
146 auto Form = FormValue.getValue().getForm();
147 bool indirect = false;
148 do {
149 indirect = false;
150 switch (Form) {
151 case dwarf::DW_FORM_addr:
152 case dwarf::DW_FORM_GNU_addr_index:
153 if (auto Val = FormValue.getValue().getAsAddress())
154 NewValue.Value = Val.getValue();
155 break;
156 case dwarf::DW_FORM_ref_addr:
157 case dwarf::DW_FORM_ref1:
158 case dwarf::DW_FORM_ref2:
159 case dwarf::DW_FORM_ref4:
160 case dwarf::DW_FORM_ref8:
161 case dwarf::DW_FORM_ref_udata:
162 case dwarf::DW_FORM_ref_sig8:
163 if (auto Val = FormValue.getValue().getAsReferenceUVal())
164 NewValue.Value = Val.getValue();
165 break;
166 case dwarf::DW_FORM_exprloc:
167 case dwarf::DW_FORM_block:
168 case dwarf::DW_FORM_block1:
169 case dwarf::DW_FORM_block2:
170 case dwarf::DW_FORM_block4:
171 if (auto Val = FormValue.getValue().getAsBlock()) {
172 auto BlockData = Val.getValue();
173 std::copy(BlockData.begin(), BlockData.end(),
174 std::back_inserter(NewValue.BlockData));
176 NewValue.Value = NewValue.BlockData.size();
177 break;
178 case dwarf::DW_FORM_data1:
179 case dwarf::DW_FORM_flag:
180 case dwarf::DW_FORM_data2:
181 case dwarf::DW_FORM_data4:
182 case dwarf::DW_FORM_data8:
183 case dwarf::DW_FORM_sdata:
184 case dwarf::DW_FORM_udata:
185 case dwarf::DW_FORM_ref_sup4:
186 case dwarf::DW_FORM_ref_sup8:
187 if (auto Val = FormValue.getValue().getAsUnsignedConstant())
188 NewValue.Value = Val.getValue();
189 break;
190 case dwarf::DW_FORM_string:
191 if (auto Val = FormValue.getValue().getAsCString())
192 NewValue.CStr = Val.getValue();
193 break;
194 case dwarf::DW_FORM_indirect:
195 indirect = true;
196 if (auto Val = FormValue.getValue().getAsUnsignedConstant()) {
197 NewValue.Value = Val.getValue();
198 NewEntry.Values.push_back(NewValue);
199 Form = static_cast<dwarf::Form>(Val.getValue());
201 break;
202 case dwarf::DW_FORM_strp:
203 case dwarf::DW_FORM_sec_offset:
204 case dwarf::DW_FORM_GNU_ref_alt:
205 case dwarf::DW_FORM_GNU_strp_alt:
206 case dwarf::DW_FORM_line_strp:
207 case dwarf::DW_FORM_strp_sup:
208 case dwarf::DW_FORM_GNU_str_index:
209 case dwarf::DW_FORM_strx:
210 if (auto Val = FormValue.getValue().getAsCStringOffset())
211 NewValue.Value = Val.getValue();
212 break;
213 case dwarf::DW_FORM_flag_present:
214 NewValue.Value = 1;
215 break;
216 default:
217 break;
219 } while (indirect);
220 NewEntry.Values.push_back(NewValue);
224 NewUnit.Entries.push_back(NewEntry);
226 Y.CompileUnits.push_back(NewUnit);
230 bool dumpFileEntry(DataExtractor &Data, uint32_t &Offset,
231 DWARFYAML::File &File) {
232 File.Name = Data.getCStr(&Offset);
233 if (File.Name.empty())
234 return false;
235 File.DirIdx = Data.getULEB128(&Offset);
236 File.ModTime = Data.getULEB128(&Offset);
237 File.Length = Data.getULEB128(&Offset);
238 return true;
241 void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
242 for (const auto &CU : DCtx.compile_units()) {
243 auto CUDIE = CU->getUnitDIE();
244 if (!CUDIE)
245 continue;
246 if (auto StmtOffset =
247 dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) {
248 DWARFYAML::LineTable DebugLines;
249 DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data,
250 DCtx.isLittleEndian(), CU->getAddressByteSize());
251 uint32_t Offset = *StmtOffset;
252 dumpInitialLength(LineData, Offset, DebugLines.Length);
253 uint64_t LineTableLength = DebugLines.Length.getLength();
254 uint64_t SizeOfPrologueLength = DebugLines.Length.isDWARF64() ? 8 : 4;
255 DebugLines.Version = LineData.getU16(&Offset);
256 DebugLines.PrologueLength =
257 LineData.getUnsigned(&Offset, SizeOfPrologueLength);
258 const uint64_t EndPrologue = DebugLines.PrologueLength + Offset;
260 DebugLines.MinInstLength = LineData.getU8(&Offset);
261 if (DebugLines.Version >= 4)
262 DebugLines.MaxOpsPerInst = LineData.getU8(&Offset);
263 DebugLines.DefaultIsStmt = LineData.getU8(&Offset);
264 DebugLines.LineBase = LineData.getU8(&Offset);
265 DebugLines.LineRange = LineData.getU8(&Offset);
266 DebugLines.OpcodeBase = LineData.getU8(&Offset);
268 DebugLines.StandardOpcodeLengths.reserve(DebugLines.OpcodeBase - 1);
269 for (uint8_t i = 1; i < DebugLines.OpcodeBase; ++i)
270 DebugLines.StandardOpcodeLengths.push_back(LineData.getU8(&Offset));
272 while (Offset < EndPrologue) {
273 StringRef Dir = LineData.getCStr(&Offset);
274 if (!Dir.empty())
275 DebugLines.IncludeDirs.push_back(Dir);
276 else
277 break;
280 while (Offset < EndPrologue) {
281 DWARFYAML::File TmpFile;
282 if (dumpFileEntry(LineData, Offset, TmpFile))
283 DebugLines.Files.push_back(TmpFile);
284 else
285 break;
288 const uint64_t LineEnd =
289 LineTableLength + *StmtOffset + SizeOfPrologueLength;
290 while (Offset < LineEnd) {
291 DWARFYAML::LineTableOpcode NewOp;
292 NewOp.Opcode = (dwarf::LineNumberOps)LineData.getU8(&Offset);
293 if (NewOp.Opcode == 0) {
294 auto StartExt = Offset;
295 NewOp.ExtLen = LineData.getULEB128(&Offset);
296 NewOp.SubOpcode =
297 (dwarf::LineNumberExtendedOps)LineData.getU8(&Offset);
298 switch (NewOp.SubOpcode) {
299 case dwarf::DW_LNE_set_address:
300 case dwarf::DW_LNE_set_discriminator:
301 NewOp.Data = LineData.getAddress(&Offset);
302 break;
303 case dwarf::DW_LNE_define_file:
304 dumpFileEntry(LineData, Offset, NewOp.FileEntry);
305 break;
306 case dwarf::DW_LNE_end_sequence:
307 break;
308 default:
309 while (Offset < StartExt + NewOp.ExtLen)
310 NewOp.UnknownOpcodeData.push_back(LineData.getU8(&Offset));
312 } else if (NewOp.Opcode < DebugLines.OpcodeBase) {
313 switch (NewOp.Opcode) {
314 case dwarf::DW_LNS_copy:
315 case dwarf::DW_LNS_negate_stmt:
316 case dwarf::DW_LNS_set_basic_block:
317 case dwarf::DW_LNS_const_add_pc:
318 case dwarf::DW_LNS_set_prologue_end:
319 case dwarf::DW_LNS_set_epilogue_begin:
320 break;
322 case dwarf::DW_LNS_advance_pc:
323 case dwarf::DW_LNS_set_file:
324 case dwarf::DW_LNS_set_column:
325 case dwarf::DW_LNS_set_isa:
326 NewOp.Data = LineData.getULEB128(&Offset);
327 break;
329 case dwarf::DW_LNS_advance_line:
330 NewOp.SData = LineData.getSLEB128(&Offset);
331 break;
333 case dwarf::DW_LNS_fixed_advance_pc:
334 NewOp.Data = LineData.getU16(&Offset);
335 break;
337 default:
338 for (uint8_t i = 0;
339 i < DebugLines.StandardOpcodeLengths[NewOp.Opcode - 1]; ++i)
340 NewOp.StandardOpcodeData.push_back(LineData.getULEB128(&Offset));
343 DebugLines.Opcodes.push_back(NewOp);
345 Y.DebugLines.push_back(DebugLines);
350 std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) {
351 dumpDebugAbbrev(DCtx, Y);
352 dumpDebugStrings(DCtx, Y);
353 dumpDebugARanges(DCtx, Y);
354 dumpDebugPubSections(DCtx, Y);
355 dumpDebugInfo(DCtx, Y);
356 dumpDebugLines(DCtx, Y);
357 return obj2yaml_error::success;