1 //===- DWARFYAML.cpp - DWARF YAMLIO implementation ------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file defines classes for handling the YAML representation of DWARF Debug
12 //===----------------------------------------------------------------------===//
14 #include "llvm/ObjectYAML/DWARFYAML.h"
15 #include "llvm/BinaryFormat/Dwarf.h"
16 #include "llvm/Support/Errc.h"
17 #include "llvm/Support/Error.h"
21 bool DWARFYAML::Data::isEmpty() const {
22 return getNonEmptySectionNames().empty();
25 SetVector
<StringRef
> DWARFYAML::Data::getNonEmptySectionNames() const {
26 SetVector
<StringRef
> SecNames
;
28 SecNames
.insert("debug_str");
30 SecNames
.insert("debug_aranges");
32 SecNames
.insert("debug_ranges");
33 if (!DebugLines
.empty())
34 SecNames
.insert("debug_line");
36 SecNames
.insert("debug_addr");
37 if (!DebugAbbrev
.empty())
38 SecNames
.insert("debug_abbrev");
39 if (!CompileUnits
.empty())
40 SecNames
.insert("debug_info");
42 SecNames
.insert("debug_pubnames");
44 SecNames
.insert("debug_pubtypes");
46 SecNames
.insert("debug_gnu_pubnames");
48 SecNames
.insert("debug_gnu_pubtypes");
50 SecNames
.insert("debug_str_offsets");
52 SecNames
.insert("debug_rnglists");
54 SecNames
.insert("debug_loclists");
56 SecNames
.insert("debug_names");
60 Expected
<DWARFYAML::Data::AbbrevTableInfo
>
61 DWARFYAML::Data::getAbbrevTableInfoByID(uint64_t ID
) const {
62 if (AbbrevTableInfoMap
.empty()) {
63 uint64_t AbbrevTableOffset
= 0;
64 for (const auto &[Index
, AbbrevTable
] : enumerate(DebugAbbrev
)) {
65 // If the abbrev table's ID isn't specified, we use the index as its ID.
66 uint64_t AbbrevTableID
= AbbrevTable
.ID
.value_or(Index
);
67 auto It
= AbbrevTableInfoMap
.insert(
68 {AbbrevTableID
, AbbrevTableInfo
{/*Index=*/Index
,
69 /*Offset=*/AbbrevTableOffset
}});
71 return createStringError(
72 errc::invalid_argument
,
73 "the ID (%" PRIu64
") of abbrev table with index %zu has been used "
74 "by abbrev table with index %" PRIu64
,
75 AbbrevTableID
, Index
, It
.first
->second
.Index
);
77 AbbrevTableOffset
+= getAbbrevTableContentByIndex(Index
).size();
81 auto It
= AbbrevTableInfoMap
.find(ID
);
82 if (It
== AbbrevTableInfoMap
.end())
83 return createStringError(errc::invalid_argument
,
84 "cannot find abbrev table whose ID is %" PRIu64
,
91 void MappingTraits
<DWARFYAML::Data
>::mapping(IO
&IO
, DWARFYAML::Data
&DWARF
) {
92 void *OldContext
= IO
.getContext();
93 DWARFYAML::DWARFContext DWARFCtx
;
94 IO
.setContext(&DWARFCtx
);
95 IO
.mapOptional("debug_str", DWARF
.DebugStrings
);
96 IO
.mapOptional("debug_abbrev", DWARF
.DebugAbbrev
);
97 IO
.mapOptional("debug_aranges", DWARF
.DebugAranges
);
98 IO
.mapOptional("debug_ranges", DWARF
.DebugRanges
);
99 IO
.mapOptional("debug_pubnames", DWARF
.PubNames
);
100 IO
.mapOptional("debug_pubtypes", DWARF
.PubTypes
);
101 DWARFCtx
.IsGNUPubSec
= true;
102 IO
.mapOptional("debug_gnu_pubnames", DWARF
.GNUPubNames
);
103 IO
.mapOptional("debug_gnu_pubtypes", DWARF
.GNUPubTypes
);
104 IO
.mapOptional("debug_info", DWARF
.CompileUnits
);
105 IO
.mapOptional("debug_line", DWARF
.DebugLines
);
106 IO
.mapOptional("debug_addr", DWARF
.DebugAddr
);
107 IO
.mapOptional("debug_str_offsets", DWARF
.DebugStrOffsets
);
108 IO
.mapOptional("debug_rnglists", DWARF
.DebugRnglists
);
109 IO
.mapOptional("debug_loclists", DWARF
.DebugLoclists
);
110 IO
.mapOptional("debug_names", DWARF
.DebugNames
);
111 IO
.setContext(OldContext
);
114 void MappingTraits
<DWARFYAML::AbbrevTable
>::mapping(
115 IO
&IO
, DWARFYAML::AbbrevTable
&AbbrevTable
) {
116 IO
.mapOptional("ID", AbbrevTable
.ID
);
117 IO
.mapOptional("Table", AbbrevTable
.Table
);
120 void MappingTraits
<DWARFYAML::Abbrev
>::mapping(IO
&IO
,
121 DWARFYAML::Abbrev
&Abbrev
) {
122 IO
.mapOptional("Code", Abbrev
.Code
);
123 IO
.mapRequired("Tag", Abbrev
.Tag
);
124 IO
.mapRequired("Children", Abbrev
.Children
);
125 IO
.mapOptional("Attributes", Abbrev
.Attributes
);
128 void MappingTraits
<DWARFYAML::IdxForm
>::mapping(IO
&IO
,
129 DWARFYAML::IdxForm
&IdxForm
) {
130 IO
.mapRequired("Idx", IdxForm
.Idx
);
131 IO
.mapRequired("Form", IdxForm
.Form
);
134 void MappingTraits
<DWARFYAML::DebugNameAbbreviation
>::mapping(
135 IO
&IO
, DWARFYAML::DebugNameAbbreviation
&DebugNameAbbreviation
) {
136 IO
.mapRequired("Code", DebugNameAbbreviation
.Code
);
137 IO
.mapRequired("Tag", DebugNameAbbreviation
.Tag
);
138 IO
.mapRequired("Indices", DebugNameAbbreviation
.Indices
);
141 void MappingTraits
<DWARFYAML::DebugNameEntry
>::mapping(
142 IO
&IO
, DWARFYAML::DebugNameEntry
&DebugNameEntry
) {
143 IO
.mapRequired("Name", DebugNameEntry
.NameStrp
);
144 IO
.mapRequired("Code", DebugNameEntry
.Code
);
145 IO
.mapOptional("Values", DebugNameEntry
.Values
);
148 void MappingTraits
<DWARFYAML::DebugNamesSection
>::mapping(
149 IO
&IO
, DWARFYAML::DebugNamesSection
&DebugNames
) {
150 IO
.mapRequired("Abbreviations", DebugNames
.Abbrevs
);
151 IO
.mapRequired("Entries", DebugNames
.Entries
);
154 void MappingTraits
<DWARFYAML::AttributeAbbrev
>::mapping(
155 IO
&IO
, DWARFYAML::AttributeAbbrev
&AttAbbrev
) {
156 IO
.mapRequired("Attribute", AttAbbrev
.Attribute
);
157 IO
.mapRequired("Form", AttAbbrev
.Form
);
158 if(AttAbbrev
.Form
== dwarf::DW_FORM_implicit_const
)
159 IO
.mapRequired("Value", AttAbbrev
.Value
);
162 void MappingTraits
<DWARFYAML::ARangeDescriptor
>::mapping(
163 IO
&IO
, DWARFYAML::ARangeDescriptor
&Descriptor
) {
164 IO
.mapRequired("Address", Descriptor
.Address
);
165 IO
.mapRequired("Length", Descriptor
.Length
);
168 void MappingTraits
<DWARFYAML::ARange
>::mapping(IO
&IO
,
169 DWARFYAML::ARange
&ARange
) {
170 IO
.mapOptional("Format", ARange
.Format
, dwarf::DWARF32
);
171 IO
.mapOptional("Length", ARange
.Length
);
172 IO
.mapRequired("Version", ARange
.Version
);
173 IO
.mapRequired("CuOffset", ARange
.CuOffset
);
174 IO
.mapOptional("AddressSize", ARange
.AddrSize
);
175 IO
.mapOptional("SegmentSelectorSize", ARange
.SegSize
, 0);
176 IO
.mapOptional("Descriptors", ARange
.Descriptors
);
179 void MappingTraits
<DWARFYAML::RangeEntry
>::mapping(
180 IO
&IO
, DWARFYAML::RangeEntry
&Descriptor
) {
181 IO
.mapRequired("LowOffset", Descriptor
.LowOffset
);
182 IO
.mapRequired("HighOffset", Descriptor
.HighOffset
);
185 void MappingTraits
<DWARFYAML::Ranges
>::mapping(IO
&IO
,
186 DWARFYAML::Ranges
&DebugRanges
) {
187 IO
.mapOptional("Offset", DebugRanges
.Offset
);
188 IO
.mapOptional("AddrSize", DebugRanges
.AddrSize
);
189 IO
.mapRequired("Entries", DebugRanges
.Entries
);
192 void MappingTraits
<DWARFYAML::PubEntry
>::mapping(IO
&IO
,
193 DWARFYAML::PubEntry
&Entry
) {
194 IO
.mapRequired("DieOffset", Entry
.DieOffset
);
195 if (static_cast<DWARFYAML::DWARFContext
*>(IO
.getContext())->IsGNUPubSec
)
196 IO
.mapRequired("Descriptor", Entry
.Descriptor
);
197 IO
.mapRequired("Name", Entry
.Name
);
200 void MappingTraits
<DWARFYAML::PubSection
>::mapping(
201 IO
&IO
, DWARFYAML::PubSection
&Section
) {
202 IO
.mapOptional("Format", Section
.Format
, dwarf::DWARF32
);
203 IO
.mapRequired("Length", Section
.Length
);
204 IO
.mapRequired("Version", Section
.Version
);
205 IO
.mapRequired("UnitOffset", Section
.UnitOffset
);
206 IO
.mapRequired("UnitSize", Section
.UnitSize
);
207 IO
.mapRequired("Entries", Section
.Entries
);
210 void MappingTraits
<DWARFYAML::Unit
>::mapping(IO
&IO
, DWARFYAML::Unit
&Unit
) {
211 IO
.mapOptional("Format", Unit
.Format
, dwarf::DWARF32
);
212 IO
.mapOptional("Length", Unit
.Length
);
213 IO
.mapRequired("Version", Unit
.Version
);
214 if (Unit
.Version
>= 5)
215 IO
.mapRequired("UnitType", Unit
.Type
);
216 IO
.mapOptional("AbbrevTableID", Unit
.AbbrevTableID
);
217 IO
.mapOptional("AbbrOffset", Unit
.AbbrOffset
);
218 IO
.mapOptional("AddrSize", Unit
.AddrSize
);
219 IO
.mapOptional("Entries", Unit
.Entries
);
222 void MappingTraits
<DWARFYAML::Entry
>::mapping(IO
&IO
, DWARFYAML::Entry
&Entry
) {
223 IO
.mapRequired("AbbrCode", Entry
.AbbrCode
);
224 IO
.mapOptional("Values", Entry
.Values
);
227 void MappingTraits
<DWARFYAML::FormValue
>::mapping(
228 IO
&IO
, DWARFYAML::FormValue
&FormValue
) {
229 IO
.mapOptional("Value", FormValue
.Value
);
230 if (!FormValue
.CStr
.empty() || !IO
.outputting())
231 IO
.mapOptional("CStr", FormValue
.CStr
);
232 if (!FormValue
.BlockData
.empty() || !IO
.outputting())
233 IO
.mapOptional("BlockData", FormValue
.BlockData
);
236 void MappingTraits
<DWARFYAML::File
>::mapping(IO
&IO
, DWARFYAML::File
&File
) {
237 IO
.mapRequired("Name", File
.Name
);
238 IO
.mapRequired("DirIdx", File
.DirIdx
);
239 IO
.mapRequired("ModTime", File
.ModTime
);
240 IO
.mapRequired("Length", File
.Length
);
243 void MappingTraits
<DWARFYAML::LineTableOpcode
>::mapping(
244 IO
&IO
, DWARFYAML::LineTableOpcode
&LineTableOpcode
) {
245 IO
.mapRequired("Opcode", LineTableOpcode
.Opcode
);
246 if (LineTableOpcode
.Opcode
== dwarf::DW_LNS_extended_op
) {
247 IO
.mapOptional("ExtLen", LineTableOpcode
.ExtLen
);
248 IO
.mapRequired("SubOpcode", LineTableOpcode
.SubOpcode
);
251 if (!LineTableOpcode
.UnknownOpcodeData
.empty() || !IO
.outputting())
252 IO
.mapOptional("UnknownOpcodeData", LineTableOpcode
.UnknownOpcodeData
);
253 if (!LineTableOpcode
.UnknownOpcodeData
.empty() || !IO
.outputting())
254 IO
.mapOptional("StandardOpcodeData", LineTableOpcode
.StandardOpcodeData
);
255 if (!LineTableOpcode
.FileEntry
.Name
.empty() || !IO
.outputting())
256 IO
.mapOptional("FileEntry", LineTableOpcode
.FileEntry
);
257 if (LineTableOpcode
.Opcode
== dwarf::DW_LNS_advance_line
|| !IO
.outputting())
258 IO
.mapOptional("SData", LineTableOpcode
.SData
);
259 IO
.mapOptional("Data", LineTableOpcode
.Data
);
262 void MappingTraits
<DWARFYAML::LineTable
>::mapping(
263 IO
&IO
, DWARFYAML::LineTable
&LineTable
) {
264 IO
.mapOptional("Format", LineTable
.Format
, dwarf::DWARF32
);
265 IO
.mapOptional("Length", LineTable
.Length
);
266 IO
.mapRequired("Version", LineTable
.Version
);
267 IO
.mapOptional("PrologueLength", LineTable
.PrologueLength
);
268 IO
.mapRequired("MinInstLength", LineTable
.MinInstLength
);
269 if(LineTable
.Version
>= 4)
270 IO
.mapRequired("MaxOpsPerInst", LineTable
.MaxOpsPerInst
);
271 IO
.mapRequired("DefaultIsStmt", LineTable
.DefaultIsStmt
);
272 IO
.mapRequired("LineBase", LineTable
.LineBase
);
273 IO
.mapRequired("LineRange", LineTable
.LineRange
);
274 IO
.mapOptional("OpcodeBase", LineTable
.OpcodeBase
);
275 IO
.mapOptional("StandardOpcodeLengths", LineTable
.StandardOpcodeLengths
);
276 IO
.mapOptional("IncludeDirs", LineTable
.IncludeDirs
);
277 IO
.mapOptional("Files", LineTable
.Files
);
278 IO
.mapOptional("Opcodes", LineTable
.Opcodes
);
281 void MappingTraits
<DWARFYAML::SegAddrPair
>::mapping(
282 IO
&IO
, DWARFYAML::SegAddrPair
&SegAddrPair
) {
283 IO
.mapOptional("Segment", SegAddrPair
.Segment
, 0);
284 IO
.mapOptional("Address", SegAddrPair
.Address
, 0);
287 void MappingTraits
<DWARFYAML::AddrTableEntry
>::mapping(
288 IO
&IO
, DWARFYAML::AddrTableEntry
&AddrTable
) {
289 IO
.mapOptional("Format", AddrTable
.Format
, dwarf::DWARF32
);
290 IO
.mapOptional("Length", AddrTable
.Length
);
291 IO
.mapRequired("Version", AddrTable
.Version
);
292 IO
.mapOptional("AddressSize", AddrTable
.AddrSize
);
293 IO
.mapOptional("SegmentSelectorSize", AddrTable
.SegSelectorSize
, 0);
294 IO
.mapOptional("Entries", AddrTable
.SegAddrPairs
);
297 void MappingTraits
<DWARFYAML::StringOffsetsTable
>::mapping(
298 IO
&IO
, DWARFYAML::StringOffsetsTable
&StrOffsetsTable
) {
299 IO
.mapOptional("Format", StrOffsetsTable
.Format
, dwarf::DWARF32
);
300 IO
.mapOptional("Length", StrOffsetsTable
.Length
);
301 IO
.mapOptional("Version", StrOffsetsTable
.Version
, 5);
302 IO
.mapOptional("Padding", StrOffsetsTable
.Padding
, 0);
303 IO
.mapOptional("Offsets", StrOffsetsTable
.Offsets
);
306 void MappingTraits
<DWARFYAML::DWARFOperation
>::mapping(
307 IO
&IO
, DWARFYAML::DWARFOperation
&DWARFOperation
) {
308 IO
.mapRequired("Operator", DWARFOperation
.Operator
);
309 IO
.mapOptional("Values", DWARFOperation
.Values
);
312 void MappingTraits
<DWARFYAML::RnglistEntry
>::mapping(
313 IO
&IO
, DWARFYAML::RnglistEntry
&RnglistEntry
) {
314 IO
.mapRequired("Operator", RnglistEntry
.Operator
);
315 IO
.mapOptional("Values", RnglistEntry
.Values
);
318 void MappingTraits
<DWARFYAML::LoclistEntry
>::mapping(
319 IO
&IO
, DWARFYAML::LoclistEntry
&LoclistEntry
) {
320 IO
.mapRequired("Operator", LoclistEntry
.Operator
);
321 IO
.mapOptional("Values", LoclistEntry
.Values
);
322 IO
.mapOptional("DescriptionsLength", LoclistEntry
.DescriptionsLength
);
323 IO
.mapOptional("Descriptions", LoclistEntry
.Descriptions
);
326 template <typename EntryType
>
327 void MappingTraits
<DWARFYAML::ListEntries
<EntryType
>>::mapping(
328 IO
&IO
, DWARFYAML::ListEntries
<EntryType
> &ListEntries
) {
329 IO
.mapOptional("Entries", ListEntries
.Entries
);
330 IO
.mapOptional("Content", ListEntries
.Content
);
333 template <typename EntryType
>
334 std::string MappingTraits
<DWARFYAML::ListEntries
<EntryType
>>::validate(
335 IO
&IO
, DWARFYAML::ListEntries
<EntryType
> &ListEntries
) {
336 if (ListEntries
.Entries
&& ListEntries
.Content
)
337 return "Entries and Content can't be used together";
341 template <typename EntryType
>
342 void MappingTraits
<DWARFYAML::ListTable
<EntryType
>>::mapping(
343 IO
&IO
, DWARFYAML::ListTable
<EntryType
> &ListTable
) {
344 IO
.mapOptional("Format", ListTable
.Format
, dwarf::DWARF32
);
345 IO
.mapOptional("Length", ListTable
.Length
);
346 IO
.mapOptional("Version", ListTable
.Version
, 5);
347 IO
.mapOptional("AddressSize", ListTable
.AddrSize
);
348 IO
.mapOptional("SegmentSelectorSize", ListTable
.SegSelectorSize
, 0);
349 IO
.mapOptional("OffsetEntryCount", ListTable
.OffsetEntryCount
);
350 IO
.mapOptional("Offsets", ListTable
.Offsets
);
351 IO
.mapOptional("Lists", ListTable
.Lists
);
354 } // end namespace yaml
356 } // end namespace llvm