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