1 //===-- DWARFUnit.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 "DWARFUnit.h" 11 12 #include "Plugins/Language/ObjC/ObjCLanguage.h" 13 #include "lldb/Core/Module.h" 14 #include "lldb/Host/StringConvert.h" 15 #include "lldb/Symbol/CompileUnit.h" 16 #include "lldb/Symbol/LineTable.h" 17 #include "lldb/Symbol/ObjectFile.h" 18 #include "lldb/Utility/Timer.h" 19 20 #include "DWARFDIECollection.h" 21 #include "DWARFDebugAbbrev.h" 22 #include "DWARFDebugAranges.h" 23 #include "DWARFDebugInfo.h" 24 #include "LogChannelDWARF.h" 25 #include "NameToDIE.h" 26 #include "SymbolFileDWARFDebugMap.h" 27 #include "SymbolFileDWARFDwo.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 using namespace std; 32 33 extern int g_verbose; 34 35 DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf) : m_dwarf(dwarf) {} 36 37 DWARFUnit::~DWARFUnit() {} 38 39 //---------------------------------------------------------------------- 40 // ParseCompileUnitDIEsIfNeeded 41 // 42 // Parses a compile unit and indexes its DIEs if it hasn't already been done. 43 //---------------------------------------------------------------------- 44 size_t DWARFUnit::ExtractDIEsIfNeeded(bool cu_die_only) { 45 const size_t initial_die_array_size = m_die_array.size(); 46 if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) 47 return 0; // Already parsed 48 49 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 50 Timer scoped_timer( 51 func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded( cu_die_only = %i )", 52 m_offset, cu_die_only); 53 54 // Set the offset to that of the first DIE and calculate the start of the 55 // next compilation unit header. 56 lldb::offset_t offset = GetFirstDIEOffset(); 57 lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); 58 59 DWARFDebugInfoEntry die; 60 // Keep a flat array of the DIE for binary lookup by DIE offset 61 if (!cu_die_only) { 62 Log *log( 63 LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); 64 if (log) { 65 m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( 66 log, 67 "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at " 68 ".debug_info[0x%8.8x]", 69 GetOffset()); 70 } 71 } 72 73 uint32_t depth = 0; 74 // We are in our compile unit, parse starting at the offset we were told to 75 // parse 76 const DWARFDataExtractor &data = GetData(); 77 std::vector<uint32_t> die_index_stack; 78 die_index_stack.reserve(32); 79 die_index_stack.push_back(0); 80 bool prev_die_had_children = false; 81 DWARFFormValue::FixedFormSizes fixed_form_sizes = 82 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 83 IsDWARF64()); 84 while (offset < next_cu_offset && 85 die.FastExtract(data, this, fixed_form_sizes, &offset)) { 86 // if (log) 87 // log->Printf("0x%8.8x: %*.*s%s%s", 88 // die.GetOffset(), 89 // depth * 2, depth * 2, "", 90 // DW_TAG_value_to_name (die.Tag()), 91 // die.HasChildren() ? " *" : ""); 92 93 const bool null_die = die.IsNULL(); 94 if (depth == 0) { 95 if (initial_die_array_size == 0) 96 AddUnitDIE(die); 97 uint64_t base_addr = die.GetAttributeValueAsAddress( 98 m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 99 if (base_addr == LLDB_INVALID_ADDRESS) 100 base_addr = 101 die.GetAttributeValueAsAddress(m_dwarf, this, DW_AT_entry_pc, 0); 102 SetBaseAddress(base_addr); 103 if (cu_die_only) 104 return 1; 105 } else { 106 if (null_die) { 107 if (prev_die_had_children) { 108 // This will only happen if a DIE says is has children but all it 109 // contains is a NULL tag. Since we are removing the NULL DIEs from 110 // the list (saves up to 25% in C++ code), we need a way to let the 111 // DIE know that it actually doesn't have children. 112 if (!m_die_array.empty()) 113 m_die_array.back().SetEmptyChildren(true); 114 } 115 } else { 116 die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); 117 118 if (die_index_stack.back()) 119 m_die_array[die_index_stack.back()].SetSiblingIndex( 120 m_die_array.size() - die_index_stack.back()); 121 122 // Only push the DIE if it isn't a NULL DIE 123 m_die_array.push_back(die); 124 } 125 } 126 127 if (null_die) { 128 // NULL DIE. 129 if (!die_index_stack.empty()) 130 die_index_stack.pop_back(); 131 132 if (depth > 0) 133 --depth; 134 if (depth == 0) 135 break; // We are done with this compile unit! 136 137 prev_die_had_children = false; 138 } else { 139 die_index_stack.back() = m_die_array.size() - 1; 140 // Normal DIE 141 const bool die_has_children = die.HasChildren(); 142 if (die_has_children) { 143 die_index_stack.push_back(0); 144 ++depth; 145 } 146 prev_die_had_children = die_has_children; 147 } 148 } 149 150 // Give a little bit of info if we encounter corrupt DWARF (our offset should 151 // always terminate at or before the start of the next compilation unit 152 // header). 153 if (offset > next_cu_offset) { 154 m_dwarf->GetObjectFile()->GetModule()->ReportWarning( 155 "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " 156 "0x%8.8" PRIx64 "\n", 157 GetOffset(), offset); 158 } 159 160 // Since std::vector objects will double their size, we really need to make a 161 // new array with the perfect size so we don't end up wasting space. So here 162 // we copy and swap to make sure we don't have any extra memory taken up. 163 164 if (m_die_array.size() < m_die_array.capacity()) { 165 DWARFDebugInfoEntry::collection exact_size_die_array(m_die_array.begin(), 166 m_die_array.end()); 167 exact_size_die_array.swap(m_die_array); 168 } 169 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 170 if (log && log->GetVerbose()) { 171 StreamString strm; 172 Dump(&strm); 173 if (m_die_array.empty()) 174 strm.Printf("error: no DIE for compile unit"); 175 else 176 m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); 177 log->PutString(strm.GetString()); 178 } 179 180 if (!m_dwo_symbol_file) 181 return m_die_array.size(); 182 183 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 184 size_t dwo_die_count = dwo_cu->ExtractDIEsIfNeeded(cu_die_only); 185 return m_die_array.size() + dwo_die_count - 186 1; // We have 2 CU die, but we want to count it only as one 187 } 188 189 void DWARFUnit::AddUnitDIE(DWARFDebugInfoEntry &die) { 190 assert(m_die_array.empty() && "Compile unit DIE already added"); 191 192 // The average bytes per DIE entry has been seen to be around 14-20 so lets 193 // pre-reserve half of that since we are now stripping the NULL tags. 194 195 // Only reserve the memory if we are adding children of the main compile unit 196 // DIE. The compile unit DIE is always the first entry, so if our size is 1, 197 // then we are adding the first compile unit child DIE and should reserve the 198 // memory. 199 m_die_array.reserve(GetDebugInfoSize() / 24); 200 m_die_array.push_back(die); 201 202 const DWARFDebugInfoEntry &cu_die = m_die_array.front(); 203 std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 204 m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); 205 if (!dwo_symbol_file) 206 return; 207 208 DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 209 if (!dwo_cu) 210 return; // Can't fetch the compile unit from the dwo file. 211 212 DWARFDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 213 if (!dwo_cu_die.IsValid()) 214 return; // Can't fetch the compile unit DIE from the dwo file. 215 216 uint64_t main_dwo_id = 217 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0); 218 uint64_t sub_dwo_id = 219 dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); 220 if (main_dwo_id != sub_dwo_id) 221 return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to 222 // a differectn compilation. 223 224 m_dwo_symbol_file = std::move(dwo_symbol_file); 225 226 dw_addr_t addr_base = 227 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0); 228 dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( 229 m_dwarf, this, DW_AT_GNU_ranges_base, 0); 230 dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset); 231 } 232 233 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { 234 if (DIE()) { 235 const DWARFDebugAranges &func_aranges = GetFunctionAranges(); 236 237 // Re-check the aranges auto pointer contents in case it was created above 238 if (!func_aranges.IsEmpty()) 239 return GetDIE(func_aranges.FindAddress(address)); 240 } 241 return DWARFDIE(); 242 } 243 244 size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, 245 DWARFDIECollection &dies, 246 uint32_t depth) const { 247 size_t old_size = dies.Size(); 248 DWARFDebugInfoEntry::const_iterator pos; 249 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 250 for (pos = m_die_array.begin(); pos != end; ++pos) { 251 if (pos->Tag() == tag) 252 dies.Append(DWARFDIE(this, &(*pos))); 253 } 254 255 // Return the number of DIEs added to the collection 256 return dies.Size() - old_size; 257 } 258 259 260 lldb::user_id_t DWARFUnit::GetID() const { 261 dw_offset_t local_id = 262 m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; 263 if (m_dwarf) 264 return DIERef(local_id, local_id).GetUID(m_dwarf); 265 else 266 return local_id; 267 } 268 269 dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { 270 return m_offset + GetLengthByteSize() + GetLength(); 271 } 272 273 size_t DWARFUnit::GetDebugInfoSize() const { 274 return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 275 } 276 277 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 278 return m_abbrevs; 279 } 280 281 dw_offset_t DWARFUnit::GetAbbrevOffset() const { 282 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 283 } 284 285 void DWARFUnit::SetAddrBase(dw_addr_t addr_base, 286 dw_addr_t ranges_base, 287 dw_offset_t base_obj_offset) { 288 m_addr_base = addr_base; 289 m_ranges_base = ranges_base; 290 m_base_obj_offset = base_obj_offset; 291 } 292 293 void DWARFUnit::ClearDIEs(bool keep_compile_unit_die) { 294 if (m_die_array.size() > 1) { 295 // std::vectors never get any smaller when resized to a smaller size, or 296 // when clear() or erase() are called, the size will report that it is 297 // smaller, but the memory allocated remains intact (call capacity() to see 298 // this). So we need to create a temporary vector and swap the contents 299 // which will cause just the internal pointers to be swapped so that when 300 // "tmp_array" goes out of scope, it will destroy the contents. 301 302 // Save at least the compile unit DIE 303 DWARFDebugInfoEntry::collection tmp_array; 304 m_die_array.swap(tmp_array); 305 if (keep_compile_unit_die) 306 m_die_array.push_back(tmp_array.front()); 307 } 308 309 if (m_dwo_symbol_file) 310 m_dwo_symbol_file->GetCompileUnit()->ClearDIEs(keep_compile_unit_die); 311 } 312 313 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, 314 DWARFDebugAranges *debug_aranges) { 315 // This function is usually called if there in no .debug_aranges section in 316 // order to produce a compile unit level set of address ranges that is 317 // accurate. 318 319 size_t num_debug_aranges = debug_aranges->GetNumRanges(); 320 321 // First get the compile unit DIE only and check if it has a DW_AT_ranges 322 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 323 324 const dw_offset_t cu_offset = GetOffset(); 325 if (die) { 326 DWARFRangeList ranges; 327 const size_t num_ranges = 328 die->GetAttributeAddressRanges(dwarf, this, ranges, false); 329 if (num_ranges > 0) { 330 // This compile unit has DW_AT_ranges, assume this is correct if it is 331 // present since clang no longer makes .debug_aranges by default and it 332 // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with 333 // recent GCC builds. 334 for (size_t i = 0; i < num_ranges; ++i) { 335 const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); 336 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 337 range.GetRangeEnd()); 338 } 339 340 return; // We got all of our ranges from the DW_AT_ranges attribute 341 } 342 } 343 // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF 344 345 // If the DIEs weren't parsed, then we don't want all dies for all compile 346 // units to stay loaded when they weren't needed. So we can end up parsing 347 // the DWARF and then throwing them all away to keep memory usage down. 348 const bool clear_dies = ExtractDIEsIfNeeded(false) > 1; 349 350 die = DIEPtr(); 351 if (die) 352 die->BuildAddressRangeTable(dwarf, this, debug_aranges); 353 354 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 355 // We got nothing from the functions, maybe we have a line tables only 356 // situation. Check the line tables and build the arange table from this. 357 SymbolContext sc; 358 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 359 if (sc.comp_unit) { 360 SymbolFileDWARFDebugMap *debug_map_sym_file = 361 m_dwarf->GetDebugMapSymfile(); 362 if (debug_map_sym_file == NULL) { 363 LineTable *line_table = sc.comp_unit->GetLineTable(); 364 365 if (line_table) { 366 LineTable::FileAddressRanges file_ranges; 367 const bool append = true; 368 const size_t num_ranges = 369 line_table->GetContiguousFileAddressRanges(file_ranges, append); 370 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 371 const LineTable::FileAddressRanges::Entry &range = 372 file_ranges.GetEntryRef(idx); 373 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 374 range.GetRangeEnd()); 375 } 376 } 377 } else 378 debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges); 379 } 380 } 381 382 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 383 // We got nothing from the functions, maybe we have a line tables only 384 // situation. Check the line tables and build the arange table from this. 385 SymbolContext sc; 386 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 387 if (sc.comp_unit) { 388 LineTable *line_table = sc.comp_unit->GetLineTable(); 389 390 if (line_table) { 391 LineTable::FileAddressRanges file_ranges; 392 const bool append = true; 393 const size_t num_ranges = 394 line_table->GetContiguousFileAddressRanges(file_ranges, append); 395 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 396 const LineTable::FileAddressRanges::Entry &range = 397 file_ranges.GetEntryRef(idx); 398 debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), 399 range.GetRangeEnd()); 400 } 401 } 402 } 403 } 404 405 // Keep memory down by clearing DIEs if this generate function caused them to 406 // be parsed 407 if (clear_dies) 408 ClearDIEs(true); 409 } 410 411 lldb::ByteOrder DWARFUnit::GetByteOrder() const { 412 return m_dwarf->GetObjectFile()->GetByteOrder(); 413 } 414 415 TypeSystem *DWARFUnit::GetTypeSystem() { 416 if (m_dwarf) 417 return m_dwarf->GetTypeSystemForLanguage(GetLanguageType()); 418 else 419 return nullptr; 420 } 421 422 DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { 423 return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 424 IsDWARF64()); 425 } 426 427 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 428 429 bool DWARFUnit::HasDIEsParsed() const { return m_die_array.size() > 1; } 430 431 //---------------------------------------------------------------------- 432 // Compare function DWARFDebugAranges::Range structures 433 //---------------------------------------------------------------------- 434 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 435 const dw_offset_t die_offset) { 436 return die.GetOffset() < die_offset; 437 } 438 439 //---------------------------------------------------------------------- 440 // GetDIE() 441 // 442 // Get the DIE (Debug Information Entry) with the specified offset by first 443 // checking if the DIE is contained within this compile unit and grabbing the 444 // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 445 //---------------------------------------------------------------------- 446 DWARFDIE 447 DWARFUnit::GetDIE(dw_offset_t die_offset) { 448 if (die_offset != DW_INVALID_OFFSET) { 449 if (GetDwoSymbolFile()) 450 return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); 451 452 if (ContainsDIEOffset(die_offset)) { 453 ExtractDIEsIfNeeded(false); 454 DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 455 DWARFDebugInfoEntry::const_iterator pos = 456 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 457 if (pos != end) { 458 if (die_offset == (*pos).GetOffset()) 459 return DWARFDIE(this, &(*pos)); 460 } 461 } else { 462 // Don't specify the compile unit offset as we don't know it because the 463 // DIE belongs to 464 // a different compile unit in the same symbol file. 465 return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset); 466 } 467 } 468 return DWARFDIE(); // Not found 469 } 470 471 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 472 if (cu) 473 return cu->GetAddressByteSize(); 474 return DWARFUnit::GetDefaultAddressSize(); 475 } 476 477 bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { 478 if (cu) 479 return cu->IsDWARF64(); 480 return false; 481 } 482 483 uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 484 485 void *DWARFUnit::GetUserData() const { return m_user_data; } 486 487 void DWARFUnit::SetUserData(void *d) { 488 m_user_data = d; 489 if (m_dwo_symbol_file) 490 m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); 491 } 492 493 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 494 if (GetProducer() == eProducerLLVMGCC) 495 return false; 496 return true; 497 } 498 499 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 500 // llvm-gcc makes completely invalid decl file attributes and won't ever be 501 // fixed, so we need to know to ignore these. 502 return GetProducer() == eProducerLLVMGCC; 503 } 504 505 bool DWARFUnit::Supports_unnamed_objc_bitfields() { 506 if (GetProducer() == eProducerClang) { 507 const uint32_t major_version = GetProducerVersionMajor(); 508 if (major_version > 425 || 509 (major_version == 425 && GetProducerVersionUpdate() >= 13)) 510 return true; 511 else 512 return false; 513 } 514 return true; // Assume all other compilers didn't have incorrect ObjC bitfield 515 // info 516 } 517 518 SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; } 519 520 void DWARFUnit::ParseProducerInfo() { 521 m_producer_version_major = UINT32_MAX; 522 m_producer_version_minor = UINT32_MAX; 523 m_producer_version_update = UINT32_MAX; 524 525 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 526 if (die) { 527 528 const char *producer_cstr = 529 die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL); 530 if (producer_cstr) { 531 RegularExpression llvm_gcc_regex( 532 llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " 533 "Inc\\. build [0-9]+\\) \\(LLVM build " 534 "[\\.0-9]+\\)$")); 535 if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) { 536 m_producer = eProducerLLVMGCC; 537 } else if (strstr(producer_cstr, "clang")) { 538 static RegularExpression g_clang_version_regex( 539 llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); 540 RegularExpression::Match regex_match(3); 541 if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), 542 ®ex_match)) { 543 std::string str; 544 if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) 545 m_producer_version_major = 546 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 547 if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) 548 m_producer_version_minor = 549 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 550 if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) 551 m_producer_version_update = 552 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 553 } 554 m_producer = eProducerClang; 555 } else if (strstr(producer_cstr, "GNU")) 556 m_producer = eProducerGCC; 557 } 558 } 559 if (m_producer == eProducerInvalid) 560 m_producer = eProcucerOther; 561 } 562 563 DWARFProducer DWARFUnit::GetProducer() { 564 if (m_producer == eProducerInvalid) 565 ParseProducerInfo(); 566 return m_producer; 567 } 568 569 uint32_t DWARFUnit::GetProducerVersionMajor() { 570 if (m_producer_version_major == 0) 571 ParseProducerInfo(); 572 return m_producer_version_major; 573 } 574 575 uint32_t DWARFUnit::GetProducerVersionMinor() { 576 if (m_producer_version_minor == 0) 577 ParseProducerInfo(); 578 return m_producer_version_minor; 579 } 580 581 uint32_t DWARFUnit::GetProducerVersionUpdate() { 582 if (m_producer_version_update == 0) 583 ParseProducerInfo(); 584 return m_producer_version_update; 585 } 586 LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { 587 // Note: user languages between lo_user and hi_user must be handled 588 // explicitly here. 589 switch (val) { 590 case DW_LANG_Mips_Assembler: 591 return eLanguageTypeMipsAssembler; 592 case DW_LANG_GOOGLE_RenderScript: 593 return eLanguageTypeExtRenderScript; 594 default: 595 return static_cast<LanguageType>(val); 596 } 597 } 598 599 LanguageType DWARFUnit::GetLanguageType() { 600 if (m_language_type != eLanguageTypeUnknown) 601 return m_language_type; 602 603 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 604 if (die) 605 m_language_type = LanguageTypeFromDWARF( 606 die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0)); 607 return m_language_type; 608 } 609 610 bool DWARFUnit::GetIsOptimized() { 611 if (m_is_optimized == eLazyBoolCalculate) { 612 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 613 if (die) { 614 m_is_optimized = eLazyBoolNo; 615 if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized, 616 0) == 1) { 617 m_is_optimized = eLazyBoolYes; 618 } 619 } 620 } 621 return m_is_optimized == eLazyBoolYes; 622 } 623 624 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { 625 return m_dwo_symbol_file.get(); 626 } 627 628 dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } 629 630 void DWARFUnit::Index(NameToDIE &func_basenames, NameToDIE &func_fullnames, 631 NameToDIE &func_methods, NameToDIE &func_selectors, 632 NameToDIE &objc_class_selectors, NameToDIE &globals, 633 NameToDIE &types, NameToDIE &namespaces) { 634 assert(!m_dwarf->GetBaseCompileUnit() && 635 "DWARFUnit associated with .dwo or .dwp " 636 "should not be indexed directly"); 637 638 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS)); 639 640 if (log) { 641 m_dwarf->GetObjectFile()->GetModule()->LogMessage( 642 log, "DWARFUnit::Index() for compile unit at .debug_info[0x%8.8x]", 643 GetOffset()); 644 } 645 646 const LanguageType cu_language = GetLanguageType(); 647 DWARFFormValue::FixedFormSizes fixed_form_sizes = 648 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 649 IsDWARF64()); 650 651 IndexPrivate(this, cu_language, fixed_form_sizes, GetOffset(), func_basenames, 652 func_fullnames, func_methods, func_selectors, 653 objc_class_selectors, globals, types, namespaces); 654 655 SymbolFileDWARFDwo *dwo_symbol_file = GetDwoSymbolFile(); 656 if (dwo_symbol_file) { 657 IndexPrivate( 658 dwo_symbol_file->GetCompileUnit(), cu_language, fixed_form_sizes, 659 GetOffset(), func_basenames, func_fullnames, func_methods, 660 func_selectors, objc_class_selectors, globals, types, namespaces); 661 } 662 } 663 664 void DWARFUnit::IndexPrivate( 665 DWARFUnit *dwarf_cu, const LanguageType cu_language, 666 const DWARFFormValue::FixedFormSizes &fixed_form_sizes, 667 const dw_offset_t cu_offset, NameToDIE &func_basenames, 668 NameToDIE &func_fullnames, NameToDIE &func_methods, 669 NameToDIE &func_selectors, NameToDIE &objc_class_selectors, 670 NameToDIE &globals, NameToDIE &types, NameToDIE &namespaces) { 671 DWARFDebugInfoEntry::const_iterator pos; 672 DWARFDebugInfoEntry::const_iterator begin = dwarf_cu->m_die_array.begin(); 673 DWARFDebugInfoEntry::const_iterator end = dwarf_cu->m_die_array.end(); 674 for (pos = begin; pos != end; ++pos) { 675 const DWARFDebugInfoEntry &die = *pos; 676 677 const dw_tag_t tag = die.Tag(); 678 679 switch (tag) { 680 case DW_TAG_array_type: 681 case DW_TAG_base_type: 682 case DW_TAG_class_type: 683 case DW_TAG_constant: 684 case DW_TAG_enumeration_type: 685 case DW_TAG_inlined_subroutine: 686 case DW_TAG_namespace: 687 case DW_TAG_string_type: 688 case DW_TAG_structure_type: 689 case DW_TAG_subprogram: 690 case DW_TAG_subroutine_type: 691 case DW_TAG_typedef: 692 case DW_TAG_union_type: 693 case DW_TAG_unspecified_type: 694 case DW_TAG_variable: 695 break; 696 697 default: 698 continue; 699 } 700 701 DWARFAttributes attributes; 702 const char *name = NULL; 703 const char *mangled_cstr = NULL; 704 bool is_declaration = false; 705 // bool is_artificial = false; 706 bool has_address = false; 707 bool has_location_or_const_value = false; 708 bool is_global_or_static_variable = false; 709 710 DWARFFormValue specification_die_form; 711 const size_t num_attributes = 712 die.GetAttributes(dwarf_cu, fixed_form_sizes, attributes); 713 if (num_attributes > 0) { 714 for (uint32_t i = 0; i < num_attributes; ++i) { 715 dw_attr_t attr = attributes.AttributeAtIndex(i); 716 DWARFFormValue form_value; 717 switch (attr) { 718 case DW_AT_name: 719 if (attributes.ExtractFormValueAtIndex(i, form_value)) 720 name = form_value.AsCString(); 721 break; 722 723 case DW_AT_declaration: 724 if (attributes.ExtractFormValueAtIndex(i, form_value)) 725 is_declaration = form_value.Unsigned() != 0; 726 break; 727 728 // case DW_AT_artificial: 729 // if (attributes.ExtractFormValueAtIndex(i, 730 // form_value)) 731 // is_artificial = form_value.Unsigned() != 0; 732 // break; 733 734 case DW_AT_MIPS_linkage_name: 735 case DW_AT_linkage_name: 736 if (attributes.ExtractFormValueAtIndex(i, form_value)) 737 mangled_cstr = form_value.AsCString(); 738 break; 739 740 case DW_AT_low_pc: 741 case DW_AT_high_pc: 742 case DW_AT_ranges: 743 has_address = true; 744 break; 745 746 case DW_AT_entry_pc: 747 has_address = true; 748 break; 749 750 case DW_AT_location: 751 case DW_AT_const_value: 752 has_location_or_const_value = true; 753 if (tag == DW_TAG_variable) { 754 const DWARFDebugInfoEntry *parent_die = die.GetParent(); 755 while (parent_die != NULL) { 756 switch (parent_die->Tag()) { 757 case DW_TAG_subprogram: 758 case DW_TAG_lexical_block: 759 case DW_TAG_inlined_subroutine: 760 // Even if this is a function level static, we don't add it. We 761 // could theoretically add these if we wanted to by 762 // introspecting into the DW_AT_location and seeing if the 763 // location describes a hard coded address, but we don't want 764 // the performance penalty of that right now. 765 is_global_or_static_variable = false; 766 // if (attributes.ExtractFormValueAtIndex(dwarf, i, 767 // form_value)) { 768 // // If we have valid block data, then we have location 769 // // expression bytesthat are fixed (not a location list). 770 // const uint8_t *block_data = form_value.BlockData(); 771 // if (block_data) { 772 // uint32_t block_length = form_value.Unsigned(); 773 // if (block_length == 1 + 774 // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) { 775 // if (block_data[0] == DW_OP_addr) 776 // add_die = true; 777 // } 778 // } 779 // } 780 parent_die = NULL; // Terminate the while loop. 781 break; 782 783 case DW_TAG_compile_unit: 784 case DW_TAG_partial_unit: 785 is_global_or_static_variable = true; 786 parent_die = NULL; // Terminate the while loop. 787 break; 788 789 default: 790 parent_die = 791 parent_die->GetParent(); // Keep going in the while loop. 792 break; 793 } 794 } 795 } 796 break; 797 798 case DW_AT_specification: 799 if (attributes.ExtractFormValueAtIndex(i, form_value)) 800 specification_die_form = form_value; 801 break; 802 } 803 } 804 } 805 806 switch (tag) { 807 case DW_TAG_subprogram: 808 if (has_address) { 809 if (name) { 810 ObjCLanguage::MethodName objc_method(name, true); 811 if (objc_method.IsValid(true)) { 812 ConstString objc_class_name_with_category( 813 objc_method.GetClassNameWithCategory()); 814 ConstString objc_selector_name(objc_method.GetSelector()); 815 ConstString objc_fullname_no_category_name( 816 objc_method.GetFullNameWithoutCategory(true)); 817 ConstString objc_class_name_no_category(objc_method.GetClassName()); 818 func_fullnames.Insert(ConstString(name), 819 DIERef(cu_offset, die.GetOffset())); 820 if (objc_class_name_with_category) 821 objc_class_selectors.Insert(objc_class_name_with_category, 822 DIERef(cu_offset, die.GetOffset())); 823 if (objc_class_name_no_category && 824 objc_class_name_no_category != objc_class_name_with_category) 825 objc_class_selectors.Insert(objc_class_name_no_category, 826 DIERef(cu_offset, die.GetOffset())); 827 if (objc_selector_name) 828 func_selectors.Insert(objc_selector_name, 829 DIERef(cu_offset, die.GetOffset())); 830 if (objc_fullname_no_category_name) 831 func_fullnames.Insert(objc_fullname_no_category_name, 832 DIERef(cu_offset, die.GetOffset())); 833 } 834 // If we have a mangled name, then the DW_AT_name attribute is 835 // usually the method name without the class or any parameters 836 const DWARFDebugInfoEntry *parent = die.GetParent(); 837 bool is_method = false; 838 if (parent) { 839 dw_tag_t parent_tag = parent->Tag(); 840 if (parent_tag == DW_TAG_class_type || 841 parent_tag == DW_TAG_structure_type) { 842 is_method = true; 843 } else { 844 if (specification_die_form.IsValid()) { 845 DWARFDIE specification_die = 846 dwarf_cu->GetSymbolFileDWARF()->DebugInfo()->GetDIE( 847 DIERef(specification_die_form)); 848 if (specification_die.GetParent().IsStructOrClass()) 849 is_method = true; 850 } 851 } 852 } 853 854 if (is_method) 855 func_methods.Insert(ConstString(name), 856 DIERef(cu_offset, die.GetOffset())); 857 else 858 func_basenames.Insert(ConstString(name), 859 DIERef(cu_offset, die.GetOffset())); 860 861 if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) 862 func_fullnames.Insert(ConstString(name), 863 DIERef(cu_offset, die.GetOffset())); 864 } 865 if (mangled_cstr) { 866 // Make sure our mangled name isn't the same string table entry as 867 // our name. If it starts with '_', then it is ok, else compare the 868 // string to make sure it isn't the same and we don't end up with 869 // duplicate entries 870 if (name && name != mangled_cstr && 871 ((mangled_cstr[0] == '_') || 872 (::strcmp(name, mangled_cstr) != 0))) { 873 func_fullnames.Insert(ConstString(mangled_cstr), 874 DIERef(cu_offset, die.GetOffset())); 875 } 876 } 877 } 878 break; 879 880 case DW_TAG_inlined_subroutine: 881 if (has_address) { 882 if (name) 883 func_basenames.Insert(ConstString(name), 884 DIERef(cu_offset, die.GetOffset())); 885 if (mangled_cstr) { 886 // Make sure our mangled name isn't the same string table entry as 887 // our name. If it starts with '_', then it is ok, else compare the 888 // string to make sure it isn't the same and we don't end up with 889 // duplicate entries 890 if (name && name != mangled_cstr && 891 ((mangled_cstr[0] == '_') || 892 (::strcmp(name, mangled_cstr) != 0))) { 893 func_fullnames.Insert(ConstString(mangled_cstr), 894 DIERef(cu_offset, die.GetOffset())); 895 } 896 } else 897 func_fullnames.Insert(ConstString(name), 898 DIERef(cu_offset, die.GetOffset())); 899 } 900 break; 901 902 case DW_TAG_array_type: 903 case DW_TAG_base_type: 904 case DW_TAG_class_type: 905 case DW_TAG_constant: 906 case DW_TAG_enumeration_type: 907 case DW_TAG_string_type: 908 case DW_TAG_structure_type: 909 case DW_TAG_subroutine_type: 910 case DW_TAG_typedef: 911 case DW_TAG_union_type: 912 case DW_TAG_unspecified_type: 913 if (name && !is_declaration) 914 types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); 915 if (mangled_cstr && !is_declaration) 916 types.Insert(ConstString(mangled_cstr), 917 DIERef(cu_offset, die.GetOffset())); 918 break; 919 920 case DW_TAG_namespace: 921 if (name) 922 namespaces.Insert(ConstString(name), 923 DIERef(cu_offset, die.GetOffset())); 924 break; 925 926 case DW_TAG_variable: 927 if (name && has_location_or_const_value && is_global_or_static_variable) { 928 globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); 929 // Be sure to include variables by their mangled and demangled names if 930 // they have any since a variable can have a basename "i", a mangled 931 // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name 932 // "(anonymous namespace)::i"... 933 934 // Make sure our mangled name isn't the same string table entry as our 935 // name. If it starts with '_', then it is ok, else compare the string 936 // to make sure it isn't the same and we don't end up with duplicate 937 // entries 938 if (mangled_cstr && name != mangled_cstr && 939 ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { 940 Mangled mangled(ConstString(mangled_cstr), true); 941 globals.Insert(mangled.GetMangledName(), 942 DIERef(cu_offset, die.GetOffset())); 943 ConstString demangled = mangled.GetDemangledName(cu_language); 944 if (demangled) 945 globals.Insert(demangled, DIERef(cu_offset, die.GetOffset())); 946 } 947 } 948 break; 949 950 default: 951 continue; 952 } 953 } 954 } 955 956 const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 957 if (m_func_aranges_ap.get() == NULL) { 958 m_func_aranges_ap.reset(new DWARFDebugAranges()); 959 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 960 961 if (log) { 962 m_dwarf->GetObjectFile()->GetModule()->LogMessage( 963 log, 964 "DWARFUnit::GetFunctionAranges() for compile unit at " 965 ".debug_info[0x%8.8x]", 966 GetOffset()); 967 } 968 const DWARFDebugInfoEntry *die = DIEPtr(); 969 if (die) 970 die->BuildFunctionAddressRangeTable(m_dwarf, this, 971 m_func_aranges_ap.get()); 972 973 if (m_dwo_symbol_file) { 974 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 975 const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); 976 if (dwo_die) 977 dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, 978 m_func_aranges_ap.get()); 979 } 980 981 const bool minimize = false; 982 m_func_aranges_ap->Sort(minimize); 983 } 984 return *m_func_aranges_ap.get(); 985 } 986 987