HashedNameToDIE.h revision e0028b827759c5ad2cbc45947371c362193a63bc
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 uint32_t 310 Read (const lldb_private::DataExtractor &data, uint32_t offset) 311 { 312 ClearAtoms (); 313 314 die_base_offset = data.GetU32 (&offset); 315 316 const uint32_t atom_count = data.GetU32 (&offset); 317 if (atom_count == 0x00060003u) 318 { 319 // Old format, deal with contents of old pre-release format 320 while (data.GetU32(&offset)) 321 /* do nothing */; 322 323 // Hardcode to the only known value for now. 324 AppendAtom (eAtomTypeDIEOffset, DW_FORM_data4); 325 } 326 else 327 { 328 for (uint32_t i=0; i<atom_count; ++i) 329 { 330 AtomType type = (AtomType)data.GetU16 (&offset); 331 dw_form_t form = (dw_form_t)data.GetU16 (&offset); 332 AppendAtom (type, form); 333 } 334 } 335 return offset; 336 } 337 338// virtual void 339// Write (BinaryStreamBuf &s); 340 341 size_t 342 GetByteSize () const 343 { 344 // Add an extra count to the atoms size for the zero termination Atom that gets 345 // written to disk 346 return sizeof(die_base_offset) + sizeof(uint32_t) + atoms.size() * sizeof(Atom); 347 } 348 349 size_t 350 GetMinumumHashDataByteSize () const 351 { 352 return min_hash_data_byte_size; 353 } 354 355 bool 356 HashDataHasFixedByteSize() const 357 { 358 return hash_data_has_fixed_byte_size; 359 } 360 }; 361 362 struct Header : public MappedHash::Header<Prologue> 363 { 364 Header (dw_offset_t _die_base_offset = 0) 365 { 366 } 367 368 virtual 369 ~Header() 370 { 371 } 372 373 virtual size_t 374 GetByteSize (const HeaderData &header_data) 375 { 376 return header_data.GetByteSize(); 377 } 378 379 // virtual void 380 // Dump (std::ostream* ostrm_ptr); 381 // 382 virtual uint32_t 383 Read (lldb_private::DataExtractor &data, uint32_t offset) 384 { 385 offset = MappedHash::Header<Prologue>::Read (data, offset); 386 if (offset != UINT32_MAX) 387 { 388 offset = header_data.Read (data, offset); 389 } 390 return offset; 391 } 392 393 bool 394 Read (const lldb_private::DataExtractor &data, 395 uint32_t *offset_ptr, 396 DIEInfo &hash_data) const 397 { 398 const size_t num_atoms = header_data.atoms.size(); 399 if (num_atoms == 0) 400 return false; 401 402 for (size_t i=0; i<num_atoms; ++i) 403 { 404 DWARFFormValue form_value (header_data.atoms[i].form); 405 406 if (!form_value.ExtractValue(data, offset_ptr, NULL)) 407 return false; 408 409 switch (header_data.atoms[i].type) 410 { 411 case eAtomTypeDIEOffset: // DIE offset, check form for encoding 412 hash_data.offset = form_value.Reference (header_data.die_base_offset); 413 break; 414 415 case eAtomTypeTag: // DW_TAG value for the DIE 416 hash_data.tag = form_value.Unsigned (); 417 418 case eAtomTypeTypeFlags: // Flags from enum TypeFlags 419 hash_data.type_flags = form_value.Unsigned (); 420 break; 421 default: 422 return false; 423 break; 424 } 425 } 426 return true; 427 } 428 429 void 430 Dump (lldb_private::Stream& strm, const DIEInfo &hash_data) const 431 { 432 const size_t num_atoms = header_data.atoms.size(); 433 for (size_t i=0; i<num_atoms; ++i) 434 { 435 if (i > 0) 436 strm.PutCString (", "); 437 438 DWARFFormValue form_value (header_data.atoms[i].form); 439 switch (header_data.atoms[i].type) 440 { 441 case eAtomTypeDIEOffset: // DIE offset, check form for encoding 442 strm.Printf ("{0x%8.8x}", hash_data.offset); 443 break; 444 445 case eAtomTypeTag: // DW_TAG value for the DIE 446 { 447 const char *tag_cstr = lldb_private::DW_TAG_value_to_name (hash_data.tag); 448 if (tag_cstr) 449 strm.PutCString (tag_cstr); 450 else 451 strm.Printf ("DW_TAG_(0x%4.4x)", hash_data.tag); 452 } 453 break; 454 455 case eAtomTypeTypeFlags: // Flags from enum TypeFlags 456 strm.Printf ("0x%2.2x", hash_data.type_flags); 457 if (hash_data.type_flags) 458 { 459 strm.PutCString (" ("); 460 if (hash_data.type_flags & eTypeFlagClassIsImplementation) 461 strm.PutCString (" implementation"); 462 strm.PutCString (" )"); 463 } 464 break; 465 466 default: 467 strm.Printf ("AtomType(0x%x)", header_data.atoms[i].type); 468 break; 469 } 470 } 471 } 472 }; 473 474// class ExportTable 475// { 476// public: 477// ExportTable (); 478// 479// void 480// AppendNames (DWARFDebugPubnamesSet &pubnames_set, 481// StringTable &string_table); 482// 483// void 484// AppendNamesEntry (SymbolFileDWARF *dwarf2Data, 485// const DWARFCompileUnit* cu, 486// const DWARFDebugInfoEntry* die, 487// StringTable &string_table); 488// 489// void 490// AppendTypesEntry (DWARFData *dwarf2Data, 491// const DWARFCompileUnit* cu, 492// const DWARFDebugInfoEntry* die, 493// StringTable &string_table); 494// 495// size_t 496// Save (BinaryStreamBuf &names_data, const StringTable &string_table); 497// 498// void 499// AppendName (const char *name, 500// uint32_t die_offset, 501// StringTable &string_table, 502// dw_offset_t name_debug_str_offset = DW_INVALID_OFFSET); // If "name" has already been looked up, then it can be supplied 503// void 504// AppendType (const char *name, 505// uint32_t die_offset, 506// StringTable &string_table); 507// 508// 509// protected: 510// struct Entry 511// { 512// uint32_t hash; 513// uint32_t str_offset; 514// uint32_t die_offset; 515// }; 516// 517// // Map uniqued .debug_str offset to the corresponding DIE offsets 518// typedef std::map<uint32_t, DIEInfoArray> NameInfo; 519// // Map a name hash to one or more name infos 520// typedef std::map<uint32_t, NameInfo> BucketEntry; 521// 522// static uint32_t 523// GetByteSize (const NameInfo &name_info); 524// 525// typedef std::vector<BucketEntry> BucketEntryColl; 526// typedef std::vector<Entry> EntryColl; 527// EntryColl m_entries; 528// 529// }; 530 531 532 // A class for reading and using a saved hash table from a block of data 533 // in memory 534 class MemoryTable : public MappedHash::MemoryTable<uint32_t, DWARFMappedHash::Header, DIEInfoArray> 535 { 536 public: 537 538 MemoryTable (lldb_private::DataExtractor &table_data, 539 const lldb_private::DataExtractor &string_table, 540 const char *name) : 541 MappedHash::MemoryTable<uint32_t, Header, DIEInfoArray> (table_data), 542 m_data (table_data), 543 m_string_table (string_table), 544 m_name (name) 545 { 546 } 547 548 virtual 549 ~MemoryTable () 550 { 551 } 552 553 virtual const char * 554 GetStringForKeyType (KeyType key) const 555 { 556 // The key in the DWARF table is the .debug_str offset for the string 557 return m_string_table.PeekCStr (key); 558 } 559 560 virtual Result 561 GetHashDataForName (const char *name, 562 uint32_t* hash_data_offset_ptr, 563 Pair &pair) const 564 { 565 pair.key = m_data.GetU32 (hash_data_offset_ptr); 566 pair.value.clear(); 567 568 // If the key is zero, this terminates our chain of HashData objects 569 // for this hash value. 570 if (pair.key == 0) 571 return eResultEndOfHashData; 572 573 // There definitely should be a string for this string offset, if 574 // there isn't, there is something wrong, return and error 575 const char *strp_cstr = m_string_table.PeekCStr (pair.key); 576 if (strp_cstr == NULL) 577 { 578 *hash_data_offset_ptr = UINT32_MAX; 579 return eResultError; 580 } 581 582 const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); 583 const uint32_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize(); 584 if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) 585 { 586 // We have at least one HashData entry, and we have enough 587 // data to parse at leats "count" HashData enties. 588 589 // First make sure the entire C string matches... 590 const bool match = strcmp (name, strp_cstr) == 0; 591 592 if (!match && m_header.header_data.HashDataHasFixedByteSize()) 593 { 594 // If the string doesn't match and we have fixed size data, 595 // we can just add the total byte size of all HashData objects 596 // to the hash data offset and be done... 597 *hash_data_offset_ptr += min_total_hash_data_size; 598 } 599 else 600 { 601 // If the string does match, or we don't have fixed size data 602 // then we need to read the hash data as a stream. If the 603 // string matches we also append all HashData objects to the 604 // value array. 605 for (uint32_t i=0; i<count; ++i) 606 { 607 DIEInfo die_info; 608 if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) 609 { 610 // Only happend the HashData if the string matched... 611 if (match) 612 pair.value.push_back (die_info); 613 } 614 else 615 { 616 // Something went wrong while reading the data 617 *hash_data_offset_ptr = UINT32_MAX; 618 return eResultError; 619 } 620 } 621 } 622 // Return the correct response depending on if the string matched 623 // or not... 624 if (match) 625 return eResultKeyMatch; // The key (cstring) matches and we have lookup results! 626 else 627 return eResultKeyMismatch; // The key doesn't match, this function will get called 628 // again for the next key/value or the key terminator 629 // which in our case is a zero .debug_str offset. 630 } 631 else 632 { 633 *hash_data_offset_ptr = UINT32_MAX; 634 return eResultError; 635 } 636 } 637 638 virtual Result 639 AppendHashDataForRegularExpression (const lldb_private::RegularExpression& regex, 640 uint32_t* hash_data_offset_ptr, 641 Pair &pair) const 642 { 643 pair.key = m_data.GetU32 (hash_data_offset_ptr); 644 // If the key is zero, this terminates our chain of HashData objects 645 // for this hash value. 646 if (pair.key == 0) 647 return eResultEndOfHashData; 648 649 // There definitely should be a string for this string offset, if 650 // there isn't, there is something wrong, return and error 651 const char *strp_cstr = m_string_table.PeekCStr (pair.key); 652 if (strp_cstr == NULL) 653 return eResultError; 654 655 const uint32_t count = m_data.GetU32 (hash_data_offset_ptr); 656 const uint32_t min_total_hash_data_size = count * m_header.header_data.GetMinumumHashDataByteSize(); 657 if (count > 0 && m_data.ValidOffsetForDataOfSize (*hash_data_offset_ptr, min_total_hash_data_size)) 658 { 659 const bool match = regex.Execute(strp_cstr); 660 661 if (!match && m_header.header_data.HashDataHasFixedByteSize()) 662 { 663 // If the regex doesn't match and we have fixed size data, 664 // we can just add the total byte size of all HashData objects 665 // to the hash data offset and be done... 666 *hash_data_offset_ptr += min_total_hash_data_size; 667 } 668 else 669 { 670 // If the string does match, or we don't have fixed size data 671 // then we need to read the hash data as a stream. If the 672 // string matches we also append all HashData objects to the 673 // value array. 674 for (uint32_t i=0; i<count; ++i) 675 { 676 DIEInfo die_info; 677 if (m_header.Read(m_data, hash_data_offset_ptr, die_info)) 678 { 679 // Only happend the HashData if the string matched... 680 if (match) 681 pair.value.push_back (die_info); 682 } 683 else 684 { 685 // Something went wrong while reading the data 686 *hash_data_offset_ptr = UINT32_MAX; 687 return eResultError; 688 } 689 } 690 } 691 // Return the correct response depending on if the string matched 692 // or not... 693 if (match) 694 return eResultKeyMatch; // The key (cstring) matches and we have lookup results! 695 else 696 return eResultKeyMismatch; // The key doesn't match, this function will get called 697 // again for the next key/value or the key terminator 698 // which in our case is a zero .debug_str offset. 699 } 700 else 701 { 702 *hash_data_offset_ptr = UINT32_MAX; 703 return eResultError; 704 } 705 } 706 707 size_t 708 AppendAllDIEsThatMatchingRegex (const lldb_private::RegularExpression& regex, 709 DIEInfoArray &die_info_array) const 710 { 711 const uint32_t hash_count = m_header.hashes_count; 712 Pair pair; 713 for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) 714 { 715 uint32_t hash_data_offset = GetHashDataOffset (offset_idx); 716 while (hash_data_offset != UINT32_MAX) 717 { 718 const uint32_t prev_hash_data_offset = hash_data_offset; 719 Result hash_result = AppendHashDataForRegularExpression (regex, &hash_data_offset, pair); 720 if (prev_hash_data_offset == hash_data_offset) 721 break; 722 723 // Check the result of getting our hash data 724 switch (hash_result) 725 { 726 case eResultKeyMatch: 727 case eResultKeyMismatch: 728 // Whether we matches or not, it doesn't matter, we 729 // keep looking. 730 break; 731 732 case eResultEndOfHashData: 733 case eResultError: 734 hash_data_offset = UINT32_MAX; 735 break; 736 } 737 } 738 } 739 die_info_array.swap (pair.value); 740 return die_info_array.size(); 741 } 742 743 size_t 744 AppendAllDIEsInRange (const uint32_t die_offset_start, 745 const uint32_t die_offset_end, 746 DIEInfoArray &die_info_array) const 747 { 748 const uint32_t hash_count = m_header.hashes_count; 749 for (uint32_t offset_idx=0; offset_idx<hash_count; ++offset_idx) 750 { 751 bool done = false; 752 uint32_t hash_data_offset = GetHashDataOffset (offset_idx); 753 while (!done && hash_data_offset != UINT32_MAX) 754 { 755 KeyType key = m_data.GetU32 (&hash_data_offset); 756 // If the key is zero, this terminates our chain of HashData objects 757 // for this hash value. 758 if (key == 0) 759 break; 760 761 const uint32_t count = m_data.GetU32 (&hash_data_offset); 762 for (uint32_t i=0; i<count; ++i) 763 { 764 DIEInfo die_info; 765 if (m_header.Read(m_data, &hash_data_offset, die_info)) 766 { 767 if (die_info.offset == 0) 768 done = true; 769 if (die_offset_start <= die_info.offset && die_info.offset < die_offset_end) 770 die_info_array.push_back(die_info); 771 } 772 } 773 } 774 } 775 return die_info_array.size(); 776 } 777 778 size_t 779 FindByName (const char *name, DIEArray &die_offsets) 780 { 781 DIEInfoArray die_info_array; 782 if (FindByName(name, die_info_array)) 783 DWARFMappedHash::ExtractDIEArray (die_info_array, die_offsets); 784 return die_info_array.size(); 785 } 786 787 size_t 788 FindByNameAndTag (const char *name, 789 const dw_tag_t tag, 790 DIEArray &die_offsets) 791 { 792 DIEInfoArray die_info_array; 793 if (FindByName(name, die_info_array)) 794 DWARFMappedHash::ExtractDIEArray (die_info_array, tag, die_offsets); 795 return die_info_array.size(); 796 } 797 798 size_t 799 FindCompleteObjCClassByName (const char *name, DIEArray &die_offsets, bool must_be_implementation) 800 { 801 DIEInfoArray die_info_array; 802 if (FindByName(name, die_info_array)) 803 { 804 if (must_be_implementation && GetHeader().header_data.ContainsAtom (eAtomTypeTypeFlags)) 805 { 806 // If we have two atoms, then we have the DIE offset and 807 // the type flags so we can find the objective C class 808 // efficiently. 809 DWARFMappedHash::ExtractTypesFromDIEArray (die_info_array, 810 UINT32_MAX, 811 eTypeFlagClassIsImplementation, 812 die_offsets); 813 } 814 else 815 { 816 // We don't only want the one true definition, so try and see 817 // what we can find, and only return class or struct DIEs. 818 // If we do have the full implementation, then return it alone, 819 // else return all possible matches. 820 const bool return_implementation_only_if_available = true; 821 DWARFMappedHash::ExtractClassOrStructDIEArray (die_info_array, 822 return_implementation_only_if_available, 823 die_offsets); 824 } 825 } 826 return die_offsets.size(); 827 } 828 829 size_t 830 FindByName (const char *name, DIEInfoArray &die_info_array) 831 { 832 Pair kv_pair; 833 size_t old_size = die_info_array.size(); 834 if (Find (name, kv_pair)) 835 { 836 die_info_array.swap(kv_pair.value); 837 return die_info_array.size() - old_size; 838 } 839 return 0; 840 } 841 842 protected: 843 const lldb_private::DataExtractor &m_data; 844 const lldb_private::DataExtractor &m_string_table; 845 std::string m_name; 846 }; 847}; 848 849 850#endif // SymbolFileDWARF_HashedNameToDIE_h_ 851