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