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

source code of llvm/include/llvm/ObjectYAML/DWARFYAML.h