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