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