diff options
Diffstat (limited to 'contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp')
| -rw-r--r-- | contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp new file mode 100644 index 000000000000..9746ad76c930 --- /dev/null +++ b/contrib/llvm-project/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -0,0 +1,272 @@ +//===-- DebugNamesDWARFIndex.cpp -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h" +#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" +#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" +#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" +#include "lldb/Utility/RegularExpression.h" +#include "lldb/Utility/Stream.h" + +using namespace lldb_private; +using namespace lldb; + +llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>> +DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names, + DWARFDataExtractor debug_str, + DWARFDebugInfo *debug_info) { + if (!debug_info) { + return llvm::make_error<llvm::StringError>("debug info null", + llvm::inconvertibleErrorCode()); + } + auto index_up = llvm::make_unique<DebugNames>(debug_names.GetAsLLVM(), + debug_str.GetAsLLVM()); + if (llvm::Error E = index_up->extract()) + return std::move(E); + + return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex( + module, std::move(index_up), debug_names, debug_str, *debug_info)); +} + +llvm::DenseSet<dw_offset_t> +DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) { + llvm::DenseSet<dw_offset_t> result; + for (const DebugNames::NameIndex &ni : debug_names) { + for (uint32_t cu = 0; cu < ni.getCUCount(); ++cu) + result.insert(ni.getCUOffset(cu)); + } + return result; +} + +llvm::Optional<DIERef> +DebugNamesDWARFIndex::ToDIERef(const DebugNames::Entry &entry) { + llvm::Optional<uint64_t> cu_offset = entry.getCUOffset(); + if (!cu_offset) + return llvm::None; + + DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset); + if (!cu) + return llvm::None; + + // This initializes the DWO symbol file. It's not possible for + // GetDwoSymbolFile to call this automatically because of mutual recursion + // between this and DWARFDebugInfoEntry::GetAttributeValue. + cu->ExtractUnitDIEIfNeeded(); + cu = &cu->GetNonSkeletonUnit(); + + if (llvm::Optional<uint64_t> die_offset = entry.getDIEUnitOffset()) + return DIERef(cu->GetSymbolFileDWARF().GetDwoNum(), + DIERef::Section::DebugInfo, cu->GetOffset() + *die_offset); + + return llvm::None; +} + +void DebugNamesDWARFIndex::Append(const DebugNames::Entry &entry, + DIEArray &offsets) { + if (llvm::Optional<DIERef> ref = ToDIERef(entry)) + offsets.push_back(*ref); +} + +void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error, + const DebugNames::NameIndex &ni, + llvm::StringRef name) { + // Ignore SentinelErrors, log everything else. + LLDB_LOG_ERROR( + LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS), + handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}), + "Failed to parse index entries for index at {1:x}, name {2}: {0}", + ni.getUnitOffset(), name); +} + +void DebugNamesDWARFIndex::GetGlobalVariables(ConstString basename, + DIEArray &offsets) { + m_fallback.GetGlobalVariables(basename, offsets); + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(basename.GetStringRef())) { + if (entry.tag() != DW_TAG_variable) + continue; + + Append(entry, offsets); + } +} + +void DebugNamesDWARFIndex::GetGlobalVariables(const RegularExpression ®ex, + DIEArray &offsets) { + m_fallback.GetGlobalVariables(regex, offsets); + + for (const DebugNames::NameIndex &ni: *m_debug_names_up) { + for (DebugNames::NameTableEntry nte: ni) { + if (!regex.Execute(nte.getString())) + continue; + + uint32_t entry_offset = nte.getEntryOffset(); + llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); + for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { + if (entry_or->tag() != DW_TAG_variable) + continue; + + Append(*entry_or, offsets); + } + MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); + } + } +} + +void DebugNamesDWARFIndex::GetGlobalVariables(const DWARFUnit &cu, + DIEArray &offsets) { + m_fallback.GetGlobalVariables(cu, offsets); + + uint64_t cu_offset = cu.GetOffset(); + for (const DebugNames::NameIndex &ni: *m_debug_names_up) { + for (DebugNames::NameTableEntry nte: ni) { + uint32_t entry_offset = nte.getEntryOffset(); + llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); + for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { + if (entry_or->tag() != DW_TAG_variable) + continue; + if (entry_or->getCUOffset() != cu_offset) + continue; + + Append(*entry_or, offsets); + } + MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); + } + } +} + +void DebugNamesDWARFIndex::GetCompleteObjCClass(ConstString class_name, + bool must_be_implementation, + DIEArray &offsets) { + m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, offsets); + + // Keep a list of incomplete types as fallback for when we don't find the + // complete type. + DIEArray incomplete_types; + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(class_name.GetStringRef())) { + if (entry.tag() != DW_TAG_structure_type && + entry.tag() != DW_TAG_class_type) + continue; + + llvm::Optional<DIERef> ref = ToDIERef(entry); + if (!ref) + continue; + + DWARFUnit *cu = m_debug_info.GetUnit(*ref); + if (!cu || !cu->Supports_DW_AT_APPLE_objc_complete_type()) { + incomplete_types.push_back(*ref); + continue; + } + + // FIXME: We should return DWARFDIEs so we don't have to resolve it twice. + DWARFDIE die = m_debug_info.GetDIE(*ref); + if (!die) + continue; + + if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) { + // If we find the complete version we're done. + offsets.push_back(*ref); + return; + } else { + incomplete_types.push_back(*ref); + } + } + + offsets.insert(offsets.end(), incomplete_types.begin(), + incomplete_types.end()); +} + +void DebugNamesDWARFIndex::GetTypes(ConstString name, DIEArray &offsets) { + m_fallback.GetTypes(name, offsets); + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(name.GetStringRef())) { + if (isType(entry.tag())) + Append(entry, offsets); + } +} + +void DebugNamesDWARFIndex::GetTypes(const DWARFDeclContext &context, + DIEArray &offsets) { + m_fallback.GetTypes(context, offsets); + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(context[0].name)) { + if (entry.tag() == context[0].tag) + Append(entry, offsets); + } +} + +void DebugNamesDWARFIndex::GetNamespaces(ConstString name, DIEArray &offsets) { + m_fallback.GetNamespaces(name, offsets); + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(name.GetStringRef())) { + if (entry.tag() == DW_TAG_namespace) + Append(entry, offsets); + } +} + +void DebugNamesDWARFIndex::GetFunctions( + ConstString name, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask, + std::vector<DWARFDIE> &dies) { + + std::vector<DWARFDIE> v; + m_fallback.GetFunctions(name, dwarf, parent_decl_ctx, name_type_mask, v); + + for (const DebugNames::Entry &entry : + m_debug_names_up->equal_range(name.GetStringRef())) { + Tag tag = entry.tag(); + if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) + continue; + + if (llvm::Optional<DIERef> ref = ToDIERef(entry)) + ProcessFunctionDIE(name.GetStringRef(), *ref, dwarf, parent_decl_ctx, + name_type_mask, v); + } + + std::set<DWARFDebugInfoEntry *> seen; + for (DWARFDIE die : v) + if (seen.insert(die.GetDIE()).second) + dies.push_back(die); +} + +void DebugNamesDWARFIndex::GetFunctions(const RegularExpression ®ex, + DIEArray &offsets) { + m_fallback.GetFunctions(regex, offsets); + + for (const DebugNames::NameIndex &ni: *m_debug_names_up) { + for (DebugNames::NameTableEntry nte: ni) { + if (!regex.Execute(nte.getString())) + continue; + + uint32_t entry_offset = nte.getEntryOffset(); + llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset); + for (; entry_or; entry_or = ni.getEntry(&entry_offset)) { + Tag tag = entry_or->tag(); + if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) + continue; + + Append(*entry_or, offsets); + } + MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); + } + } +} + +void DebugNamesDWARFIndex::Dump(Stream &s) { + m_fallback.Dump(s); + + std::string data; + llvm::raw_string_ostream os(data); + m_debug_names_up->dump(os); + s.PutCString(os.str()); +} |
