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