1 //===------ dwarf2yaml.cpp - obj2yaml conversion tool -----------*- C++ -*-===//
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 #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"
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();
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);
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);
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
);
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
))
135 NewEntry
.AbbrCode
= EntryData
.getULEB128(&offset
);
137 auto AbbrevDecl
= DIE
.getAbbreviationDeclarationPtr();
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
);
146 auto Form
= FormValue
.getValue().getForm();
147 bool indirect
= false;
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();
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();
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();
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();
190 case dwarf::DW_FORM_string
:
191 if (auto Val
= FormValue
.getValue().getAsCString())
192 NewValue
.CStr
= Val
.getValue();
194 case dwarf::DW_FORM_indirect
:
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());
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();
213 case dwarf::DW_FORM_flag_present
:
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())
235 File
.DirIdx
= Data
.getULEB128(&Offset
);
236 File
.ModTime
= Data
.getULEB128(&Offset
);
237 File
.Length
= Data
.getULEB128(&Offset
);
241 void dumpDebugLines(DWARFContext
&DCtx
, DWARFYAML::Data
&Y
) {
242 for (const auto &CU
: DCtx
.compile_units()) {
243 auto CUDIE
= CU
->getUnitDIE();
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
);
275 DebugLines
.IncludeDirs
.push_back(Dir
);
280 while (Offset
< EndPrologue
) {
281 DWARFYAML::File TmpFile
;
282 if (dumpFileEntry(LineData
, Offset
, TmpFile
))
283 DebugLines
.Files
.push_back(TmpFile
);
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
);
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
);
303 case dwarf::DW_LNE_define_file
:
304 dumpFileEntry(LineData
, Offset
, NewOp
.FileEntry
);
306 case dwarf::DW_LNE_end_sequence
:
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
:
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
);
329 case dwarf::DW_LNS_advance_line
:
330 NewOp
.SData
= LineData
.getSLEB128(&Offset
);
333 case dwarf::DW_LNS_fixed_advance_pc
:
334 NewOp
.Data
= LineData
.getU16(&Offset
);
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
;