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 "lldb/Core/Module.h" 13 #include "lldb/Host/StringConvert.h" 14 #include "lldb/Symbol/CompileUnit.h" 15 #include "lldb/Symbol/LineTable.h" 16 #include "lldb/Symbol/ObjectFile.h" 17 #include "lldb/Utility/LLDBAssert.h" 18 #include "lldb/Utility/StreamString.h" 19 #include "lldb/Utility/Timer.h" 20 21 #include "DWARFDIECollection.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) 35 : m_dwarf(dwarf), m_cancel_scopes(false) {} 36 37 DWARFUnit::~DWARFUnit() {} 38 39 //---------------------------------------------------------------------- 40 // Parses first DIE of a compile unit. 41 //---------------------------------------------------------------------- 42 void DWARFUnit::ExtractUnitDIEIfNeeded() { 43 { 44 llvm::sys::ScopedReader lock(m_first_die_mutex); 45 if (m_first_die) 46 return; // Already parsed 47 } 48 llvm::sys::ScopedWriter lock(m_first_die_mutex); 49 if (m_first_die) 50 return; // Already parsed 51 52 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 53 Timer scoped_timer( 54 func_cat, "%8.8x: DWARFUnit::ExtractUnitDIEIfNeeded()", m_offset); 55 56 // Set the offset to that of the first DIE and calculate the start of the 57 // next compilation unit header. 58 lldb::offset_t offset = GetFirstDIEOffset(); 59 60 // We are in our compile unit, parse starting at the offset we were told to 61 // parse 62 const DWARFDataExtractor &data = GetData(); 63 DWARFFormValue::FixedFormSizes fixed_form_sizes = 64 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 65 IsDWARF64()); 66 if (offset < GetNextCompileUnitOffset() && 67 m_first_die.FastExtract(data, this, fixed_form_sizes, &offset)) { 68 AddUnitDIE(m_first_die); 69 return; 70 } 71 72 ExtractDIEsEndCheck(offset); 73 } 74 75 //---------------------------------------------------------------------- 76 // Parses a compile unit and indexes its DIEs if it hasn't already been done. 77 // It will leave this compile unit extracted forever. 78 //---------------------------------------------------------------------- 79 void DWARFUnit::ExtractDIEsIfNeeded() { 80 m_cancel_scopes = true; 81 82 { 83 llvm::sys::ScopedReader lock(m_die_array_mutex); 84 if (!m_die_array.empty()) 85 return; // Already parsed 86 } 87 llvm::sys::ScopedWriter lock(m_die_array_mutex); 88 if (!m_die_array.empty()) 89 return; // Already parsed 90 91 ExtractDIEsRWLocked(); 92 } 93 94 //---------------------------------------------------------------------- 95 // Parses a compile unit and indexes its DIEs if it hasn't already been done. 96 // It will clear this compile unit after returned instance gets out of scope, 97 // no other ScopedExtractDIEs instance is running for this compile unit 98 // and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs 99 // lifetime. 100 //---------------------------------------------------------------------- 101 DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() { 102 ScopedExtractDIEs scoped(this); 103 104 { 105 llvm::sys::ScopedReader lock(m_die_array_mutex); 106 if (!m_die_array.empty()) 107 return scoped; // Already parsed 108 } 109 llvm::sys::ScopedWriter lock(m_die_array_mutex); 110 if (!m_die_array.empty()) 111 return scoped; // Already parsed 112 113 // Otherwise m_die_array would be already populated. 114 lldbassert(!m_cancel_scopes); 115 116 ExtractDIEsRWLocked(); 117 scoped.m_clear_dies = true; 118 return scoped; 119 } 120 121 DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit *cu) : m_cu(cu) { 122 lldbassert(m_cu); 123 m_cu->m_die_array_scoped_mutex.lock_shared(); 124 } 125 126 DWARFUnit::ScopedExtractDIEs::~ScopedExtractDIEs() { 127 if (!m_cu) 128 return; 129 m_cu->m_die_array_scoped_mutex.unlock_shared(); 130 if (!m_clear_dies || m_cu->m_cancel_scopes) 131 return; 132 // Be sure no other ScopedExtractDIEs is running anymore. 133 llvm::sys::ScopedWriter lock_scoped(m_cu->m_die_array_scoped_mutex); 134 llvm::sys::ScopedWriter lock(m_cu->m_die_array_mutex); 135 if (m_cu->m_cancel_scopes) 136 return; 137 m_cu->ClearDIEsRWLocked(); 138 } 139 140 DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs) 141 : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) { 142 rhs.m_cu = nullptr; 143 } 144 145 DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=( 146 DWARFUnit::ScopedExtractDIEs &&rhs) { 147 m_cu = rhs.m_cu; 148 rhs.m_cu = nullptr; 149 m_clear_dies = rhs.m_clear_dies; 150 return *this; 151 } 152 153 //---------------------------------------------------------------------- 154 // Parses a compile unit and indexes its DIEs, m_die_array_mutex must be 155 // held R/W and m_die_array must be empty. 156 //---------------------------------------------------------------------- 157 void DWARFUnit::ExtractDIEsRWLocked() { 158 llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex); 159 160 static Timer::Category func_cat(LLVM_PRETTY_FUNCTION); 161 Timer scoped_timer( 162 func_cat, "%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", m_offset); 163 164 // Set the offset to that of the first DIE and calculate the start of the 165 // next compilation unit header. 166 lldb::offset_t offset = GetFirstDIEOffset(); 167 lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); 168 169 DWARFDebugInfoEntry die; 170 // Keep a flat array of the DIE for binary lookup by DIE offset 171 Log *log( 172 LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); 173 if (log) { 174 m_dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( 175 log, 176 "DWARFUnit::ExtractDIEsIfNeeded () for compile unit at " 177 ".debug_info[0x%8.8x]", 178 GetOffset()); 179 } 180 181 uint32_t depth = 0; 182 // We are in our compile unit, parse starting at the offset we were told to 183 // parse 184 const DWARFDataExtractor &data = GetData(); 185 std::vector<uint32_t> die_index_stack; 186 die_index_stack.reserve(32); 187 die_index_stack.push_back(0); 188 bool prev_die_had_children = false; 189 DWARFFormValue::FixedFormSizes fixed_form_sizes = 190 DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 191 IsDWARF64()); 192 while (offset < next_cu_offset && 193 die.FastExtract(data, this, fixed_form_sizes, &offset)) { 194 // if (log) 195 // log->Printf("0x%8.8x: %*.*s%s%s", 196 // die.GetOffset(), 197 // depth * 2, depth * 2, "", 198 // DW_TAG_value_to_name (die.Tag()), 199 // die.HasChildren() ? " *" : ""); 200 201 const bool null_die = die.IsNULL(); 202 if (depth == 0) { 203 assert(m_die_array.empty() && "Compile unit DIE already added"); 204 205 // The average bytes per DIE entry has been seen to be around 14-20 so 206 // lets pre-reserve half of that since we are now stripping the NULL 207 // tags. 208 209 // Only reserve the memory if we are adding children of the main 210 // compile unit DIE. The compile unit DIE is always the first entry, so 211 // if our size is 1, then we are adding the first compile unit child 212 // DIE and should reserve the memory. 213 m_die_array.reserve(GetDebugInfoSize() / 24); 214 m_die_array.push_back(die); 215 216 if (!m_first_die) 217 AddUnitDIE(m_die_array.front()); 218 } else { 219 if (null_die) { 220 if (prev_die_had_children) { 221 // This will only happen if a DIE says is has children but all it 222 // contains is a NULL tag. Since we are removing the NULL DIEs from 223 // the list (saves up to 25% in C++ code), we need a way to let the 224 // DIE know that it actually doesn't have children. 225 if (!m_die_array.empty()) 226 m_die_array.back().SetHasChildren(false); 227 } 228 } else { 229 die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); 230 231 if (die_index_stack.back()) 232 m_die_array[die_index_stack.back()].SetSiblingIndex( 233 m_die_array.size() - die_index_stack.back()); 234 235 // Only push the DIE if it isn't a NULL DIE 236 m_die_array.push_back(die); 237 } 238 } 239 240 if (null_die) { 241 // NULL DIE. 242 if (!die_index_stack.empty()) 243 die_index_stack.pop_back(); 244 245 if (depth > 0) 246 --depth; 247 if (depth == 0) 248 break; // We are done with this compile unit! 249 250 prev_die_had_children = false; 251 } else { 252 die_index_stack.back() = m_die_array.size() - 1; 253 // Normal DIE 254 const bool die_has_children = die.HasChildren(); 255 if (die_has_children) { 256 die_index_stack.push_back(0); 257 ++depth; 258 } 259 prev_die_had_children = die_has_children; 260 } 261 } 262 263 if (!m_die_array.empty()) { 264 if (m_first_die) { 265 // Only needed for the assertion. 266 m_first_die.SetHasChildren(m_die_array.front().HasChildren()); 267 lldbassert(m_first_die == m_die_array.front()); 268 } 269 m_first_die = m_die_array.front(); 270 } 271 272 m_die_array.shrink_to_fit(); 273 274 ExtractDIEsEndCheck(offset); 275 276 if (m_dwo_symbol_file) { 277 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 278 dwo_cu->ExtractDIEsIfNeeded(); 279 } 280 } 281 282 //-------------------------------------------------------------------------- 283 // Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded(). 284 //-------------------------------------------------------------------------- 285 void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { 286 // Give a little bit of info if we encounter corrupt DWARF (our offset should 287 // always terminate at or before the start of the next compilation unit 288 // header). 289 if (offset > GetNextCompileUnitOffset()) { 290 m_dwarf->GetObjectFile()->GetModule()->ReportWarning( 291 "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " 292 "0x%8.8" PRIx64 "\n", 293 GetOffset(), offset); 294 } 295 296 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 297 if (log && log->GetVerbose()) { 298 StreamString strm; 299 Dump(&strm); 300 if (m_die_array.empty()) 301 strm.Printf("error: no DIE for compile unit"); 302 else 303 m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); 304 log->PutString(strm.GetString()); 305 } 306 } 307 308 // m_die_array_mutex must be already held as read/write. 309 void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { 310 SetAddrBase( 311 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_addr_base, 0)); 312 SetRangesBase(cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, 313 DW_AT_rnglists_base, 0)); 314 315 uint64_t base_addr = cu_die.GetAttributeValueAsAddress( 316 m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 317 if (base_addr == LLDB_INVALID_ADDRESS) 318 base_addr = cu_die.GetAttributeValueAsAddress( 319 m_dwarf, this, DW_AT_entry_pc, 0); 320 SetBaseAddress(base_addr); 321 322 std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 323 m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); 324 if (!dwo_symbol_file) 325 return; 326 327 DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 328 if (!dwo_cu) 329 return; // Can't fetch the compile unit from the dwo file. 330 331 DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 332 if (!dwo_cu_die.IsValid()) 333 return; // Can't fetch the compile unit DIE from the dwo file. 334 335 uint64_t main_dwo_id = 336 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0); 337 uint64_t sub_dwo_id = 338 dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); 339 if (main_dwo_id != sub_dwo_id) 340 return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to 341 // a differectn compilation. 342 343 m_dwo_symbol_file = std::move(dwo_symbol_file); 344 345 dw_addr_t addr_base = 346 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0); 347 dwo_cu->SetAddrBase(addr_base); 348 349 dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( 350 m_dwarf, this, DW_AT_GNU_ranges_base, 0); 351 dwo_cu->SetRangesBase(ranges_base); 352 353 dwo_cu->SetBaseObjOffset(m_offset); 354 } 355 356 DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { 357 if (DIE()) { 358 const DWARFDebugAranges &func_aranges = GetFunctionAranges(); 359 360 // Re-check the aranges auto pointer contents in case it was created above 361 if (!func_aranges.IsEmpty()) 362 return GetDIE(func_aranges.FindAddress(address)); 363 } 364 return DWARFDIE(); 365 } 366 367 size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, 368 DWARFDIECollection &dies, 369 uint32_t depth) const { 370 size_t old_size = dies.Size(); 371 { 372 llvm::sys::ScopedReader lock(m_die_array_mutex); 373 DWARFDebugInfoEntry::const_iterator pos; 374 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 375 for (pos = m_die_array.begin(); pos != end; ++pos) { 376 if (pos->Tag() == tag) 377 dies.Append(DWARFDIE(this, &(*pos))); 378 } 379 } 380 381 // Return the number of DIEs added to the collection 382 return dies.Size() - old_size; 383 } 384 385 386 lldb::user_id_t DWARFUnit::GetID() const { 387 dw_offset_t local_id = 388 m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; 389 if (m_dwarf) 390 return DIERef(local_id, local_id).GetUID(m_dwarf); 391 else 392 return local_id; 393 } 394 395 dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { 396 return m_offset + GetLengthByteSize() + GetLength(); 397 } 398 399 size_t DWARFUnit::GetDebugInfoSize() const { 400 return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 401 } 402 403 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 404 return m_abbrevs; 405 } 406 407 dw_offset_t DWARFUnit::GetAbbrevOffset() const { 408 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 409 } 410 411 void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; } 412 413 void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { 414 m_ranges_base = ranges_base; 415 } 416 417 void DWARFUnit::SetBaseObjOffset(dw_offset_t base_obj_offset) { 418 m_base_obj_offset = base_obj_offset; 419 } 420 421 // It may be called only with m_die_array_mutex held R/W. 422 void DWARFUnit::ClearDIEsRWLocked() { 423 m_die_array.clear(); 424 m_die_array.shrink_to_fit(); 425 426 if (m_dwo_symbol_file) 427 m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked(); 428 } 429 430 void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, 431 DWARFDebugAranges *debug_aranges) { 432 // This function is usually called if there in no .debug_aranges section in 433 // order to produce a compile unit level set of address ranges that is 434 // accurate. 435 436 size_t num_debug_aranges = debug_aranges->GetNumRanges(); 437 438 // First get the compile unit DIE only and check if it has a DW_AT_ranges 439 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 440 441 const dw_offset_t cu_offset = GetOffset(); 442 if (die) { 443 DWARFRangeList ranges; 444 const size_t num_ranges = 445 die->GetAttributeAddressRanges(dwarf, this, ranges, false); 446 if (num_ranges > 0) { 447 // This compile unit has DW_AT_ranges, assume this is correct if it is 448 // present since clang no longer makes .debug_aranges by default and it 449 // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with 450 // recent GCC builds. 451 for (size_t i = 0; i < num_ranges; ++i) { 452 const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); 453 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 454 range.GetRangeEnd()); 455 } 456 457 return; // We got all of our ranges from the DW_AT_ranges attribute 458 } 459 } 460 // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF 461 462 // If the DIEs weren't parsed, then we don't want all dies for all compile 463 // units to stay loaded when they weren't needed. So we can end up parsing 464 // the DWARF and then throwing them all away to keep memory usage down. 465 ScopedExtractDIEs clear_dies(ExtractDIEsScoped()); 466 467 die = DIEPtr(); 468 if (die) 469 die->BuildAddressRangeTable(dwarf, this, debug_aranges); 470 471 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 472 // We got nothing from the functions, maybe we have a line tables only 473 // situation. Check the line tables and build the arange table from this. 474 SymbolContext sc; 475 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 476 if (sc.comp_unit) { 477 SymbolFileDWARFDebugMap *debug_map_sym_file = 478 m_dwarf->GetDebugMapSymfile(); 479 if (debug_map_sym_file == NULL) { 480 LineTable *line_table = sc.comp_unit->GetLineTable(); 481 482 if (line_table) { 483 LineTable::FileAddressRanges file_ranges; 484 const bool append = true; 485 const size_t num_ranges = 486 line_table->GetContiguousFileAddressRanges(file_ranges, append); 487 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 488 const LineTable::FileAddressRanges::Entry &range = 489 file_ranges.GetEntryRef(idx); 490 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 491 range.GetRangeEnd()); 492 } 493 } 494 } else 495 debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges); 496 } 497 } 498 499 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 500 // We got nothing from the functions, maybe we have a line tables only 501 // situation. Check the line tables and build the arange table from this. 502 SymbolContext sc; 503 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 504 if (sc.comp_unit) { 505 LineTable *line_table = sc.comp_unit->GetLineTable(); 506 507 if (line_table) { 508 LineTable::FileAddressRanges file_ranges; 509 const bool append = true; 510 const size_t num_ranges = 511 line_table->GetContiguousFileAddressRanges(file_ranges, append); 512 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 513 const LineTable::FileAddressRanges::Entry &range = 514 file_ranges.GetEntryRef(idx); 515 debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), 516 range.GetRangeEnd()); 517 } 518 } 519 } 520 } 521 } 522 523 lldb::ByteOrder DWARFUnit::GetByteOrder() const { 524 return m_dwarf->GetObjectFile()->GetByteOrder(); 525 } 526 527 TypeSystem *DWARFUnit::GetTypeSystem() { 528 if (m_dwarf) 529 return m_dwarf->GetTypeSystemForLanguage(GetLanguageType()); 530 else 531 return nullptr; 532 } 533 534 DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { 535 return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 536 IsDWARF64()); 537 } 538 539 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 540 541 //---------------------------------------------------------------------- 542 // Compare function DWARFDebugAranges::Range structures 543 //---------------------------------------------------------------------- 544 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 545 const dw_offset_t die_offset) { 546 return die.GetOffset() < die_offset; 547 } 548 549 //---------------------------------------------------------------------- 550 // GetDIE() 551 // 552 // Get the DIE (Debug Information Entry) with the specified offset by first 553 // checking if the DIE is contained within this compile unit and grabbing the 554 // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 555 //---------------------------------------------------------------------- 556 DWARFDIE 557 DWARFUnit::GetDIE(dw_offset_t die_offset) { 558 if (die_offset != DW_INVALID_OFFSET) { 559 if (GetDwoSymbolFile()) 560 return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); 561 562 if (ContainsDIEOffset(die_offset)) { 563 ExtractDIEsIfNeeded(); 564 DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 565 DWARFDebugInfoEntry::const_iterator pos = 566 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 567 if (pos != end) { 568 if (die_offset == (*pos).GetOffset()) 569 return DWARFDIE(this, &(*pos)); 570 } 571 } else { 572 // Don't specify the compile unit offset as we don't know it because the 573 // DIE belongs to 574 // a different compile unit in the same symbol file. 575 return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset); 576 } 577 } 578 return DWARFDIE(); // Not found 579 } 580 581 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 582 if (cu) 583 return cu->GetAddressByteSize(); 584 return DWARFUnit::GetDefaultAddressSize(); 585 } 586 587 bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { 588 if (cu) 589 return cu->IsDWARF64(); 590 return false; 591 } 592 593 uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 594 595 void *DWARFUnit::GetUserData() const { return m_user_data; } 596 597 void DWARFUnit::SetUserData(void *d) { 598 m_user_data = d; 599 if (m_dwo_symbol_file) 600 m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); 601 } 602 603 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 604 if (GetProducer() == eProducerLLVMGCC) 605 return false; 606 return true; 607 } 608 609 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 610 // llvm-gcc makes completely invalid decl file attributes and won't ever be 611 // fixed, so we need to know to ignore these. 612 return GetProducer() == eProducerLLVMGCC; 613 } 614 615 bool DWARFUnit::Supports_unnamed_objc_bitfields() { 616 if (GetProducer() == eProducerClang) { 617 const uint32_t major_version = GetProducerVersionMajor(); 618 if (major_version > 425 || 619 (major_version == 425 && GetProducerVersionUpdate() >= 13)) 620 return true; 621 else 622 return false; 623 } 624 return true; // Assume all other compilers didn't have incorrect ObjC bitfield 625 // info 626 } 627 628 SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; } 629 630 void DWARFUnit::ParseProducerInfo() { 631 m_producer_version_major = UINT32_MAX; 632 m_producer_version_minor = UINT32_MAX; 633 m_producer_version_update = UINT32_MAX; 634 635 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 636 if (die) { 637 638 const char *producer_cstr = 639 die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL); 640 if (producer_cstr) { 641 RegularExpression llvm_gcc_regex( 642 llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " 643 "Inc\\. build [0-9]+\\) \\(LLVM build " 644 "[\\.0-9]+\\)$")); 645 if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) { 646 m_producer = eProducerLLVMGCC; 647 } else if (strstr(producer_cstr, "clang")) { 648 static RegularExpression g_clang_version_regex( 649 llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); 650 RegularExpression::Match regex_match(3); 651 if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), 652 ®ex_match)) { 653 std::string str; 654 if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) 655 m_producer_version_major = 656 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 657 if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) 658 m_producer_version_minor = 659 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 660 if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) 661 m_producer_version_update = 662 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 663 } 664 m_producer = eProducerClang; 665 } else if (strstr(producer_cstr, "GNU")) 666 m_producer = eProducerGCC; 667 } 668 } 669 if (m_producer == eProducerInvalid) 670 m_producer = eProcucerOther; 671 } 672 673 DWARFProducer DWARFUnit::GetProducer() { 674 if (m_producer == eProducerInvalid) 675 ParseProducerInfo(); 676 return m_producer; 677 } 678 679 uint32_t DWARFUnit::GetProducerVersionMajor() { 680 if (m_producer_version_major == 0) 681 ParseProducerInfo(); 682 return m_producer_version_major; 683 } 684 685 uint32_t DWARFUnit::GetProducerVersionMinor() { 686 if (m_producer_version_minor == 0) 687 ParseProducerInfo(); 688 return m_producer_version_minor; 689 } 690 691 uint32_t DWARFUnit::GetProducerVersionUpdate() { 692 if (m_producer_version_update == 0) 693 ParseProducerInfo(); 694 return m_producer_version_update; 695 } 696 LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { 697 // Note: user languages between lo_user and hi_user must be handled 698 // explicitly here. 699 switch (val) { 700 case DW_LANG_Mips_Assembler: 701 return eLanguageTypeMipsAssembler; 702 case DW_LANG_GOOGLE_RenderScript: 703 return eLanguageTypeExtRenderScript; 704 default: 705 return static_cast<LanguageType>(val); 706 } 707 } 708 709 LanguageType DWARFUnit::GetLanguageType() { 710 if (m_language_type != eLanguageTypeUnknown) 711 return m_language_type; 712 713 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 714 if (die) 715 m_language_type = LanguageTypeFromDWARF( 716 die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0)); 717 return m_language_type; 718 } 719 720 bool DWARFUnit::GetIsOptimized() { 721 if (m_is_optimized == eLazyBoolCalculate) { 722 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 723 if (die) { 724 m_is_optimized = eLazyBoolNo; 725 if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized, 726 0) == 1) { 727 m_is_optimized = eLazyBoolYes; 728 } 729 } 730 } 731 return m_is_optimized == eLazyBoolYes; 732 } 733 734 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { 735 return m_dwo_symbol_file.get(); 736 } 737 738 dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } 739 740 const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 741 if (m_func_aranges_ap.get() == NULL) { 742 m_func_aranges_ap.reset(new DWARFDebugAranges()); 743 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 744 745 if (log) { 746 m_dwarf->GetObjectFile()->GetModule()->LogMessage( 747 log, 748 "DWARFUnit::GetFunctionAranges() for compile unit at " 749 ".debug_info[0x%8.8x]", 750 GetOffset()); 751 } 752 const DWARFDebugInfoEntry *die = DIEPtr(); 753 if (die) 754 die->BuildFunctionAddressRangeTable(m_dwarf, this, 755 m_func_aranges_ap.get()); 756 757 if (m_dwo_symbol_file) { 758 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 759 const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); 760 if (dwo_die) 761 dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, 762 m_func_aranges_ap.get()); 763 } 764 765 const bool minimize = false; 766 m_func_aranges_ap->Sort(minimize); 767 } 768 return *m_func_aranges_ap.get(); 769 } 770 771