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