1 //===-- DWARFUnit.cpp -----------------------------------------------------===// 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/Symbol/ObjectFile.h" 13 #include "lldb/Utility/LLDBAssert.h" 14 #include "lldb/Utility/StreamString.h" 15 #include "lldb/Utility/Timer.h" 16 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h" 17 #include "llvm/Object/Error.h" 18 19 #include "DWARFCompileUnit.h" 20 #include "DWARFDebugAranges.h" 21 #include "DWARFDebugInfo.h" 22 #include "DWARFTypeUnit.h" 23 #include "LogChannelDWARF.h" 24 #include "SymbolFileDWARFDwo.h" 25 26 using namespace lldb; 27 using namespace lldb_private; 28 using namespace lldb_private::dwarf; 29 30 extern int g_verbose; 31 32 DWARFUnit::DWARFUnit(SymbolFileDWARF &dwarf, lldb::user_id_t uid, 33 const DWARFUnitHeader &header, 34 const DWARFAbbreviationDeclarationSet &abbrevs, 35 DIERef::Section section, bool is_dwo) 36 : UserID(uid), m_dwarf(dwarf), m_header(header), m_abbrevs(&abbrevs), 37 m_cancel_scopes(false), m_section(section), m_is_dwo(is_dwo), 38 m_has_parsed_non_skeleton_unit(false), m_dwo_id(header.GetDWOId()) {} 39 40 DWARFUnit::~DWARFUnit() = default; 41 42 // Parses first DIE of a compile unit, excluding DWO. 43 void DWARFUnit::ExtractUnitDIENoDwoIfNeeded() { 44 { 45 llvm::sys::ScopedReader lock(m_first_die_mutex); 46 if (m_first_die) 47 return; // Already parsed 48 } 49 llvm::sys::ScopedWriter lock(m_first_die_mutex); 50 if (m_first_die) 51 return; // Already parsed 52 53 ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef()); 54 LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractUnitDIENoDwoIfNeeded()", 55 GetOffset()); 56 57 // Set the offset to that of the first DIE and calculate the start of the 58 // next compilation unit header. 59 lldb::offset_t offset = GetFirstDIEOffset(); 60 61 // We are in our compile unit, parse starting at the offset we were told to 62 // parse 63 const DWARFDataExtractor &data = GetData(); 64 if (offset < GetNextUnitOffset() && 65 m_first_die.Extract(data, this, &offset)) { 66 AddUnitDIE(m_first_die); 67 return; 68 } 69 } 70 71 // Parses first DIE of a compile unit including DWO. 72 void DWARFUnit::ExtractUnitDIEIfNeeded() { 73 ExtractUnitDIENoDwoIfNeeded(); 74 75 if (m_has_parsed_non_skeleton_unit) 76 return; 77 78 m_has_parsed_non_skeleton_unit = true; 79 80 std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file = 81 m_dwarf.GetDwoSymbolFileForCompileUnit(*this, m_first_die); 82 if (!dwo_symbol_file) 83 return; 84 85 DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(m_dwo_id); 86 87 if (!dwo_cu) 88 return; // Can't fetch the compile unit from the dwo file. 89 dwo_cu->SetUserData(this); 90 91 DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); 92 if (!dwo_cu_die.IsValid()) 93 return; // Can't fetch the compile unit DIE from the dwo file. 94 95 // Here for DWO CU we want to use the address base set in the skeleton unit 96 // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base 97 // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_* 98 // attributes which were applicable to the DWO units. The corresponding 99 // DW_AT_* attributes standardized in DWARF v5 are also applicable to the 100 // main unit in contrast. 101 if (m_addr_base) 102 dwo_cu->SetAddrBase(*m_addr_base); 103 else if (m_gnu_addr_base) 104 dwo_cu->SetAddrBase(*m_gnu_addr_base); 105 106 if (GetVersion() <= 4 && m_gnu_ranges_base) 107 dwo_cu->SetRangesBase(*m_gnu_ranges_base); 108 else if (dwo_symbol_file->GetDWARFContext() 109 .getOrLoadRngListsData() 110 .GetByteSize() > 0) 111 dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32)); 112 113 if (GetVersion() >= 5 && 114 dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() > 115 0) 116 dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32)); 117 118 dwo_cu->SetBaseAddress(GetBaseAddress()); 119 120 m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu); 121 } 122 123 // Parses a compile unit and indexes its DIEs if it hasn't already been done. 124 // It will leave this compile unit extracted forever. 125 void DWARFUnit::ExtractDIEsIfNeeded() { 126 m_cancel_scopes = true; 127 128 { 129 llvm::sys::ScopedReader lock(m_die_array_mutex); 130 if (!m_die_array.empty()) 131 return; // Already parsed 132 } 133 llvm::sys::ScopedWriter lock(m_die_array_mutex); 134 if (!m_die_array.empty()) 135 return; // Already parsed 136 137 ExtractDIEsRWLocked(); 138 } 139 140 // Parses a compile unit and indexes its DIEs if it hasn't already been done. 141 // It will clear this compile unit after returned instance gets out of scope, 142 // no other ScopedExtractDIEs instance is running for this compile unit 143 // and no ExtractDIEsIfNeeded() has been executed during this ScopedExtractDIEs 144 // lifetime. 145 DWARFUnit::ScopedExtractDIEs DWARFUnit::ExtractDIEsScoped() { 146 ScopedExtractDIEs scoped(*this); 147 148 { 149 llvm::sys::ScopedReader lock(m_die_array_mutex); 150 if (!m_die_array.empty()) 151 return scoped; // Already parsed 152 } 153 llvm::sys::ScopedWriter lock(m_die_array_mutex); 154 if (!m_die_array.empty()) 155 return scoped; // Already parsed 156 157 // Otherwise m_die_array would be already populated. 158 lldbassert(!m_cancel_scopes); 159 160 ExtractDIEsRWLocked(); 161 scoped.m_clear_dies = true; 162 return scoped; 163 } 164 165 DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(DWARFUnit &cu) : m_cu(&cu) { 166 m_cu->m_die_array_scoped_mutex.lock_shared(); 167 } 168 169 DWARFUnit::ScopedExtractDIEs::~ScopedExtractDIEs() { 170 if (!m_cu) 171 return; 172 m_cu->m_die_array_scoped_mutex.unlock_shared(); 173 if (!m_clear_dies || m_cu->m_cancel_scopes) 174 return; 175 // Be sure no other ScopedExtractDIEs is running anymore. 176 llvm::sys::ScopedWriter lock_scoped(m_cu->m_die_array_scoped_mutex); 177 llvm::sys::ScopedWriter lock(m_cu->m_die_array_mutex); 178 if (m_cu->m_cancel_scopes) 179 return; 180 m_cu->ClearDIEsRWLocked(); 181 } 182 183 DWARFUnit::ScopedExtractDIEs::ScopedExtractDIEs(ScopedExtractDIEs &&rhs) 184 : m_cu(rhs.m_cu), m_clear_dies(rhs.m_clear_dies) { 185 rhs.m_cu = nullptr; 186 } 187 188 DWARFUnit::ScopedExtractDIEs &DWARFUnit::ScopedExtractDIEs::operator=( 189 DWARFUnit::ScopedExtractDIEs &&rhs) { 190 m_cu = rhs.m_cu; 191 rhs.m_cu = nullptr; 192 m_clear_dies = rhs.m_clear_dies; 193 return *this; 194 } 195 196 // Parses a compile unit and indexes its DIEs, m_die_array_mutex must be 197 // held R/W and m_die_array must be empty. 198 void DWARFUnit::ExtractDIEsRWLocked() { 199 llvm::sys::ScopedWriter first_die_lock(m_first_die_mutex); 200 201 ElapsedTime elapsed(m_dwarf.GetDebugInfoParseTimeRef()); 202 LLDB_SCOPED_TIMERF("%8.8x: DWARFUnit::ExtractDIEsIfNeeded()", GetOffset()); 203 204 // Set the offset to that of the first DIE and calculate the start of the 205 // next compilation unit header. 206 lldb::offset_t offset = GetFirstDIEOffset(); 207 lldb::offset_t next_cu_offset = GetNextUnitOffset(); 208 209 DWARFDebugInfoEntry die; 210 211 uint32_t depth = 0; 212 // We are in our compile unit, parse starting at the offset we were told to 213 // parse 214 const DWARFDataExtractor &data = GetData(); 215 std::vector<uint32_t> die_index_stack; 216 die_index_stack.reserve(32); 217 die_index_stack.push_back(0); 218 bool prev_die_had_children = false; 219 while (offset < next_cu_offset && die.Extract(data, this, &offset)) { 220 const bool null_die = die.IsNULL(); 221 if (depth == 0) { 222 assert(m_die_array.empty() && "Compile unit DIE already added"); 223 224 // The average bytes per DIE entry has been seen to be around 14-20 so 225 // lets pre-reserve half of that since we are now stripping the NULL 226 // tags. 227 228 // Only reserve the memory if we are adding children of the main 229 // compile unit DIE. The compile unit DIE is always the first entry, so 230 // if our size is 1, then we are adding the first compile unit child 231 // DIE and should reserve the memory. 232 m_die_array.reserve(GetDebugInfoSize() / 24); 233 m_die_array.push_back(die); 234 235 if (!m_first_die) 236 AddUnitDIE(m_die_array.front()); 237 238 // With -fsplit-dwarf-inlining, clang will emit non-empty skeleton compile 239 // units. We are not able to access these DIE *and* the dwo file 240 // simultaneously. We also don't need to do that as the dwo file will 241 // contain a superset of information. So, we don't even attempt to parse 242 // any remaining DIEs. 243 if (m_dwo) { 244 m_die_array.front().SetHasChildren(false); 245 break; 246 } 247 248 } else { 249 if (null_die) { 250 if (prev_die_had_children) { 251 // This will only happen if a DIE says is has children but all it 252 // contains is a NULL tag. Since we are removing the NULL DIEs from 253 // the list (saves up to 25% in C++ code), we need a way to let the 254 // DIE know that it actually doesn't have children. 255 if (!m_die_array.empty()) 256 m_die_array.back().SetHasChildren(false); 257 } 258 } else { 259 die.SetParentIndex(m_die_array.size() - die_index_stack[depth - 1]); 260 261 if (die_index_stack.back()) 262 m_die_array[die_index_stack.back()].SetSiblingIndex( 263 m_die_array.size() - die_index_stack.back()); 264 265 // Only push the DIE if it isn't a NULL DIE 266 m_die_array.push_back(die); 267 } 268 } 269 270 if (null_die) { 271 // NULL DIE. 272 if (!die_index_stack.empty()) 273 die_index_stack.pop_back(); 274 275 if (depth > 0) 276 --depth; 277 prev_die_had_children = false; 278 } else { 279 die_index_stack.back() = m_die_array.size() - 1; 280 // Normal DIE 281 const bool die_has_children = die.HasChildren(); 282 if (die_has_children) { 283 die_index_stack.push_back(0); 284 ++depth; 285 } 286 prev_die_had_children = die_has_children; 287 } 288 289 if (depth == 0) 290 break; // We are done with this compile unit! 291 } 292 293 if (!m_die_array.empty()) { 294 // The last die cannot have children (if it did, it wouldn't be the last one). 295 // This only makes a difference for malformed dwarf that does not have a 296 // terminating null die. 297 m_die_array.back().SetHasChildren(false); 298 299 if (m_first_die) { 300 // Only needed for the assertion. 301 m_first_die.SetHasChildren(m_die_array.front().HasChildren()); 302 lldbassert(m_first_die == m_die_array.front()); 303 } 304 m_first_die = m_die_array.front(); 305 } 306 307 m_die_array.shrink_to_fit(); 308 309 if (m_dwo) 310 m_dwo->ExtractDIEsIfNeeded(); 311 } 312 313 // This is used when a split dwarf is enabled. 314 // A skeleton compilation unit may contain the DW_AT_str_offsets_base attribute 315 // that points to the first string offset of the CU contribution to the 316 // .debug_str_offsets. At the same time, the corresponding split debug unit also 317 // may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and 318 // for that case, we should find the offset (skip the section header). 319 void DWARFUnit::SetDwoStrOffsetsBase() { 320 lldb::offset_t baseOffset = 0; 321 322 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { 323 if (const auto *contribution = 324 entry->getContribution(llvm::DW_SECT_STR_OFFSETS)) 325 baseOffset = contribution->Offset; 326 else 327 return; 328 } 329 330 if (GetVersion() >= 5) { 331 const DWARFDataExtractor &strOffsets = 332 GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); 333 uint64_t length = strOffsets.GetU32(&baseOffset); 334 if (length == 0xffffffff) 335 length = strOffsets.GetU64(&baseOffset); 336 337 // Check version. 338 if (strOffsets.GetU16(&baseOffset) < 5) 339 return; 340 341 // Skip padding. 342 baseOffset += 2; 343 } 344 345 SetStrOffsetsBase(baseOffset); 346 } 347 348 uint64_t DWARFUnit::GetDWOId() { 349 ExtractUnitDIENoDwoIfNeeded(); 350 return m_dwo_id; 351 } 352 353 // m_die_array_mutex must be already held as read/write. 354 void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { 355 DWARFAttributes attributes; 356 size_t num_attributes = cu_die.GetAttributes(this, attributes); 357 358 // Extract DW_AT_addr_base first, as other attributes may need it. 359 for (size_t i = 0; i < num_attributes; ++i) { 360 if (attributes.AttributeAtIndex(i) != DW_AT_addr_base) 361 continue; 362 DWARFFormValue form_value; 363 if (attributes.ExtractFormValueAtIndex(i, form_value)) { 364 SetAddrBase(form_value.Unsigned()); 365 break; 366 } 367 } 368 369 for (size_t i = 0; i < num_attributes; ++i) { 370 dw_attr_t attr = attributes.AttributeAtIndex(i); 371 DWARFFormValue form_value; 372 if (!attributes.ExtractFormValueAtIndex(i, form_value)) 373 continue; 374 switch (attr) { 375 case DW_AT_loclists_base: 376 SetLoclistsBase(form_value.Unsigned()); 377 break; 378 case DW_AT_rnglists_base: 379 SetRangesBase(form_value.Unsigned()); 380 break; 381 case DW_AT_str_offsets_base: 382 SetStrOffsetsBase(form_value.Unsigned()); 383 break; 384 case DW_AT_low_pc: 385 SetBaseAddress(form_value.Address()); 386 break; 387 case DW_AT_entry_pc: 388 // If the value was already set by DW_AT_low_pc, don't update it. 389 if (m_base_addr == LLDB_INVALID_ADDRESS) 390 SetBaseAddress(form_value.Address()); 391 break; 392 case DW_AT_stmt_list: 393 m_line_table_offset = form_value.Unsigned(); 394 break; 395 case DW_AT_GNU_addr_base: 396 m_gnu_addr_base = form_value.Unsigned(); 397 break; 398 case DW_AT_GNU_ranges_base: 399 m_gnu_ranges_base = form_value.Unsigned(); 400 break; 401 case DW_AT_GNU_dwo_id: 402 m_dwo_id = form_value.Unsigned(); 403 break; 404 } 405 } 406 407 if (m_is_dwo) { 408 m_has_parsed_non_skeleton_unit = true; 409 SetDwoStrOffsetsBase(); 410 return; 411 } 412 } 413 414 size_t DWARFUnit::GetDebugInfoSize() const { 415 return GetLengthByteSize() + GetLength() - GetHeaderByteSize(); 416 } 417 418 const DWARFAbbreviationDeclarationSet *DWARFUnit::GetAbbreviations() const { 419 return m_abbrevs; 420 } 421 422 dw_offset_t DWARFUnit::GetAbbrevOffset() const { 423 return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 424 } 425 426 dw_offset_t DWARFUnit::GetLineTableOffset() { 427 ExtractUnitDIENoDwoIfNeeded(); 428 return m_line_table_offset; 429 } 430 431 void DWARFUnit::SetAddrBase(dw_addr_t addr_base) { m_addr_base = addr_base; } 432 433 // Parse the rangelist table header, including the optional array of offsets 434 // following it (DWARF v5 and later). 435 template <typename ListTableType> 436 static llvm::Expected<ListTableType> 437 ParseListTableHeader(const llvm::DWARFDataExtractor &data, uint64_t offset, 438 DwarfFormat format) { 439 // We are expected to be called with Offset 0 or pointing just past the table 440 // header. Correct Offset in the latter case so that it points to the start 441 // of the header. 442 if (offset == 0) { 443 // This means DW_AT_rnglists_base is missing and therefore DW_FORM_rnglistx 444 // cannot be handled. Returning a default-constructed ListTableType allows 445 // DW_FORM_sec_offset to be supported. 446 return ListTableType(); 447 } 448 449 uint64_t HeaderSize = llvm::DWARFListTableHeader::getHeaderSize(format); 450 if (offset < HeaderSize) 451 return llvm::createStringError(std::errc::invalid_argument, 452 "did not detect a valid" 453 " list table with base = 0x%" PRIx64 "\n", 454 offset); 455 offset -= HeaderSize; 456 ListTableType Table; 457 if (llvm::Error E = Table.extractHeaderAndOffsets(data, &offset)) 458 return std::move(E); 459 return Table; 460 } 461 462 void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) { 463 uint64_t offset = 0; 464 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { 465 const auto *contribution = entry->getContribution(llvm::DW_SECT_LOCLISTS); 466 if (!contribution) { 467 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 468 "Failed to find location list contribution for CU with DWO Id " 469 "0x%" PRIx64, 470 this->GetDWOId()); 471 return; 472 } 473 offset += contribution->Offset; 474 } 475 m_loclists_base = loclists_base; 476 477 uint64_t header_size = llvm::DWARFListTableHeader::getHeaderSize(DWARF32); 478 if (loclists_base < header_size) 479 return; 480 481 m_loclist_table_header.emplace(".debug_loclists", "locations"); 482 offset += loclists_base - header_size; 483 if (llvm::Error E = m_loclist_table_header->extract( 484 m_dwarf.GetDWARFContext().getOrLoadLocListsData().GetAsLLVM(), 485 &offset)) { 486 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 487 "Failed to extract location list table at offset 0x%" PRIx64 488 " (location list base: 0x%" PRIx64 "): %s", 489 offset, loclists_base, toString(std::move(E)).c_str()); 490 } 491 } 492 493 std::unique_ptr<llvm::DWARFLocationTable> 494 DWARFUnit::GetLocationTable(const DataExtractor &data) const { 495 llvm::DWARFDataExtractor llvm_data( 496 data.GetData(), data.GetByteOrder() == lldb::eByteOrderLittle, 497 data.GetAddressByteSize()); 498 499 if (m_is_dwo || GetVersion() >= 5) 500 return std::make_unique<llvm::DWARFDebugLoclists>(llvm_data, GetVersion()); 501 return std::make_unique<llvm::DWARFDebugLoc>(llvm_data); 502 } 503 504 DWARFDataExtractor DWARFUnit::GetLocationData() const { 505 DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext(); 506 const DWARFDataExtractor &data = 507 GetVersion() >= 5 ? Ctx.getOrLoadLocListsData() : Ctx.getOrLoadLocData(); 508 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { 509 if (const auto *contribution = entry->getContribution( 510 GetVersion() >= 5 ? llvm::DW_SECT_LOCLISTS : llvm::DW_SECT_EXT_LOC)) 511 return DWARFDataExtractor(data, contribution->Offset, 512 contribution->Length); 513 return DWARFDataExtractor(); 514 } 515 return data; 516 } 517 518 DWARFDataExtractor DWARFUnit::GetRnglistData() const { 519 DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext(); 520 const DWARFDataExtractor &data = Ctx.getOrLoadRngListsData(); 521 if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { 522 if (const auto *contribution = 523 entry->getContribution(llvm::DW_SECT_RNGLISTS)) 524 return DWARFDataExtractor(data, contribution->Offset, 525 contribution->Length); 526 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 527 "Failed to find range list contribution for CU with signature " 528 "0x%" PRIx64, 529 entry->getSignature()); 530 531 return DWARFDataExtractor(); 532 } 533 return data; 534 } 535 536 void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { 537 lldbassert(!m_rnglist_table_done); 538 539 m_ranges_base = ranges_base; 540 } 541 542 const llvm::Optional<llvm::DWARFDebugRnglistTable> & 543 DWARFUnit::GetRnglistTable() { 544 if (GetVersion() >= 5 && !m_rnglist_table_done) { 545 m_rnglist_table_done = true; 546 if (auto table_or_error = 547 ParseListTableHeader<llvm::DWARFDebugRnglistTable>( 548 GetRnglistData().GetAsLLVM(), m_ranges_base, DWARF32)) 549 m_rnglist_table = std::move(table_or_error.get()); 550 else 551 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 552 "Failed to extract range list table at offset 0x%" PRIx64 ": %s", 553 m_ranges_base, toString(table_or_error.takeError()).c_str()); 554 } 555 return m_rnglist_table; 556 } 557 558 // This function is called only for DW_FORM_rnglistx. 559 llvm::Expected<uint64_t> DWARFUnit::GetRnglistOffset(uint32_t Index) { 560 if (!GetRnglistTable()) 561 return llvm::createStringError(std::errc::invalid_argument, 562 "missing or invalid range list table"); 563 if (!m_ranges_base) 564 return llvm::createStringError(std::errc::invalid_argument, 565 "DW_FORM_rnglistx cannot be used without " 566 "DW_AT_rnglists_base for CU at 0x%8.8x", 567 GetOffset()); 568 if (llvm::Optional<uint64_t> off = GetRnglistTable()->getOffsetEntry( 569 GetRnglistData().GetAsLLVM(), Index)) 570 return *off + m_ranges_base; 571 return llvm::createStringError( 572 std::errc::invalid_argument, 573 "invalid range list table index %u; OffsetEntryCount is %u, " 574 "DW_AT_rnglists_base is %" PRIu64, 575 Index, GetRnglistTable()->getOffsetEntryCount(), m_ranges_base); 576 } 577 578 void DWARFUnit::SetStrOffsetsBase(dw_offset_t str_offsets_base) { 579 m_str_offsets_base = str_offsets_base; 580 } 581 582 dw_addr_t DWARFUnit::ReadAddressFromDebugAddrSection(uint32_t index) const { 583 uint32_t index_size = GetAddressByteSize(); 584 dw_offset_t addr_base = GetAddrBase(); 585 dw_addr_t offset = addr_base + index * index_size; 586 const DWARFDataExtractor &data = 587 m_dwarf.GetDWARFContext().getOrLoadAddrData(); 588 if (data.ValidOffsetForDataOfSize(offset, index_size)) 589 return data.GetMaxU64_unchecked(&offset, index_size); 590 return LLDB_INVALID_ADDRESS; 591 } 592 593 // It may be called only with m_die_array_mutex held R/W. 594 void DWARFUnit::ClearDIEsRWLocked() { 595 m_die_array.clear(); 596 m_die_array.shrink_to_fit(); 597 598 if (m_dwo) 599 m_dwo->ClearDIEsRWLocked(); 600 } 601 602 lldb::ByteOrder DWARFUnit::GetByteOrder() const { 603 return m_dwarf.GetObjectFile()->GetByteOrder(); 604 } 605 606 void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } 607 608 // Compare function DWARFDebugAranges::Range structures 609 static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, 610 const dw_offset_t die_offset) { 611 return die.GetOffset() < die_offset; 612 } 613 614 // GetDIE() 615 // 616 // Get the DIE (Debug Information Entry) with the specified offset by first 617 // checking if the DIE is contained within this compile unit and grabbing the 618 // DIE from this compile unit. Otherwise we grab the DIE from the DWARF file. 619 DWARFDIE 620 DWARFUnit::GetDIE(dw_offset_t die_offset) { 621 if (die_offset == DW_INVALID_OFFSET) 622 return DWARFDIE(); // Not found 623 624 if (!ContainsDIEOffset(die_offset)) { 625 GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError( 626 "GetDIE for DIE 0x%" PRIx32 " is outside of its CU 0x%" PRIx32, 627 die_offset, GetOffset()); 628 return DWARFDIE(); // Not found 629 } 630 631 ExtractDIEsIfNeeded(); 632 DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); 633 DWARFDebugInfoEntry::const_iterator pos = 634 lower_bound(m_die_array.cbegin(), end, die_offset, CompareDIEOffset); 635 636 if (pos != end && die_offset == (*pos).GetOffset()) 637 return DWARFDIE(this, &(*pos)); 638 return DWARFDIE(); // Not found 639 } 640 641 DWARFUnit &DWARFUnit::GetNonSkeletonUnit() { 642 ExtractUnitDIEIfNeeded(); 643 if (m_dwo) 644 return *m_dwo; 645 return *this; 646 } 647 648 uint8_t DWARFUnit::GetAddressByteSize(const DWARFUnit *cu) { 649 if (cu) 650 return cu->GetAddressByteSize(); 651 return DWARFUnit::GetDefaultAddressSize(); 652 } 653 654 uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } 655 656 void *DWARFUnit::GetUserData() const { return m_user_data; } 657 658 void DWARFUnit::SetUserData(void *d) { m_user_data = d; } 659 660 bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { 661 return GetProducer() != eProducerLLVMGCC; 662 } 663 664 bool DWARFUnit::DW_AT_decl_file_attributes_are_invalid() { 665 // llvm-gcc makes completely invalid decl file attributes and won't ever be 666 // fixed, so we need to know to ignore these. 667 return GetProducer() == eProducerLLVMGCC; 668 } 669 670 bool DWARFUnit::Supports_unnamed_objc_bitfields() { 671 if (GetProducer() == eProducerClang) 672 return GetProducerVersion() >= llvm::VersionTuple(425, 0, 13); 673 // Assume all other compilers didn't have incorrect ObjC bitfield info. 674 return true; 675 } 676 677 void DWARFUnit::ParseProducerInfo() { 678 m_producer = eProducerOther; 679 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 680 if (!die) 681 return; 682 683 llvm::StringRef producer( 684 die->GetAttributeValueAsString(this, DW_AT_producer, nullptr)); 685 if (producer.empty()) 686 return; 687 688 static const RegularExpression g_swiftlang_version_regex( 689 llvm::StringRef(R"(swiftlang-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?))")); 690 static const RegularExpression g_clang_version_regex( 691 llvm::StringRef(R"(clang-([0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?))")); 692 static const RegularExpression g_llvm_gcc_regex( 693 llvm::StringRef(R"(4\.[012]\.[01] )" 694 R"(\(Based on Apple Inc\. build [0-9]+\) )" 695 R"(\(LLVM build [\.0-9]+\)$)")); 696 697 llvm::SmallVector<llvm::StringRef, 3> matches; 698 if (g_swiftlang_version_regex.Execute(producer, &matches)) { 699 m_producer_version.tryParse(matches[1]); 700 m_producer = eProducerSwift; 701 } else if (producer.contains("clang")) { 702 if (g_clang_version_regex.Execute(producer, &matches)) 703 m_producer_version.tryParse(matches[1]); 704 m_producer = eProducerClang; 705 } else if (producer.contains("GNU")) { 706 m_producer = eProducerGCC; 707 } else if (g_llvm_gcc_regex.Execute(producer)) { 708 m_producer = eProducerLLVMGCC; 709 } 710 } 711 712 DWARFProducer DWARFUnit::GetProducer() { 713 if (m_producer == eProducerInvalid) 714 ParseProducerInfo(); 715 return m_producer; 716 } 717 718 llvm::VersionTuple DWARFUnit::GetProducerVersion() { 719 if (m_producer_version.empty()) 720 ParseProducerInfo(); 721 return m_producer_version; 722 } 723 724 uint64_t DWARFUnit::GetDWARFLanguageType() { 725 if (m_language_type) 726 return *m_language_type; 727 728 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 729 if (!die) 730 m_language_type = 0; 731 else 732 m_language_type = die->GetAttributeValueAsUnsigned(this, DW_AT_language, 0); 733 return *m_language_type; 734 } 735 736 bool DWARFUnit::GetIsOptimized() { 737 if (m_is_optimized == eLazyBoolCalculate) { 738 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 739 if (die) { 740 m_is_optimized = eLazyBoolNo; 741 if (die->GetAttributeValueAsUnsigned(this, DW_AT_APPLE_optimized, 0) == 742 1) { 743 m_is_optimized = eLazyBoolYes; 744 } 745 } 746 } 747 return m_is_optimized == eLazyBoolYes; 748 } 749 750 FileSpec::Style DWARFUnit::GetPathStyle() { 751 if (!m_comp_dir) 752 ComputeCompDirAndGuessPathStyle(); 753 return m_comp_dir->GetPathStyle(); 754 } 755 756 const FileSpec &DWARFUnit::GetCompilationDirectory() { 757 if (!m_comp_dir) 758 ComputeCompDirAndGuessPathStyle(); 759 return *m_comp_dir; 760 } 761 762 const FileSpec &DWARFUnit::GetAbsolutePath() { 763 if (!m_file_spec) 764 ComputeAbsolutePath(); 765 return *m_file_spec; 766 } 767 768 FileSpec DWARFUnit::GetFile(size_t file_idx) { 769 return m_dwarf.GetFile(*this, file_idx); 770 } 771 772 // DWARF2/3 suggests the form hostname:pathname for compilation directory. 773 // Remove the host part if present. 774 static llvm::StringRef 775 removeHostnameFromPathname(llvm::StringRef path_from_dwarf) { 776 if (!path_from_dwarf.contains(':')) 777 return path_from_dwarf; 778 llvm::StringRef host, path; 779 std::tie(host, path) = path_from_dwarf.split(':'); 780 781 if (host.contains('/')) 782 return path_from_dwarf; 783 784 // check whether we have a windows path, and so the first character is a 785 // drive-letter not a hostname. 786 if (host.size() == 1 && llvm::isAlpha(host[0]) && 787 (path.startswith("\\") || path.startswith("/"))) 788 return path_from_dwarf; 789 790 return path; 791 } 792 793 void DWARFUnit::ComputeCompDirAndGuessPathStyle() { 794 m_comp_dir = FileSpec(); 795 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 796 if (!die) 797 return; 798 799 llvm::StringRef comp_dir = removeHostnameFromPathname( 800 die->GetAttributeValueAsString(this, DW_AT_comp_dir, nullptr)); 801 if (!comp_dir.empty()) { 802 FileSpec::Style comp_dir_style = 803 FileSpec::GuessPathStyle(comp_dir).value_or(FileSpec::Style::native); 804 m_comp_dir = FileSpec(comp_dir, comp_dir_style); 805 } else { 806 // Try to detect the style based on the DW_AT_name attribute, but just store 807 // the detected style in the m_comp_dir field. 808 const char *name = 809 die->GetAttributeValueAsString(this, DW_AT_name, nullptr); 810 m_comp_dir = FileSpec( 811 "", FileSpec::GuessPathStyle(name).value_or(FileSpec::Style::native)); 812 } 813 } 814 815 void DWARFUnit::ComputeAbsolutePath() { 816 m_file_spec = FileSpec(); 817 const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); 818 if (!die) 819 return; 820 821 m_file_spec = 822 FileSpec(die->GetAttributeValueAsString(this, DW_AT_name, nullptr), 823 GetPathStyle()); 824 825 if (m_file_spec->IsRelative()) 826 m_file_spec->MakeAbsolute(GetCompilationDirectory()); 827 } 828 829 SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() { 830 ExtractUnitDIEIfNeeded(); 831 if (m_dwo) 832 return &llvm::cast<SymbolFileDWARFDwo>(m_dwo->GetSymbolFileDWARF()); 833 return nullptr; 834 } 835 836 const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { 837 if (m_func_aranges_up == nullptr) { 838 m_func_aranges_up = std::make_unique<DWARFDebugAranges>(); 839 const DWARFDebugInfoEntry *die = DIEPtr(); 840 if (die) 841 die->BuildFunctionAddressRangeTable(this, m_func_aranges_up.get()); 842 843 if (m_dwo) { 844 const DWARFDebugInfoEntry *dwo_die = m_dwo->DIEPtr(); 845 if (dwo_die) 846 dwo_die->BuildFunctionAddressRangeTable(m_dwo.get(), 847 m_func_aranges_up.get()); 848 } 849 850 const bool minimize = false; 851 m_func_aranges_up->Sort(minimize); 852 } 853 return *m_func_aranges_up; 854 } 855 856 llvm::Expected<DWARFUnitHeader> 857 DWARFUnitHeader::extract(const DWARFDataExtractor &data, 858 DIERef::Section section, 859 lldb_private::DWARFContext &context, 860 lldb::offset_t *offset_ptr) { 861 DWARFUnitHeader header; 862 header.m_offset = *offset_ptr; 863 header.m_length = data.GetDWARFInitialLength(offset_ptr); 864 header.m_version = data.GetU16(offset_ptr); 865 if (header.m_version == 5) { 866 header.m_unit_type = data.GetU8(offset_ptr); 867 header.m_addr_size = data.GetU8(offset_ptr); 868 header.m_abbr_offset = data.GetDWARFOffset(offset_ptr); 869 if (header.m_unit_type == llvm::dwarf::DW_UT_skeleton || 870 header.m_unit_type == llvm::dwarf::DW_UT_split_compile) 871 header.m_dwo_id = data.GetU64(offset_ptr); 872 } else { 873 header.m_abbr_offset = data.GetDWARFOffset(offset_ptr); 874 header.m_addr_size = data.GetU8(offset_ptr); 875 header.m_unit_type = 876 section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile; 877 } 878 879 if (header.IsTypeUnit()) { 880 header.m_type_hash = data.GetU64(offset_ptr); 881 header.m_type_offset = data.GetDWARFOffset(offset_ptr); 882 } 883 884 if (context.isDwo()) { 885 const llvm::DWARFUnitIndex *Index; 886 if (header.IsTypeUnit()) { 887 Index = &context.GetAsLLVM().getTUIndex(); 888 if (*Index) 889 header.m_index_entry = Index->getFromHash(header.m_type_hash); 890 } else { 891 Index = &context.GetAsLLVM().getCUIndex(); 892 if (*Index && header.m_version >= 5) 893 header.m_index_entry = Index->getFromHash(header.m_dwo_id); 894 } 895 if (!header.m_index_entry) 896 header.m_index_entry = Index->getFromOffset(header.m_offset); 897 } 898 899 if (header.m_index_entry) { 900 if (header.m_abbr_offset) { 901 return llvm::createStringError( 902 llvm::inconvertibleErrorCode(), 903 "Package unit with a non-zero abbreviation offset"); 904 } 905 auto *unit_contrib = header.m_index_entry->getContribution(); 906 if (!unit_contrib || unit_contrib->Length != header.m_length + 4) { 907 return llvm::createStringError(llvm::inconvertibleErrorCode(), 908 "Inconsistent DWARF package unit index"); 909 } 910 auto *abbr_entry = 911 header.m_index_entry->getContribution(llvm::DW_SECT_ABBREV); 912 if (!abbr_entry) { 913 return llvm::createStringError( 914 llvm::inconvertibleErrorCode(), 915 "DWARF package index missing abbreviation column"); 916 } 917 header.m_abbr_offset = abbr_entry->Offset; 918 } 919 920 bool length_OK = data.ValidOffset(header.GetNextUnitOffset() - 1); 921 bool version_OK = SymbolFileDWARF::SupportedVersion(header.m_version); 922 bool addr_size_OK = (header.m_addr_size == 4) || (header.m_addr_size == 8); 923 bool type_offset_OK = 924 !header.IsTypeUnit() || (header.m_type_offset <= header.GetLength()); 925 926 if (!length_OK) 927 return llvm::make_error<llvm::object::GenericBinaryError>( 928 "Invalid unit length"); 929 if (!version_OK) 930 return llvm::make_error<llvm::object::GenericBinaryError>( 931 "Unsupported unit version"); 932 if (!addr_size_OK) 933 return llvm::make_error<llvm::object::GenericBinaryError>( 934 "Invalid unit address size"); 935 if (!type_offset_OK) 936 return llvm::make_error<llvm::object::GenericBinaryError>( 937 "Type offset out of range"); 938 939 return header; 940 } 941 942 llvm::Expected<DWARFUnitSP> 943 DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, 944 const DWARFDataExtractor &debug_info, 945 DIERef::Section section, lldb::offset_t *offset_ptr) { 946 assert(debug_info.ValidOffset(*offset_ptr)); 947 948 auto expected_header = DWARFUnitHeader::extract( 949 debug_info, section, dwarf.GetDWARFContext(), offset_ptr); 950 if (!expected_header) 951 return expected_header.takeError(); 952 953 const DWARFDebugAbbrev *abbr = dwarf.DebugAbbrev(); 954 if (!abbr) 955 return llvm::make_error<llvm::object::GenericBinaryError>( 956 "No debug_abbrev data"); 957 958 bool abbr_offset_OK = 959 dwarf.GetDWARFContext().getOrLoadAbbrevData().ValidOffset( 960 expected_header->GetAbbrOffset()); 961 if (!abbr_offset_OK) 962 return llvm::make_error<llvm::object::GenericBinaryError>( 963 "Abbreviation offset for unit is not valid"); 964 965 const DWARFAbbreviationDeclarationSet *abbrevs = 966 abbr->GetAbbreviationDeclarationSet(expected_header->GetAbbrOffset()); 967 if (!abbrevs) 968 return llvm::make_error<llvm::object::GenericBinaryError>( 969 "No abbrev exists at the specified offset."); 970 971 bool is_dwo = dwarf.GetDWARFContext().isDwo(); 972 if (expected_header->IsTypeUnit()) 973 return DWARFUnitSP(new DWARFTypeUnit(dwarf, uid, *expected_header, *abbrevs, 974 section, is_dwo)); 975 return DWARFUnitSP(new DWARFCompileUnit(dwarf, uid, *expected_header, 976 *abbrevs, section, is_dwo)); 977 } 978 979 const lldb_private::DWARFDataExtractor &DWARFUnit::GetData() const { 980 return m_section == DIERef::Section::DebugTypes 981 ? m_dwarf.GetDWARFContext().getOrLoadDebugTypesData() 982 : m_dwarf.GetDWARFContext().getOrLoadDebugInfoData(); 983 } 984 985 uint32_t DWARFUnit::GetHeaderByteSize() const { 986 switch (m_header.GetUnitType()) { 987 case llvm::dwarf::DW_UT_compile: 988 case llvm::dwarf::DW_UT_partial: 989 return GetVersion() < 5 ? 11 : 12; 990 case llvm::dwarf::DW_UT_skeleton: 991 case llvm::dwarf::DW_UT_split_compile: 992 return 20; 993 case llvm::dwarf::DW_UT_type: 994 case llvm::dwarf::DW_UT_split_type: 995 return GetVersion() < 5 ? 23 : 24; 996 } 997 llvm_unreachable("invalid UnitType."); 998 } 999 1000 llvm::Optional<uint64_t> 1001 DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { 1002 offset_t offset = GetStrOffsetsBase() + index * 4; 1003 return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); 1004 } 1005 1006 llvm::Expected<DWARFRangeList> 1007 DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { 1008 if (GetVersion() <= 4) { 1009 const DWARFDebugRanges *debug_ranges = m_dwarf.GetDebugRanges(); 1010 if (!debug_ranges) 1011 return llvm::make_error<llvm::object::GenericBinaryError>( 1012 "No debug_ranges section"); 1013 DWARFRangeList ranges; 1014 debug_ranges->FindRanges(this, offset, ranges); 1015 return ranges; 1016 } 1017 1018 if (!GetRnglistTable()) 1019 return llvm::createStringError(std::errc::invalid_argument, 1020 "missing or invalid range list table"); 1021 1022 llvm::DWARFDataExtractor data = GetRnglistData().GetAsLLVM(); 1023 1024 // As DW_AT_rnglists_base may be missing we need to call setAddressSize. 1025 data.setAddressSize(m_header.GetAddressByteSize()); 1026 auto range_list_or_error = GetRnglistTable()->findList(data, offset); 1027 if (!range_list_or_error) 1028 return range_list_or_error.takeError(); 1029 1030 llvm::Expected<llvm::DWARFAddressRangesVector> llvm_ranges = 1031 range_list_or_error->getAbsoluteRanges( 1032 llvm::object::SectionedAddress{GetBaseAddress()}, 1033 GetAddressByteSize(), [&](uint32_t index) { 1034 uint32_t index_size = GetAddressByteSize(); 1035 dw_offset_t addr_base = GetAddrBase(); 1036 lldb::offset_t offset = addr_base + index * index_size; 1037 return llvm::object::SectionedAddress{ 1038 m_dwarf.GetDWARFContext().getOrLoadAddrData().GetMaxU64( 1039 &offset, index_size)}; 1040 }); 1041 if (!llvm_ranges) 1042 return llvm_ranges.takeError(); 1043 1044 DWARFRangeList ranges; 1045 for (const llvm::DWARFAddressRange &llvm_range : *llvm_ranges) { 1046 ranges.Append(DWARFRangeList::Entry(llvm_range.LowPC, 1047 llvm_range.HighPC - llvm_range.LowPC)); 1048 } 1049 return ranges; 1050 } 1051 1052 llvm::Expected<DWARFRangeList> 1053 DWARFUnit::FindRnglistFromIndex(uint32_t index) { 1054 llvm::Expected<uint64_t> maybe_offset = GetRnglistOffset(index); 1055 if (!maybe_offset) 1056 return maybe_offset.takeError(); 1057 return FindRnglistFromOffset(*maybe_offset); 1058 } 1059