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