1 //===-- HashedNameToDIE.h ---------------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #ifndef SymbolFileDWARF_HashedNameToDIE_h_ 11 #define SymbolFileDWARF_HashedNameToDIE_h_ 12 13 #include <vector> 14 #include "lldb/lldb-defines.h" 15 #include "lldb/Core/dwarf.h" 16 17 class SymbolFileDWARF; 18 19 typedef std::vector<dw_offset_t> DIEArray; 20 21 class HashedNameToDIE 22 { 23 public: 24 enum NameFlags 25 { 26 eNameFlagIsExternal = (1u << 0), 27 eNameFlagIsClassCXX = (1u << 1), 28 eNameFlagIsClassObjC = (1u << 2), 29 eNameFlagIsClassObjCMaster = (1u << 3) 30 }; 31 32 enum TypeFlags 33 { 34 eTypeFlagIsExternal = (1u << 0) 35 }; 36 37 enum HashFunctionType 38 { 39 eHashFunctionDJB = 0u, // Daniel J Bernstein hash function that is also used by the ELF GNU_HASH sections 40 }; 41 42 static const uint32_t HASH_MAGIC = 0x48415348u; 43 44 struct Header 45 { 46 uint32_t magic; // 'HASH' magic value to allow endian detection 47 uint16_t version; // Version number 48 uint8_t addr_bytesize; // Size in bytes of an address 49 uint8_t hash_function; // The hash function enumeration that was used 50 uint32_t bucket_count; // The number of buckets in this hash table 51 uint32_t hashes_count; // The total number of unique hash values and hash data offsets in this table 52 uint32_t prologue_length; // The length of the prologue 53 54 Header (uint32_t _prologue_length) : 55 magic (HASH_MAGIC), 56 version (1), 57 addr_bytesize (4), 58 hash_function (eHashFunctionDJB), 59 bucket_count (0), 60 hashes_count (0), 61 prologue_length (_prologue_length) 62 { 63 } 64 65 virtual 66 ~Header () 67 { 68 } 69 70 virtual size_t 71 GetByteSize() const 72 { 73 return sizeof(magic) + 74 sizeof(version) + 75 sizeof(addr_bytesize) + 76 sizeof(hash_function) + 77 sizeof(bucket_count) + 78 sizeof(hashes_count) + 79 sizeof(prologue_length) + 80 prologue_length; 81 } 82 83 virtual void 84 Dump (lldb_private::Stream &s); 85 86 virtual uint32_t 87 Read (const lldb_private::DataExtractor &data, uint32_t offset); 88 }; 89 90 struct DWARF 91 { 92 enum AtomType 93 { 94 eAtomTypeNULL = 0u, 95 eAtomTypeHashString = 1u, // String value for hash, use DW_FORM_strp (preferred) or DW_FORM_string 96 eAtomTypeHashLength = 2u, // Length of data for the previous string refered by the last eAtomTypeHashString atom 97 eAtomTypeArraySize = 3u, // A count that specifies a number of atoms that follow this entry, the next atom defines what the atom type for the array is 98 eAtomTypeDIEOffset = 4u, // DIE offset, check form for encoding. If DW_FORM_ref1,2,4,8 or DW_FORM_ref_udata, then this value is added to the prologue 99 eAtomTypeTag = 5u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 100 eAtomTypeNameFlags = 6u, // Flags from enum NameFlags 101 eAtomTypeTypeFlags = 7u, // Flags from enum TypeFlags 102 }; 103 104 struct Atom 105 { 106 uint16_t type; 107 dw_form_t form; 108 109 Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) : 110 type (t), 111 form (f) 112 { 113 } 114 }; 115 116 typedef std::vector<Atom> AtomArray; 117 118 119 static const char * 120 GetAtomTypeName (uint16_t atom) 121 { 122 switch (atom) 123 { 124 case eAtomTypeNULL: return "NULL"; 125 case eAtomTypeHashString: return "hash-string"; 126 case eAtomTypeHashLength: return "hash-data-length"; 127 case eAtomTypeArraySize: return "array-size"; 128 case eAtomTypeDIEOffset: return "die-offset"; 129 case eAtomTypeTag: return "die-tag"; 130 case eAtomTypeNameFlags: return "name-flags"; 131 case eAtomTypeTypeFlags: return "type-flags"; 132 } 133 return "<invalid>"; 134 } 135 struct Prologue 136 { 137 // DIE offset base so die offsets in hash_data can be CU relative 138 dw_offset_t die_base_offset; 139 AtomArray atoms; 140 141 Prologue (dw_offset_t _die_base_offset = 0) : 142 die_base_offset (_die_base_offset) 143 { 144 // Define an array of DIE offsets by first defining an array, 145 // and then define the atom type for the array, in this case 146 // we have an array of DIE offsets 147 atoms.push_back (Atom(eAtomTypeArraySize, DW_FORM_data4)); 148 atoms.push_back (Atom(eAtomTypeDIEOffset, DW_FORM_data4)); 149 } 150 151 virtual 152 ~Prologue () 153 { 154 } 155 156 157 virtual void 158 Clear () 159 { 160 die_base_offset = 0; 161 atoms.clear(); 162 } 163 164 virtual void 165 Dump (lldb_private::Stream &s); 166 167 virtual uint32_t 168 Read (const lldb_private::DataExtractor &data, uint32_t offset); 169 170 size_t 171 GetByteSize () const 172 { 173 // Add an extra count to the atoms size for the zero termination Atom that gets 174 // written to disk 175 return sizeof(die_base_offset) + ((atoms.size() + 1) * sizeof(Atom)); 176 } 177 }; 178 179 struct Header : public HashedNameToDIE::Header 180 { 181 Header (dw_offset_t _die_base_offset = 0) : 182 HashedNameToDIE::Header (sizeof(Prologue)), 183 dwarf_prologue (_die_base_offset) 184 { 185 } 186 187 virtual 188 ~Header () 189 { 190 } 191 192 Prologue dwarf_prologue; 193 194 virtual void 195 Dump (lldb_private::Stream &s); 196 197 virtual uint32_t 198 Read (const lldb_private::DataExtractor &data, uint32_t offset); 199 }; 200 201 }; 202 203 204 class MemoryTable 205 { 206 public: 207 208 MemoryTable (SymbolFileDWARF *dwarf, 209 const lldb_private::DataExtractor &data, 210 bool is_apple_names); 211 212 ~MemoryTable () 213 { 214 } 215 216 bool 217 Initialize (); 218 219 bool 220 IsValid () const 221 { 222 return m_header.version > 0; 223 } 224 225 uint32_t 226 GetOffsetOfBucketEntry (uint32_t idx) const 227 { 228 if (idx < m_header.bucket_count) 229 return m_header.GetByteSize() + 4 * idx; 230 return UINT32_MAX; 231 } 232 233 uint32_t 234 GetOffsetOfHashValue (uint32_t idx) const 235 { 236 if (idx < m_header.hashes_count) 237 return m_header.GetByteSize() + 238 4 * m_header.bucket_count + 239 4 * idx; 240 return UINT32_MAX; 241 } 242 243 uint32_t 244 GetOffsetOfHashDataOffset (uint32_t idx) const 245 { 246 if (idx < m_header.hashes_count) 247 { 248 return m_header.GetByteSize() + 249 4 * m_header.bucket_count + 250 4 * m_header.hashes_count + 251 4 * idx; 252 } 253 return UINT32_MAX; 254 } 255 256 void 257 Dump (lldb_private::Stream &s); 258 259 size_t 260 Find (const char *name, DIEArray &die_ofsets) const; 261 262 protected: 263 const lldb_private::DataExtractor &m_data; 264 const lldb_private::DataExtractor &m_string_table; 265 bool m_is_apple_names; // true => .apple_names, false => .apple_types 266 DWARF::Header m_header; 267 }; 268 }; 269 270 #endif // SymbolFileDWARF_HashedNameToDIE_h_ 271