xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ObjectYAML/DWARFYAML.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 IdxForm {
122   dwarf::Index Idx;
123   dwarf::Form Form;
124 };
125 
126 struct DebugNameAbbreviation {
127   yaml::Hex64 Code;
128   dwarf::Tag Tag;
129   std::vector<IdxForm> Indices;
130 };
131 
132 struct DebugNameEntry {
133   yaml::Hex32 NameStrp;
134   yaml::Hex64 Code;
135   std::vector<yaml::Hex64> Values;
136 };
137 
138 struct DebugNamesSection {
139   std::vector<DebugNameAbbreviation> Abbrevs;
140   std::vector<DebugNameEntry> Entries;
141 };
142 
143 struct File {
144   StringRef Name;
145   uint64_t DirIdx;
146   uint64_t ModTime;
147   uint64_t Length;
148 };
149 
150 struct 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 
161 struct 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 
178 struct SegAddrPair {
179   yaml::Hex64 Segment;
180   yaml::Hex64 Address;
181 };
182 
183 struct 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 
192 struct 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 
200 struct DWARFOperation {
201   dwarf::LocationAtom Operator;
202   std::vector<yaml::Hex64> Values;
203 };
204 
205 struct RnglistEntry {
206   dwarf::RnglistEntries Operator;
207   std::vector<yaml::Hex64> Values;
208 };
209 
210 struct LoclistEntry {
211   dwarf::LoclistEntries Operator;
212   std::vector<yaml::Hex64> Values;
213   std::optional<yaml::Hex64> DescriptionsLength;
214   std::vector<DWARFOperation> Descriptions;
215 };
216 
217 template <typename EntryType> struct ListEntries {
218   std::optional<std::vector<EntryType>> Entries;
219   std::optional<yaml::BinaryRef> Content;
220 };
221 
222 template <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 
233 struct 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 
266 private:
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 
274 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AttributeAbbrev)
LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Abbrev)275 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Abbrev)
276 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AbbrevTable)
277 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARangeDescriptor)
278 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARange)
279 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RangeEntry)
280 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Ranges)
281 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::PubEntry)
282 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Unit)
283 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::FormValue)
284 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Entry)
285 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::File)
286 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTable)
287 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTableOpcode)
288 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::SegAddrPair)
289 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AddrTableEntry)
290 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::StringOffsetsTable)
291 LLVM_YAML_IS_SEQUENCE_VECTOR(
292     llvm::DWARFYAML::ListTable<DWARFYAML::RnglistEntry>)
293 LLVM_YAML_IS_SEQUENCE_VECTOR(
294     llvm::DWARFYAML::ListEntries<DWARFYAML::RnglistEntry>)
295 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RnglistEntry)
296 LLVM_YAML_IS_SEQUENCE_VECTOR(
297     llvm::DWARFYAML::ListTable<DWARFYAML::LoclistEntry>)
298 LLVM_YAML_IS_SEQUENCE_VECTOR(
299     llvm::DWARFYAML::ListEntries<DWARFYAML::LoclistEntry>)
300 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LoclistEntry)
301 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::DWARFOperation)
302 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::DebugNameEntry)
303 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::DebugNameAbbreviation)
304 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::IdxForm)
305 
306 namespace llvm {
307 namespace yaml {
308 
309 template <> struct MappingTraits<DWARFYAML::Data> {
310   static void mapping(IO &IO, DWARFYAML::Data &DWARF);
311 };
312 
313 template <> struct MappingTraits<DWARFYAML::AbbrevTable> {
314   static void mapping(IO &IO, DWARFYAML::AbbrevTable &AbbrevTable);
315 };
316 
317 template <> struct MappingTraits<DWARFYAML::Abbrev> {
318   static void mapping(IO &IO, DWARFYAML::Abbrev &Abbrev);
319 };
320 
321 template <> struct MappingTraits<DWARFYAML::AttributeAbbrev> {
322   static void mapping(IO &IO, DWARFYAML::AttributeAbbrev &AttAbbrev);
323 };
324 
325 template <> struct MappingTraits<DWARFYAML::ARangeDescriptor> {
326   static void mapping(IO &IO, DWARFYAML::ARangeDescriptor &Descriptor);
327 };
328 
329 template <> struct MappingTraits<DWARFYAML::ARange> {
330   static void mapping(IO &IO, DWARFYAML::ARange &ARange);
331 };
332 
333 template <> struct MappingTraits<DWARFYAML::RangeEntry> {
334   static void mapping(IO &IO, DWARFYAML::RangeEntry &Entry);
335 };
336 
337 template <> struct MappingTraits<DWARFYAML::Ranges> {
338   static void mapping(IO &IO, DWARFYAML::Ranges &Ranges);
339 };
340 
341 template <> struct MappingTraits<DWARFYAML::PubEntry> {
342   static void mapping(IO &IO, DWARFYAML::PubEntry &Entry);
343 };
344 
345 template <> struct MappingTraits<DWARFYAML::PubSection> {
346   static void mapping(IO &IO, DWARFYAML::PubSection &Section);
347 };
348 
349 template <> struct MappingTraits<DWARFYAML::Unit> {
350   static void mapping(IO &IO, DWARFYAML::Unit &Unit);
351 };
352 
353 template <> struct MappingTraits<DWARFYAML::DebugNamesSection> {
354   static void mapping(IO &IO, DWARFYAML::DebugNamesSection &);
355 };
356 template <> struct MappingTraits<DWARFYAML::DebugNameEntry> {
357   static void mapping(IO &IO, DWARFYAML::DebugNameEntry &);
358 };
359 template <> struct MappingTraits<DWARFYAML::DebugNameAbbreviation> {
360   static void mapping(IO &IO, DWARFYAML::DebugNameAbbreviation &);
361 };
362 template <> struct MappingTraits<DWARFYAML::IdxForm> {
363   static void mapping(IO &IO, DWARFYAML::IdxForm &);
364 };
365 
366 template <> struct MappingTraits<DWARFYAML::Entry> {
367   static void mapping(IO &IO, DWARFYAML::Entry &Entry);
368 };
369 
370 template <> struct MappingTraits<DWARFYAML::FormValue> {
371   static void mapping(IO &IO, DWARFYAML::FormValue &FormValue);
372 };
373 
374 template <> struct MappingTraits<DWARFYAML::File> {
375   static void mapping(IO &IO, DWARFYAML::File &File);
376 };
377 
378 template <> struct MappingTraits<DWARFYAML::LineTableOpcode> {
379   static void mapping(IO &IO, DWARFYAML::LineTableOpcode &LineTableOpcode);
380 };
381 
382 template <> struct MappingTraits<DWARFYAML::LineTable> {
383   static void mapping(IO &IO, DWARFYAML::LineTable &LineTable);
384 };
385 
386 template <> struct MappingTraits<DWARFYAML::SegAddrPair> {
387   static void mapping(IO &IO, DWARFYAML::SegAddrPair &SegAddrPair);
388 };
389 
390 template <> struct MappingTraits<DWARFYAML::DWARFOperation> {
391   static void mapping(IO &IO, DWARFYAML::DWARFOperation &DWARFOperation);
392 };
393 
394 template <typename EntryType>
395 struct MappingTraits<DWARFYAML::ListTable<EntryType>> {
396   static void mapping(IO &IO, DWARFYAML::ListTable<EntryType> &ListTable);
397 };
398 
399 template <typename EntryType>
400 struct 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 
406 template <> struct MappingTraits<DWARFYAML::RnglistEntry> {
407   static void mapping(IO &IO, DWARFYAML::RnglistEntry &RnglistEntry);
408 };
409 
410 template <> struct MappingTraits<DWARFYAML::LoclistEntry> {
411   static void mapping(IO &IO, DWARFYAML::LoclistEntry &LoclistEntry);
412 };
413 
414 template <> struct MappingTraits<DWARFYAML::AddrTableEntry> {
415   static void mapping(IO &IO, DWARFYAML::AddrTableEntry &AddrTable);
416 };
417 
418 template <> struct MappingTraits<DWARFYAML::StringOffsetsTable> {
419   static void mapping(IO &IO, DWARFYAML::StringOffsetsTable &StrOffsetsTable);
420 };
421 
422 template <> struct ScalarEnumerationTraits<dwarf::DwarfFormat> {
423   static void enumeration(IO &IO, dwarf::DwarfFormat &Format) {
424     IO.enumCase(Format, "DWARF32", dwarf::DWARF32);
425     IO.enumCase(Format, "DWARF64", 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 
432 template <> struct ScalarEnumerationTraits<dwarf::Tag> {
433   static void enumeration(IO &io, dwarf::Tag &value) {
434 #include "llvm/BinaryFormat/Dwarf.def"
435     io.enumFallback<Hex16>(value);
436   }
437 };
438 
439 #define HANDLE_DW_LNS(unused, name)                                            \
440   io.enumCase(value, "DW_LNS_" #name, dwarf::DW_LNS_##name);
441 
442 template <> struct ScalarEnumerationTraits<dwarf::LineNumberOps> {
443   static void enumeration(IO &io, dwarf::LineNumberOps &value) {
444 #include "llvm/BinaryFormat/Dwarf.def"
445     io.enumFallback<Hex8>(value);
446   }
447 };
448 
449 #define HANDLE_DW_LNE(unused, name)                                            \
450   io.enumCase(value, "DW_LNE_" #name, dwarf::DW_LNE_##name);
451 
452 template <> struct ScalarEnumerationTraits<dwarf::LineNumberExtendedOps> {
453   static void enumeration(IO &io, dwarf::LineNumberExtendedOps &value) {
454 #include "llvm/BinaryFormat/Dwarf.def"
455     io.enumFallback<Hex16>(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 
462 template <> struct ScalarEnumerationTraits<dwarf::Attribute> {
463   static void enumeration(IO &io, dwarf::Attribute &value) {
464 #include "llvm/BinaryFormat/Dwarf.def"
465     io.enumFallback<Hex16>(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 
472 template <> struct ScalarEnumerationTraits<dwarf::Form> {
473   static void enumeration(IO &io, dwarf::Form &value) {
474 #include "llvm/BinaryFormat/Dwarf.def"
475     io.enumFallback<Hex16>(value);
476   }
477 };
478 
479 #define HANDLE_DW_IDX(unused, name)                                            \
480   io.enumCase(value, "DW_IDX_" #name, dwarf::DW_IDX_##name);
481 
482 template <> struct ScalarEnumerationTraits<dwarf::Index> {
483   static void enumeration(IO &io, dwarf::Index &value) {
484 #include "llvm/BinaryFormat/Dwarf.def"
485     io.enumFallback<Hex16>(value);
486   }
487 };
488 
489 #define HANDLE_DW_UT(unused, name)                                             \
490   io.enumCase(value, "DW_UT_" #name, dwarf::DW_UT_##name);
491 
492 template <> struct ScalarEnumerationTraits<dwarf::UnitType> {
493   static void enumeration(IO &io, dwarf::UnitType &value) {
494 #include "llvm/BinaryFormat/Dwarf.def"
495     io.enumFallback<Hex8>(value);
496   }
497 };
498 
499 template <> struct ScalarEnumerationTraits<dwarf::Constants> {
500   static void enumeration(IO &io, dwarf::Constants &value) {
501     io.enumCase(value, "DW_CHILDREN_no", dwarf::DW_CHILDREN_no);
502     io.enumCase(value, "DW_CHILDREN_yes", dwarf::DW_CHILDREN_yes);
503     io.enumFallback<Hex16>(value);
504   }
505 };
506 
507 #define HANDLE_DW_RLE(unused, name)                                            \
508   io.enumCase(value, "DW_RLE_" #name, dwarf::DW_RLE_##name);
509 
510 template <> 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 
519 template <> 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, operands, arity, version, vendor)               \
526   io.enumCase(value, "DW_OP_" #name, dwarf::DW_OP_##name);
527 
528 template <> struct ScalarEnumerationTraits<dwarf::LocationAtom> {
529   static void enumeration(IO &io, dwarf::LocationAtom &value) {
530 #include "llvm/BinaryFormat/Dwarf.def"
531     io.enumFallback<yaml::Hex8>(value);
532   }
533 };
534 
535 } // end namespace yaml
536 } // end namespace llvm
537 
538 #endif // LLVM_OBJECTYAML_DWARFYAML_H
539