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/Support/YAMLTraits.h" 22 #include <cstdint> 23 #include <vector> 24 25 namespace llvm { 26 namespace DWARFYAML { 27 28 struct InitialLength { 29 uint32_t TotalLength; 30 uint64_t TotalLength64; 31 32 bool isDWARF64() const { return TotalLength == UINT32_MAX; } 33 34 uint64_t getLength() const { 35 return isDWARF64() ? TotalLength64 : TotalLength; 36 } 37 38 void setLength(uint64_t Len) { 39 if (Len >= (uint64_t)UINT32_MAX) { 40 TotalLength64 = Len; 41 TotalLength = UINT32_MAX; 42 } else { 43 TotalLength = Len; 44 } 45 } 46 }; 47 48 struct AttributeAbbrev { 49 llvm::dwarf::Attribute Attribute; 50 llvm::dwarf::Form Form; 51 llvm::yaml::Hex64 Value; // Some DWARF5 attributes have values 52 }; 53 54 struct Abbrev { 55 Optional<yaml::Hex64> Code; 56 llvm::dwarf::Tag Tag; 57 llvm::dwarf::Constants Children; 58 std::vector<AttributeAbbrev> Attributes; 59 }; 60 61 struct ARangeDescriptor { 62 llvm::yaml::Hex64 Address; 63 uint64_t Length; 64 }; 65 66 struct ARange { 67 dwarf::DwarfFormat Format; 68 uint64_t Length; 69 uint16_t Version; 70 uint32_t CuOffset; 71 uint8_t AddrSize; 72 uint8_t SegSize; 73 std::vector<ARangeDescriptor> Descriptors; 74 }; 75 76 /// Class that describes a range list entry, or a base address selection entry 77 /// within a range list in the .debug_ranges section. 78 struct RangeEntry { 79 llvm::yaml::Hex64 LowOffset; 80 llvm::yaml::Hex64 HighOffset; 81 }; 82 83 /// Class that describes a single range list inside the .debug_ranges section. 84 struct Ranges { 85 Optional<llvm::yaml::Hex64> Offset; 86 Optional<llvm::yaml::Hex8> AddrSize; 87 std::vector<RangeEntry> Entries; 88 }; 89 90 struct PubEntry { 91 llvm::yaml::Hex32 DieOffset; 92 llvm::yaml::Hex8 Descriptor; 93 StringRef Name; 94 }; 95 96 struct PubSection { 97 InitialLength Length; 98 uint16_t Version; 99 uint32_t UnitOffset; 100 uint32_t UnitSize; 101 std::vector<PubEntry> Entries; 102 }; 103 104 struct FormValue { 105 llvm::yaml::Hex64 Value; 106 StringRef CStr; 107 std::vector<llvm::yaml::Hex8> BlockData; 108 }; 109 110 struct Entry { 111 llvm::yaml::Hex32 AbbrCode; 112 std::vector<FormValue> Values; 113 }; 114 115 /// Class that contains helpful context information when mapping YAML into DWARF 116 /// data structures. 117 struct DWARFContext { 118 bool IsGNUPubSec = false; 119 }; 120 121 struct Unit { 122 dwarf::DwarfFormat Format; 123 uint64_t Length; 124 uint16_t Version; 125 llvm::dwarf::UnitType Type; // Added in DWARF 5 126 yaml::Hex64 AbbrOffset; 127 uint8_t AddrSize; 128 std::vector<Entry> Entries; 129 }; 130 131 struct File { 132 StringRef Name; 133 uint64_t DirIdx; 134 uint64_t ModTime; 135 uint64_t Length; 136 }; 137 138 struct LineTableOpcode { 139 dwarf::LineNumberOps Opcode; 140 uint64_t ExtLen; 141 dwarf::LineNumberExtendedOps SubOpcode; 142 uint64_t Data; 143 int64_t SData; 144 File FileEntry; 145 std::vector<llvm::yaml::Hex8> UnknownOpcodeData; 146 std::vector<llvm::yaml::Hex64> StandardOpcodeData; 147 }; 148 149 struct LineTable { 150 dwarf::DwarfFormat Format; 151 uint64_t Length; 152 uint16_t Version; 153 uint64_t PrologueLength; 154 uint8_t MinInstLength; 155 uint8_t MaxOpsPerInst; 156 uint8_t DefaultIsStmt; 157 uint8_t LineBase; 158 uint8_t LineRange; 159 uint8_t OpcodeBase; 160 std::vector<uint8_t> StandardOpcodeLengths; 161 std::vector<StringRef> IncludeDirs; 162 std::vector<File> Files; 163 std::vector<LineTableOpcode> Opcodes; 164 }; 165 166 struct SegAddrPair { 167 yaml::Hex64 Segment; 168 yaml::Hex64 Address; 169 }; 170 171 struct AddrTableEntry { 172 dwarf::DwarfFormat Format; 173 Optional<yaml::Hex64> Length; 174 yaml::Hex16 Version; 175 Optional<yaml::Hex8> AddrSize; 176 yaml::Hex8 SegSelectorSize; 177 std::vector<SegAddrPair> SegAddrPairs; 178 }; 179 180 struct Data { 181 bool IsLittleEndian; 182 bool Is64BitAddrSize; 183 std::vector<Abbrev> AbbrevDecls; 184 std::vector<StringRef> DebugStrings; 185 std::vector<ARange> ARanges; 186 std::vector<Ranges> DebugRanges; 187 std::vector<AddrTableEntry> DebugAddr; 188 Optional<PubSection> PubNames; 189 Optional<PubSection> PubTypes; 190 191 Optional<PubSection> GNUPubNames; 192 Optional<PubSection> GNUPubTypes; 193 194 std::vector<Unit> CompileUnits; 195 196 std::vector<LineTable> DebugLines; 197 198 bool isEmpty() const; 199 200 SetVector<StringRef> getUsedSectionNames() const; 201 }; 202 203 } // end namespace DWARFYAML 204 } // end namespace llvm 205 206 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AttributeAbbrev) 207 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Abbrev) 208 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARangeDescriptor) 209 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::ARange) 210 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::RangeEntry) 211 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Ranges) 212 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::PubEntry) 213 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Unit) 214 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::FormValue) 215 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::Entry) 216 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::File) 217 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTable) 218 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::LineTableOpcode) 219 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::SegAddrPair) 220 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::DWARFYAML::AddrTableEntry) 221 222 namespace llvm { 223 namespace yaml { 224 225 template <> struct MappingTraits<DWARFYAML::Data> { 226 static void mapping(IO &IO, DWARFYAML::Data &DWARF); 227 }; 228 229 template <> struct MappingTraits<DWARFYAML::Abbrev> { 230 static void mapping(IO &IO, DWARFYAML::Abbrev &Abbrev); 231 }; 232 233 template <> struct MappingTraits<DWARFYAML::AttributeAbbrev> { 234 static void mapping(IO &IO, DWARFYAML::AttributeAbbrev &AttAbbrev); 235 }; 236 237 template <> struct MappingTraits<DWARFYAML::ARangeDescriptor> { 238 static void mapping(IO &IO, DWARFYAML::ARangeDescriptor &Descriptor); 239 }; 240 241 template <> struct MappingTraits<DWARFYAML::ARange> { 242 static void mapping(IO &IO, DWARFYAML::ARange &ARange); 243 }; 244 245 template <> struct MappingTraits<DWARFYAML::RangeEntry> { 246 static void mapping(IO &IO, DWARFYAML::RangeEntry &Entry); 247 }; 248 249 template <> struct MappingTraits<DWARFYAML::Ranges> { 250 static void mapping(IO &IO, DWARFYAML::Ranges &Ranges); 251 }; 252 253 template <> struct MappingTraits<DWARFYAML::PubEntry> { 254 static void mapping(IO &IO, DWARFYAML::PubEntry &Entry); 255 }; 256 257 template <> struct MappingTraits<DWARFYAML::PubSection> { 258 static void mapping(IO &IO, DWARFYAML::PubSection &Section); 259 }; 260 261 template <> struct MappingTraits<DWARFYAML::Unit> { 262 static void mapping(IO &IO, DWARFYAML::Unit &Unit); 263 }; 264 265 template <> struct MappingTraits<DWARFYAML::Entry> { 266 static void mapping(IO &IO, DWARFYAML::Entry &Entry); 267 }; 268 269 template <> struct MappingTraits<DWARFYAML::FormValue> { 270 static void mapping(IO &IO, DWARFYAML::FormValue &FormValue); 271 }; 272 273 template <> struct MappingTraits<DWARFYAML::File> { 274 static void mapping(IO &IO, DWARFYAML::File &File); 275 }; 276 277 template <> struct MappingTraits<DWARFYAML::LineTableOpcode> { 278 static void mapping(IO &IO, DWARFYAML::LineTableOpcode &LineTableOpcode); 279 }; 280 281 template <> struct MappingTraits<DWARFYAML::LineTable> { 282 static void mapping(IO &IO, DWARFYAML::LineTable &LineTable); 283 }; 284 285 template <> struct MappingTraits<DWARFYAML::SegAddrPair> { 286 static void mapping(IO &IO, DWARFYAML::SegAddrPair &SegAddrPair); 287 }; 288 289 template <> struct MappingTraits<DWARFYAML::AddrTableEntry> { 290 static void mapping(IO &IO, DWARFYAML::AddrTableEntry &AddrTable); 291 }; 292 293 template <> struct MappingTraits<DWARFYAML::InitialLength> { 294 static void mapping(IO &IO, DWARFYAML::InitialLength &DWARF); 295 }; 296 297 template <> struct ScalarEnumerationTraits<dwarf::DwarfFormat> { 298 static void enumeration(IO &IO, dwarf::DwarfFormat &Format) { 299 IO.enumCase(Format, "DWARF32", dwarf::DWARF32); 300 IO.enumCase(Format, "DWARF64", dwarf::DWARF64); 301 } 302 }; 303 304 #define HANDLE_DW_TAG(unused, name, unused2, unused3, unused4) \ 305 io.enumCase(value, "DW_TAG_" #name, dwarf::DW_TAG_##name); 306 307 template <> struct ScalarEnumerationTraits<dwarf::Tag> { 308 static void enumeration(IO &io, dwarf::Tag &value) { 309 #include "llvm/BinaryFormat/Dwarf.def" 310 io.enumFallback<Hex16>(value); 311 } 312 }; 313 314 #define HANDLE_DW_LNS(unused, name) \ 315 io.enumCase(value, "DW_LNS_" #name, dwarf::DW_LNS_##name); 316 317 template <> struct ScalarEnumerationTraits<dwarf::LineNumberOps> { 318 static void enumeration(IO &io, dwarf::LineNumberOps &value) { 319 #include "llvm/BinaryFormat/Dwarf.def" 320 io.enumFallback<Hex8>(value); 321 } 322 }; 323 324 #define HANDLE_DW_LNE(unused, name) \ 325 io.enumCase(value, "DW_LNE_" #name, dwarf::DW_LNE_##name); 326 327 template <> struct ScalarEnumerationTraits<dwarf::LineNumberExtendedOps> { 328 static void enumeration(IO &io, dwarf::LineNumberExtendedOps &value) { 329 #include "llvm/BinaryFormat/Dwarf.def" 330 io.enumFallback<Hex16>(value); 331 } 332 }; 333 334 #define HANDLE_DW_AT(unused, name, unused2, unused3) \ 335 io.enumCase(value, "DW_AT_" #name, dwarf::DW_AT_##name); 336 337 template <> struct ScalarEnumerationTraits<dwarf::Attribute> { 338 static void enumeration(IO &io, dwarf::Attribute &value) { 339 #include "llvm/BinaryFormat/Dwarf.def" 340 io.enumFallback<Hex16>(value); 341 } 342 }; 343 344 #define HANDLE_DW_FORM(unused, name, unused2, unused3) \ 345 io.enumCase(value, "DW_FORM_" #name, dwarf::DW_FORM_##name); 346 347 template <> struct ScalarEnumerationTraits<dwarf::Form> { 348 static void enumeration(IO &io, dwarf::Form &value) { 349 #include "llvm/BinaryFormat/Dwarf.def" 350 io.enumFallback<Hex16>(value); 351 } 352 }; 353 354 #define HANDLE_DW_UT(unused, name) \ 355 io.enumCase(value, "DW_UT_" #name, dwarf::DW_UT_##name); 356 357 template <> struct ScalarEnumerationTraits<dwarf::UnitType> { 358 static void enumeration(IO &io, dwarf::UnitType &value) { 359 #include "llvm/BinaryFormat/Dwarf.def" 360 io.enumFallback<Hex8>(value); 361 } 362 }; 363 364 template <> struct ScalarEnumerationTraits<dwarf::Constants> { 365 static void enumeration(IO &io, dwarf::Constants &value) { 366 io.enumCase(value, "DW_CHILDREN_no", dwarf::DW_CHILDREN_no); 367 io.enumCase(value, "DW_CHILDREN_yes", dwarf::DW_CHILDREN_yes); 368 io.enumFallback<Hex16>(value); 369 } 370 }; 371 372 } // end namespace yaml 373 } // end namespace llvm 374 375 #endif // LLVM_OBJECTYAML_DWARFYAML_H 376