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