1 //===-- DWARFCompileUnit.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 "DWARFCompileUnit.h" 11 12 #include "lldb/Core/Mangled.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Core/Stream.h" 15 #include "lldb/Core/Timer.h" 16 #include "lldb/Symbol/ObjectFile.h" 17 #include "lldb/Target/ObjCLanguageRuntime.h" 18 19 #include "DWARFDebugAbbrev.h" 20 #include "DWARFDebugAranges.h" 21 #include "DWARFDebugInfo.h" 22 #include "DWARFDIECollection.h" 23 #include "DWARFFormValue.h" 24 #include "LogChannelDWARF.h" 25 #include "NameToDIE.h" 26 #include "SymbolFileDWARF.h" 27 28 using namespace lldb; 29 using namespace lldb_private; 30 using namespace std; 31 32 33 extern int g_verbose; 34 35 DWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) : 36 m_dwarf2Data (dwarf2Data), 37 m_abbrevs (NULL), 38 m_user_data (NULL), 39 m_die_array (), 40 m_func_aranges_ap (), 41 m_base_addr (0), 42 m_offset (DW_INVALID_OFFSET), 43 m_length (0), 44 m_version (0), 45 m_addr_size (DWARFCompileUnit::GetDefaultAddressSize()) 46 { 47 } 48 49 void 50 DWARFCompileUnit::Clear() 51 { 52 m_offset = DW_INVALID_OFFSET; 53 m_length = 0; 54 m_version = 0; 55 m_abbrevs = NULL; 56 m_addr_size = DWARFCompileUnit::GetDefaultAddressSize(); 57 m_base_addr = 0; 58 m_die_array.clear(); 59 m_func_aranges_ap.reset(); 60 m_user_data = NULL; 61 } 62 63 bool 64 DWARFCompileUnit::Extract(const DataExtractor &debug_info, uint32_t* offset_ptr) 65 { 66 Clear(); 67 68 m_offset = *offset_ptr; 69 70 if (debug_info.ValidOffset(*offset_ptr)) 71 { 72 dw_offset_t abbr_offset; 73 const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev(); 74 m_length = debug_info.GetU32(offset_ptr); 75 m_version = debug_info.GetU16(offset_ptr); 76 abbr_offset = debug_info.GetU32(offset_ptr); 77 m_addr_size = debug_info.GetU8 (offset_ptr); 78 79 bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); 80 bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 81 bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); 82 bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 83 84 if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL) 85 { 86 m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); 87 return true; 88 } 89 90 // reset the offset to where we tried to parse from if anything went wrong 91 *offset_ptr = m_offset; 92 } 93 94 return false; 95 } 96 97 98 dw_offset_t 99 DWARFCompileUnit::Extract(dw_offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs) 100 { 101 Clear(); 102 103 m_offset = offset; 104 105 if (debug_info_data.ValidOffset(offset)) 106 { 107 m_length = debug_info_data.GetU32(&offset); 108 m_version = debug_info_data.GetU16(&offset); 109 bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset(); 110 m_abbrevs = abbrevs; 111 m_addr_size = debug_info_data.GetU8 (&offset); 112 113 bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 114 bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 115 116 if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset)) 117 return offset; 118 } 119 return DW_INVALID_OFFSET; 120 } 121 122 void 123 DWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) 124 { 125 if (m_die_array.size() > 1) 126 { 127 // std::vectors never get any smaller when resized to a smaller size, 128 // or when clear() or erase() are called, the size will report that it 129 // is smaller, but the memory allocated remains intact (call capacity() 130 // to see this). So we need to create a temporary vector and swap the 131 // contents which will cause just the internal pointers to be swapped 132 // so that when "tmp_array" goes out of scope, it will destroy the 133 // contents. 134 135 // Save at least the compile unit DIE 136 DWARFDebugInfoEntry::collection tmp_array; 137 m_die_array.swap(tmp_array); 138 if (keep_compile_unit_die) 139 m_die_array.push_back(tmp_array.front()); 140 } 141 } 142 143 //---------------------------------------------------------------------- 144 // ParseCompileUnitDIEsIfNeeded 145 // 146 // Parses a compile unit and indexes its DIEs if it hasn't already been 147 // done. 148 //---------------------------------------------------------------------- 149 size_t 150 DWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) 151 { 152 const size_t initial_die_array_size = m_die_array.size(); 153 if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) 154 return 0; // Already parsed 155 156 Timer scoped_timer (__PRETTY_FUNCTION__, 157 "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )", 158 m_offset, 159 cu_die_only); 160 161 // Set the offset to that of the first DIE and calculate the start of the 162 // next compilation unit header. 163 uint32_t offset = GetFirstDIEOffset(); 164 uint32_t next_cu_offset = GetNextCompileUnitOffset(); 165 166 DWARFDebugInfoEntry die; 167 // Keep a flat array of the DIE for binary lookup by DIE offset 168 if (!cu_die_only) 169 { 170 LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 171 if (log) 172 { 173 m_dwarf2Data->LogMessage (log.get(), 174 "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at .debug_info[0x%8.8x]", 175 GetOffset()); 176 } 177 } 178 179 uint32_t depth = 0; 180 // We are in our compile unit, parse starting at the offset 181 // we were told to parse 182 const DataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data(); 183 std::vector<uint32_t> die_index_stack; 184 die_index_stack.reserve(32); 185 die_index_stack.push_back(0); 186 bool prev_die_had_children = false; 187 const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); 188 while (offset < next_cu_offset && 189 die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset)) 190 { 191 // if (log) 192 // log->Printf("0x%8.8x: %*.*s%s%s", 193 // die.GetOffset(), 194 // depth * 2, depth * 2, "", 195 // DW_TAG_value_to_name (die.Tag()), 196 // die.HasChildren() ? " *" : ""); 197 198 const bool null_die = die.IsNULL(); 199 if (depth == 0) 200 { 201 uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 202 if (base_addr == LLDB_INVALID_ADDRESS) 203 base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0); 204 SetBaseAddress (base_addr); 205 if (initial_die_array_size == 0) 206 AddDIE (die); 207 if (cu_die_only) 208 return 1; 209 } 210 else 211 { 212 if (null_die) 213 { 214 if (prev_die_had_children) 215 { 216 // This will only happen if a DIE says is has children 217 // but all it contains is a NULL tag. Since we are removing 218 // the NULL DIEs from the list (saves up to 25% in C++ code), 219 // we need a way to let the DIE know that it actually doesn't 220 // have children. 221 if (!m_die_array.empty()) 222 m_die_array.back().SetEmptyChildren(true); 223 } 224 } 225 else 226 { 227 die.SetParentIndex(m_die_array.size() - die_index_stack[depth-1]); 228 229 if (die_index_stack.back()) 230 m_die_array[die_index_stack.back()].SetSiblingIndex(m_die_array.size()-die_index_stack.back()); 231 232 // Only push the DIE if it isn't a NULL DIE 233 m_die_array.push_back(die); 234 } 235 } 236 237 if (null_die) 238 { 239 // NULL DIE. 240 if (!die_index_stack.empty()) 241 die_index_stack.pop_back(); 242 243 if (depth > 0) 244 --depth; 245 if (depth == 0) 246 break; // We are done with this compile unit! 247 248 prev_die_had_children = false; 249 } 250 else 251 { 252 die_index_stack.back() = m_die_array.size() - 1; 253 // Normal DIE 254 const bool die_has_children = die.HasChildren(); 255 if (die_has_children) 256 { 257 die_index_stack.push_back(0); 258 ++depth; 259 } 260 prev_die_had_children = die_has_children; 261 } 262 } 263 264 // Give a little bit of info if we encounter corrupt DWARF (our offset 265 // should always terminate at or before the start of the next compilation 266 // unit header). 267 if (offset > next_cu_offset) 268 { 269 m_dwarf2Data->ReportWarning ("DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8x\n", 270 GetOffset(), 271 offset); 272 } 273 274 // Since std::vector objects will double their size, we really need to 275 // make a new array with the perfect size so we don't end up wasting 276 // space. So here we copy and swap to make sure we don't have any extra 277 // memory taken up. 278 279 if (m_die_array.size () < m_die_array.capacity()) 280 { 281 DWARFDebugInfoEntry::collection exact_size_die_array (m_die_array.begin(), m_die_array.end()); 282 exact_size_die_array.swap (m_die_array); 283 } 284 LogSP log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_DEBUG_INFO | DWARF_LOG_VERBOSE)); 285 if (log) 286 { 287 StreamString strm; 288 DWARFDebugInfoEntry::DumpDIECollection (strm, m_die_array); 289 log->PutCString (strm.GetString().c_str()); 290 } 291 292 return m_die_array.size(); 293 } 294 295 296 dw_offset_t 297 DWARFCompileUnit::GetAbbrevOffset() const 298 { 299 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 300 } 301 302 303 304 bool 305 DWARFCompileUnit::Verify(Stream *s) const 306 { 307 const DataExtractor& debug_info = m_dwarf2Data->get_debug_info_data(); 308 bool valid_offset = debug_info.ValidOffset(m_offset); 309 bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); 310 bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 311 bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset()); 312 bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 313 bool verbose = s->GetVerbose(); 314 if (valid_offset && length_OK && version_OK && addr_size_OK && abbr_offset_OK) 315 { 316 if (verbose) 317 s->Printf(" 0x%8.8x: OK\n", m_offset); 318 return true; 319 } 320 else 321 { 322 s->Printf(" 0x%8.8x: ", m_offset); 323 324 m_dwarf2Data->get_debug_info_data().Dump (s, m_offset, lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, 0); 325 s->EOL(); 326 if (valid_offset) 327 { 328 if (!length_OK) 329 s->Printf(" The length (0x%8.8x) for this compile unit is too large for the .debug_info provided.\n", m_length); 330 if (!version_OK) 331 s->Printf(" The 16 bit compile unit header version is not supported.\n"); 332 if (!abbr_offset_OK) 333 s->Printf(" The offset into the .debug_abbrev section (0x%8.8x) is not valid.\n", GetAbbrevOffset()); 334 if (!addr_size_OK) 335 s->Printf(" The address size is unsupported: 0x%2.2x\n", m_addr_size); 336 } 337 else 338 s->Printf(" The start offset of the compile unit header in the .debug_info is invalid.\n"); 339 } 340 return false; 341 } 342 343 344 void 345 DWARFCompileUnit::Dump(Stream *s) const 346 { 347 s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at {0x%8.8x})\n", 348 m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, GetNextCompileUnitOffset()); 349 } 350 351 352 static uint8_t g_default_addr_size = 4; 353 354 uint8_t 355 DWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu) 356 { 357 if (cu) 358 return cu->GetAddressByteSize(); 359 return DWARFCompileUnit::GetDefaultAddressSize(); 360 } 361 362 uint8_t 363 DWARFCompileUnit::GetDefaultAddressSize() 364 { 365 return g_default_addr_size; 366 } 367 368 void 369 DWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) 370 { 371 g_default_addr_size = addr_size; 372 } 373 374 void 375 DWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, 376 DWARFDebugAranges* debug_aranges, 377 bool clear_dies_if_already_not_parsed) 378 { 379 // This function is usually called if there in no .debug_aranges section 380 // in order to produce a compile unit level set of address ranges that 381 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 382 // all compile units to stay loaded when they weren't needed. So we can end 383 // up parsing the DWARF and then throwing them all away to keep memory usage 384 // down. 385 const bool clear_dies = ExtractDIEsIfNeeded (false) > 1; 386 387 DIE()->BuildAddressRangeTable(dwarf2Data, this, debug_aranges); 388 389 // Keep memory down by clearing DIEs if this generate function 390 // caused them to be parsed 391 if (clear_dies) 392 ClearDIEs (true); 393 394 } 395 396 397 const DWARFDebugAranges & 398 DWARFCompileUnit::GetFunctionAranges () 399 { 400 if (m_func_aranges_ap.get() == NULL) 401 { 402 m_func_aranges_ap.reset (new DWARFDebugAranges()); 403 LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 404 405 if (log) 406 { 407 m_dwarf2Data->LogMessage (log.get(), 408 "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]", 409 GetOffset()); 410 } 411 DIE()->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get()); 412 const bool minimize = false; 413 m_func_aranges_ap->Sort(minimize); 414 } 415 return *m_func_aranges_ap.get(); 416 } 417 418 bool 419 DWARFCompileUnit::LookupAddress 420 ( 421 const dw_addr_t address, 422 DWARFDebugInfoEntry** function_die_handle, 423 DWARFDebugInfoEntry** block_die_handle 424 ) 425 { 426 bool success = false; 427 428 if (function_die_handle != NULL && DIE()) 429 { 430 431 const DWARFDebugAranges &func_aranges = GetFunctionAranges (); 432 433 // Re-check the aranges auto pointer contents in case it was created above 434 if (!func_aranges.IsEmpty()) 435 { 436 *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address)); 437 if (*function_die_handle != NULL) 438 { 439 success = true; 440 if (block_die_handle != NULL) 441 { 442 DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild(); 443 while (child) 444 { 445 if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle)) 446 break; 447 child = child->GetSibling(); 448 } 449 } 450 } 451 } 452 } 453 return success; 454 } 455 456 //---------------------------------------------------------------------- 457 // Compare function DWARFDebugAranges::Range structures 458 //---------------------------------------------------------------------- 459 static bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) 460 { 461 return die1.GetOffset() < die2.GetOffset(); 462 } 463 464 //---------------------------------------------------------------------- 465 // GetDIEPtr() 466 // 467 // Get the DIE (Debug Information Entry) with the specified offset. 468 //---------------------------------------------------------------------- 469 DWARFDebugInfoEntry* 470 DWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset) 471 { 472 if (die_offset != DW_INVALID_OFFSET) 473 { 474 ExtractDIEsIfNeeded (false); 475 DWARFDebugInfoEntry compare_die; 476 compare_die.SetOffset(die_offset); 477 DWARFDebugInfoEntry::iterator end = m_die_array.end(); 478 DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); 479 if (pos != end) 480 { 481 if (die_offset == (*pos).GetOffset()) 482 return &(*pos); 483 } 484 } 485 return NULL; // Not found in any compile units 486 } 487 488 //---------------------------------------------------------------------- 489 // GetDIEPtrContainingOffset() 490 // 491 // Get the DIE (Debug Information Entry) that contains the specified 492 // .debug_info offset. 493 //---------------------------------------------------------------------- 494 const DWARFDebugInfoEntry* 495 DWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset) 496 { 497 if (die_offset != DW_INVALID_OFFSET) 498 { 499 ExtractDIEsIfNeeded (false); 500 DWARFDebugInfoEntry compare_die; 501 compare_die.SetOffset(die_offset); 502 DWARFDebugInfoEntry::iterator end = m_die_array.end(); 503 DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); 504 if (pos != end) 505 { 506 if (die_offset >= (*pos).GetOffset()) 507 { 508 DWARFDebugInfoEntry::iterator next = pos + 1; 509 if (next != end) 510 { 511 if (die_offset < (*next).GetOffset()) 512 return &(*pos); 513 } 514 } 515 } 516 } 517 return NULL; // Not found in any compile units 518 } 519 520 521 522 size_t 523 DWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const 524 { 525 size_t old_size = dies.Size(); 526 DWARFDebugInfoEntry::const_iterator pos; 527 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 528 for (pos = m_die_array.begin(); pos != end; ++pos) 529 { 530 if (pos->Tag() == tag) 531 dies.Append (&(*pos)); 532 } 533 534 // Return the number of DIEs added to the collection 535 return dies.Size() - old_size; 536 } 537 538 //void 539 //DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx) 540 //{ 541 // m_global_die_indexes.push_back (die_idx); 542 //} 543 // 544 // 545 //void 546 //DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die) 547 //{ 548 // // Indexes to all file level global and static variables 549 // m_global_die_indexes; 550 // 551 // if (m_die_array.empty()) 552 // return; 553 // 554 // const DWARFDebugInfoEntry* first_die = &m_die_array[0]; 555 // const DWARFDebugInfoEntry* end = first_die + m_die_array.size(); 556 // if (first_die <= die && die < end) 557 // m_global_die_indexes.push_back (die - first_die); 558 //} 559 560 561 void 562 DWARFCompileUnit::Index (const uint32_t cu_idx, 563 NameToDIE& func_basenames, 564 NameToDIE& func_fullnames, 565 NameToDIE& func_methods, 566 NameToDIE& func_selectors, 567 NameToDIE& objc_class_selectors, 568 NameToDIE& globals, 569 NameToDIE& types, 570 NameToDIE& namespaces) 571 { 572 const DataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data(); 573 574 const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); 575 576 LogSP log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS)); 577 578 if (log) 579 { 580 m_dwarf2Data->LogMessage (log.get(), 581 "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]", 582 GetOffset()); 583 } 584 585 DWARFDebugInfoEntry::const_iterator pos; 586 DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin(); 587 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 588 for (pos = begin; pos != end; ++pos) 589 { 590 const DWARFDebugInfoEntry &die = *pos; 591 592 const dw_tag_t tag = die.Tag(); 593 594 switch (tag) 595 { 596 case DW_TAG_subprogram: 597 case DW_TAG_inlined_subroutine: 598 case DW_TAG_base_type: 599 case DW_TAG_class_type: 600 case DW_TAG_constant: 601 case DW_TAG_enumeration_type: 602 case DW_TAG_string_type: 603 case DW_TAG_subroutine_type: 604 case DW_TAG_structure_type: 605 case DW_TAG_union_type: 606 case DW_TAG_typedef: 607 case DW_TAG_namespace: 608 case DW_TAG_variable: 609 case DW_TAG_unspecified_type: 610 break; 611 612 default: 613 continue; 614 } 615 616 DWARFDebugInfoEntry::Attributes attributes; 617 const char *name = NULL; 618 const char *mangled_cstr = NULL; 619 bool is_variable = false; 620 bool is_declaration = false; 621 bool is_artificial = false; 622 bool has_address = false; 623 bool has_location = false; 624 bool is_global_or_static_variable = false; 625 626 dw_offset_t specification_die_offset = DW_INVALID_OFFSET; 627 const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes); 628 if (num_attributes > 0) 629 { 630 is_variable = tag == DW_TAG_variable; 631 632 for (uint32_t i=0; i<num_attributes; ++i) 633 { 634 dw_attr_t attr = attributes.AttributeAtIndex(i); 635 DWARFFormValue form_value; 636 switch (attr) 637 { 638 case DW_AT_name: 639 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 640 name = form_value.AsCString(debug_str); 641 break; 642 643 case DW_AT_declaration: 644 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 645 is_declaration = form_value.Unsigned() != 0; 646 break; 647 648 case DW_AT_artificial: 649 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 650 is_artificial = form_value.Unsigned() != 0; 651 break; 652 653 case DW_AT_MIPS_linkage_name: 654 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 655 mangled_cstr = form_value.AsCString(debug_str); 656 break; 657 658 case DW_AT_low_pc: 659 case DW_AT_high_pc: 660 case DW_AT_ranges: 661 has_address = true; 662 break; 663 664 case DW_AT_entry_pc: 665 has_address = true; 666 break; 667 668 case DW_AT_location: 669 has_location = true; 670 if (tag == DW_TAG_variable) 671 { 672 const DWARFDebugInfoEntry* parent_die = die.GetParent(); 673 while ( parent_die != NULL ) 674 { 675 switch (parent_die->Tag()) 676 { 677 case DW_TAG_subprogram: 678 case DW_TAG_lexical_block: 679 case DW_TAG_inlined_subroutine: 680 // Even if this is a function level static, we don't add it. We could theoretically 681 // add these if we wanted to by introspecting into the DW_AT_location and seeing 682 // if the location describes a hard coded address, but we dont want the performance 683 // penalty of that right now. 684 is_global_or_static_variable = false; 685 // if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) 686 // { 687 // // If we have valid block data, then we have location expression bytes 688 // // that are fixed (not a location list). 689 // const uint8_t *block_data = form_value.BlockData(); 690 // if (block_data) 691 // { 692 // uint32_t block_length = form_value.Unsigned(); 693 // if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) 694 // { 695 // if (block_data[0] == DW_OP_addr) 696 // add_die = true; 697 // } 698 // } 699 // } 700 parent_die = NULL; // Terminate the while loop. 701 break; 702 703 case DW_TAG_compile_unit: 704 is_global_or_static_variable = true; 705 parent_die = NULL; // Terminate the while loop. 706 break; 707 708 default: 709 parent_die = parent_die->GetParent(); // Keep going in the while loop. 710 break; 711 } 712 } 713 } 714 break; 715 716 case DW_AT_specification: 717 if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 718 specification_die_offset = form_value.Reference(this); 719 break; 720 } 721 } 722 } 723 724 switch (tag) 725 { 726 case DW_TAG_subprogram: 727 if (has_address) 728 { 729 if (name) 730 { 731 // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the 732 // simple inlined check outside the call. 733 if (ObjCLanguageRuntime::IsPossibleObjCMethodName(name)) 734 { 735 ConstString objc_class_name; 736 ConstString objc_selector_name; 737 ConstString objc_fullname_no_category_name; 738 if (ObjCLanguageRuntime::ParseMethodName (name, 739 &objc_class_name, 740 &objc_selector_name, 741 &objc_fullname_no_category_name)) 742 { 743 objc_class_selectors.Insert(objc_class_name, die.GetOffset()); 744 745 func_selectors.Insert (objc_selector_name, die.GetOffset()); 746 func_fullnames.Insert (ConstString(name), die.GetOffset()); 747 if (objc_fullname_no_category_name) 748 { 749 func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset()); 750 } 751 } 752 } 753 // If we have a mangled name, then the DW_AT_name attribute 754 // is usually the method name without the class or any parameters 755 const DWARFDebugInfoEntry *parent = die.GetParent(); 756 bool is_method = false; 757 if (parent) 758 { 759 dw_tag_t parent_tag = parent->Tag(); 760 if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) 761 { 762 is_method = true; 763 } 764 else 765 { 766 if (specification_die_offset != DW_INVALID_OFFSET) 767 { 768 const DWARFDebugInfoEntry *specification_die 769 = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL); 770 if (specification_die) 771 { 772 parent = specification_die->GetParent(); 773 if (parent) 774 { 775 parent_tag = parent->Tag(); 776 777 if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) 778 is_method = true; 779 } 780 } 781 } 782 } 783 } 784 785 786 if (is_method) 787 func_methods.Insert (ConstString(name), die.GetOffset()); 788 else 789 func_basenames.Insert (ConstString(name), die.GetOffset()); 790 } 791 if (mangled_cstr) 792 { 793 // Make sure our mangled name isn't the same string table entry 794 // as our name. If it starts with '_', then it is ok, else compare 795 // the string to make sure it isn't the same and we don't end up 796 // with duplicate entries 797 if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 798 { 799 Mangled mangled (mangled_cstr, true); 800 func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); 801 if (mangled.GetDemangledName()) 802 func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset()); 803 } 804 } 805 } 806 break; 807 808 case DW_TAG_inlined_subroutine: 809 if (has_address) 810 { 811 if (name) 812 func_basenames.Insert (ConstString(name), die.GetOffset()); 813 if (mangled_cstr) 814 { 815 // Make sure our mangled name isn't the same string table entry 816 // as our name. If it starts with '_', then it is ok, else compare 817 // the string to make sure it isn't the same and we don't end up 818 // with duplicate entries 819 if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 820 { 821 Mangled mangled (mangled_cstr, true); 822 func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); 823 if (mangled.GetDemangledName()) 824 func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset()); 825 } 826 } 827 } 828 break; 829 830 case DW_TAG_base_type: 831 case DW_TAG_class_type: 832 case DW_TAG_constant: 833 case DW_TAG_enumeration_type: 834 case DW_TAG_string_type: 835 case DW_TAG_subroutine_type: 836 case DW_TAG_structure_type: 837 case DW_TAG_union_type: 838 case DW_TAG_typedef: 839 case DW_TAG_unspecified_type: 840 if (name && is_declaration == false) 841 { 842 types.Insert (ConstString(name), die.GetOffset()); 843 } 844 break; 845 846 case DW_TAG_namespace: 847 if (name) 848 namespaces.Insert (ConstString(name), die.GetOffset()); 849 break; 850 851 case DW_TAG_variable: 852 if (name && has_location && is_global_or_static_variable) 853 { 854 globals.Insert (ConstString(name), die.GetOffset()); 855 // Be sure to include variables by their mangled and demangled 856 // names if they have any since a variable can have a basename 857 // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled 858 // mangled name "(anonymous namespace)::i"... 859 860 // Make sure our mangled name isn't the same string table entry 861 // as our name. If it starts with '_', then it is ok, else compare 862 // the string to make sure it isn't the same and we don't end up 863 // with duplicate entries 864 if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 865 { 866 Mangled mangled (mangled_cstr, true); 867 globals.Insert (mangled.GetMangledName(), die.GetOffset()); 868 if (mangled.GetDemangledName()) 869 globals.Insert (mangled.GetDemangledName(), die.GetOffset()); 870 } 871 } 872 break; 873 874 default: 875 continue; 876 } 877 } 878 } 879 880 881