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