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)
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