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