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