blob: 1ce6c036e6f5f5a5c7b8136f3731a248c1c2dc20 [file] [log] [blame]
Chris Bieneman15235052016-12-07 21:47:28 +00001//===------ 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//===----------------------------------------------------------------------===//
9
10#include "Error.h"
11#include "llvm/DebugInfo/DWARF/DWARFContext.h"
Chris Bieneman18245f62016-12-09 00:26:44 +000012#include "llvm/DebugInfo/DWARF/DWARFDebugArangeSet.h"
Chris Bieneman7d466452016-12-22 22:44:27 +000013#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
Chris Bieneman15235052016-12-07 21:47:28 +000014#include "llvm/ObjectYAML/DWARFYAML.h"
15
Chris Bieneman7d466452016-12-22 22:44:27 +000016#include <algorithm>
17
Chris Bieneman15235052016-12-07 21:47:28 +000018using namespace llvm;
19
Chris Bienemanad76c972017-03-03 21:11:55 +000020void 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);
25}
26
Rafael Espindolaee809ac2017-07-19 22:27:28 +000027void dumpDebugAbbrev(DWARFContext &DCtx, DWARFYAML::Data &Y) {
Chris Bieneman15235052016-12-07 21:47:28 +000028 auto AbbrevSetPtr = DCtx.getDebugAbbrev();
29 if (AbbrevSetPtr) {
30 for (auto AbbrvDeclSet : *AbbrevSetPtr) {
31 for (auto AbbrvDecl : AbbrvDeclSet.second) {
Chris Bieneman4d6c7e92016-12-08 17:46:57 +000032 DWARFYAML::Abbrev Abbrv;
Chris Bieneman15235052016-12-07 21:47:28 +000033 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()) {
Chris Bieneman4d6c7e92016-12-08 17:46:57 +000038 DWARFYAML::AttributeAbbrev AttAbrv;
Chris Bieneman15235052016-12-07 21:47:28 +000039 AttAbrv.Attribute = Attribute.Attr;
40 AttAbrv.Form = Attribute.Form;
Chris Bieneman64cf2ce2017-03-06 23:22:49 +000041 if (AttAbrv.Form == dwarf::DW_FORM_implicit_const)
Benjamin Kramer3ef466f2017-09-21 15:32:05 +000042 AttAbrv.Value = Attribute.getImplicitConstValue();
Chris Bieneman15235052016-12-07 21:47:28 +000043 Abbrv.Attributes.push_back(AttAbrv);
44 }
45 Y.AbbrevDecls.push_back(Abbrv);
46 }
47 }
48 }
49}
50
Rafael Espindolaee809ac2017-07-19 22:27:28 +000051void dumpDebugStrings(DWARFContext &DCtx, DWARFYAML::Data &Y) {
52 StringRef RemainingTable = DCtx.getDWARFObj().getStringSection();
Chris Bieneman15235052016-12-07 21:47:28 +000053 while (RemainingTable.size() > 0) {
54 auto SymbolPair = RemainingTable.split('\0');
55 RemainingTable = SymbolPair.second;
56 Y.DebugStrings.push_back(SymbolPair.first);
57 }
58}
59
Rafael Espindolaee809ac2017-07-19 22:27:28 +000060void dumpDebugARanges(DWARFContext &DCtx, DWARFYAML::Data &Y) {
61 DataExtractor ArangesData(DCtx.getDWARFObj().getARangeSection(),
62 DCtx.isLittleEndian(), 0);
Chris Bieneman18245f62016-12-09 00:26:44 +000063 uint32_t Offset = 0;
64 DWARFDebugArangeSet Set;
65
66 while (Set.extract(ArangesData, &Offset)) {
67 DWARFYAML::ARange Range;
Chris Bienemanad76c972017-03-03 21:11:55 +000068 Range.Length.setLength(Set.getHeader().Length);
Chris Bieneman18245f62016-12-09 00:26:44 +000069 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);
78 }
79 Y.ARanges.push_back(Range);
80 }
81}
82
Rafael Espindolaee809ac2017-07-19 22:27:28 +000083void dumpPubSection(DWARFContext &DCtx, DWARFYAML::PubSection &Y,
Fangrui Songb87342a2018-11-11 18:57:28 +000084 DWARFSection Section) {
85 DWARFDataExtractor PubSectionData(DCtx.getDWARFObj(), Section,
86 DCtx.isLittleEndian(), 0);
Chris Bienemanc2813d92016-12-19 22:22:12 +000087 uint32_t Offset = 0;
Chris Bienemanad76c972017-03-03 21:11:55 +000088 dumpInitialLength(PubSectionData, Offset, Y.Length);
Chris Bienemanc2813d92016-12-19 22:22:12 +000089 Y.Version = PubSectionData.getU16(&Offset);
90 Y.UnitOffset = PubSectionData.getU32(&Offset);
91 Y.UnitSize = PubSectionData.getU32(&Offset);
Chris Bienemanad76c972017-03-03 21:11:55 +000092 while (Offset < Y.Length.getLength()) {
Chris Bienemanc2813d92016-12-19 22:22:12 +000093 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);
99 }
100}
101
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000102void dumpDebugPubSections(DWARFContext &DCtx, DWARFYAML::Data &Y) {
103 const DWARFObject &D = DCtx.getDWARFObj();
Chris Bienemanc2813d92016-12-19 22:22:12 +0000104 Y.PubNames.IsGNUStyle = false;
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000105 dumpPubSection(DCtx, Y.PubNames, D.getPubNamesSection());
Chris Bienemanc2813d92016-12-19 22:22:12 +0000106
107 Y.PubTypes.IsGNUStyle = false;
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000108 dumpPubSection(DCtx, Y.PubTypes, D.getPubTypesSection());
Chris Bienemanc2813d92016-12-19 22:22:12 +0000109
110 Y.GNUPubNames.IsGNUStyle = true;
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000111 dumpPubSection(DCtx, Y.GNUPubNames, D.getGnuPubNamesSection());
Chris Bienemanc2813d92016-12-19 22:22:12 +0000112
113 Y.GNUPubTypes.IsGNUStyle = true;
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000114 dumpPubSection(DCtx, Y.GNUPubTypes, D.getGnuPubTypesSection());
Chris Bienemanc2813d92016-12-19 22:22:12 +0000115}
116
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000117void dumpDebugInfo(DWARFContext &DCtx, DWARFYAML::Data &Y) {
Chris Bieneman7d466452016-12-22 22:44:27 +0000118 for (const auto &CU : DCtx.compile_units()) {
119 DWARFYAML::Unit NewUnit;
Chris Bienemanad76c972017-03-03 21:11:55 +0000120 NewUnit.Length.setLength(CU->getLength());
Chris Bieneman7d466452016-12-22 22:44:27 +0000121 NewUnit.Version = CU->getVersion();
Chris Bienemanda6d07a2017-03-07 18:50:58 +0000122 if(NewUnit.Version >= 5)
123 NewUnit.Type = (dwarf::UnitType)CU->getUnitType();
Chris Bieneman7d466452016-12-22 22:44:27 +0000124 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();
130
131 assert(EntryData.isValidOffset(offset) && "Invalid DIE Offset");
132 if (!EntryData.isValidOffset(offset))
133 continue;
134
135 NewEntry.AbbrCode = EntryData.getULEB128(&offset);
136
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);
Greg Claytonbeabb632017-01-13 21:08:18 +0000143 auto FormValue = DIEWrapper.find(AttrSpec.Attr);
Chris Bieneman6c9c3a72017-01-10 06:22:49 +0000144 if (!FormValue)
Chris Bieneman7d466452016-12-22 22:44:27 +0000145 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));
175 }
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:
Paul Robinson18557472017-03-06 22:20:03 +0000185 case dwarf::DW_FORM_ref_sup4:
186 case dwarf::DW_FORM_ref_sup8:
Chris Bieneman7d466452016-12-22 22:44:27 +0000187 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());
200 }
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:
Chris Bieneman7d466452016-12-22 22:44:27 +0000208 case dwarf::DW_FORM_GNU_str_index:
Wolfgang Piebc9977b62017-06-06 01:22:34 +0000209 case dwarf::DW_FORM_strx:
Chris Bieneman7d466452016-12-22 22:44:27 +0000210 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;
218 }
219 } while (indirect);
220 NewEntry.Values.push_back(NewValue);
221 }
222 }
223
224 NewUnit.Entries.push_back(NewEntry);
225 }
226 Y.CompileUnits.push_back(NewUnit);
227 }
228}
229
Chris Bieneman6c9c3a72017-01-10 06:22:49 +0000230bool 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;
239}
240
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000241void dumpDebugLines(DWARFContext &DCtx, DWARFYAML::Data &Y) {
Chris Bieneman6c9c3a72017-01-10 06:22:49 +0000242 for (const auto &CU : DCtx.compile_units()) {
243 auto CUDIE = CU->getUnitDIE();
244 if (!CUDIE)
245 continue;
246 if (auto StmtOffset =
Greg Claytonbeabb632017-01-13 21:08:18 +0000247 dwarf::toSectionOffset(CUDIE.find(dwarf::DW_AT_stmt_list))) {
Chris Bieneman6c9c3a72017-01-10 06:22:49 +0000248 DWARFYAML::LineTable DebugLines;
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000249 DataExtractor LineData(DCtx.getDWARFObj().getLineSection().Data,
250 DCtx.isLittleEndian(), CU->getAddressByteSize());
Chris Bieneman6c9c3a72017-01-10 06:22:49 +0000251 uint32_t Offset = *StmtOffset;
Chris Bienemanad76c972017-03-03 21:11:55 +0000252 dumpInitialLength(LineData, Offset, DebugLines.Length);
253 uint64_t LineTableLength = DebugLines.Length.getLength();
254 uint64_t SizeOfPrologueLength = DebugLines.Length.isDWARF64() ? 8 : 4;
Chris Bieneman6c9c3a72017-01-10 06:22:49 +0000255 DebugLines.Version = LineData.getU16(&Offset);
256 DebugLines.PrologueLength =
257 LineData.getUnsigned(&Offset, SizeOfPrologueLength);
258 const uint64_t EndPrologue = DebugLines.PrologueLength + Offset;
259
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);
267
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));
271
272 while (Offset < EndPrologue) {
273 StringRef Dir = LineData.getCStr(&Offset);
274 if (!Dir.empty())
275 DebugLines.IncludeDirs.push_back(Dir);
276 else
277 break;
278 }
279
280 while (Offset < EndPrologue) {
281 DWARFYAML::File TmpFile;
282 if (dumpFileEntry(LineData, Offset, TmpFile))
283 DebugLines.Files.push_back(TmpFile);
284 else
285 break;
286 }
287
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));
311 }
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;
321
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;
328
329 case dwarf::DW_LNS_advance_line:
330 NewOp.SData = LineData.getSLEB128(&Offset);
331 break;
332
333 case dwarf::DW_LNS_fixed_advance_pc:
334 NewOp.Data = LineData.getU16(&Offset);
335 break;
336
337 default:
338 for (uint8_t i = 0;
339 i < DebugLines.StandardOpcodeLengths[NewOp.Opcode - 1]; ++i)
340 NewOp.StandardOpcodeData.push_back(LineData.getULEB128(&Offset));
341 }
342 }
343 DebugLines.Opcodes.push_back(NewOp);
344 }
345 Y.DebugLines.push_back(DebugLines);
346 }
347 }
348}
349
Rafael Espindolaee809ac2017-07-19 22:27:28 +0000350std::error_code dwarf2yaml(DWARFContext &DCtx, DWARFYAML::Data &Y) {
Chris Bieneman15235052016-12-07 21:47:28 +0000351 dumpDebugAbbrev(DCtx, Y);
352 dumpDebugStrings(DCtx, Y);
Chris Bieneman18245f62016-12-09 00:26:44 +0000353 dumpDebugARanges(DCtx, Y);
Chris Bienemanc2813d92016-12-19 22:22:12 +0000354 dumpDebugPubSections(DCtx, Y);
Chris Bieneman7d466452016-12-22 22:44:27 +0000355 dumpDebugInfo(DCtx, Y);
Chris Bieneman6c9c3a72017-01-10 06:22:49 +0000356 dumpDebugLines(DCtx, Y);
Chris Bieneman15235052016-12-07 21:47:28 +0000357 return obj2yaml_error::success;
358}