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