DWARFUnit.cpp revision 336985
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 28using namespace lldb; 29using namespace lldb_private; 30using namespace std; 31 32extern int g_verbose; 33 34DWARFUnit::DWARFUnit(SymbolFileDWARF *dwarf) 35 : m_dwarf(dwarf), m_cancel_scopes(false) {} 36 37DWARFUnit::~DWARFUnit() {} 38 39//---------------------------------------------------------------------- 40// Parses first DIE of a compile unit. 41//---------------------------------------------------------------------- 42void 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//---------------------------------------------------------------------- 79void 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//---------------------------------------------------------------------- 101DWARFUnit::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 121DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit *cu) : m_cu(cu) { 122 lldbassert(m_cu); 123 m_cu->m_die_array_scoped_mutex.lock_shared(); 124} 125 126DWARFUnit::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 140DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs) 141 : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) { 142 rhs.m_cu = nullptr; 143} 144 145DWARFUnit::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//---------------------------------------------------------------------- 157void 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().SetEmptyChildren(true); 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 lldbassert(!m_first_die || m_first_die == m_die_array.front()); 265 m_first_die = m_die_array.front(); 266 } 267 268 m_die_array.shrink_to_fit(); 269 270 ExtractDIEsEndCheck(offset); 271 272 if (m_dwo_symbol_file) { 273 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 274 dwo_cu->ExtractDIEsIfNeeded(); 275 } 276} 277 278//-------------------------------------------------------------------------- 279// Final checks for both ExtractUnitDIEIfNeeded() and ExtractDIEsIfNeeded(). 280//-------------------------------------------------------------------------- 281void DWARFUnit::ExtractDIEsEndCheck(lldb::offset_t offset) const { 282 // Give a little bit of info if we encounter corrupt DWARF (our offset should 283 // always terminate at or before the start of the next compilation unit 284 // header). 285 if (offset > GetNextCompileUnitOffset()) { 286 m_dwarf->GetObjectFile()->GetModule()->ReportWarning( 287 "DWARF compile unit extends beyond its bounds cu 0x%8.8x at " 288 "0x%8.8" PRIx64 "\n", 289 GetOffset(), offset); 290 } 291 292 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_INFO)); 293 if (log && log->GetVerbose()) { 294 StreamString strm; 295 Dump(&strm); 296 if (m_die_array.empty()) 297 strm.Printf("error: no DIE for compile unit"); 298 else 299 m_die_array[0].Dump(m_dwarf, this, strm, UINT32_MAX); 300 log->PutString(strm.GetString()); 301 } 302} 303 304// m_die_array_mutex must be already held as read/write. 305void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { 306 uint64_t base_addr = cu_die.GetAttributeValueAsAddress( 307 m_dwarf, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 308 if (base_addr == LLDB_INVALID_ADDRESS) 309 base_addr = cu_die.GetAttributeValueAsAddress( 310 m_dwarf, this, DW_AT_entry_pc, 0); 311 SetBaseAddress(base_addr); 312 313 std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 314 m_dwarf->GetDwoSymbolFileForCompileUnit(*this, cu_die); 315 if (!dwo_symbol_file) 316 return; 317 318 DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); 319 if (!dwo_cu) 320 return; // Can't fetch the compile unit from the dwo file. 321 322 DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 323 if (!dwo_cu_die.IsValid()) 324 return; // Can't fetch the compile unit DIE from the dwo file. 325 326 uint64_t main_dwo_id = 327 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_dwo_id, 0); 328 uint64_t sub_dwo_id = 329 dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); 330 if (main_dwo_id != sub_dwo_id) 331 return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to 332 // a differectn compilation. 333 334 m_dwo_symbol_file = std::move(dwo_symbol_file); 335 336 dw_addr_t addr_base = 337 cu_die.GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_GNU_addr_base, 0); 338 dw_addr_t ranges_base = cu_die.GetAttributeValueAsUnsigned( 339 m_dwarf, this, DW_AT_GNU_ranges_base, 0); 340 dwo_cu->SetAddrBase(addr_base, ranges_base, m_offset); 341} 342 343DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { 344 if (DIE()) { 345 const DWARFDebugAranges &func_aranges = GetFunctionAranges(); 346 347 // Re-check the aranges auto pointer contents in case it was created above 348 if (!func_aranges.IsEmpty()) 349 return GetDIE(func_aranges.FindAddress(address)); 350 } 351 return DWARFDIE(); 352} 353 354size_t DWARFUnit::AppendDIEsWithTag(const dw_tag_t tag, 355 DWARFDIECollection &dies, 356 uint32_t depth) const { 357 size_t old_size = dies.Size(); 358 { 359 llvm::sys::ScopedReader lock(m_die_array_mutex); 360 DWARFDebugInfoEntry::const_iterator pos; 361 DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 362 for (pos = m_die_array.begin(); pos != end; ++pos) { 363 if (pos->Tag() == tag) 364 dies.Append(DWARFDIE(this, &(*pos))); 365 } 366 } 367 368 // Return the number of DIEs added to the collection 369 return dies.Size() - old_size; 370} 371 372 373lldb::user_id_t DWARFUnit::GetID() const { 374 dw_offset_t local_id = 375 m_base_obj_offset != DW_INVALID_OFFSET ? m_base_obj_offset : m_offset; 376 if (m_dwarf) 377 return DIERef(local_id, local_id).GetUID(m_dwarf); 378 else 379 return local_id; 380} 381 382dw_offset_t DWARFUnit::GetNextCompileUnitOffset() const { 383 return m_offset + GetLengthByteSize() + GetLength(); 384} 385 386size_t DWARFUnit::GetDebugInfoSize() const { 387 return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 388} 389 390const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 391 return m_abbrevs; 392} 393 394dw_offset_t DWARFUnit::GetAbbrevOffset() const { 395 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 396} 397 398void DWARFUnit::SetAddrBase(dw_addr_t addr_base, 399 dw_addr_t ranges_base, 400 dw_offset_t base_obj_offset) { 401 m_addr_base = addr_base; 402 m_ranges_base = ranges_base; 403 m_base_obj_offset = base_obj_offset; 404} 405 406// It may be called only with m_die_array_mutex held R/W. 407void DWARFUnit::ClearDIEsRWLocked() { 408 m_die_array.clear(); 409 m_die_array.shrink_to_fit(); 410 411 if (m_dwo_symbol_file) 412 m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked(); 413} 414 415void DWARFUnit::BuildAddressRangeTable(SymbolFileDWARF *dwarf, 416 DWARFDebugAranges *debug_aranges) { 417 // This function is usually called if there in no .debug_aranges section in 418 // order to produce a compile unit level set of address ranges that is 419 // accurate. 420 421 size_t num_debug_aranges = debug_aranges->GetNumRanges(); 422 423 // First get the compile unit DIE only and check if it has a DW_AT_ranges 424 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 425 426 const dw_offset_t cu_offset = GetOffset(); 427 if (die) { 428 DWARFRangeList ranges; 429 const size_t num_ranges = 430 die->GetAttributeAddressRanges(dwarf, this, ranges, false); 431 if (num_ranges > 0) { 432 // This compile unit has DW_AT_ranges, assume this is correct if it is 433 // present since clang no longer makes .debug_aranges by default and it 434 // emits DW_AT_ranges for DW_TAG_compile_units. GCC also does this with 435 // recent GCC builds. 436 for (size_t i = 0; i < num_ranges; ++i) { 437 const DWARFRangeList::Entry &range = ranges.GetEntryRef(i); 438 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 439 range.GetRangeEnd()); 440 } 441 442 return; // We got all of our ranges from the DW_AT_ranges attribute 443 } 444 } 445 // We don't have a DW_AT_ranges attribute, so we need to parse the DWARF 446 447 // If the DIEs weren't parsed, then we don't want all dies for all compile 448 // units to stay loaded when they weren't needed. So we can end up parsing 449 // the DWARF and then throwing them all away to keep memory usage down. 450 ScopedExtractDIEs clear_dies(ExtractDIEsScoped()); 451 452 die = DIEPtr(); 453 if (die) 454 die->BuildAddressRangeTable(dwarf, this, debug_aranges); 455 456 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 457 // We got nothing from the functions, maybe we have a line tables only 458 // situation. Check the line tables and build the arange table from this. 459 SymbolContext sc; 460 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 461 if (sc.comp_unit) { 462 SymbolFileDWARFDebugMap *debug_map_sym_file = 463 m_dwarf->GetDebugMapSymfile(); 464 if (debug_map_sym_file == NULL) { 465 LineTable *line_table = sc.comp_unit->GetLineTable(); 466 467 if (line_table) { 468 LineTable::FileAddressRanges file_ranges; 469 const bool append = true; 470 const size_t num_ranges = 471 line_table->GetContiguousFileAddressRanges(file_ranges, append); 472 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 473 const LineTable::FileAddressRanges::Entry &range = 474 file_ranges.GetEntryRef(idx); 475 debug_aranges->AppendRange(cu_offset, range.GetRangeBase(), 476 range.GetRangeEnd()); 477 } 478 } 479 } else 480 debug_map_sym_file->AddOSOARanges(dwarf, debug_aranges); 481 } 482 } 483 484 if (debug_aranges->GetNumRanges() == num_debug_aranges) { 485 // We got nothing from the functions, maybe we have a line tables only 486 // situation. Check the line tables and build the arange table from this. 487 SymbolContext sc; 488 sc.comp_unit = dwarf->GetCompUnitForDWARFCompUnit(this); 489 if (sc.comp_unit) { 490 LineTable *line_table = sc.comp_unit->GetLineTable(); 491 492 if (line_table) { 493 LineTable::FileAddressRanges file_ranges; 494 const bool append = true; 495 const size_t num_ranges = 496 line_table->GetContiguousFileAddressRanges(file_ranges, append); 497 for (uint32_t idx = 0; idx < num_ranges; ++idx) { 498 const LineTable::FileAddressRanges::Entry &range = 499 file_ranges.GetEntryRef(idx); 500 debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), 501 range.GetRangeEnd()); 502 } 503 } 504 } 505 } 506} 507 508lldb::ByteOrder DWARFUnit::GetByteOrder() const { 509 return m_dwarf->GetObjectFile()->GetByteOrder(); 510} 511 512TypeSystem *DWARFUnit::GetTypeSystem() { 513 if (m_dwarf) 514 return m_dwarf->GetTypeSystemForLanguage(GetLanguageType()); 515 else 516 return nullptr; 517} 518 519DWARFFormValue::FixedFormSizes DWARFUnit::GetFixedFormSizes() { 520 return DWARFFormValue::GetFixedFormSizesForAddressSize(GetAddressByteSize(), 521 IsDWARF64()); 522} 523 524void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 525 526//---------------------------------------------------------------------- 527// Compare function DWARFDebugAranges::Range structures 528//---------------------------------------------------------------------- 529static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 530 const dw_offset_t die_offset) { 531 return die.GetOffset() < die_offset; 532} 533 534//---------------------------------------------------------------------- 535// GetDIE() 536// 537// Get the DIE (Debug Information Entry) with the specified offset by first 538// checking if the DIE is contained within this compile unit and grabbing the 539// DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 540//---------------------------------------------------------------------- 541DWARFDIE 542DWARFUnit::GetDIE(dw_offset_t die_offset) { 543 if (die_offset != DW_INVALID_OFFSET) { 544 if (GetDwoSymbolFile()) 545 return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); 546 547 if (ContainsDIEOffset(die_offset)) { 548 ExtractDIEsIfNeeded(); 549 DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 550 DWARFDebugInfoEntry::const_iterator pos = 551 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 552 if (pos != end) { 553 if (die_offset == (*pos).GetOffset()) 554 return DWARFDIE(this, &(*pos)); 555 } 556 } else { 557 // Don't specify the compile unit offset as we don't know it because the 558 // DIE belongs to 559 // a different compile unit in the same symbol file. 560 return m_dwarf->DebugInfo()->GetDIEForDIEOffset(die_offset); 561 } 562 } 563 return DWARFDIE(); // Not found 564} 565 566uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 567 if (cu) 568 return cu->GetAddressByteSize(); 569 return DWARFUnit::GetDefaultAddressSize(); 570} 571 572bool DWARFUnit::IsDWARF64(const DWARFUnit *cu) { 573 if (cu) 574 return cu->IsDWARF64(); 575 return false; 576} 577 578uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 579 580void *DWARFUnit::GetUserData() const { return m_user_data; } 581 582void DWARFUnit::SetUserData(void *d) { 583 m_user_data = d; 584 if (m_dwo_symbol_file) 585 m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); 586} 587 588bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 589 if (GetProducer() == eProducerLLVMGCC) 590 return false; 591 return true; 592} 593 594bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 595 // llvm-gcc makes completely invalid decl file attributes and won't ever be 596 // fixed, so we need to know to ignore these. 597 return GetProducer() == eProducerLLVMGCC; 598} 599 600bool DWARFUnit::Supports_unnamed_objc_bitfields() { 601 if (GetProducer() == eProducerClang) { 602 const uint32_t major_version = GetProducerVersionMajor(); 603 if (major_version > 425 || 604 (major_version == 425 && GetProducerVersionUpdate() >= 13)) 605 return true; 606 else 607 return false; 608 } 609 return true; // Assume all other compilers didn't have incorrect ObjC bitfield 610 // info 611} 612 613SymbolFileDWARF *DWARFUnit::GetSymbolFileDWARF() const { return m_dwarf; } 614 615void DWARFUnit::ParseProducerInfo() { 616 m_producer_version_major = UINT32_MAX; 617 m_producer_version_minor = UINT32_MAX; 618 m_producer_version_update = UINT32_MAX; 619 620 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 621 if (die) { 622 623 const char *producer_cstr = 624 die->GetAttributeValueAsString(m_dwarf, this, DW_AT_producer, NULL); 625 if (producer_cstr) { 626 RegularExpression llvm_gcc_regex( 627 llvm::StringRef("^4\\.[012]\\.[01] \\(Based on Apple " 628 "Inc\\. build [0-9]+\\) \\(LLVM build " 629 "[\\.0-9]+\\)$")); 630 if (llvm_gcc_regex.Execute(llvm::StringRef(producer_cstr))) { 631 m_producer = eProducerLLVMGCC; 632 } else if (strstr(producer_cstr, "clang")) { 633 static RegularExpression g_clang_version_regex( 634 llvm::StringRef("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)")); 635 RegularExpression::Match regex_match(3); 636 if (g_clang_version_regex.Execute(llvm::StringRef(producer_cstr), 637 ®ex_match)) { 638 std::string str; 639 if (regex_match.GetMatchAtIndex(producer_cstr, 1, str)) 640 m_producer_version_major = 641 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 642 if (regex_match.GetMatchAtIndex(producer_cstr, 2, str)) 643 m_producer_version_minor = 644 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 645 if (regex_match.GetMatchAtIndex(producer_cstr, 3, str)) 646 m_producer_version_update = 647 StringConvert::ToUInt32(str.c_str(), UINT32_MAX, 10); 648 } 649 m_producer = eProducerClang; 650 } else if (strstr(producer_cstr, "GNU")) 651 m_producer = eProducerGCC; 652 } 653 } 654 if (m_producer == eProducerInvalid) 655 m_producer = eProcucerOther; 656} 657 658DWARFProducer DWARFUnit::GetProducer() { 659 if (m_producer == eProducerInvalid) 660 ParseProducerInfo(); 661 return m_producer; 662} 663 664uint32_t DWARFUnit::GetProducerVersionMajor() { 665 if (m_producer_version_major == 0) 666 ParseProducerInfo(); 667 return m_producer_version_major; 668} 669 670uint32_t DWARFUnit::GetProducerVersionMinor() { 671 if (m_producer_version_minor == 0) 672 ParseProducerInfo(); 673 return m_producer_version_minor; 674} 675 676uint32_t DWARFUnit::GetProducerVersionUpdate() { 677 if (m_producer_version_update == 0) 678 ParseProducerInfo(); 679 return m_producer_version_update; 680} 681LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { 682 // Note: user languages between lo_user and hi_user must be handled 683 // explicitly here. 684 switch (val) { 685 case DW_LANG_Mips_Assembler: 686 return eLanguageTypeMipsAssembler; 687 case DW_LANG_GOOGLE_RenderScript: 688 return eLanguageTypeExtRenderScript; 689 default: 690 return static_cast<LanguageType>(val); 691 } 692} 693 694LanguageType DWARFUnit::GetLanguageType() { 695 if (m_language_type != eLanguageTypeUnknown) 696 return m_language_type; 697 698 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 699 if (die) 700 m_language_type = LanguageTypeFromDWARF( 701 die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_language, 0)); 702 return m_language_type; 703} 704 705bool DWARFUnit::GetIsOptimized() { 706 if (m_is_optimized == eLazyBoolCalculate) { 707 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 708 if (die) { 709 m_is_optimized = eLazyBoolNo; 710 if (die->GetAttributeValueAsUnsigned(m_dwarf, this, DW_AT_APPLE_optimized, 711 0) == 1) { 712 m_is_optimized = eLazyBoolYes; 713 } 714 } 715 } 716 return m_is_optimized == eLazyBoolYes; 717} 718 719SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() const { 720 return m_dwo_symbol_file.get(); 721} 722 723dw_offset_t DWARFUnit::GetBaseObjOffset() const { return m_base_obj_offset; } 724 725const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 726 if (m_func_aranges_ap.get() == NULL) { 727 m_func_aranges_ap.reset(new DWARFDebugAranges()); 728 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 729 730 if (log) { 731 m_dwarf->GetObjectFile()->GetModule()->LogMessage( 732 log, 733 "DWARFUnit::GetFunctionAranges() for compile unit at " 734 ".debug_info[0x%8.8x]", 735 GetOffset()); 736 } 737 const DWARFDebugInfoEntry *die = DIEPtr(); 738 if (die) 739 die->BuildFunctionAddressRangeTable(m_dwarf, this, 740 m_func_aranges_ap.get()); 741 742 if (m_dwo_symbol_file) { 743 DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); 744 const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); 745 if (dwo_die) 746 dwo_die->BuildFunctionAddressRangeTable(m_dwo_symbol_file.get(), dwo_cu, 747 m_func_aranges_ap.get()); 748 } 749 750 const bool minimize = false; 751 m_func_aranges_ap->Sort(minimize); 752 } 753 return *m_func_aranges_ap.get(); 754} 755 756