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");
58 Expected
<DWARFYAML::Data::AbbrevTableInfo
>
59 DWARFYAML::Data::getAbbrevTableInfoByID(uint64_t ID
) const {
60 if (AbbrevTableInfoMap
.empty()) {
61 uint64_t AbbrevTableOffset
= 0;
62 for (auto &AbbrevTable
: enumerate(DebugAbbrev
)) {
63 // If the abbrev table's ID isn't specified, we use the index as its ID.
64 uint64_t AbbrevTableID
=
65 AbbrevTable
.value().ID
.getValueOr(AbbrevTable
.index());
66 auto It
= AbbrevTableInfoMap
.insert(
67 {AbbrevTableID
, AbbrevTableInfo
{/*Index=*/AbbrevTable
.index(),
68 /*Offset=*/AbbrevTableOffset
}});
70 return createStringError(
71 errc::invalid_argument
,
72 "the ID (%" PRIu64
") of abbrev table with index %zu has been used "
73 "by abbrev table with index %" PRIu64
,
74 AbbrevTableID
, AbbrevTable
.index(), It
.first
->second
.Index
);
77 getAbbrevTableContentByIndex(AbbrevTable
.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
.setContext(OldContext
);
113 void MappingTraits
<DWARFYAML::AbbrevTable
>::mapping(
114 IO
&IO
, DWARFYAML::AbbrevTable
&AbbrevTable
) {
115 IO
.mapOptional("ID", AbbrevTable
.ID
);
116 IO
.mapOptional("Table", AbbrevTable
.Table
);
119 void MappingTraits
<DWARFYAML::Abbrev
>::mapping(IO
&IO
,
120 DWARFYAML::Abbrev
&Abbrev
) {
121 IO
.mapOptional("Code", Abbrev
.Code
);
122 IO
.mapRequired("Tag", Abbrev
.Tag
);
123 IO
.mapRequired("Children", Abbrev
.Children
);
124 IO
.mapOptional("Attributes", Abbrev
.Attributes
);
127 void MappingTraits
<DWARFYAML::AttributeAbbrev
>::mapping(
128 IO
&IO
, DWARFYAML::AttributeAbbrev
&AttAbbrev
) {
129 IO
.mapRequired("Attribute", AttAbbrev
.Attribute
);
130 IO
.mapRequired("Form", AttAbbrev
.Form
);
131 if(AttAbbrev
.Form
== dwarf::DW_FORM_implicit_const
)
132 IO
.mapRequired("Value", AttAbbrev
.Value
);
135 void MappingTraits
<DWARFYAML::ARangeDescriptor
>::mapping(
136 IO
&IO
, DWARFYAML::ARangeDescriptor
&Descriptor
) {
137 IO
.mapRequired("Address", Descriptor
.Address
);
138 IO
.mapRequired("Length", Descriptor
.Length
);
141 void MappingTraits
<DWARFYAML::ARange
>::mapping(IO
&IO
,
142 DWARFYAML::ARange
&ARange
) {
143 IO
.mapOptional("Format", ARange
.Format
, dwarf::DWARF32
);
144 IO
.mapOptional("Length", ARange
.Length
);
145 IO
.mapRequired("Version", ARange
.Version
);
146 IO
.mapRequired("CuOffset", ARange
.CuOffset
);
147 IO
.mapOptional("AddressSize", ARange
.AddrSize
);
148 IO
.mapOptional("SegmentSelectorSize", ARange
.SegSize
, 0);
149 IO
.mapOptional("Descriptors", ARange
.Descriptors
);
152 void MappingTraits
<DWARFYAML::RangeEntry
>::mapping(
153 IO
&IO
, DWARFYAML::RangeEntry
&Descriptor
) {
154 IO
.mapRequired("LowOffset", Descriptor
.LowOffset
);
155 IO
.mapRequired("HighOffset", Descriptor
.HighOffset
);
158 void MappingTraits
<DWARFYAML::Ranges
>::mapping(IO
&IO
,
159 DWARFYAML::Ranges
&DebugRanges
) {
160 IO
.mapOptional("Offset", DebugRanges
.Offset
);
161 IO
.mapOptional("AddrSize", DebugRanges
.AddrSize
);
162 IO
.mapRequired("Entries", DebugRanges
.Entries
);
165 void MappingTraits
<DWARFYAML::PubEntry
>::mapping(IO
&IO
,
166 DWARFYAML::PubEntry
&Entry
) {
167 IO
.mapRequired("DieOffset", Entry
.DieOffset
);
168 if (static_cast<DWARFYAML::DWARFContext
*>(IO
.getContext())->IsGNUPubSec
)
169 IO
.mapRequired("Descriptor", Entry
.Descriptor
);
170 IO
.mapRequired("Name", Entry
.Name
);
173 void MappingTraits
<DWARFYAML::PubSection
>::mapping(
174 IO
&IO
, DWARFYAML::PubSection
&Section
) {
175 IO
.mapOptional("Format", Section
.Format
, dwarf::DWARF32
);
176 IO
.mapRequired("Length", Section
.Length
);
177 IO
.mapRequired("Version", Section
.Version
);
178 IO
.mapRequired("UnitOffset", Section
.UnitOffset
);
179 IO
.mapRequired("UnitSize", Section
.UnitSize
);
180 IO
.mapRequired("Entries", Section
.Entries
);
183 void MappingTraits
<DWARFYAML::Unit
>::mapping(IO
&IO
, DWARFYAML::Unit
&Unit
) {
184 IO
.mapOptional("Format", Unit
.Format
, dwarf::DWARF32
);
185 IO
.mapOptional("Length", Unit
.Length
);
186 IO
.mapRequired("Version", Unit
.Version
);
187 if (Unit
.Version
>= 5)
188 IO
.mapRequired("UnitType", Unit
.Type
);
189 IO
.mapOptional("AbbrevTableID", Unit
.AbbrevTableID
);
190 IO
.mapOptional("AbbrOffset", Unit
.AbbrOffset
);
191 IO
.mapOptional("AddrSize", Unit
.AddrSize
);
192 IO
.mapOptional("Entries", Unit
.Entries
);
195 void MappingTraits
<DWARFYAML::Entry
>::mapping(IO
&IO
, DWARFYAML::Entry
&Entry
) {
196 IO
.mapRequired("AbbrCode", Entry
.AbbrCode
);
197 IO
.mapOptional("Values", Entry
.Values
);
200 void MappingTraits
<DWARFYAML::FormValue
>::mapping(
201 IO
&IO
, DWARFYAML::FormValue
&FormValue
) {
202 IO
.mapOptional("Value", FormValue
.Value
);
203 if (!FormValue
.CStr
.empty() || !IO
.outputting())
204 IO
.mapOptional("CStr", FormValue
.CStr
);
205 if (!FormValue
.BlockData
.empty() || !IO
.outputting())
206 IO
.mapOptional("BlockData", FormValue
.BlockData
);
209 void MappingTraits
<DWARFYAML::File
>::mapping(IO
&IO
, DWARFYAML::File
&File
) {
210 IO
.mapRequired("Name", File
.Name
);
211 IO
.mapRequired("DirIdx", File
.DirIdx
);
212 IO
.mapRequired("ModTime", File
.ModTime
);
213 IO
.mapRequired("Length", File
.Length
);
216 void MappingTraits
<DWARFYAML::LineTableOpcode
>::mapping(
217 IO
&IO
, DWARFYAML::LineTableOpcode
&LineTableOpcode
) {
218 IO
.mapRequired("Opcode", LineTableOpcode
.Opcode
);
219 if (LineTableOpcode
.Opcode
== dwarf::DW_LNS_extended_op
) {
220 IO
.mapOptional("ExtLen", LineTableOpcode
.ExtLen
);
221 IO
.mapRequired("SubOpcode", LineTableOpcode
.SubOpcode
);
224 if (!LineTableOpcode
.UnknownOpcodeData
.empty() || !IO
.outputting())
225 IO
.mapOptional("UnknownOpcodeData", LineTableOpcode
.UnknownOpcodeData
);
226 if (!LineTableOpcode
.UnknownOpcodeData
.empty() || !IO
.outputting())
227 IO
.mapOptional("StandardOpcodeData", LineTableOpcode
.StandardOpcodeData
);
228 if (!LineTableOpcode
.FileEntry
.Name
.empty() || !IO
.outputting())
229 IO
.mapOptional("FileEntry", LineTableOpcode
.FileEntry
);
230 if (LineTableOpcode
.Opcode
== dwarf::DW_LNS_advance_line
|| !IO
.outputting())
231 IO
.mapOptional("SData", LineTableOpcode
.SData
);
232 IO
.mapOptional("Data", LineTableOpcode
.Data
);
235 void MappingTraits
<DWARFYAML::LineTable
>::mapping(
236 IO
&IO
, DWARFYAML::LineTable
&LineTable
) {
237 IO
.mapOptional("Format", LineTable
.Format
, dwarf::DWARF32
);
238 IO
.mapOptional("Length", LineTable
.Length
);
239 IO
.mapRequired("Version", LineTable
.Version
);
240 IO
.mapOptional("PrologueLength", LineTable
.PrologueLength
);
241 IO
.mapRequired("MinInstLength", LineTable
.MinInstLength
);
242 if(LineTable
.Version
>= 4)
243 IO
.mapRequired("MaxOpsPerInst", LineTable
.MaxOpsPerInst
);
244 IO
.mapRequired("DefaultIsStmt", LineTable
.DefaultIsStmt
);
245 IO
.mapRequired("LineBase", LineTable
.LineBase
);
246 IO
.mapRequired("LineRange", LineTable
.LineRange
);
247 IO
.mapOptional("OpcodeBase", LineTable
.OpcodeBase
);
248 IO
.mapOptional("StandardOpcodeLengths", LineTable
.StandardOpcodeLengths
);
249 IO
.mapOptional("IncludeDirs", LineTable
.IncludeDirs
);
250 IO
.mapOptional("Files", LineTable
.Files
);
251 IO
.mapOptional("Opcodes", LineTable
.Opcodes
);
254 void MappingTraits
<DWARFYAML::SegAddrPair
>::mapping(
255 IO
&IO
, DWARFYAML::SegAddrPair
&SegAddrPair
) {
256 IO
.mapOptional("Segment", SegAddrPair
.Segment
, 0);
257 IO
.mapOptional("Address", SegAddrPair
.Address
, 0);
260 void MappingTraits
<DWARFYAML::AddrTableEntry
>::mapping(
261 IO
&IO
, DWARFYAML::AddrTableEntry
&AddrTable
) {
262 IO
.mapOptional("Format", AddrTable
.Format
, dwarf::DWARF32
);
263 IO
.mapOptional("Length", AddrTable
.Length
);
264 IO
.mapRequired("Version", AddrTable
.Version
);
265 IO
.mapOptional("AddressSize", AddrTable
.AddrSize
);
266 IO
.mapOptional("SegmentSelectorSize", AddrTable
.SegSelectorSize
, 0);
267 IO
.mapOptional("Entries", AddrTable
.SegAddrPairs
);
270 void MappingTraits
<DWARFYAML::StringOffsetsTable
>::mapping(
271 IO
&IO
, DWARFYAML::StringOffsetsTable
&StrOffsetsTable
) {
272 IO
.mapOptional("Format", StrOffsetsTable
.Format
, dwarf::DWARF32
);
273 IO
.mapOptional("Length", StrOffsetsTable
.Length
);
274 IO
.mapOptional("Version", StrOffsetsTable
.Version
, 5);
275 IO
.mapOptional("Padding", StrOffsetsTable
.Padding
, 0);
276 IO
.mapOptional("Offsets", StrOffsetsTable
.Offsets
);
279 void MappingTraits
<DWARFYAML::DWARFOperation
>::mapping(
280 IO
&IO
, DWARFYAML::DWARFOperation
&DWARFOperation
) {
281 IO
.mapRequired("Operator", DWARFOperation
.Operator
);
282 IO
.mapOptional("Values", DWARFOperation
.Values
);
285 void MappingTraits
<DWARFYAML::RnglistEntry
>::mapping(
286 IO
&IO
, DWARFYAML::RnglistEntry
&RnglistEntry
) {
287 IO
.mapRequired("Operator", RnglistEntry
.Operator
);
288 IO
.mapOptional("Values", RnglistEntry
.Values
);
291 void MappingTraits
<DWARFYAML::LoclistEntry
>::mapping(
292 IO
&IO
, DWARFYAML::LoclistEntry
&LoclistEntry
) {
293 IO
.mapRequired("Operator", LoclistEntry
.Operator
);
294 IO
.mapOptional("Values", LoclistEntry
.Values
);
295 IO
.mapOptional("DescriptionsLength", LoclistEntry
.DescriptionsLength
);
296 IO
.mapOptional("Descriptions", LoclistEntry
.Descriptions
);
299 template <typename EntryType
>
300 void MappingTraits
<DWARFYAML::ListEntries
<EntryType
>>::mapping(
301 IO
&IO
, DWARFYAML::ListEntries
<EntryType
> &ListEntries
) {
302 IO
.mapOptional("Entries", ListEntries
.Entries
);
303 IO
.mapOptional("Content", ListEntries
.Content
);
306 template <typename EntryType
>
307 std::string MappingTraits
<DWARFYAML::ListEntries
<EntryType
>>::validate(
308 IO
&IO
, DWARFYAML::ListEntries
<EntryType
> &ListEntries
) {
309 if (ListEntries
.Entries
&& ListEntries
.Content
)
310 return "Entries and Content can't be used together";
314 template <typename EntryType
>
315 void MappingTraits
<DWARFYAML::ListTable
<EntryType
>>::mapping(
316 IO
&IO
, DWARFYAML::ListTable
<EntryType
> &ListTable
) {
317 IO
.mapOptional("Format", ListTable
.Format
, dwarf::DWARF32
);
318 IO
.mapOptional("Length", ListTable
.Length
);
319 IO
.mapOptional("Version", ListTable
.Version
, 5);
320 IO
.mapOptional("AddressSize", ListTable
.AddrSize
);
321 IO
.mapOptional("SegmentSelectorSize", ListTable
.SegSelectorSize
, 0);
322 IO
.mapOptional("OffsetEntryCount", ListTable
.OffsetEntryCount
);
323 IO
.mapOptional("Offsets", ListTable
.Offsets
);
324 IO
.mapOptional("Lists", ListTable
.Lists
);
327 } // end namespace yaml
329 } // end namespace llvm