1 //===- DWARFUnitIndex.h -----------------------------------------*- 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 #ifndef LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H 10 #define LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H 11 12 #include "llvm/ADT/ArrayRef.h" 13 #include "llvm/ADT/StringRef.h" 14 #include <cstdint> 15 #include <memory> 16 17 namespace llvm { 18 19 class raw_ostream; 20 class DataExtractor; 21 22 /// The enum of section identifiers to be used in internal interfaces. 23 /// 24 /// Pre-standard implementation of package files defined a number of section 25 /// identifiers with values that clash definitions in the DWARFv5 standard. 26 /// See https://gcc.gnu.org/wiki/DebugFissionDWP and Section 7.3.5.3 in DWARFv5. 27 /// 28 /// The following identifiers are the same in the proposal and in DWARFv5: 29 /// - DW_SECT_INFO = 1 (.debug_info.dwo) 30 /// - DW_SECT_ABBREV = 3 (.debug_abbrev.dwo) 31 /// - DW_SECT_LINE = 4 (.debug_line.dwo) 32 /// - DW_SECT_STR_OFFSETS = 6 (.debug_str_offsets.dwo) 33 /// 34 /// The following identifiers are defined only in DWARFv5: 35 /// - DW_SECT_LOCLISTS = 5 (.debug_loclists.dwo) 36 /// - DW_SECT_RNGLISTS = 8 (.debug_rnglists.dwo) 37 /// 38 /// The following identifiers are defined only in the GNU proposal: 39 /// - DW_SECT_TYPES = 2 (.debug_types.dwo) 40 /// - DW_SECT_LOC = 5 (.debug_loc.dwo) 41 /// - DW_SECT_MACINFO = 7 (.debug_macinfo.dwo) 42 /// 43 /// DW_SECT_MACRO for the .debug_macro.dwo section is defined in both standards, 44 /// but with different values, 8 in GNU and 7 in DWARFv5. 45 /// 46 /// This enum defines constants to represent the identifiers of both sets. 47 /// For DWARFv5 ones, the values are the same as defined in the standard. 48 /// For pre-standard ones that correspond to sections being deprecated in 49 /// DWARFv5, the values are chosen arbitrary and a tag "_EXT_" is added to 50 /// the names. 51 /// 52 /// The enum is for internal use only. The user should not expect the values 53 /// to correspond to any input/output constants. Special conversion functions, 54 /// serializeSectionKind() and deserializeSectionKind(), should be used for 55 /// the translation. 56 enum DWARFSectionKind { 57 /// Denotes a value read from an index section that does not correspond 58 /// to any of the supported standards. 59 DW_SECT_EXT_unknown = 0, 60 #define HANDLE_DW_SECT(ID, NAME) DW_SECT_##NAME = ID, 61 #include "llvm/BinaryFormat/Dwarf.def" 62 DW_SECT_EXT_TYPES = 2, 63 DW_SECT_EXT_LOC = 9, 64 DW_SECT_EXT_MACINFO = 10, 65 }; 66 67 inline const char *toString(DWARFSectionKind Kind) { 68 switch (Kind) { 69 case DW_SECT_EXT_unknown: 70 return "Unknown DW_SECT value 0"; 71 #define STRINGIZE(X) #X 72 #define HANDLE_DW_SECT(ID, NAME) \ 73 case DW_SECT_##NAME: \ 74 return "DW_SECT_" STRINGIZE(NAME); 75 #include "llvm/BinaryFormat/Dwarf.def" 76 case DW_SECT_EXT_TYPES: 77 return "DW_SECT_TYPES"; 78 case DW_SECT_EXT_LOC: 79 return "DW_SECT_LOC"; 80 case DW_SECT_EXT_MACINFO: 81 return "DW_SECT_MACINFO"; 82 } 83 llvm_unreachable("unknown DWARFSectionKind"); 84 } 85 86 /// Convert the internal value for a section kind to an on-disk value. 87 /// 88 /// The conversion depends on the version of the index section. 89 /// IndexVersion is expected to be either 2 for pre-standard GNU proposal 90 /// or 5 for DWARFv5 package file. 91 uint32_t serializeSectionKind(DWARFSectionKind Kind, unsigned IndexVersion); 92 93 /// Convert a value read from an index section to the internal representation. 94 /// 95 /// The conversion depends on the index section version, which is expected 96 /// to be either 2 for pre-standard GNU proposal or 5 for DWARFv5 package file. 97 DWARFSectionKind deserializeSectionKind(uint32_t Value, unsigned IndexVersion); 98 99 class DWARFUnitIndex { 100 struct Header { 101 uint32_t Version; 102 uint32_t NumColumns; 103 uint32_t NumUnits; 104 uint32_t NumBuckets = 0; 105 106 bool parse(DataExtractor IndexData, uint64_t *OffsetPtr); 107 void dump(raw_ostream &OS) const; 108 }; 109 110 public: 111 class Entry { 112 public: 113 class SectionContribution { 114 private: 115 uint64_t Offset; 116 uint64_t Length; 117 118 public: 119 SectionContribution() : Offset(0), Length(0) {} 120 SectionContribution(uint64_t Offset, uint64_t Length) 121 : Offset(Offset), Length(Length) {} 122 123 void setOffset(uint64_t Value) { Offset = Value; } 124 void setLength(uint64_t Value) { Length = Value; } 125 uint64_t getOffset() const { return Offset; } 126 uint64_t getLength() const { return Length; } 127 uint32_t getOffset32() const { return (uint32_t)Offset; } 128 uint32_t getLength32() const { return (uint32_t)Length; } 129 }; 130 131 private: 132 const DWARFUnitIndex *Index; 133 uint64_t Signature; 134 std::unique_ptr<SectionContribution[]> Contributions; 135 friend class DWARFUnitIndex; 136 137 public: 138 const SectionContribution *getContribution(DWARFSectionKind Sec) const; 139 const SectionContribution *getContribution() const; 140 SectionContribution &getContribution(); 141 142 const SectionContribution *getContributions() const { 143 return Contributions.get(); 144 } 145 146 uint64_t getSignature() const { return Signature; } 147 bool isValid() { return Index; } 148 }; 149 150 private: 151 struct Header Header; 152 153 DWARFSectionKind InfoColumnKind; 154 int InfoColumn = -1; 155 std::unique_ptr<DWARFSectionKind[]> ColumnKinds; 156 // This is a parallel array of section identifiers as they read from the input 157 // file. The mapping from raw values to DWARFSectionKind is not revertable in 158 // case of unknown identifiers, so we keep them here. 159 std::unique_ptr<uint32_t[]> RawSectionIds; 160 std::unique_ptr<Entry[]> Rows; 161 mutable std::vector<Entry *> OffsetLookup; 162 163 static StringRef getColumnHeader(DWARFSectionKind DS); 164 165 bool parseImpl(DataExtractor IndexData); 166 167 public: 168 DWARFUnitIndex(DWARFSectionKind InfoColumnKind) 169 : InfoColumnKind(InfoColumnKind) {} 170 171 explicit operator bool() const { return Header.NumBuckets; } 172 173 bool parse(DataExtractor IndexData); 174 void dump(raw_ostream &OS) const; 175 176 uint32_t getVersion() const { return Header.Version; } 177 178 const Entry *getFromOffset(uint64_t Offset) const; 179 const Entry *getFromHash(uint64_t Offset) const; 180 181 ArrayRef<DWARFSectionKind> getColumnKinds() const { 182 return ArrayRef(ColumnKinds.get(), Header.NumColumns); 183 } 184 185 ArrayRef<Entry> getRows() const { 186 return ArrayRef(Rows.get(), Header.NumBuckets); 187 } 188 189 MutableArrayRef<Entry> getMutableRows() { 190 return MutableArrayRef(Rows.get(), Header.NumBuckets); 191 } 192 }; 193 194 } // end namespace llvm 195 196 #endif // LLVM_DEBUGINFO_DWARF_DWARFUNITINDEX_H 197