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