HashedNameToDIE.h revision 36da2aa6dc5ad9994b638ed09eb81c44cc05540b
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 15#include "DWARFDefines.h" 16#include "DWARFFormValue.h" 17 18#include "lldb/lldb-defines.h" 19#include "lldb/Core/dwarf.h" 20#include "lldb/Core/RegularExpression.h" 21#include "lldb/Core/MappedHash.h" 22 23 24class SymbolFileDWARF; 25class DWARFCompileUnit; 26class DWARFDebugInfoEntry; 27 28struct DWARFMappedHash 29{ 30 struct DIEInfo 31 { 32 dw_offset_t offset; // The DIE offset 33 dw_tag_t tag; 34 uint32_t type_flags; // Any flags for this DIEInfo 35 36 DIEInfo () : 37 offset (DW_INVALID_OFFSET), 38 tag (0), 39 type_flags (0) 40 { 41 } 42 43 DIEInfo (dw_offset_t o, dw_tag_t t, uint32_t f) : 44 offset(o), 45 tag (t), 46 type_flags (f) 47 { 48 } 49 50 void 51 Clear() 52 { 53 offset = DW_INVALID_OFFSET; 54 tag = 0; 55 type_flags = 0; 56 } 57 }; 58 59 typedef std::vector<DIEInfo> DIEInfoArray; 60 typedef std::vector<uint32_t> DIEArray; 61 62 static void 63 ExtractDIEArray (const DIEInfoArray &die_info_array, 64 DIEArray &die_offsets) 65 { 66 const size_t count = die_info_array.size(); 67 for (size_t i=0; i<count; ++i) 68 { 69 die_offsets.push_back (die_info_array[i].offset); 70 } 71 } 72 73 static void 74 ExtractDIEArray (const DIEInfoArray &die_info_array, 75 const dw_tag_t tag, 76 DIEArray &die_offsets) 77 { 78 if (tag == 0) 79 { 80 ExtractDIEArray (die_info_array, die_offsets); 81 } 82 else 83 { 84 const size_t count = die_info_array.size(); 85 for (size_t i=0; i<count; ++i) 86 { 87 const dw_tag_t die_tag = die_info_array[i].tag; 88 bool tag_matches = die_tag == 0 || tag == die_tag; 89 if (!tag_matches) 90 { 91 if (die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) 92 tag_matches = tag == DW_TAG_structure_type || tag == DW_TAG_class_type; 93 } 94 if (tag_matches) 95 die_offsets.push_back (die_info_array[i].offset); 96 } 97 } 98 } 99 enum AtomType 100 { 101 eAtomTypeNULL = 0u, 102 eAtomTypeDIEOffset = 1u, // DIE offset, check form for encoding 103 eAtomTypeCUOffset = 2u, // DIE offset of the compiler unit header that contains the item in question 104 eAtomTypeTag = 3u, // DW_TAG_xxx value, should be encoded as DW_FORM_data1 (if no tags exceed 255) or DW_FORM_data2 105 eAtomTypeNameFlags = 4u, // Flags from enum NameFlags 106 eAtomTypeTypeFlags = 5u // Flags from enum TypeFlags 107 }; 108 109 // Bit definitions for the eAtomTypeTypeFlags flags 110 enum TypeFlags 111 { 112 // Always set for C++, only set for ObjC if this is the 113 // @implementation for class 114 eTypeFlagClassIsImplementation = ( 1u << 1 ) 115 }; 116 117 118 static void 119 ExtractClassOrStructDIEArray (const DIEInfoArray &die_info_array, 120 bool return_implementation_only_if_available, 121 DIEArray &die_offsets) 122 { 123 const size_t count = die_info_array.size(); 124 for (size_t i=0; i<count; ++i) 125 { 126 const dw_tag_t die_tag = die_info_array[i].tag; 127 if (die_tag == 0 || die_tag == DW_TAG_class_type || die_tag == DW_TAG_structure_type) 128 { 129 if (die_info_array[i].type_flags & eTypeFlagClassIsImplementation) 130 { 131 if (return_implementation_only_if_available) 132 { 133 // We found the one true definiton for this class, so 134 // only return that 135 die_offsets.clear(); 136 die_offsets.push_back (die_info_array[i].offset); 137 return; 138 } 139 else 140 { 141 // Put the one true definition as the first entry so it 142 // matches first 143 die_offsets.insert (die_offsets.begin(), die_info_array[i].offset); 144 } 145 } 146 else 147 { 148 die_offsets.push_back (die_info_array[i].offset); 149 } 150 } 151 } 152 } 153 154 static void 155 ExtractTypesFromDIEArray (const DIEInfoArray &die_info_array, 156 uint32_t type_flag_mask, 157 uint32_t type_flag_value, 158 DIEArray &die_offsets) 159 { 160 const size_t count = die_info_array.size(); 161 for (size_t i=0; i<count; ++i) 162 { 163 if ((die_info_array[i].type_flags & type_flag_mask) == type_flag_value) 164 die_offsets.push_back (die_info_array[i].offset); 165 } 166 } 167 168 struct Atom 169 { 170 uint16_t type; 171 dw_form_t form; 172 173 Atom (uint16_t t = eAtomTypeNULL, dw_form_t f = 0) : 174 type (t), 175 form (f) 176 { 177 } 178 }; 179 180 typedef std::vector<Atom> AtomArray; 181 182 static uint32_t 183 GetTypeFlags (SymbolFileDWARF *dwarf2Data, 184 const DWARFCompileUnit* cu, 185 const DWARFDebugInfoEntry* die); 186 187 188 static const char * 189 GetAtomTypeName (uint16_t atom) 190 { 191 switch (atom) 192 { 193 case eAtomTypeNULL: return "NULL"; 194 case eAtomTypeDIEOffset: return "die-offset"; 195 case eAtomTypeCUOffset: return "cu-offset"; 196 case eAtomTypeTag: return "die-tag"; 197 case eAtomTypeNameFlags: return "name-flags"; 198 case eAtomTypeTypeFlags: return "type-flags"; 199 } 200 return "<invalid>"; 201 } 202 struct Prologue 203 { 204 // DIE offset base so die offsets in hash_data can be CU relative 205 dw_offset_t die_base_offset; 206 AtomArray atoms; 207 uint32_t atom_mask; 208 size_t min_hash_data_byte_size; 209 bool hash_data_has_fixed_byte_size; 210 211 Prologue (dw_offset_t _die_base_offset = 0) : 212 die_base_offset (_die_base_offset), 213 atoms(), 214 atom_mask (0), 215 min_hash_data_byte_size(0), 216 hash_data_has_fixed_byte_size(true) 217 { 218 // Define an array of DIE offsets by first defining an array, 219 // and then define the atom type for the array, in this case 220 // we have an array of DIE offsets 221 AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); 222 } 223 224 virtual ~Prologue() 225 { 226 } 227 228 void 229 ClearAtoms () 230 { 231 hash_data_has_fixed_byte_size = true; 232 min_hash_data_byte_size = 0; 233 atom_mask = 0; 234 atoms.clear(); 235 } 236 237 bool 238 ContainsAtom (AtomType atom_type) const 239 { 240 return (atom_mask & (1u << atom_type)) != 0; 241 } 242 243 virtual void 244 Clear () 245 { 246 die_base_offset = 0; 247 ClearAtoms (); 248 } 249 250 void 251 AppendAtom (AtomType type, dw_form_t form) 252 { 253 atoms.push_back (Atom(type, form)); 254 atom_mask |= 1u << type; 255 switch (form) 256 { 257 case DW_FORM_indirect: 258 case DW_FORM_exprloc: 259 case DW_FORM_flag_present: 260 case DW_FORM_ref_sig8: 261 assert (!"Unhandled atom form"); 262 break; 263 264 case DW_FORM_string: 265 case DW_FORM_block: 266 case DW_FORM_block1: 267 case DW_FORM_sdata: 268 case DW_FORM_udata: 269 case DW_FORM_ref_udata: 270 hash_data_has_fixed_byte_size = false; 271 // Fall through to the cases below... 272 case DW_FORM_flag: 273 case DW_FORM_data1: 274 case DW_FORM_ref1: 275 case DW_FORM_sec_offset: 276 min_hash_data_byte_size += 1; 277 break; 278 279 case DW_FORM_block2: 280 hash_data_has_fixed_byte_size = false; 281 // Fall through to the cases below... 282 case DW_FORM_data2: 283 case DW_FORM_ref2: 284 min_hash_data_byte_size += 2; 285 break; 286 287 case DW_FORM_block4: 288 hash_data_has_fixed_byte_size = false; 289 // Fall through to the cases below... 290 case DW_FORM_data4: 291 case DW_FORM_ref4: 292 case DW_FORM_addr: 293 case DW_FORM_ref_addr: 294 case DW_FORM_strp: 295 min_hash_data_byte_size += 4; 296 break; 297 298 case DW_FORM_data8: 299 case DW_FORM_ref8: 300 min_hash_data_byte_size += 8; 301 break; 302 303 } 304 } 305 306// void 307// Dump (std::ostream* ostrm_ptr); 308 309 lldb::offset_t 310 Read (const lldb_private::DataExtractor &data, 311 lldb::offset_t offset) 312 { 313 ClearAtoms (); 314 315 die_base_offset = data.GetU32 (&offset); 316 317 const uint32_t atom_count = data.GetU32 (&offset); 318 if (atom_count == 0x00060003u) 319 { 320 // Old format, deal with contents of old pre-release format 321 while (data.GetU32(&offset)) 322 /* do nothing */; 323 324 // Hardcode to the only known value for now. 325 AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); 326 } 327 else 328 { 329 for (uint32_t i=0; i<atom_count; ++i) 330 { 331 AtomType type = (AtomType)data.GetU16 (&offset); 332 dw_form_t form = (dw_form_t)data.GetU16 (&offset); 333 AppendAtom (type, form); 334 } 335 } 336 return offset; 337 } 338 339// virtual void 340// Write (BinaryStreamBuf &s); 341 342 size_t 343 GetByteSize () const 344 { 345 // Add an extra count to the atoms size for the zero termination Atom that gets 346 // written to disk 347 return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); 348 } 349 350 size_t 351 GetMinumumHashDataByteSize () const 352 { 353 return min_hash_data_byte_size; 354 } 355 356 bool 357 HashDataHasFixedByteSize() const 358 { 359 return hash_data_has_fixed_byte_size; 360 } 361 }; 362 363 struct Header : public MappedHash::Header<Prologue> 364 { 365 Header (dw_offset_t _die_base_offset = 0) 366 { 367 } 368 369 virtual 370 ~Header() 371 { 372 } 373 374 virtual size_t 375 GetByteSize (const HeaderData &header_data) 376 { 377 return header_data.GetByteSize(); 378 } 379 380 // virtual void 381 // Dump (std::ostream* ostrm_ptr); 382 // 383 virtual lldb::offset_t 384 Read (lldb_private::DataExtractor &data, lldb::offset_t offset) 385 { 386 offset = MappedHash::Header<Prologue>::Read (data, offset); 387 if (offset != UINT32_MAX) 388 { 389 offset = header_data.Read (data, offset); 390 } 391 return offset; 392 } 393 394 bool 395 Read (const lldb_private::DataExtractor &data, 396 lldb::offset_t *offset_ptr, 397 DIEInfo &hash_data) const 398 { 399 const size_t num_atoms = header_data.atoms.size(); 400 if (num_atoms == 0) 401 return false; 402 403 for (size_t i=0; i<num_atoms; ++i) 404 { 405 DWARFFormValue form_value (header_data.atoms[i].form); 406 407 if (!form_value.ExtractValue(data, offset_ptr, NULL)) 408 return false; 409 410 switch (header_data.atoms[i].type) 411 { 412 case eAtomTypeDIEOffset: // DIE offset, check form for encoding 413 hash_data.offset = (dw_offset_t)form_value.Reference (header_data.die_base_offset); 414 break; 415 416 case eAtomTypeTag: // DW_TAG value for the DIE 417 hash_data.tag = (dw_tag_t)form_value.Unsigned (); 418 419 case eAtomTypeTypeFlags: // Flags from enum TypeFlags 420 hash_data.type_flags = (uint32_t)form_value.Unsigned (); 421 break; 422 default: 423 return false; 424 break; 425 } 426 } 427 return true; 428 } 429 430 void 431 Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const 432 { 433 const size_t num_atoms = header_data.atoms.size(); 434 for (size_t i=0; i<num_atoms; ++i) 435 { 436 if (i > 0) 437 strm.PutCString (", "); 438 439 DWARFFormValue form_value (header_data.atoms[i].form); 440 switch (header_data.atoms[i].type) 441 { 442 case eAtomTypeDIEOffset: // DIE offset, check form for encoding 443 strm.Printf ("{0x%8.8x}", hash_data.offset); 444 break; 445 446 case eAtomTypeTag: // DW_TAG value for the DIE 447 { 448 const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag); 449 if (tag_cstr) 450 strm.PutCString (tag_cstr); 451 else 452 strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag); 453 } 454 break; 455 456 case eAtomTypeTypeFlags: // Flags from enum TypeFlags 457 strm.Printf ("0x%2.2x", hash_data.type_flags); 458 if (hash_data.type_flags) 459 { 460 strm.PutCString (" ("); 461 if (hash_data.type_flags & eTypeFlagClassIsImplementation) 462 strm.PutCString (" implementation"); 463 strm.PutCString (" )"); 464 } 465 break; 466 467 default: 468 strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); 469 break; 470 } 471 } 472 } 473 }; 474 475// class ExportTable 476// { 477// public: 478// ExportTable (); 479// 480// void 481// AppendNames (DWARFDebugPubnamesSet &pubnames_set, 482// StringTable &string_table); 483// 484// void 485// AppendNamesEntry (SymbolFileDWARF *dwarf2Data, 486// const DWARFCompileUnit* cu, 487// const DWARFDebugInfoEntry* die, 488// StringTable &string_table); 489// 490// void 491// AppendTypesEntry (DWARFData *dwarf2Data, 492// const DWARFCompileUnit* cu, 493// const DWARFDebugInfoEntry* die, 494// StringTable &string_table); 495// 496// size_t 497// Save (BinaryStreamBuf &names_data, const StringTable &string_table); 498// 499// void 500// AppendName (const char *name, 501// uint32_t die_offset, 502// StringTable &string_table, 503// dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied 504// void 505// AppendType (const char *name, 506// uint32_t die_offset, 507// StringTable &string_table); 508// 509// 510// protected: 511// struct Entry 512// { 513// uint32_t hash; 514// uint32_t str_offset; 515// uint32_t die_offset; 516// }; 517// 518// // Map uniqued .debug_str offset to the corresponding DIE offsets 519// typedef std::map<uint32_t, DIEInfoArray> NameInfo; 520// // Map a name hash to one or more name infos 521// typedef std::map<uint32_t, NameInfo> BucketEntry; 522// 523// static uint32_t 524// GetByteSize (const NameInfo &name_info); 525// 526// typedef std::vector<BucketEntry> BucketEntryColl; 527// typedef std::vector<Entry> EntryColl; 528// EntryColl m_entries; 529// 530// }; 531 532 533 // A class for reading and using a saved hash table from a block of data 534 // in memory 535 class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray> 536 { 537 public: 538 539 MemoryTable (lldb_private::DataExtractor &table_data, 540 const lldb_private::DataExtractor &string_table, 541 const char *name) : 542 MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data), 543 m_data (table_data), 544 m_string_table (string_table), 545 m_name (name) 546 { 547 } 548 549 virtual 550 ~MemoryTable () 551 { 552 } 553 554 virtual const char * 555 GetStringForKeyType (KeyType key) const 556 { 557 // The key in the DWARF table is the .debug_str offset for the string 558 return m_string_table.PeekCStr (key); 559 } 560 561 virtual Result 562 GetHashDataForName (const char *name, 563 lldb::offset_t* hash_data_offset_ptr, 564 Pair &pair) const 565 { 566 pair.key = m_data.GetU32 (hash_data_offset_ptr); 567 pair.value.clear(); 568 569 // If the key is zero, this terminates our chain of HashData objects 570 // for this hash value. 571 if (pair.key == 0) 572 return eResultEndOfHashData; 573 574 // There definitely should be a string for this string offset, if 575 // there isn't, there is something wrong, return and error 576 const char *strp_cstr = m_string_table.PeekCStr (pair.key); 577 if (strp_cstr == NULL) 578 { 579 *hash_data_offset_ptr = UINT32_MAX; 580 return eResultError; 581 } 582 583 const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); 584 const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize(); 585 if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) 586 { 587 // We have at least one HashData entry, and we have enough 588 // data to parse at leats "count" HashData enties. 589 590 // First make sure the entire C string matches... 591 const bool match = strcmp (name, strp_cstr) == 0; 592 593 if (!match && m_header.header_data.HashDataHasFixedByteSize()) 594 { 595 // If the string doesn't match and we have fixed size data, 596 // we can just add the total byte size of all HashData objects 597 // to the hash data offset and be done... 598 *hash_data_offset_ptr += min_total_hash_data_size; 599 } 600 else 601 { 602 // If the string does match, or we don't have fixed size data 603 // then we need to read the hash data as a stream. If the 604 // string matches we also append all HashData objects to the 605 // value array. 606 for (uint32_t i=0; i<count; ++i) 607 { 608 DIEInfo die_info; 609 if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) 610 { 611 // Only happend the HashData if the string matched... 612 if (match) 613 pair.value.push_back (die_info); 614 } 615 else 616 { 617 // Something went wrong while reading the data 618 *hash_data_offset_ptr = UINT32_MAX; 619 return eResultError; 620 } 621 } 622 } 623 // Return the correct response depending on if the string matched 624 // or not... 625 if (match) 626 return eResultKeyMatch; // The key (cstring) matches and we have lookup results! 627 else 628 return eResultKeyMismatch; // The key doesn't match, this function will get called 629 // again for the next key/value or the key terminator 630 // which in our case is a zero .debug_str offset. 631 } 632 else 633 { 634 *hash_data_offset_ptr = UINT32_MAX; 635 return eResultError; 636 } 637 } 638 639 virtual Result 640 AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex, 641 lldb::offset_t* hash_data_offset_ptr, 642 Pair &pair) const 643 { 644 pair.key = m_data.GetU32 (hash_data_offset_ptr); 645 // If the key is zero, this terminates our chain of HashData objects 646 // for this hash value. 647 if (pair.key == 0) 648 return eResultEndOfHashData; 649 650 // There definitely should be a string for this string offset, if 651 // there isn't, there is something wrong, return and error 652 const char *strp_cstr = m_string_table.PeekCStr (pair.key); 653 if (strp_cstr == NULL) 654 return eResultError; 655 656 const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); 657 const size_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize(); 658 if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) 659 { 660 const bool match = regex.Execute(strp_cstr); 661 662 if (!match && m_header.header_data.HashDataHasFixedByteSize()) 663 { 664 // If the regex doesn't match and we have fixed size data, 665 // we can just add the total byte size of all HashData objects 666 // to the hash data offset and be done... 667 *hash_data_offset_ptr += min_total_hash_data_size; 668 } 669 else 670 { 671 // If the string does match, or we don't have fixed size data 672 // then we need to read the hash data as a stream. If the 673 // string matches we also append all HashData objects to the 674 // value array. 675 for (uint32_t i=0; i<count; ++i) 676 { 677 DIEInfo die_info; 678 if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) 679 { 680 // Only happend the HashData if the string matched... 681 if (match) 682 pair.value.push_back (die_info); 683 } 684 else 685 { 686 // Something went wrong while reading the data 687 *hash_data_offset_ptr = UINT32_MAX; 688 return eResultError; 689 } 690 } 691 } 692 // Return the correct response depending on if the string matched 693 // or not... 694 if (match) 695 return eResultKeyMatch; // The key (cstring) matches and we have lookup results! 696 else 697 return eResultKeyMismatch; // The key doesn't match, this function will get called 698 // again for the next key/value or the key terminator 699 // which in our case is a zero .debug_str offset. 700 } 701 else 702 { 703 *hash_data_offset_ptr = UINT32_MAX; 704 return eResultError; 705 } 706 } 707 708 size_t 709 AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex, 710 DIEInfoArray &die_info_array) const 711 { 712 const uint32_t hash_count = m_header.hashes_count; 713 Pair pair; 714 for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) 715 { 716 lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); 717 while (hash_data_offset != UINT32_MAX) 718 { 719 const lldb::offset_t prev_hash_data_offset = hash_data_offset; 720 Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair); 721 if (prev_hash_data_offset == hash_data_offset) 722 break; 723 724 // Check the result of getting our hash data 725 switch (hash_result) 726 { 727 case eResultKeyMatch: 728 case eResultKeyMismatch: 729 // Whether we matches or not, it doesn't matter, we 730 // keep looking. 731 break; 732 733 case eResultEndOfHashData: 734 case eResultError: 735 hash_data_offset = UINT32_MAX; 736 break; 737 } 738 } 739 } 740 die_info_array.swap (pair.value); 741 return die_info_array.size(); 742 } 743 744 size_t 745 AppendAllDIEsInRange (const uint32_t die_offset_start, 746 const uint32_t die_offset_end, 747 DIEInfoArray &die_info_array) const 748 { 749 const uint32_t hash_count = m_header.hashes_count; 750 for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) 751 { 752 bool done = false; 753 lldb::offset_t hash_data_offset = GetHashDataOffset (offset_idx); 754 while (!done && hash_data_offset != UINT32_MAX) 755 { 756 KeyType key = m_data.GetU32 (&hash_data_offset); 757 // If the key is zero, this terminates our chain of HashData objects 758 // for this hash value. 759 if (key == 0) 760 break; 761 762 const uint32_t count = m_data.GetU32 (&hash_data_offset); 763 for (uint32_t i=0; i<count; ++i) 764 { 765 DIEInfo die_info; 766 if (m_header.Read(m_data, &hash_data_offset, die_info)) 767 { 768 if (die_info.offset == 0) 769 done = true; 770 if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end) 771 die_info_array.push_back(die_info); 772 } 773 } 774 } 775 } 776 return die_info_array.size(); 777 } 778 779 size_t 780 FindByName (const char *name, DIEArray &die_offsets) 781 { 782 DIEInfoArray die_info_array; 783 if (FindByName(name, die_info_array)) 784 DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); 785 return die_info_array.size(); 786 } 787 788 size_t 789 FindByNameAndTag (const char *name, 790 const dw_tag_t tag, 791 DIEArray &die_offsets) 792 { 793 DIEInfoArray die_info_array; 794 if (FindByName(name, die_info_array)) 795 DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets); 796 return die_info_array.size(); 797 } 798 799 size_t 800 FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation) 801 { 802 DIEInfoArray die_info_array; 803 if (FindByName(name, die_info_array)) 804 { 805 if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags)) 806 { 807 // If we have two atoms, then we have the DIE offset and 808 // the type flags so we can find the objective C class 809 // efficiently. 810 DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array, 811 UINT32_MAX, 812 eTypeFlagClassIsImplementation, 813 die_offsets); 814 } 815 else 816 { 817 // We don't only want the one true definition, so try and see 818 // what we can find, and only return class or struct DIEs. 819 // If we do have the full implementation, then return it alone, 820 // else return all possible matches. 821 const bool return_implementation_only_if_available = true; 822 DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array, 823 return_implementation_only_if_available, 824 die_offsets); 825 } 826 } 827 return die_offsets.size(); 828 } 829 830 size_t 831 FindByName (const char *name, DIEInfoArray &die_info_array) 832 { 833 Pair kv_pair; 834 size_t old_size = die_info_array.size(); 835 if (Find (name, kv_pair)) 836 { 837 die_info_array.swap(kv_pair.value); 838 return die_info_array.size() - old_size; 839 } 840 return 0; 841 } 842 843 protected: 844 const lldb_private::DataExtractor &m_data; 845 const lldb_private::DataExtractor &m_string_table; 846 std::string m_name; 847 }; 848}; 849 850 851#endif // SymbolFileDWARF_HashedNameToDIE_h_ 852