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 (const auto &[Index
, AbbrevTable
] : enumerate(DebugAbbrev
)) {
63 // If the abbrev table's ID isn't specified, we use the index as its ID.
64 uint64_t AbbrevTableID
= AbbrevTable
.ID
.value_or(Index
);
65 auto It
= AbbrevTableInfoMap
.insert(
66 {AbbrevTableID
, AbbrevTableInfo
{/*Index=*/Index
,
67 /*Offset=*/AbbrevTableOffset
}});
69 return createStringError(
70 errc::invalid_argument
,
71 "the ID (%" PRIu64
") of abbrev table with index %zu has been used "
72 "by abbrev table with index %" PRIu64
,
73 AbbrevTableID
, Index
, It
.first
->second
.Index
);
75 AbbrevTableOffset
+= getAbbrevTableContentByIndex(Index
).size();
79 auto It
= AbbrevTableInfoMap
.find(ID
);
80 if (It
== AbbrevTableInfoMap
.end())
81 return createStringError(errc::invalid_argument
,
82 "cannot find abbrev table whose ID is %" PRIu64
,
89 void MappingTraits
<DWARFYAML::Data
>::mapping(IO
&IO
, DWARFYAML::Data
&DWARF
) {
90 void *OldContext
= IO
.getContext();
91 DWARFYAML::DWARFContext DWARFCtx
;
92 IO
.setContext(&DWARFCtx
);
93 IO
.mapOptional("debug_str", DWARF
.DebugStrings
);
94 IO
.mapOptional("debug_abbrev", DWARF
.DebugAbbrev
);
95 IO
.mapOptional("debug_aranges", DWARF
.DebugAranges
);
96 IO
.mapOptional("debug_ranges", DWARF
.DebugRanges
);
97 IO
.mapOptional("debug_pubnames", DWARF
.PubNames
);
98 IO
.mapOptional("debug_pubtypes", DWARF
.PubTypes
);
99 DWARFCtx
.IsGNUPubSec
= true;
100 IO
.mapOptional("debug_gnu_pubnames", DWARF
.GNUPubNames
);
101 IO
.mapOptional("debug_gnu_pubtypes", DWARF
.GNUPubTypes
);
102 IO
.mapOptional("debug_info", DWARF
.CompileUnits
);
103 IO
.mapOptional("debug_line", DWARF
.DebugLines
);
104 IO
.mapOptional("debug_addr", DWARF
.DebugAddr
);
105 IO
.mapOptional("debug_str_offsets", DWARF
.DebugStrOffsets
);
106 IO
.mapOptional("debug_rnglists", DWARF
.DebugRnglists
);
107 IO
.mapOptional("debug_loclists", DWARF
.DebugLoclists
);
108 IO
.setContext(OldContext
);
111 void MappingTraits
<DWARFYAML::AbbrevTable
>::mapping(
112 IO
&IO
, DWARFYAML::AbbrevTable
&AbbrevTable
) {
113 IO
.mapOptional("ID", AbbrevTable
.ID
);
114 IO
.mapOptional("Table", AbbrevTable
.Table
);
117 void MappingTraits
<DWARFYAML::Abbrev
>::mapping(IO
&IO
,
118 DWARFYAML::Abbrev
&Abbrev
) {
119 IO
.mapOptional("Code", Abbrev
.Code
);
120 IO
.mapRequired("Tag", Abbrev
.Tag
);
121 IO
.mapRequired("Children", Abbrev
.Children
);
122 IO
.mapOptional("Attributes", Abbrev
.Attributes
);
125 void MappingTraits
<DWARFYAML::AttributeAbbrev
>::mapping(
126 IO
&IO
, DWARFYAML::AttributeAbbrev
&AttAbbrev
) {
127 IO
.mapRequired("Attribute", AttAbbrev
.Attribute
);
128 IO
.mapRequired("Form", AttAbbrev
.Form
);
129 if(AttAbbrev
.Form
== dwarf::DW_FORM_implicit_const
)
130 IO
.mapRequired("Value", AttAbbrev
.Value
);
133 void MappingTraits
<DWARFYAML::ARangeDescriptor
>::mapping(
134 IO
&IO
, DWARFYAML::ARangeDescriptor
&Descriptor
) {
135 IO
.mapRequired("Address", Descriptor
.Address
);
136 IO
.mapRequired("Length", Descriptor
.Length
);
139 void MappingTraits
<DWARFYAML::ARange
>::mapping(IO
&IO
,
140 DWARFYAML::ARange
&ARange
) {
141 IO
.mapOptional("Format", ARange
.Format
, dwarf::DWARF32
);
142 IO
.mapOptional("Length", ARange
.Length
);
143 IO
.mapRequired("Version", ARange
.Version
);
144 IO
.mapRequired("CuOffset", ARange
.CuOffset
);
145 IO
.mapOptional("AddressSize", ARange
.AddrSize
);
146 IO
.mapOptional("SegmentSelectorSize", ARange
.SegSize
, 0);
147 IO
.mapOptional("Descriptors", ARange
.Descriptors
);
150 void MappingTraits
<DWARFYAML::RangeEntry
>::mapping(
151 IO
&IO
, DWARFYAML::RangeEntry
&Descriptor
) {
152 IO
.mapRequired("LowOffset", Descriptor
.LowOffset
);
153 IO
.mapRequired("HighOffset", Descriptor
.HighOffset
);
156 void MappingTraits
<DWARFYAML::Ranges
>::mapping(IO
&IO
,
157 DWARFYAML::Ranges
&DebugRanges
) {
158 IO
.mapOptional("Offset", DebugRanges
.Offset
);
159 IO
.mapOptional("AddrSize", DebugRanges
.AddrSize
);
160 IO
.mapRequired("Entries", DebugRanges
.Entries
);
163 void MappingTraits
<DWARFYAML::PubEntry
>::mapping(IO
&IO
,
164 DWARFYAML::PubEntry
&Entry
) {
165 IO
.mapRequired("DieOffset", Entry
.DieOffset
);
166 if (static_cast<DWARFYAML::DWARFContext
*>(IO
.getContext())->IsGNUPubSec
)
167 IO
.mapRequired("Descriptor", Entry
.Descriptor
);
168 IO
.mapRequired("Name", Entry
.Name
);
171 void MappingTraits
<DWARFYAML::PubSection
>::mapping(
172 IO
&IO
, DWARFYAML::PubSection
&Section
) {
173 IO
.mapOptional("Format", Section
.Format
, dwarf::DWARF32
);
174 IO
.mapRequired("Length", Section
.Length
);
175 IO
.mapRequired("Version", Section
.Version
);
176 IO
.mapRequired("UnitOffset", Section
.UnitOffset
);
177 IO
.mapRequired("UnitSize", Section
.UnitSize
);
178 IO
.mapRequired("Entries", Section
.Entries
);
181 void MappingTraits
<DWARFYAML::Unit
>::mapping(IO
&IO
, DWARFYAML::Unit
&Unit
) {
182 IO
.mapOptional("Format", Unit
.Format
, dwarf::DWARF32
);
183 IO
.mapOptional("Length", Unit
.Length
);
184 IO
.mapRequired("Version", Unit
.Version
);
185 if (Unit
.Version
>= 5)
186 IO
.mapRequired("UnitType", Unit
.Type
);
187 IO
.mapOptional("AbbrevTableID", Unit
.AbbrevTableID
);
188 IO
.mapOptional("AbbrOffset", Unit
.AbbrOffset
);
189 IO
.mapOptional("AddrSize", Unit
.AddrSize
);
190 IO
.mapOptional("Entries", Unit
.Entries
);
193 void MappingTraits
<DWARFYAML::Entry
>::mapping(IO
&IO
, DWARFYAML::Entry
&Entry
) {
194 IO
.mapRequired("AbbrCode", Entry
.AbbrCode
);
195 IO
.mapOptional("Values", Entry
.Values
);
198 void MappingTraits
<DWARFYAML::FormValue
>::mapping(
199 IO
&IO
, DWARFYAML::FormValue
&FormValue
) {
200 IO
.mapOptional("Value", FormValue
.Value
);
201 if (!FormValue
.CStr
.empty() || !IO
.outputting())
202 IO
.mapOptional("CStr", FormValue
.CStr
);
203 if (!FormValue
.BlockData
.empty() || !IO
.outputting())
204 IO
.mapOptional("BlockData", FormValue
.BlockData
);
207 void MappingTraits
<DWARFYAML::File
>::mapping(IO
&IO
, DWARFYAML::File
&File
) {
208 IO
.mapRequired("Name", File
.Name
);
209 IO
.mapRequired("DirIdx", File
.DirIdx
);
210 IO
.mapRequired("ModTime", File
.ModTime
);
211 IO
.mapRequired("Length", File
.Length
);
214 void MappingTraits
<DWARFYAML::LineTableOpcode
>::mapping(
215 IO
&IO
, DWARFYAML::LineTableOpcode
&LineTableOpcode
) {
216 IO
.mapRequired("Opcode", LineTableOpcode
.Opcode
);
217 if (LineTableOpcode
.Opcode
== dwarf::DW_LNS_extended_op
) {
218 IO
.mapOptional("ExtLen", LineTableOpcode
.ExtLen
);
219 IO
.mapRequired("SubOpcode", LineTableOpcode
.SubOpcode
);
222 if (!LineTableOpcode
.UnknownOpcodeData
.empty() || !IO
.outputting())
223 IO
.mapOptional("UnknownOpcodeData", LineTableOpcode
.UnknownOpcodeData
);
224 if (!LineTableOpcode
.UnknownOpcodeData
.empty() || !IO
.outputting())
225 IO
.mapOptional("StandardOpcodeData", LineTableOpcode
.StandardOpcodeData
);
226 if (!LineTableOpcode
.FileEntry
.Name
.empty() || !IO
.outputting())
227 IO
.mapOptional("FileEntry", LineTableOpcode
.FileEntry
);
228 if (LineTableOpcode
.Opcode
== dwarf::DW_LNS_advance_line
|| !IO
.outputting())
229 IO
.mapOptional("SData", LineTableOpcode
.SData
);
230 IO
.mapOptional("Data", LineTableOpcode
.Data
);
233 void MappingTraits
<DWARFYAML::LineTable
>::mapping(
234 IO
&IO
, DWARFYAML::LineTable
&LineTable
) {
235 IO
.mapOptional("Format", LineTable
.Format
, dwarf::DWARF32
);
236 IO
.mapOptional("Length", LineTable
.Length
);
237 IO
.mapRequired("Version", LineTable
.Version
);
238 IO
.mapOptional("PrologueLength", LineTable
.PrologueLength
);
239 IO
.mapRequired("MinInstLength", LineTable
.MinInstLength
);
240 if(LineTable
.Version
>= 4)
241 IO
.mapRequired("MaxOpsPerInst", LineTable
.MaxOpsPerInst
);
242 IO
.mapRequired("DefaultIsStmt", LineTable
.DefaultIsStmt
);
243 IO
.mapRequired("LineBase", LineTable
.LineBase
);
244 IO
.mapRequired("LineRange", LineTable
.LineRange
);
245 IO
.mapOptional("OpcodeBase", LineTable
.OpcodeBase
);
246 IO
.mapOptional("StandardOpcodeLengths", LineTable
.StandardOpcodeLengths
);
247 IO
.mapOptional("IncludeDirs", LineTable
.IncludeDirs
);
248 IO
.mapOptional("Files", LineTable
.Files
);
249 IO
.mapOptional("Opcodes", LineTable
.Opcodes
);
252 void MappingTraits
<DWARFYAML::SegAddrPair
>::mapping(
253 IO
&IO
, DWARFYAML::SegAddrPair
&SegAddrPair
) {
254 IO
.mapOptional("Segment", SegAddrPair
.Segment
, 0);
255 IO
.mapOptional("Address", SegAddrPair
.Address
, 0);
258 void MappingTraits
<DWARFYAML::AddrTableEntry
>::mapping(
259 IO
&IO
, DWARFYAML::AddrTableEntry
&AddrTable
) {
260 IO
.mapOptional("Format", AddrTable
.Format
, dwarf::DWARF32
);
261 IO
.mapOptional("Length", AddrTable
.Length
);
262 IO
.mapRequired("Version", AddrTable
.Version
);
263 IO
.mapOptional("AddressSize", AddrTable
.AddrSize
);
264 IO
.mapOptional("SegmentSelectorSize", AddrTable
.SegSelectorSize
, 0);
265 IO
.mapOptional("Entries", AddrTable
.SegAddrPairs
);
268 void MappingTraits
<DWARFYAML::StringOffsetsTable
>::mapping(
269 IO
&IO
, DWARFYAML::StringOffsetsTable
&StrOffsetsTable
) {
270 IO
.mapOptional("Format", StrOffsetsTable
.Format
, dwarf::DWARF32
);
271 IO
.mapOptional("Length", StrOffsetsTable
.Length
);
272 IO
.mapOptional("Version", StrOffsetsTable
.Version
, 5);
273 IO
.mapOptional("Padding", StrOffsetsTable
.Padding
, 0);
274 IO
.mapOptional("Offsets", StrOffsetsTable
.Offsets
);
277 void MappingTraits
<DWARFYAML::DWARFOperation
>::mapping(
278 IO
&IO
, DWARFYAML::DWARFOperation
&DWARFOperation
) {
279 IO
.mapRequired("Operator", DWARFOperation
.Operator
);
280 IO
.mapOptional("Values", DWARFOperation
.Values
);
283 void MappingTraits
<DWARFYAML::RnglistEntry
>::mapping(
284 IO
&IO
, DWARFYAML::RnglistEntry
&RnglistEntry
) {
285 IO
.mapRequired("Operator", RnglistEntry
.Operator
);
286 IO
.mapOptional("Values", RnglistEntry
.Values
);
289 void MappingTraits
<DWARFYAML::LoclistEntry
>::mapping(
290 IO
&IO
, DWARFYAML::LoclistEntry
&LoclistEntry
) {
291 IO
.mapRequired("Operator", LoclistEntry
.Operator
);
292 IO
.mapOptional("Values", LoclistEntry
.Values
);
293 IO
.mapOptional("DescriptionsLength", LoclistEntry
.DescriptionsLength
);
294 IO
.mapOptional("Descriptions", LoclistEntry
.Descriptions
);
297 template <typename EntryType
>
298 void MappingTraits
<DWARFYAML::ListEntries
<EntryType
>>::mapping(
299 IO
&IO
, DWARFYAML::ListEntries
<EntryType
> &ListEntries
) {
300 IO
.mapOptional("Entries", ListEntries
.Entries
);
301 IO
.mapOptional("Content", ListEntries
.Content
);
304 template <typename EntryType
>
305 std::string MappingTraits
<DWARFYAML::ListEntries
<EntryType
>>::validate(
306 IO
&IO
, DWARFYAML::ListEntries
<EntryType
> &ListEntries
) {
307 if (ListEntries
.Entries
&& ListEntries
.Content
)
308 return "Entries and Content can't be used together";
312 template <typename EntryType
>
313 void MappingTraits
<DWARFYAML::ListTable
<EntryType
>>::mapping(
314 IO
&IO
, DWARFYAML::ListTable
<EntryType
> &ListTable
) {
315 IO
.mapOptional("Format", ListTable
.Format
, dwarf::DWARF32
);
316 IO
.mapOptional("Length", ListTable
.Length
);
317 IO
.mapOptional("Version", ListTable
.Version
, 5);
318 IO
.mapOptional("AddressSize", ListTable
.AddrSize
);
319 IO
.mapOptional("SegmentSelectorSize", ListTable
.SegSelectorSize
, 0);
320 IO
.mapOptional("OffsetEntryCount", ListTable
.OffsetEntryCount
);
321 IO
.mapOptional("Offsets", ListTable
.Offsets
);
322 IO
.mapOptional("Lists", ListTable
.Lists
);
325 } // end namespace yaml
327 } // end namespace llvm