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