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