1254721Semaste//===-- HashedNameToDIE.h ---------------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#ifndef SymbolFileDWARF_HashedNameToDIE_h_ 11254721Semaste#define SymbolFileDWARF_HashedNameToDIE_h_ 12254721Semaste 13254721Semaste#include <vector> 14254721Semaste 15254721Semaste#include "DWARFDefines.h" 16254721Semaste#include "DWARFFormValue.h" 17254721Semaste 18254721Semaste#include "lldb/lldb-defines.h" 19254721Semaste#include "lldb/Core/dwarf.h" 20254721Semaste#include "lldb/Core/RegularExpression.h" 21254721Semaste#include "lldb/Core/MappedHash.h" 22254721Semaste 23254721Semaste 24254721Semasteclass SymbolFileDWARF; 25254721Semasteclass DWARFCompileUnit; 26254721Semasteclass DWARFDebugInfoEntry; 27254721Semaste 28254721Semastestruct DWARFMappedHash 29254721Semaste{ 30254721Semaste struct DIEInfo 31254721Semaste { 32254721Semaste dw_offset_t offset; // The DIE offset 33254721Semaste dw_tag_t tag; 34254721Semaste uint32_t type_flags; // Any flags for this DIEInfo 35254721Semaste uint32_t qualified_name_hash; // A 32 bit hash of the fully qualified name 36254721Semaste 37254721Semaste DIEInfo () : 38254721Semaste offset (DW_INVALID_OFFSET), 39254721Semaste tag (0), 40254721Semaste type_flags (0), 41254721Semaste qualified_name_hash (0) 42254721Semaste { 43254721Semaste } 44254721Semaste 45254721Semaste DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f, uint32_t h) : 46254721Semaste offset(o), 47254721Semaste tag (t), 48254721Semaste type_flags (f), 49254721Semaste qualified_name_hash (h) 50254721Semaste { 51254721Semaste } 52254721Semaste 53254721Semaste void 54254721Semaste Clear() 55254721Semaste { 56254721Semaste offset = DW_INVALID_OFFSET; 57254721Semaste tag = 0; 58254721Semaste type_flags = 0; 59254721Semaste qualified_name_hash = 0; 60254721Semaste } 61254721Semaste }; 62254721Semaste 63254721Semaste typedef std::vector<DIEInfo> DIEInfoArray; 64254721Semaste typedef std::vector<uint32_t> DIEArray; 65254721Semaste 66254721Semaste static void 67254721Semaste ExtractDIEArray (const DIEInfoArray &die_info_array, 68254721Semaste DIEArray &die_offsets) 69254721Semaste { 70254721Semaste const size_t count = die_info_array.size(); 71254721Semaste for (size_t i=0; i<count; ++i) 72254721Semaste { 73254721Semaste die_offsets.push_back (die_info_array[i].offset); 74254721Semaste } 75254721Semaste } 76254721Semaste 77254721Semaste static void 78254721Semaste ExtractDIEArray (const DIEInfoArray &die_info_array, 79254721Semaste const dw_tag_t tag, 80254721Semaste DIEArray &die_offsets) 81254721Semaste { 82254721Semaste if (tag == 0) 83254721Semaste { 84254721Semaste ExtractDIEArray (die_info_array, die_offsets); 85254721Semaste } 86254721Semaste else 87254721Semaste { 88254721Semaste const size_t count = die_info_array.size(); 89254721Semaste for (size_t i=0; i<count; ++i) 90254721Semaste { 91254721Semaste const dw_tag_t die_tag = die_info_array[i].tag; 92254721Semaste bool tag_matches = die_tag == 0 || tag == die_tag; 93254721Semaste if (!tag_matches) 94254721Semaste { 95254721Semaste if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) 96254721Semaste tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; 97254721Semaste } 98254721Semaste if (tag_matches) 99254721Semaste die_offsets.push_back (die_info_array[i].offset); 100254721Semaste } 101254721Semaste } 102254721Semaste } 103254721Semaste 104254721Semaste static void 105254721Semaste ExtractDIEArray (const DIEInfoArray &die_info_array, 106254721Semaste const dw_tag_t tag, 107254721Semaste const uint32_t qualified_name_hash, 108254721Semaste DIEArray &die_offsets) 109254721Semaste { 110254721Semaste if (tag == 0) 111254721Semaste { 112254721Semaste ExtractDIEArray (die_info_array, die_offsets); 113254721Semaste } 114254721Semaste else 115254721Semaste { 116254721Semaste const size_t count = die_info_array.size(); 117254721Semaste for (size_t i=0; i<count; ++i) 118254721Semaste { 119254721Semaste if (qualified_name_hash != die_info_array[i].qualified_name_hash) 120254721Semaste continue; 121254721Semaste const dw_tag_t die_tag = die_info_array[i].tag; 122254721Semaste bool tag_matches = die_tag == 0 || tag == die_tag; 123254721Semaste if (!tag_matches) 124254721Semaste { 125254721Semaste if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) 126254721Semaste tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; 127254721Semaste } 128254721Semaste if (tag_matches) 129254721Semaste die_offsets.push_back (die_info_array[i].offset); 130254721Semaste } 131254721Semaste } 132254721Semaste } 133254721Semaste 134254721Semaste enum AtomType 135254721Semaste { 136254721Semaste eAtomTypeNULL = 0u, 137254721Semaste eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding 138254721Semaste eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question 139254721Semaste eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 140254721Semaste eAtomTypeNameFlags = 4u, // Flags from enum NameFlags 141254721Semaste eAtomTypeTypeFlags = 5u, // Flags from enum TypeFlags, 142254721Semaste eAtomTypeQualNameHash = 6u // A 32 bit hash of the full qualified name (since all hash entries are basename only) 143254721Semaste // For example a type like "std::vector<int>::iterator" would have a name of "iterator" 144254721Semaste // and a 32 bit hash for "std::vector<int>::iterator" to allow us to not have to pull 145254721Semaste // in debug info for a type when we know the fully qualified name. 146254721Semaste }; 147254721Semaste 148254721Semaste // Bit definitions for the eAtomTypeTypeFlags flags 149254721Semaste enum TypeFlags 150254721Semaste { 151254721Semaste // Always set for C++, only set for ObjC if this is the 152254721Semaste // @implementation for class 153254721Semaste eTypeFlagClassIsImplementation = ( 1u << 1 ) 154254721Semaste }; 155254721Semaste 156254721Semaste 157254721Semaste static void 158254721Semaste ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, 159254721Semaste bool return_implementation_only_if_available, 160254721Semaste DIEArray &die_offsets) 161254721Semaste { 162254721Semaste const size_t count = die_info_array.size(); 163254721Semaste for (size_t i=0; i<count; ++i) 164254721Semaste { 165254721Semaste const dw_tag_t die_tag = die_info_array[i].tag; 166254721Semaste if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) 167254721Semaste { 168254721Semaste if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) 169254721Semaste { 170254721Semaste if (return_implementation_only_if_available) 171254721Semaste { 172254721Semaste // We found the one true definiton for this class, so 173254721Semaste // only return that 174254721Semaste die_offsets.clear(); 175254721Semaste die_offsets.push_back (die_info_array[i].offset); 176254721Semaste return; 177254721Semaste } 178254721Semaste else 179254721Semaste { 180254721Semaste // Put the one true definition as the first entry so it 181254721Semaste // matches first 182254721Semaste die_offsets.insert (die_offsets.begin(), die_info_array[i].offset); 183254721Semaste } 184254721Semaste } 185254721Semaste else 186254721Semaste { 187254721Semaste die_offsets.push_back (die_info_array[i].offset); 188254721Semaste } 189254721Semaste } 190254721Semaste } 191254721Semaste } 192254721Semaste 193254721Semaste static void 194254721Semaste ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, 195254721Semaste uint32_t type_flag_mask, 196254721Semaste uint32_t type_flag_value, 197254721Semaste DIEArray &die_offsets) 198254721Semaste { 199254721Semaste const size_t count = die_info_array.size(); 200254721Semaste for (size_t i=0; i<count; ++i) 201254721Semaste { 202254721Semaste if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value) 203254721Semaste die_offsets.push_back (die_info_array[i].offset); 204254721Semaste } 205254721Semaste } 206254721Semaste 207254721Semaste struct Atom 208254721Semaste { 209254721Semaste uint16_t type; 210254721Semaste dw_form_t form; 211254721Semaste 212254721Semaste Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) : 213254721Semaste type (t), 214254721Semaste form (f) 215254721Semaste { 216254721Semaste } 217254721Semaste }; 218254721Semaste 219254721Semaste typedef std::vector<Atom> AtomArray; 220254721Semaste 221254721Semaste static uint32_t 222254721Semaste GetTypeFlags (SymbolFileDWARF *dwarf2Data, 223254721Semaste const DWARFCompileUnit* cu, 224254721Semaste const DWARFDebugInfoEntry* die); 225254721Semaste 226254721Semaste 227254721Semaste static const char * 228254721Semaste GetAtomTypeName (uint16_t atom) 229254721Semaste { 230254721Semaste switch (atom) 231254721Semaste { 232254721Semaste case eAtomTypeNULL: return "NULL"; 233254721Semaste case eAtomTypeDIEOffset: return "die-offset"; 234254721Semaste case eAtomTypeCUOffset: return "cu-offset"; 235254721Semaste case eAtomTypeTag: return "die-tag"; 236254721Semaste case eAtomTypeNameFlags: return "name-flags"; 237254721Semaste case eAtomTypeTypeFlags: return "type-flags"; 238254721Semaste case eAtomTypeQualNameHash: return "qualified-name-hash"; 239254721Semaste } 240254721Semaste return "<invalid>"; 241254721Semaste } 242254721Semaste struct Prologue 243254721Semaste { 244254721Semaste // DIE offset base so die offsets in hash_data can be CU relative 245254721Semaste dw_offset_t die_base_offset; 246254721Semaste AtomArray atoms; 247254721Semaste uint32_t atom_mask; 248254721Semaste size_t min_hash_data_byte_size; 249254721Semaste bool hash_data_has_fixed_byte_size; 250254721Semaste 251254721Semaste Prologue (dw_offset_t _die_base_offset = 0) : 252254721Semaste die_base_offset (_die_base_offset), 253254721Semaste atoms(), 254254721Semaste atom_mask (0), 255254721Semaste min_hash_data_byte_size(0), 256254721Semaste hash_data_has_fixed_byte_size(true) 257254721Semaste { 258254721Semaste // Define an array of DIE offsets by first defining an array, 259254721Semaste // and then define the atom type for the array, in this case 260254721Semaste // we have an array of DIE offsets 261254721Semaste AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); 262254721Semaste } 263254721Semaste 264254721Semaste virtual ~Prologue() 265254721Semaste { 266254721Semaste } 267254721Semaste 268254721Semaste void 269254721Semaste ClearAtoms () 270254721Semaste { 271254721Semaste hash_data_has_fixed_byte_size = true; 272254721Semaste min_hash_data_byte_size = 0; 273254721Semaste atom_mask = 0; 274254721Semaste atoms.clear(); 275254721Semaste } 276254721Semaste 277254721Semaste bool 278254721Semaste ContainsAtom (AtomType atom_type) const 279254721Semaste { 280254721Semaste return (atom_mask & (1u << atom_type)) != 0; 281254721Semaste } 282254721Semaste 283254721Semaste virtual void 284254721Semaste Clear () 285254721Semaste { 286254721Semaste die_base_offset = 0; 287254721Semaste ClearAtoms (); 288254721Semaste } 289254721Semaste 290254721Semaste void 291254721Semaste AppendAtom (AtomType type, dw_form_t form) 292254721Semaste { 293254721Semaste atoms.push_back (Atom(type, form)); 294254721Semaste atom_mask |= 1u << type; 295254721Semaste switch (form) 296254721Semaste { 297254721Semaste case DW_FORM_indirect: 298254721Semaste case DW_FORM_exprloc: 299254721Semaste case DW_FORM_flag_present: 300254721Semaste case DW_FORM_ref_sig8: 301254721Semaste assert (!"Unhandled atom form"); 302254721Semaste break; 303254721Semaste 304254721Semaste case DW_FORM_string: 305254721Semaste case DW_FORM_block: 306254721Semaste case DW_FORM_block1: 307254721Semaste case DW_FORM_sdata: 308254721Semaste case DW_FORM_udata: 309254721Semaste case DW_FORM_ref_udata: 310254721Semaste hash_data_has_fixed_byte_size = false; 311254721Semaste // Fall through to the cases below... 312254721Semaste case DW_FORM_flag: 313254721Semaste case DW_FORM_data1: 314254721Semaste case DW_FORM_ref1: 315254721Semaste case DW_FORM_sec_offset: 316254721Semaste min_hash_data_byte_size += 1; 317254721Semaste break; 318254721Semaste 319254721Semaste case DW_FORM_block2: 320254721Semaste hash_data_has_fixed_byte_size = false; 321254721Semaste // Fall through to the cases below... 322254721Semaste case DW_FORM_data2: 323254721Semaste case DW_FORM_ref2: 324254721Semaste min_hash_data_byte_size += 2; 325254721Semaste break; 326254721Semaste 327254721Semaste case DW_FORM_block4: 328254721Semaste hash_data_has_fixed_byte_size = false; 329254721Semaste // Fall through to the cases below... 330254721Semaste case DW_FORM_data4: 331254721Semaste case DW_FORM_ref4: 332254721Semaste case DW_FORM_addr: 333254721Semaste case DW_FORM_ref_addr: 334254721Semaste case DW_FORM_strp: 335254721Semaste min_hash_data_byte_size += 4; 336254721Semaste break; 337254721Semaste 338254721Semaste case DW_FORM_data8: 339254721Semaste case DW_FORM_ref8: 340254721Semaste min_hash_data_byte_size += 8; 341254721Semaste break; 342254721Semaste 343254721Semaste } 344254721Semaste } 345254721Semaste 346254721Semaste// void 347254721Semaste// Dump (std::ostream* ostrm_ptr); 348254721Semaste 349254721Semaste lldb::offset_t 350254721Semaste Read (const lldb_private::DataExtractor &data, 351254721Semaste lldb::offset_t offset) 352254721Semaste { 353254721Semaste ClearAtoms (); 354254721Semaste 355254721Semaste die_base_offset = data.GetU32 (&offset); 356254721Semaste 357254721Semaste const uint32_t atom_count = data.GetU32 (&offset); 358254721Semaste if (atom_count == 0x00060003u) 359254721Semaste { 360254721Semaste // Old format, deal with contents of old pre-release format 361254721Semaste while (data.GetU32(&offset)) 362254721Semaste /* do nothing */; 363254721Semaste 364254721Semaste // Hardcode to the only known value for now. 365254721Semaste AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); 366254721Semaste } 367254721Semaste else 368254721Semaste { 369254721Semaste for (uint32_t i=0; i<atom_count; ++i) 370254721Semaste { 371254721Semaste AtomType type = (AtomType)data.GetU16 (&offset); 372254721Semaste dw_form_t form = (dw_form_t)data.GetU16 (&offset); 373254721Semaste AppendAtom (type, form); 374254721Semaste } 375254721Semaste } 376254721Semaste return offset; 377254721Semaste } 378254721Semaste 379254721Semaste// virtual void 380254721Semaste// Write (BinaryStreamBuf &s); 381254721Semaste 382254721Semaste size_t 383254721Semaste GetByteSize () const 384254721Semaste { 385254721Semaste // Add an extra count to the atoms size for the zero termination Atom that gets 386254721Semaste // written to disk 387254721Semaste return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); 388254721Semaste } 389254721Semaste 390254721Semaste size_t 391254721Semaste GetMinumumHashDataByteSize () const 392254721Semaste { 393254721Semaste return min_hash_data_byte_size; 394254721Semaste } 395254721Semaste 396254721Semaste bool 397254721Semaste HashDataHasFixedByteSize() const 398254721Semaste { 399254721Semaste return hash_data_has_fixed_byte_size; 400254721Semaste } 401254721Semaste }; 402254721Semaste 403254721Semaste struct Header : public MappedHash::Header<Prologue> 404254721Semaste { 405254721Semaste Header (dw_offset_t _die_base_offset = 0) 406254721Semaste { 407254721Semaste } 408254721Semaste 409254721Semaste virtual 410254721Semaste ~Header() 411254721Semaste { 412254721Semaste } 413254721Semaste 414254721Semaste virtual size_t 415254721Semaste GetByteSize (const HeaderData &header_data) 416254721Semaste { 417254721Semaste return header_data.GetByteSize(); 418254721Semaste } 419254721Semaste 420254721Semaste // virtual void 421254721Semaste // Dump (std::ostream* ostrm_ptr); 422254721Semaste // 423254721Semaste virtual lldb::offset_t 424254721Semaste Read (lldb_private::DataExtractor &data, lldb::offset_t offset) 425254721Semaste { 426254721Semaste offset = MappedHash::Header<Prologue>::Read (data, offset); 427254721Semaste if (offset != UINT32_MAX) 428254721Semaste { 429254721Semaste offset = header_data.Read (data, offset); 430254721Semaste } 431254721Semaste return offset; 432254721Semaste } 433254721Semaste 434254721Semaste bool 435263363Semaste Read (const lldb_private::DWARFDataExtractor &data, 436254721Semaste lldb::offset_t *offset_ptr, 437254721Semaste DIEInfo &hash_data) const 438254721Semaste { 439254721Semaste const size_t num_atoms = header_data.atoms.size(); 440254721Semaste if (num_atoms == 0) 441254721Semaste return false; 442254721Semaste 443254721Semaste for (size_t i=0; i<num_atoms; ++i) 444254721Semaste { 445254721Semaste DWARFFormValue form_value (header_data.atoms[i].form); 446254721Semaste 447254721Semaste if (!form_value.ExtractValue(data, offset_ptr, NULL)) 448254721Semaste return false; 449254721Semaste 450254721Semaste switch (header_data.atoms[i].type) 451254721Semaste { 452254721Semaste case eAtomTypeDIEOffset: // DIE offset, check form for encoding 453254721Semaste hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset); 454254721Semaste break; 455254721Semaste 456254721Semaste case eAtomTypeTag: // DW_TAG value for the DIE 457254721Semaste hash_data.tag = (dw_tag_t)form_value.Unsigned (); 458254721Semaste 459254721Semaste case eAtomTypeTypeFlags: // Flags from enum TypeFlags 460254721Semaste hash_data.type_flags = (uint32_t)form_value.Unsigned (); 461254721Semaste break; 462254721Semaste 463254721Semaste case eAtomTypeQualNameHash: // Flags from enum TypeFlags 464254721Semaste hash_data.qualified_name_hash = form_value.Unsigned (); 465254721Semaste break; 466254721Semaste 467254721Semaste default: 468254721Semaste // We can always skip atomes we don't know about 469254721Semaste break; 470254721Semaste } 471254721Semaste } 472254721Semaste return true; 473254721Semaste } 474254721Semaste 475254721Semaste void 476254721Semaste Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const 477254721Semaste { 478254721Semaste const size_t num_atoms = header_data.atoms.size(); 479254721Semaste for (size_t i=0; i<num_atoms; ++i) 480254721Semaste { 481254721Semaste if (i > 0) 482254721Semaste strm.PutCString (", "); 483254721Semaste 484254721Semaste DWARFFormValue form_value (header_data.atoms[i].form); 485254721Semaste switch (header_data.atoms[i].type) 486254721Semaste { 487254721Semaste case eAtomTypeDIEOffset: // DIE offset, check form for encoding 488254721Semaste strm.Printf ("{0x%8.8x}", hash_data.offset); 489254721Semaste break; 490254721Semaste 491254721Semaste case eAtomTypeTag: // DW_TAG value for the DIE 492254721Semaste { 493254721Semaste const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag); 494254721Semaste if (tag_cstr) 495254721Semaste strm.PutCString (tag_cstr); 496254721Semaste else 497254721Semaste strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag); 498254721Semaste } 499254721Semaste break; 500254721Semaste 501254721Semaste case eAtomTypeTypeFlags: // Flags from enum TypeFlags 502254721Semaste strm.Printf ("0x%2.2x", hash_data.type_flags); 503254721Semaste if (hash_data.type_flags) 504254721Semaste { 505254721Semaste strm.PutCString (" ("); 506254721Semaste if (hash_data.type_flags & eTypeFlagClassIsImplementation) 507254721Semaste strm.PutCString (" implementation"); 508254721Semaste strm.PutCString (" )"); 509254721Semaste } 510254721Semaste break; 511254721Semaste 512254721Semaste case eAtomTypeQualNameHash: // Flags from enum TypeFlags 513254721Semaste strm.Printf ("0x%8.8x", hash_data.qualified_name_hash); 514254721Semaste break; 515254721Semaste 516254721Semaste default: 517254721Semaste strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); 518254721Semaste break; 519254721Semaste } 520254721Semaste } 521254721Semaste } 522254721Semaste }; 523254721Semaste 524254721Semaste// class ExportTable 525254721Semaste// { 526254721Semaste// public: 527254721Semaste// ExportTable (); 528254721Semaste// 529254721Semaste// void 530254721Semaste// AppendNames (DWARFDebugPubnamesSet &pubnames_set, 531254721Semaste// StringTable &string_table); 532254721Semaste// 533254721Semaste// void 534254721Semaste// AppendNamesEntry (SymbolFileDWARF *dwarf2Data, 535254721Semaste// const DWARFCompileUnit* cu, 536254721Semaste// const DWARFDebugInfoEntry* die, 537254721Semaste// StringTable &string_table); 538254721Semaste// 539254721Semaste// void 540254721Semaste// AppendTypesEntry (DWARFData *dwarf2Data, 541254721Semaste// const DWARFCompileUnit* cu, 542254721Semaste// const DWARFDebugInfoEntry* die, 543254721Semaste// StringTable &string_table); 544254721Semaste// 545254721Semaste// size_t 546254721Semaste// Save (BinaryStreamBuf &names_data, const StringTable &string_table); 547254721Semaste// 548254721Semaste// void 549254721Semaste// AppendName (const char *name, 550254721Semaste// uint32_t die_offset, 551254721Semaste// StringTable &string_table, 552254721Semaste// dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied 553254721Semaste// void 554254721Semaste// AppendType (const char *name, 555254721Semaste// uint32_t die_offset, 556254721Semaste// StringTable &string_table); 557254721Semaste// 558254721Semaste// 559254721Semaste// protected: 560254721Semaste// struct Entry 561254721Semaste// { 562254721Semaste// uint32_t hash; 563254721Semaste// uint32_t str_offset; 564254721Semaste// uint32_t die_offset; 565254721Semaste// }; 566254721Semaste// 567254721Semaste// // Map uniqued .debug_str offset to the corresponding DIE offsets 568254721Semaste// typedef std::map<uint32_t, DIEInfoArray> NameInfo; 569254721Semaste// // Map a name hash to one or more name infos 570254721Semaste// typedef std::map<uint32_t, NameInfo> BucketEntry; 571254721Semaste// 572254721Semaste// static uint32_t 573254721Semaste// GetByteSize (const NameInfo &name_info); 574254721Semaste// 575254721Semaste// typedef std::vector<BucketEntry> BucketEntryColl; 576254721Semaste// typedef std::vector<Entry> EntryColl; 577254721Semaste// EntryColl m_entries; 578254721Semaste// 579254721Semaste// }; 580254721Semaste 581254721Semaste 582254721Semaste // A class for reading and using a saved hash table from a block of data 583254721Semaste // in memory 584254721Semaste class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray> 585254721Semaste { 586254721Semaste public: 587254721Semaste 588263363Semaste MemoryTable (lldb_private::DWARFDataExtractor &table_data, 589263363Semaste const lldb_private::DWARFDataExtractor &string_table, 590254721Semaste const char *name) : 591254721Semaste MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data), 592254721Semaste m_data (table_data), 593254721Semaste m_string_table (string_table), 594254721Semaste m_name (name) 595254721Semaste { 596254721Semaste } 597254721Semaste 598254721Semaste virtual 599254721Semaste ~MemoryTable () 600254721Semaste { 601254721Semaste } 602254721Semaste 603254721Semaste virtual const char * 604254721Semaste GetStringForKeyType (KeyType key) const 605254721Semaste { 606254721Semaste // The key in the DWARF table is the .debug_str offset for the string 607254721Semaste return m_string_table.PeekCStr (key); 608254721Semaste } 609254721Semaste 610254721Semaste virtual bool 611254721Semaste ReadHashData (uint32_t hash_data_offset, 612254721Semaste HashData &hash_data) const 613254721Semaste { 614254721Semaste lldb::offset_t offset = hash_data_offset; 615254721Semaste offset += 4; // Skip string table offset that contains offset of hash name in .debug_str 616254721Semaste const uint32_t count = m_data.GetU32 (&offset); 617254721Semaste if (count > 0) 618254721Semaste { 619254721Semaste hash_data.resize(count); 620254721Semaste for (uint32_t i=0; i<count; ++i) 621254721Semaste { 622254721Semaste if (!m_header.Read(m_data, &offset, hash_data[i])) 623254721Semaste return false; 624254721Semaste } 625254721Semaste } 626254721Semaste else 627254721Semaste hash_data.clear(); 628254721Semaste return true; 629254721Semaste } 630254721Semaste 631254721Semaste virtual Result 632254721Semaste GetHashDataForName (const char *name, 633254721Semaste lldb::offset_t* hash_data_offset_ptr, 634254721Semaste Pair &pair) const 635254721Semaste { 636254721Semaste pair.key = m_data.GetU32 (hash_data_offset_ptr); 637254721Semaste pair.value.clear(); 638254721Semaste 639254721Semaste // If the key is zero, this terminates our chain of HashData objects 640254721Semaste // for this hash value. 641254721Semaste if (pair.key == 0) 642254721Semaste return eResultEndOfHashData; 643254721Semaste 644254721Semaste // There definitely should be a string for this string offset, if 645254721Semaste // there isn't, there is something wrong, return and error 646254721Semaste const char *strp_cstr = m_string_table.PeekCStr (pair.key); 647254721Semaste if (strp_cstr == NULL) 648254721Semaste { 649254721Semaste *hash_data_offset_ptr = UINT32_MAX; 650254721Semaste return eResultError; 651254721Semaste } 652254721Semaste 653254721Semaste const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); 654254721Semaste const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize(); 655254721Semaste if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) 656254721Semaste { 657254721Semaste // We have at least one HashData entry, and we have enough 658254721Semaste // data to parse at leats "count" HashData enties. 659254721Semaste 660254721Semaste // First make sure the entire C string matches... 661254721Semaste const bool match = strcmp (name, strp_cstr) == 0; 662254721Semaste 663254721Semaste if (!match && m_header.header_data.HashDataHasFixedByteSize()) 664254721Semaste { 665254721Semaste // If the string doesn't match and we have fixed size data, 666254721Semaste // we can just add the total byte size of all HashData objects 667254721Semaste // to the hash data offset and be done... 668254721Semaste *hash_data_offset_ptr += min_total_hash_data_size; 669254721Semaste } 670254721Semaste else 671254721Semaste { 672254721Semaste // If the string does match, or we don't have fixed size data 673254721Semaste // then we need to read the hash data as a stream. If the 674254721Semaste // string matches we also append all HashData objects to the 675254721Semaste // value array. 676254721Semaste for (uint32_t i=0; i<count; ++i) 677254721Semaste { 678254721Semaste DIEInfo die_info; 679254721Semaste if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) 680254721Semaste { 681254721Semaste // Only happend the HashData if the string matched... 682254721Semaste if (match) 683254721Semaste pair.value.push_back (die_info); 684254721Semaste } 685254721Semaste else 686254721Semaste { 687254721Semaste // Something went wrong while reading the data 688254721Semaste *hash_data_offset_ptr = UINT32_MAX; 689254721Semaste return eResultError; 690254721Semaste } 691254721Semaste } 692254721Semaste } 693254721Semaste // Return the correct response depending on if the string matched 694254721Semaste // or not... 695254721Semaste if (match) 696254721Semaste return eResultKeyMatch; // The key (cstring) matches and we have lookup results! 697254721Semaste else 698254721Semaste return eResultKeyMismatch; // The key doesn't match, this function will get called 699254721Semaste // again for the next key/value or the key terminator 700254721Semaste // which in our case is a zero .debug_str offset. 701254721Semaste } 702254721Semaste else 703254721Semaste { 704254721Semaste *hash_data_offset_ptr = UINT32_MAX; 705254721Semaste return eResultError; 706254721Semaste } 707254721Semaste } 708254721Semaste 709254721Semaste virtual Result 710254721Semaste AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex, 711254721Semaste lldb::offset_t* hash_data_offset_ptr, 712254721Semaste Pair &pair) const 713254721Semaste { 714254721Semaste pair.key = m_data.GetU32 (hash_data_offset_ptr); 715254721Semaste // If the key is zero, this terminates our chain of HashData objects 716254721Semaste // for this hash value. 717254721Semaste if (pair.key == 0) 718254721Semaste return eResultEndOfHashData; 719254721Semaste 720254721Semaste // There definitely should be a string for this string offset, if 721254721Semaste // there isn't, there is something wrong, return and error 722254721Semaste const char *strp_cstr = m_string_table.PeekCStr (pair.key); 723254721Semaste if (strp_cstr == NULL) 724254721Semaste return eResultError; 725254721Semaste 726254721Semaste const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); 727254721Semaste const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize(); 728254721Semaste if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) 729254721Semaste { 730254721Semaste const bool match = regex.Execute(strp_cstr); 731254721Semaste 732254721Semaste if (!match && m_header.header_data.HashDataHasFixedByteSize()) 733254721Semaste { 734254721Semaste // If the regex doesn't match and we have fixed size data, 735254721Semaste // we can just add the total byte size of all HashData objects 736254721Semaste // to the hash data offset and be done... 737254721Semaste *hash_data_offset_ptr += min_total_hash_data_size; 738254721Semaste } 739254721Semaste else 740254721Semaste { 741254721Semaste // If the string does match, or we don't have fixed size data 742254721Semaste // then we need to read the hash data as a stream. If the 743254721Semaste // string matches we also append all HashData objects to the 744254721Semaste // value array. 745254721Semaste for (uint32_t i=0; i<count; ++i) 746254721Semaste { 747254721Semaste DIEInfo die_info; 748254721Semaste if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) 749254721Semaste { 750254721Semaste // Only happend the HashData if the string matched... 751254721Semaste if (match) 752254721Semaste pair.value.push_back (die_info); 753254721Semaste } 754254721Semaste else 755254721Semaste { 756254721Semaste // Something went wrong while reading the data 757254721Semaste *hash_data_offset_ptr = UINT32_MAX; 758254721Semaste return eResultError; 759254721Semaste } 760254721Semaste } 761254721Semaste } 762254721Semaste // Return the correct response depending on if the string matched 763254721Semaste // or not... 764254721Semaste if (match) 765254721Semaste return eResultKeyMatch; // The key (cstring) matches and we have lookup results! 766254721Semaste else 767254721Semaste return eResultKeyMismatch; // The key doesn't match, this function will get called 768254721Semaste // again for the next key/value or the key terminator 769254721Semaste // which in our case is a zero .debug_str offset. 770254721Semaste } 771254721Semaste else 772254721Semaste { 773254721Semaste *hash_data_offset_ptr = UINT32_MAX; 774254721Semaste return eResultError; 775254721Semaste } 776254721Semaste } 777254721Semaste 778254721Semaste size_t 779254721Semaste AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex, 780254721Semaste DIEInfoArray &die_info_array) const 781254721Semaste { 782254721Semaste const uint32_t hash_count = m_header.hashes_count; 783254721Semaste Pair pair; 784254721Semaste for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) 785254721Semaste { 786254721Semaste lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); 787254721Semaste while (hash_data_offset != UINT32_MAX) 788254721Semaste { 789254721Semaste const lldb::offset_t prev_hash_data_offset = hash_data_offset; 790254721Semaste Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair); 791254721Semaste if (prev_hash_data_offset == hash_data_offset) 792254721Semaste break; 793254721Semaste 794254721Semaste // Check the result of getting our hash data 795254721Semaste switch (hash_result) 796254721Semaste { 797254721Semaste case eResultKeyMatch: 798254721Semaste case eResultKeyMismatch: 799254721Semaste // Whether we matches or not, it doesn't matter, we 800254721Semaste // keep looking. 801254721Semaste break; 802254721Semaste 803254721Semaste case eResultEndOfHashData: 804254721Semaste case eResultError: 805254721Semaste hash_data_offset = UINT32_MAX; 806254721Semaste break; 807254721Semaste } 808254721Semaste } 809254721Semaste } 810254721Semaste die_info_array.swap (pair.value); 811254721Semaste return die_info_array.size(); 812254721Semaste } 813254721Semaste 814254721Semaste size_t 815254721Semaste AppendAllDIEsInRange (const uint32_t die_offset_start, 816254721Semaste const uint32_t die_offset_end, 817254721Semaste DIEInfoArray &die_info_array) const 818254721Semaste { 819254721Semaste const uint32_t hash_count = m_header.hashes_count; 820254721Semaste for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) 821254721Semaste { 822254721Semaste bool done = false; 823254721Semaste lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); 824254721Semaste while (!done && hash_data_offset != UINT32_MAX) 825254721Semaste { 826254721Semaste KeyType key = m_data.GetU32 (&hash_data_offset); 827254721Semaste // If the key is zero, this terminates our chain of HashData objects 828254721Semaste // for this hash value. 829254721Semaste if (key == 0) 830254721Semaste break; 831254721Semaste 832254721Semaste const uint32_t count = m_data.GetU32 (&hash_data_offset); 833254721Semaste for (uint32_t i=0; i<count; ++i) 834254721Semaste { 835254721Semaste DIEInfo die_info; 836254721Semaste if (m_header.Read(m_data, &hash_data_offset, die_info)) 837254721Semaste { 838254721Semaste if (die_info.offset == 0) 839254721Semaste done = true; 840254721Semaste if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end) 841254721Semaste die_info_array.push_back(die_info); 842254721Semaste } 843254721Semaste } 844254721Semaste } 845254721Semaste } 846254721Semaste return die_info_array.size(); 847254721Semaste } 848254721Semaste 849254721Semaste size_t 850254721Semaste FindByName (const char *name, DIEArray &die_offsets) 851254721Semaste { 852254721Semaste DIEInfoArray die_info_array; 853254721Semaste if (FindByName(name, die_info_array)) 854254721Semaste DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); 855254721Semaste return die_info_array.size(); 856254721Semaste } 857254721Semaste 858254721Semaste size_t 859254721Semaste FindByNameAndTag (const char *name, 860254721Semaste const dw_tag_t tag, 861254721Semaste DIEArray &die_offsets) 862254721Semaste { 863254721Semaste DIEInfoArray die_info_array; 864254721Semaste if (FindByName(name, die_info_array)) 865254721Semaste DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets); 866254721Semaste return die_info_array.size(); 867254721Semaste } 868254721Semaste 869254721Semaste size_t 870254721Semaste FindByNameAndTagAndQualifiedNameHash (const char *name, 871254721Semaste const dw_tag_t tag, 872254721Semaste const uint32_t qualified_name_hash, 873254721Semaste DIEArray &die_offsets) 874254721Semaste { 875254721Semaste DIEInfoArray die_info_array; 876254721Semaste if (FindByName(name, die_info_array)) 877254721Semaste DWARFMappedHash::ExtractDIEArray (die_info_array, tag, qualified_name_hash, die_offsets); 878254721Semaste return die_info_array.size(); 879254721Semaste } 880254721Semaste 881254721Semaste size_t 882254721Semaste FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation) 883254721Semaste { 884254721Semaste DIEInfoArray die_info_array; 885254721Semaste if (FindByName(name, die_info_array)) 886254721Semaste { 887254721Semaste if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags)) 888254721Semaste { 889254721Semaste // If we have two atoms, then we have the DIE offset and 890254721Semaste // the type flags so we can find the objective C class 891254721Semaste // efficiently. 892254721Semaste DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array, 893254721Semaste UINT32_MAX, 894254721Semaste eTypeFlagClassIsImplementation, 895254721Semaste die_offsets); 896254721Semaste } 897254721Semaste else 898254721Semaste { 899254721Semaste // We don't only want the one true definition, so try and see 900254721Semaste // what we can find, and only return class or struct DIEs. 901254721Semaste // If we do have the full implementation, then return it alone, 902254721Semaste // else return all possible matches. 903254721Semaste const bool return_implementation_only_if_available = true; 904254721Semaste DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array, 905254721Semaste return_implementation_only_if_available, 906254721Semaste die_offsets); 907254721Semaste } 908254721Semaste } 909254721Semaste return die_offsets.size(); 910254721Semaste } 911254721Semaste 912254721Semaste size_t 913254721Semaste FindByName (const char *name, DIEInfoArray &die_info_array) 914254721Semaste { 915254721Semaste Pair kv_pair; 916254721Semaste size_t old_size = die_info_array.size(); 917254721Semaste if (Find (name, kv_pair)) 918254721Semaste { 919254721Semaste die_info_array.swap(kv_pair.value); 920254721Semaste return die_info_array.size() - old_size; 921254721Semaste } 922254721Semaste return 0; 923254721Semaste } 924254721Semaste 925254721Semaste protected: 926263363Semaste const lldb_private::DWARFDataExtractor &m_data; 927263363Semaste const lldb_private::DWARFDataExtractor &m_string_table; 928254721Semaste std::string m_name; 929254721Semaste }; 930254721Semaste}; 931254721Semaste 932254721Semaste 933254721Semaste#endif // SymbolFileDWARF_HashedNameToDIE_h_ 934