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