1 //===- DWARFYAML.h - DWARF YAMLIO implementation ----------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file declares classes for handling the YAML representation
11 /// of DWARF Debug Info.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLVM_OBJECTYAML_DWARFYAML_H
16 #define LLVM_OBJECTYAML_DWARFYAML_H
17
18 #include "llvm/ADT/SetVector.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/BinaryFormat/Dwarf.h"
21 #include "llvm/ObjectYAML/YAML.h"
22 #include "llvm/Support/YAMLTraits.h"
23 #include <cstdint>
24 #include <optional>
25 #include <unordered_map>
26 #include <vector>
27
28 namespace llvm {
29 namespace DWARFYAML {
30
31 struct AttributeAbbrev {
32 llvm::dwarf::Attribute Attribute;
33 llvm::dwarf::Form Form;
34 llvm::yaml::Hex64 Value; // Some DWARF5 attributes have values
35 };
36
37 struct Abbrev {
38 std::optional<yaml::Hex64> Code;
39 llvm::dwarf::Tag Tag;
40 llvm::dwarf::Constants Children;
41 std::vector<AttributeAbbrev> Attributes;
42 };
43
44 struct AbbrevTable {
45 std::optional<uint64_t> ID;
46 std::vector<Abbrev> Table;
47 };
48
49 struct ARangeDescriptor {
50 llvm::yaml::Hex64 Address;
51 yaml::Hex64 Length;
52 };
53
54 struct ARange {
55 dwarf::DwarfFormat Format;
56 std::optional<yaml::Hex64> Length;
57 uint16_t Version;
58 yaml::Hex64 CuOffset;
59 std::optional<yaml::Hex8> AddrSize;
60 yaml::Hex8 SegSize;
61 std::vector<ARangeDescriptor> Descriptors;
62 };
63
64 /// Class that describes a range list entry, or a base address selection entry
65 /// within a range list in the .debug_ranges section.
66 struct RangeEntry {
67 llvm::yaml::Hex64 LowOffset;
68 llvm::yaml::Hex64 HighOffset;
69 };
70
71 /// Class that describes a single range list inside the .debug_ranges section.
72 struct Ranges {
73 std::optional<llvm::yaml::Hex64> Offset;
74 std::optional<llvm::yaml::Hex8> AddrSize;
75 std::vector<RangeEntry> Entries;
76 };
77
78 struct PubEntry {
79 llvm::yaml::Hex32 DieOffset;
80 llvm::yaml::Hex8 Descriptor;
81 StringRef Name;
82 };
83
84 struct PubSection {
85 dwarf::DwarfFormat Format;
86 yaml::Hex64 Length;
87 uint16_t Version;
88 uint32_t UnitOffset;
89 uint32_t UnitSize;
90 std::vector<PubEntry> Entries;
91 };
92
93 struct FormValue {
94 llvm::yaml::Hex64 Value;
95 StringRef CStr;
96 std::vector<llvm::yaml::Hex8> BlockData;
97 };
98
99 struct Entry {
100 llvm::yaml::Hex32 AbbrCode;
101 std::vector<FormValue> Values;
102 };
103
104 /// Class that contains helpful context information when mapping YAML into DWARF
105 /// data structures.
106 struct DWARFContext {
107 bool IsGNUPubSec = false;
108 };
109
110 struct Unit {
111 dwarf::DwarfFormat Format;
112 std::optional<yaml::Hex64> Length;
113 uint16_t Version;
114 std::optional<uint8_t> AddrSize;
115 llvm::dwarf::UnitType Type; // Added in DWARF 5
116 std::optional<uint64_t> AbbrevTableID;
117 std::optional<yaml::Hex64> AbbrOffset;
118 std::vector<Entry> Entries;
119 };
120
121 struct File {
122 StringRef Name;
123 uint64_t DirIdx;
124 uint64_t ModTime;
125 uint64_t Length;
126 };
127
128 struct LineTableOpcode {
129 dwarf::LineNumberOps Opcode;
130 std::optional<uint64_t> ExtLen;
131 dwarf::LineNumberExtendedOps SubOpcode;
132 uint64_t Data;
133 int64_t SData;
134 File FileEntry;
135 std::vector<llvm::yaml::Hex8> UnknownOpcodeData;
136 std::vector<llvm::yaml::Hex64> StandardOpcodeData;
137 };
138
139 struct LineTable {
140 dwarf::DwarfFormat Format;
141 std::optional<uint64_t> Length;
142 uint16_t Version;
143 std::optional<uint64_t> PrologueLength;
144 uint8_t MinInstLength;
145 uint8_t MaxOpsPerInst;
146 uint8_t DefaultIsStmt;
147 uint8_t LineBase;
148 uint8_t LineRange;
149 std::optional<uint8_t> OpcodeBase;
150 std::optional<std::vector<uint8_t>> StandardOpcodeLengths;
151 std::vector<StringRef> IncludeDirs;
152 std::vector<File> Files;
153 std::vector<LineTableOpcode> Opcodes;
154 };
155
156 struct SegAddrPair {
157 yaml::Hex64 Segment;
158 yaml::Hex64 Address;
159 };
160
161 struct AddrTableEntry {
162 dwarf::DwarfFormat Format;
163 std::optional<yaml::Hex64> Length;
164 yaml::Hex16 Version;
165 std::optional<yaml::Hex8> AddrSize;
166 yaml::Hex8 SegSelectorSize;
167 std::vector<SegAddrPair> SegAddrPairs;
168 };
169
170 struct StringOffsetsTable {
171 dwarf::DwarfFormat Format;
172 std::optional<yaml::Hex64> Length;
173 yaml::Hex16 Version;
174 yaml::Hex16 Padding;
175 std::vector<yaml::Hex64> Offsets;
176 };
177
178 struct DWARFOperation {
179 dwarf::LocationAtom Operator;
180 std::vector<yaml::Hex64> Values;
181 };
182
183 struct RnglistEntry {
184 dwarf::RnglistEntries Operator;
185 std::vector<yaml::Hex64> Values;
186 };
187
188 struct LoclistEntry {
189 dwarf::LoclistEntries Operator;
190 std::vector<yaml::Hex64> Values;
191 std::optional<yaml::Hex64> DescriptionsLength;
192 std::vector<DWARFOperation> Descriptions;
193 };
194
195 template <typename EntryType> struct ListEntries {
196 std::optional<std::vector<EntryType>> Entries;
197 std::optional<yaml::BinaryRef> Content;
198 };
199
200 template <typename EntryType> struct ListTable {
201 dwarf::DwarfFormat Format;
202 std::optional<yaml::Hex64> Length;
203 yaml::Hex16 Version;
204 std::optional<yaml::Hex8> AddrSize;
205 yaml::Hex8 SegSelectorSize;
206 std::optional<uint32_t> OffsetEntryCount;
207 std::optional<std::vector<yaml::Hex64>> Offsets;
208 std::vector<ListEntries<EntryType>> Lists;
209 };
210
211 struct Data {
212 bool IsLittleEndian;
213 bool Is64BitAddrSize;
214 std::vector<AbbrevTable> DebugAbbrev;
215 std::optional<std::vector<StringRef>> DebugStrings;
216 std::optional<std::vector<StringOffsetsTable>> DebugStrOffsets;
217 std::optional<std::vector<ARange>> DebugAranges;
218 std::optional<std::vector<Ranges>> DebugRanges;
219 std::optional<std::vector<AddrTableEntry>> DebugAddr;
220 std::optional<PubSection> PubNames;
221 std::optional<PubSection> PubTypes;
222
223 std::optional<PubSection> GNUPubNames;
224 std::optional<PubSection> GNUPubTypes;
225
226 std::vector<Unit> CompileUnits;
227
228 std::vector<LineTable> DebugLines;
229 std::optional<std::vector<ListTable<RnglistEntry>>> DebugRnglists;
230 std::optional<std::vector<ListTable<LoclistEntry>>> DebugLoclists;
231
232 bool isEmpty() const;
233
234 SetVector<StringRef> getNonEmptySectionNames() const;
235
236 struct AbbrevTableInfo {
237 uint64_t Index;
238 uint64_t Offset;
239 };
240 Expected<AbbrevTableInfo> getAbbrevTableInfoByID(uint64_t ID) const;
241 StringRef getAbbrevTableContentByIndex(uint64_t Index) const;
242
243 private:
244 mutable std::unordered_map<uint64_t, AbbrevTableInfo> AbbrevTableInfoMap;
245 mutable std::unordered_map<uint64_t, std::string> AbbrevTableContents;
246 };
247
248 } // end namespace DWARFYAML
249 } // end namespace llvm
250
251 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AttributeAbbrev)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Abbrev)252 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Abbrev)
253 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AbbrevTable)
254 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARangeDescriptor)
255 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARange)
256 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RangeEntry)
257 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Ranges)
258 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::PubEntry)
259 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Unit)
260 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::FormValue)
261 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Entry)
262 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::File)
263 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTable)
264 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTableOpcode)
265 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::SegAddrPair)
266 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AddrTableEntry)
267 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::StringOffsetsTable)
268 LLVM_YAML_IS_SEQUENCE_VECTOR(
269 llvm::DWARFYAML::ListTable<DWARFYAML::RnglistEntry>)
270 LLVM_YAML_IS_SEQUENCE_VECTOR(
271 llvm::DWARFYAML::ListEntries<DWARFYAML::RnglistEntry>)
272 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RnglistEntry)
273 LLVM_YAML_IS_SEQUENCE_VECTOR(
274 llvm::DWARFYAML::ListTable<DWARFYAML::LoclistEntry>)
275 LLVM_YAML_IS_SEQUENCE_VECTOR(
276 llvm::DWARFYAML::ListEntries<DWARFYAML::LoclistEntry>)
277 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LoclistEntry)
278 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::DWARFOperation)
279
280 namespace llvm {
281 namespace yaml {
282
283 template <> struct MappingTraits<DWARFYAML::Data> {
284 static void mapping(IO &IO, DWARFYAML::Data &DWARF);
285 };
286
287 template <> struct MappingTraits<DWARFYAML::AbbrevTable> {
288 static void mapping(IO &IO, DWARFYAML::AbbrevTable &AbbrevTable);
289 };
290
291 template <> struct MappingTraits<DWARFYAML::Abbrev> {
292 static void mapping(IO &IO, DWARFYAML::Abbrev &Abbrev);
293 };
294
295 template <> struct MappingTraits<DWARFYAML::AttributeAbbrev> {
296 static void mapping(IO &IO, DWARFYAML::AttributeAbbrev &AttAbbrev);
297 };
298
299 template <> struct MappingTraits<DWARFYAML::ARangeDescriptor> {
300 static void mapping(IO &IO, DWARFYAML::ARangeDescriptor &Descriptor);
301 };
302
303 template <> struct MappingTraits<DWARFYAML::ARange> {
304 static void mapping(IO &IO, DWARFYAML::ARange &ARange);
305 };
306
307 template <> struct MappingTraits<DWARFYAML::RangeEntry> {
308 static void mapping(IO &IO, DWARFYAML::RangeEntry &Entry);
309 };
310
311 template <> struct MappingTraits<DWARFYAML::Ranges> {
312 static void mapping(IO &IO, DWARFYAML::Ranges &Ranges);
313 };
314
315 template <> struct MappingTraits<DWARFYAML::PubEntry> {
316 static void mapping(IO &IO, DWARFYAML::PubEntry &Entry);
317 };
318
319 template <> struct MappingTraits<DWARFYAML::PubSection> {
320 static void mapping(IO &IO, DWARFYAML::PubSection &Section);
321 };
322
323 template <> struct MappingTraits<DWARFYAML::Unit> {
324 static void mapping(IO &IO, DWARFYAML::Unit &Unit);
325 };
326
327 template <> struct MappingTraits<DWARFYAML::Entry> {
328 static void mapping(IO &IO, DWARFYAML::Entry &Entry);
329 };
330
331 template <> struct MappingTraits<DWARFYAML::FormValue> {
332 static void mapping(IO &IO, DWARFYAML::FormValue &FormValue);
333 };
334
335 template <> struct MappingTraits<DWARFYAML::File> {
336 static void mapping(IO &IO, DWARFYAML::File &File);
337 };
338
339 template <> struct MappingTraits<DWARFYAML::LineTableOpcode> {
340 static void mapping(IO &IO, DWARFYAML::LineTableOpcode &LineTableOpcode);
341 };
342
343 template <> struct MappingTraits<DWARFYAML::LineTable> {
344 static void mapping(IO &IO, DWARFYAML::LineTable &LineTable);
345 };
346
347 template <> struct MappingTraits<DWARFYAML::SegAddrPair> {
348 static void mapping(IO &IO, DWARFYAML::SegAddrPair &SegAddrPair);
349 };
350
351 template <> struct MappingTraits<DWARFYAML::DWARFOperation> {
352 static void mapping(IO &IO, DWARFYAML::DWARFOperation &DWARFOperation);
353 };
354
355 template <typename EntryType>
356 struct MappingTraits<DWARFYAML::ListTable<EntryType>> {
357 static void mapping(IO &IO, DWARFYAML::ListTable<EntryType> &ListTable);
358 };
359
360 template <typename EntryType>
361 struct MappingTraits<DWARFYAML::ListEntries<EntryType>> {
362 static void mapping(IO &IO, DWARFYAML::ListEntries<EntryType> &ListEntries);
363 static std::string validate(IO &IO,
364 DWARFYAML::ListEntries<EntryType> &ListEntries);
365 };
366
367 template <> struct MappingTraits<DWARFYAML::RnglistEntry> {
368 static void mapping(IO &IO, DWARFYAML::RnglistEntry &RnglistEntry);
369 };
370
371 template <> struct MappingTraits<DWARFYAML::LoclistEntry> {
372 static void mapping(IO &IO, DWARFYAML::LoclistEntry &LoclistEntry);
373 };
374
375 template <> struct MappingTraits<DWARFYAML::AddrTableEntry> {
376 static void mapping(IO &IO, DWARFYAML::AddrTableEntry &AddrTable);
377 };
378
379 template <> struct MappingTraits<DWARFYAML::StringOffsetsTable> {
380 static void mapping(IO &IO, DWARFYAML::StringOffsetsTable &StrOffsetsTable);
381 };
382
383 template <> struct ScalarEnumerationTraits<dwarf::DwarfFormat> {
384 static void enumeration(IO &IO, dwarf::DwarfFormat &Format) {
385 IO.enumCase(Format, "DWARF32", dwarf::DWARF32);
386 IO.enumCase(Format, "DWARF64", dwarf::DWARF64);
387 }
388 };
389
390 #define HANDLE_DW_TAG(unused, name, unused2, unused3, unused4) \
391 io.enumCase(value, "DW_TAG_" #name, dwarf::DW_TAG_##name);
392
393 template <> struct ScalarEnumerationTraits<dwarf::Tag> {
394 static void enumeration(IO &io, dwarf::Tag &value) {
395 #include "llvm/BinaryFormat/Dwarf.def"
396 io.enumFallback<Hex16>(value);
397 }
398 };
399
400 #define HANDLE_DW_LNS(unused, name) \
401 io.enumCase(value, "DW_LNS_" #name, dwarf::DW_LNS_##name);
402
403 template <> struct ScalarEnumerationTraits<dwarf::LineNumberOps> {
404 static void enumeration(IO &io, dwarf::LineNumberOps &value) {
405 #include "llvm/BinaryFormat/Dwarf.def"
406 io.enumFallback<Hex8>(value);
407 }
408 };
409
410 #define HANDLE_DW_LNE(unused, name) \
411 io.enumCase(value, "DW_LNE_" #name, dwarf::DW_LNE_##name);
412
413 template <> struct ScalarEnumerationTraits<dwarf::LineNumberExtendedOps> {
414 static void enumeration(IO &io, dwarf::LineNumberExtendedOps &value) {
415 #include "llvm/BinaryFormat/Dwarf.def"
416 io.enumFallback<Hex16>(value);
417 }
418 };
419
420 #define HANDLE_DW_AT(unused, name, unused2, unused3) \
421 io.enumCase(value, "DW_AT_" #name, dwarf::DW_AT_##name);
422
423 template <> struct ScalarEnumerationTraits<dwarf::Attribute> {
424 static void enumeration(IO &io, dwarf::Attribute &value) {
425 #include "llvm/BinaryFormat/Dwarf.def"
426 io.enumFallback<Hex16>(value);
427 }
428 };
429
430 #define HANDLE_DW_FORM(unused, name, unused2, unused3) \
431 io.enumCase(value, "DW_FORM_" #name, dwarf::DW_FORM_##name);
432
433 template <> struct ScalarEnumerationTraits<dwarf::Form> {
434 static void enumeration(IO &io, dwarf::Form &value) {
435 #include "llvm/BinaryFormat/Dwarf.def"
436 io.enumFallback<Hex16>(value);
437 }
438 };
439
440 #define HANDLE_DW_UT(unused, name) \
441 io.enumCase(value, "DW_UT_" #name, dwarf::DW_UT_##name);
442
443 template <> struct ScalarEnumerationTraits<dwarf::UnitType> {
444 static void enumeration(IO &io, dwarf::UnitType &value) {
445 #include "llvm/BinaryFormat/Dwarf.def"
446 io.enumFallback<Hex8>(value);
447 }
448 };
449
450 template <> struct ScalarEnumerationTraits<dwarf::Constants> {
451 static void enumeration(IO &io, dwarf::Constants &value) {
452 io.enumCase(value, "DW_CHILDREN_no", dwarf::DW_CHILDREN_no);
453 io.enumCase(value, "DW_CHILDREN_yes", dwarf::DW_CHILDREN_yes);
454 io.enumFallback<Hex16>(value);
455 }
456 };
457
458 #define HANDLE_DW_RLE(unused, name) \
459 io.enumCase(value, "DW_RLE_" #name, dwarf::DW_RLE_##name);
460
461 template <> struct ScalarEnumerationTraits<dwarf::RnglistEntries> {
462 static void enumeration(IO &io, dwarf::RnglistEntries &value) {
463 #include "llvm/BinaryFormat/Dwarf.def"
464 }
465 };
466
467 #define HANDLE_DW_LLE(unused, name) \
468 io.enumCase(value, "DW_LLE_" #name, dwarf::DW_LLE_##name);
469
470 template <> struct ScalarEnumerationTraits<dwarf::LoclistEntries> {
471 static void enumeration(IO &io, dwarf::LoclistEntries &value) {
472 #include "llvm/BinaryFormat/Dwarf.def"
473 }
474 };
475
476 #define HANDLE_DW_OP(id, name, version, vendor) \
477 io.enumCase(value, "DW_OP_" #name, dwarf::DW_OP_##name);
478
479 template <> struct ScalarEnumerationTraits<dwarf::LocationAtom> {
480 static void enumeration(IO &io, dwarf::LocationAtom &value) {
481 #include "llvm/BinaryFormat/Dwarf.def"
482 io.enumFallback<yaml::Hex8>(value);
483 }
484 };
485
486 } // end namespace yaml
487 } // end namespace llvm
488
489 #endif // LLVM_OBJECTYAML_DWARFYAML_H
490