diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp | 216 |
1 files changed, 107 insertions, 109 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index 22e3e40dac93..dfa40759a7ff 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -1,4 +1,4 @@ -//===-- DWARFUnit.cpp -------------------------------------------*- C++ -*-===// +//===-- DWARFUnit.cpp -----------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -188,7 +188,7 @@ void DWARFUnit::ExtractDIEsRWLocked() { // simultaneously. We also don't need to do that as the dwo file will // contain a superset of information. So, we don't even attempt to parse // any remaining DIEs. - if (m_dwo_symbol_file) { + if (m_dwo) { m_die_array.front().SetHasChildren(false); break; } @@ -249,10 +249,8 @@ void DWARFUnit::ExtractDIEsRWLocked() { m_die_array.shrink_to_fit(); - if (m_dwo_symbol_file) { - DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); - dwo_cu->ExtractDIEsIfNeeded(); - } + if (m_dwo) + m_dwo->ExtractDIEsIfNeeded(); } // This is used when a split dwarf is enabled. @@ -261,23 +259,33 @@ void DWARFUnit::ExtractDIEsRWLocked() { // .debug_str_offsets. At the same time, the corresponding split debug unit also // may use DW_FORM_strx* forms pointing to its own .debug_str_offsets.dwo and // for that case, we should find the offset (skip the section header). -static void SetDwoStrOffsetsBase(DWARFUnit *dwo_cu) { +void DWARFUnit::SetDwoStrOffsetsBase() { lldb::offset_t baseOffset = 0; - const DWARFDataExtractor &strOffsets = - dwo_cu->GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); - uint64_t length = strOffsets.GetU32(&baseOffset); - if (length == 0xffffffff) - length = strOffsets.GetU64(&baseOffset); + if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { + if (const auto *contribution = + entry->getContribution(llvm::DW_SECT_STR_OFFSETS)) + baseOffset = contribution->Offset; + else + return; + } - // Check version. - if (strOffsets.GetU16(&baseOffset) < 5) - return; + if (GetVersion() >= 5) { + const DWARFDataExtractor &strOffsets = + GetSymbolFileDWARF().GetDWARFContext().getOrLoadStrOffsetsData(); + uint64_t length = strOffsets.GetU32(&baseOffset); + if (length == 0xffffffff) + length = strOffsets.GetU64(&baseOffset); - // Skip padding. - baseOffset += 2; + // Check version. + if (strOffsets.GetU16(&baseOffset) < 5) + return; + + // Skip padding. + baseOffset += 2; + } - dwo_cu->SetStrOffsetsBase(baseOffset); + SetStrOffsetsBase(baseOffset); } // m_die_array_mutex must be already held as read/write. @@ -336,32 +344,27 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { } } - if (m_is_dwo) + if (m_is_dwo) { + SetDwoStrOffsetsBase(); return; + } - std::unique_ptr<SymbolFileDWARFDwo> dwo_symbol_file = + std::shared_ptr<SymbolFileDWARFDwo> dwo_symbol_file = m_dwarf.GetDwoSymbolFileForCompileUnit(*this, cu_die); if (!dwo_symbol_file) return; - DWARFUnit *dwo_cu = dwo_symbol_file->GetCompileUnit(); + uint64_t main_dwo_id = + cu_die.GetAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, 0); + DWARFUnit *dwo_cu = dwo_symbol_file->GetDWOCompileUnitForHash(main_dwo_id); if (!dwo_cu) return; // Can't fetch the compile unit from the dwo file. + dwo_cu->SetUserData(this); DWARFBaseDIE dwo_cu_die = dwo_cu->GetUnitDIEOnly(); if (!dwo_cu_die.IsValid()) return; // Can't fetch the compile unit DIE from the dwo file. - uint64_t main_dwo_id = - cu_die.GetAttributeValueAsUnsigned(this, DW_AT_GNU_dwo_id, 0); - uint64_t sub_dwo_id = - dwo_cu_die.GetAttributeValueAsUnsigned(DW_AT_GNU_dwo_id, 0); - if (main_dwo_id != sub_dwo_id) - return; // The 2 dwo ID isn't match. Don't use the dwo file as it belongs to - // a differectn compilation. - - m_dwo_symbol_file = std::move(dwo_symbol_file); - // Here for DWO CU we want to use the address base set in the skeleton unit // (DW_AT_addr_base) if it is available and use the DW_AT_GNU_addr_base // otherwise. We do that because pre-DWARF v5 could use the DW_AT_GNU_* @@ -375,21 +378,18 @@ void DWARFUnit::AddUnitDIE(const DWARFDebugInfoEntry &cu_die) { if (GetVersion() <= 4 && gnu_ranges_base) dwo_cu->SetRangesBase(*gnu_ranges_base); - else if (m_dwo_symbol_file->GetDWARFContext() + else if (dwo_symbol_file->GetDWARFContext() .getOrLoadRngListsData() .GetByteSize() > 0) dwo_cu->SetRangesBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32)); - if (GetVersion() >= 5 && m_dwo_symbol_file->GetDWARFContext() - .getOrLoadLocListsData() - .GetByteSize() > 0) + if (GetVersion() >= 5 && + dwo_symbol_file->GetDWARFContext().getOrLoadLocListsData().GetByteSize() > + 0) dwo_cu->SetLoclistsBase(llvm::DWARFListTableHeader::getHeaderSize(DWARF32)); dwo_cu->SetBaseAddress(GetBaseAddress()); - for (size_t i = 0; i < m_dwo_symbol_file->DebugInfo()->GetNumUnits(); ++i) { - DWARFUnit *unit = m_dwo_symbol_file->DebugInfo()->GetUnitAtIndex(i); - SetDwoStrOffsetsBase(unit); - } + m_dwo = std::shared_ptr<DWARFUnit>(std::move(dwo_symbol_file), dwo_cu); } DWARFDIE DWARFUnit::LookupAddress(const dw_addr_t address) { @@ -467,18 +467,25 @@ void DWARFUnit::SetLoclistsBase(dw_addr_t loclists_base) { std::unique_ptr<llvm::DWARFLocationTable> DWARFUnit::GetLocationTable(const DataExtractor &data) const { llvm::DWARFDataExtractor llvm_data( - toStringRef(data.GetData()), - data.GetByteOrder() == lldb::eByteOrderLittle, data.GetAddressByteSize()); + data.GetData(), data.GetByteOrder() == lldb::eByteOrderLittle, + data.GetAddressByteSize()); if (m_is_dwo || GetVersion() >= 5) return std::make_unique<llvm::DWARFDebugLoclists>(llvm_data, GetVersion()); return std::make_unique<llvm::DWARFDebugLoc>(llvm_data); } -const DWARFDataExtractor &DWARFUnit::GetLocationData() const { +DWARFDataExtractor DWARFUnit::GetLocationData() const { DWARFContext &Ctx = GetSymbolFileDWARF().GetDWARFContext(); - return GetVersion() >= 5 ? Ctx.getOrLoadLocListsData() - : Ctx.getOrLoadLocData(); + const DWARFDataExtractor &data = + GetVersion() >= 5 ? Ctx.getOrLoadLocListsData() : Ctx.getOrLoadLocData(); + if (const llvm::DWARFUnitIndex::Entry *entry = m_header.GetIndexEntry()) { + if (const auto *contribution = entry->getContribution(llvm::DW_SECT_EXT_LOC)) + return DWARFDataExtractor(data, contribution->Offset, + contribution->Length); + return DWARFDataExtractor(); + } + return data; } void DWARFUnit::SetRangesBase(dw_addr_t ranges_base) { @@ -506,18 +513,14 @@ void DWARFUnit::ClearDIEsRWLocked() { m_die_array.clear(); m_die_array.shrink_to_fit(); - if (m_dwo_symbol_file) - m_dwo_symbol_file->GetCompileUnit()->ClearDIEsRWLocked(); + if (m_dwo) + m_dwo->ClearDIEsRWLocked(); } lldb::ByteOrder DWARFUnit::GetByteOrder() const { return m_dwarf.GetObjectFile()->GetByteOrder(); } -llvm::Expected<TypeSystem &> DWARFUnit::GetTypeSystem() { - return m_dwarf.GetTypeSystemForLanguage(GetLanguageType()); -} - void DWARFUnit::SetBaseAddress(dw_addr_t base_addr) { m_base_addr = base_addr; } // Compare function DWARFDebugAranges::Range structures @@ -534,9 +537,6 @@ static bool CompareDIEOffset(const DWARFDebugInfoEntry &die, DWARFDIE DWARFUnit::GetDIE(dw_offset_t die_offset) { if (die_offset != DW_INVALID_OFFSET) { - if (GetDwoSymbolFile()) - return GetDwoSymbolFile()->GetCompileUnit()->GetDIE(die_offset); - if (ContainsDIEOffset(die_offset)) { ExtractDIEsIfNeeded(); DWARFDebugInfoEntry::const_iterator end = m_die_array.cend(); @@ -555,8 +555,9 @@ DWARFUnit::GetDIE(dw_offset_t die_offset) { } DWARFUnit &DWARFUnit::GetNonSkeletonUnit() { - if (SymbolFileDWARFDwo *dwo = GetDwoSymbolFile()) - return *dwo->GetCompileUnit(); + ExtractUnitDIEIfNeeded(); + if (m_dwo) + return *m_dwo; return *this; } @@ -570,11 +571,7 @@ uint8_t DWARFUnit::GetDefaultAddressSize() { return 4; } void *DWARFUnit::GetUserData() const { return m_user_data; } -void DWARFUnit::SetUserData(void *d) { - m_user_data = d; - if (m_dwo_symbol_file) - m_dwo_symbol_file->GetCompileUnit()->SetUserData(d); -} +void DWARFUnit::SetUserData(void *d) { m_user_data = d; } bool DWARFUnit::Supports_DW_AT_APPLE_objc_complete_type() { return GetProducer() != eProducerLLVMGCC; @@ -658,28 +655,17 @@ uint32_t DWARFUnit::GetProducerVersionUpdate() { ParseProducerInfo(); return m_producer_version_update; } -LanguageType DWARFUnit::LanguageTypeFromDWARF(uint64_t val) { - // Note: user languages between lo_user and hi_user must be handled - // explicitly here. - switch (val) { - case DW_LANG_Mips_Assembler: - return eLanguageTypeMipsAssembler; - case DW_LANG_GOOGLE_RenderScript: - return eLanguageTypeExtRenderScript; - default: - return static_cast<LanguageType>(val); - } -} -LanguageType DWARFUnit::GetLanguageType() { - if (m_language_type != eLanguageTypeUnknown) - return m_language_type; +uint64_t DWARFUnit::GetDWARFLanguageType() { + if (m_language_type) + return *m_language_type; const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); - if (die) - m_language_type = LanguageTypeFromDWARF( - die->GetAttributeValueAsUnsigned(this, DW_AT_language, 0)); - return m_language_type; + if (!die) + m_language_type = 0; + else + m_language_type = die->GetAttributeValueAsUnsigned(this, DW_AT_language, 0); + return *m_language_type; } bool DWARFUnit::GetIsOptimized() { @@ -738,25 +724,6 @@ removeHostnameFromPathname(llvm::StringRef path_from_dwarf) { return path; } -static FileSpec resolveCompDir(const FileSpec &path) { - bool is_symlink = SymbolFileDWARF::GetSymlinkPaths().FindFileIndex( - 0, path, /*full*/ true) != UINT32_MAX; - - if (!is_symlink) - return path; - - namespace fs = llvm::sys::fs; - if (fs::get_file_type(path.GetPath(), false) != fs::file_type::symlink_file) - return path; - - FileSpec resolved_symlink; - const auto error = FileSystem::Instance().Readlink(path, resolved_symlink); - if (error.Success()) - return resolved_symlink; - - return path; -} - void DWARFUnit::ComputeCompDirAndGuessPathStyle() { m_comp_dir = FileSpec(); const DWARFDebugInfoEntry *die = GetUnitDIEPtrOnly(); @@ -768,7 +735,7 @@ void DWARFUnit::ComputeCompDirAndGuessPathStyle() { if (!comp_dir.empty()) { FileSpec::Style comp_dir_style = FileSpec::GuessPathStyle(comp_dir).getValueOr(FileSpec::Style::native); - m_comp_dir = resolveCompDir(FileSpec(comp_dir, comp_dir_style)); + m_comp_dir = FileSpec(comp_dir, comp_dir_style); } else { // Try to detect the style based on the DW_AT_name attribute, but just store // the detected style in the m_comp_dir field. @@ -795,21 +762,22 @@ void DWARFUnit::ComputeAbsolutePath() { SymbolFileDWARFDwo *DWARFUnit::GetDwoSymbolFile() { ExtractUnitDIEIfNeeded(); - return m_dwo_symbol_file.get(); + if (m_dwo) + return &llvm::cast<SymbolFileDWARFDwo>(m_dwo->GetSymbolFileDWARF()); + return nullptr; } const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { if (m_func_aranges_up == nullptr) { - m_func_aranges_up.reset(new DWARFDebugAranges()); + m_func_aranges_up = std::make_unique<DWARFDebugAranges>(); const DWARFDebugInfoEntry *die = DIEPtr(); if (die) die->BuildFunctionAddressRangeTable(this, m_func_aranges_up.get()); - if (m_dwo_symbol_file) { - DWARFUnit *dwo_cu = m_dwo_symbol_file->GetCompileUnit(); - const DWARFDebugInfoEntry *dwo_die = dwo_cu->DIEPtr(); + if (m_dwo) { + const DWARFDebugInfoEntry *dwo_die = m_dwo->DIEPtr(); if (dwo_die) - dwo_die->BuildFunctionAddressRangeTable(dwo_cu, + dwo_die->BuildFunctionAddressRangeTable(m_dwo.get(), m_func_aranges_up.get()); } @@ -820,10 +788,13 @@ const DWARFDebugAranges &DWARFUnit::GetFunctionAranges() { } llvm::Expected<DWARFUnitHeader> -DWARFUnitHeader::extract(const DWARFDataExtractor &data, DIERef::Section section, - lldb::offset_t *offset_ptr) { +DWARFUnitHeader::extract(const DWARFDataExtractor &data, + DIERef::Section section, lldb::offset_t *offset_ptr, + const llvm::DWARFUnitIndex *index) { DWARFUnitHeader header; header.m_offset = *offset_ptr; + if (index) + header.m_index_entry = index->getFromOffset(*offset_ptr); header.m_length = data.GetDWARFInitialLength(offset_ptr); header.m_version = data.GetU16(offset_ptr); if (header.m_version == 5) { @@ -839,6 +810,26 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, DIERef::Section section section == DIERef::Section::DebugTypes ? DW_UT_type : DW_UT_compile; } + if (header.m_index_entry) { + if (header.m_abbr_offset) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Package unit with a non-zero abbreviation offset"); + } + auto *unit_contrib = header.m_index_entry->getContribution(); + if (!unit_contrib || unit_contrib->Length != header.m_length + 4) { + return llvm::createStringError(llvm::inconvertibleErrorCode(), + "Inconsistent DWARF package unit index"); + } + auto *abbr_entry = + header.m_index_entry->getContribution(llvm::DW_SECT_ABBREV); + if (!abbr_entry) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "DWARF package index missing abbreviation column"); + } + header.m_abbr_offset = abbr_entry->Offset; + } if (header.IsTypeUnit()) { header.m_type_hash = data.GetU64(offset_ptr); header.m_type_offset = data.GetDWARFOffset(offset_ptr); @@ -869,11 +860,12 @@ DWARFUnitHeader::extract(const DWARFDataExtractor &data, DIERef::Section section llvm::Expected<DWARFUnitSP> DWARFUnit::extract(SymbolFileDWARF &dwarf, user_id_t uid, const DWARFDataExtractor &debug_info, - DIERef::Section section, lldb::offset_t *offset_ptr) { + DIERef::Section section, lldb::offset_t *offset_ptr, + const llvm::DWARFUnitIndex *index) { assert(debug_info.ValidOffset(*offset_ptr)); auto expected_header = - DWARFUnitHeader::extract(debug_info, section, offset_ptr); + DWARFUnitHeader::extract(debug_info, section, offset_ptr, index); if (!expected_header) return expected_header.takeError(); @@ -924,6 +916,12 @@ uint32_t DWARFUnit::GetHeaderByteSize() const { llvm_unreachable("invalid UnitType."); } +llvm::Optional<uint64_t> +DWARFUnit::GetStringOffsetSectionItem(uint32_t index) const { + offset_t offset = GetStrOffsetsBase() + index * 4; + return m_dwarf.GetDWARFContext().getOrLoadStrOffsetsData().GetU32(&offset); +} + llvm::Expected<DWARFRangeList> DWARFUnit::FindRnglistFromOffset(dw_offset_t offset) { if (GetVersion() <= 4) { |