summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp185
1 files changed, 155 insertions, 30 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index b15e0c15fedb..d3d0110d5e30 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -7,11 +7,14 @@
//===----------------------------------------------------------------------===//
#include "SymbolFileDWARF.h"
+#include "clang/Basic/ABI.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/DebugInfo/DWARF/DWARFAddressRange.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/Threading.h"
@@ -23,6 +26,7 @@
#include "lldb/Core/Progress.h"
#include "lldb/Core/Section.h"
#include "lldb/Core/Value.h"
+#include "lldb/Expression/Expression.h"
#include "lldb/Utility/ArchSpec.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/RegularExpression.h"
@@ -79,6 +83,7 @@
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
+#include "llvm/Demangle/Demangle.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FormatVariadic.h"
@@ -2484,34 +2489,148 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die,
return false;
}
-DWARFDIE
-SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel &label) {
- DWARFDIE definition;
- Module::LookupInfo info(ConstString(label.lookup_name),
- lldb::eFunctionNameTypeFull,
- lldb::eLanguageTypeUnknown);
-
- m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
- if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
- return IterationAction::Continue;
+static llvm::StringRef ClangToItaniumCtorKind(clang::CXXCtorType kind) {
+ switch (kind) {
+ case clang::CXXCtorType::Ctor_Complete:
+ return "C1";
+ case clang::CXXCtorType::Ctor_Base:
+ return "C2";
+ case clang::CXXCtorType::Ctor_Unified:
+ return "C4";
+ case clang::CXXCtorType::Ctor_CopyingClosure:
+ case clang::CXXCtorType::Ctor_DefaultClosure:
+ case clang::CXXCtorType::Ctor_Comdat:
+ llvm_unreachable("Unexpected constructor kind.");
+ }
+}
- // We don't check whether the specification DIE for this function
- // corresponds to the declaration DIE because the declaration might be in
- // a type-unit but the definition in the compile-unit (and it's
- // specifcation would point to the declaration in the compile-unit). We
- // rely on the mangled name within the module to be enough to find us the
- // unique definition.
- definition = entry;
- return IterationAction::Stop;
- });
+static llvm::StringRef ClangToItaniumDtorKind(clang::CXXDtorType kind) {
+ switch (kind) {
+ case clang::CXXDtorType::Dtor_Deleting:
+ return "D0";
+ case clang::CXXDtorType::Dtor_Complete:
+ return "D1";
+ case clang::CXXDtorType::Dtor_Base:
+ return "D2";
+ case clang::CXXDtorType::Dtor_Unified:
+ return "D4";
+ case clang::CXXDtorType::Dtor_Comdat:
+ llvm_unreachable("Unexpected destructor kind.");
+ }
+}
+
+static llvm::StringRef
+GetItaniumCtorDtorVariant(llvm::StringRef discriminator) {
+ const bool is_ctor = discriminator.consume_front("C");
+ if (!is_ctor && !discriminator.consume_front("D"))
+ return {};
+
+ uint64_t structor_kind;
+ if (!llvm::to_integer(discriminator, structor_kind))
+ return {};
+
+ if (is_ctor) {
+ if (structor_kind > clang::CXXCtorType::Ctor_Unified)
+ return {};
+
+ return ClangToItaniumCtorKind(
+ static_cast<clang::CXXCtorType>(structor_kind));
+ }
+
+ if (structor_kind > clang::CXXDtorType::Dtor_Unified)
+ return {};
+
+ return ClangToItaniumDtorKind(static_cast<clang::CXXDtorType>(structor_kind));
+}
+
+llvm::Expected<DWARFDIE>
+SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel &label,
+ const DWARFDIE &declaration) {
+ auto do_lookup = [this](llvm::StringRef lookup_name) -> DWARFDIE {
+ DWARFDIE found;
+ Module::LookupInfo info(ConstString(lookup_name),
+ lldb::eFunctionNameTypeFull,
+ lldb::eLanguageTypeUnknown);
+
+ m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) {
+ if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))
+ return IterationAction::Continue;
+
+ found = entry;
+ return IterationAction::Stop;
+ });
+
+ return found;
+ };
+
+ DWARFDIE definition = do_lookup(label.lookup_name);
+ if (definition.IsValid())
+ return definition;
+
+ // This is not a structor lookup. Nothing else to be done here.
+ if (label.discriminator.empty())
+ return llvm::createStringError(
+ "no definition DIE found in this SymbolFile");
+
+ // We're doing a structor lookup. Maybe we didn't find the structor variant
+ // because the complete object structor was aliased to the base object
+ // structor. Try finding the alias instead.
+ //
+ // TODO: there are other reasons for why a subprogram definition might be
+ // missing. Ideally DWARF would tell us more details about which structor
+ // variant a DIE corresponds to and whether it's an alias.
+ auto subst_or_err =
+ CPlusPlusLanguage::SubstituteStructorAliases_ItaniumMangle(
+ label.lookup_name);
+ if (!subst_or_err)
+ return subst_or_err.takeError();
+
+ definition = do_lookup(*subst_or_err);
+
+ if (!definition.IsValid())
+ return llvm::createStringError(
+ "failed to find definition DIE for structor alias in fallback lookup");
return definition;
}
llvm::Expected<SymbolContext>
-SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) {
+SymbolFileDWARF::ResolveFunctionCallLabel(FunctionCallLabel &label) {
std::lock_guard<std::recursive_mutex> guard(GetModuleMutex());
+ if (!label.discriminator.empty()) {
+ llvm::StringRef from = label.discriminator[0] == 'C' ? "C4" : "D4";
+
+ llvm::StringRef variant = GetItaniumCtorDtorVariant(label.discriminator);
+ if (variant.empty())
+ return llvm::createStringError(
+ "failed to get Itanium variant for discriminator");
+
+ if (from == variant)
+ return llvm::createStringError(
+ "tried substituting unified structor variant into label");
+
+ // If we failed to substitute unified mangled name, don't try to do a lookup
+ // using the unified name because there may be multiple definitions for it
+ // in the index, and we wouldn't know which one to choose.
+ auto subst_or_err = CPlusPlusLanguage::SubstituteStructor_ItaniumMangle(
+ label.lookup_name, from, variant);
+ if (!subst_or_err)
+ return llvm::joinErrors(
+ llvm::createStringError(llvm::formatv(
+ "failed to substitute {0} for {1} in mangled name {2}:", from,
+ variant, label.lookup_name)),
+ subst_or_err.takeError());
+
+ if (!*subst_or_err)
+ return llvm::createStringError(
+ llvm::formatv("got invalid substituted mangled named (substituted "
+ "{0} for {1} in mangled name {2})",
+ from, variant, label.lookup_name));
+
+ label.lookup_name = subst_or_err->GetStringRef();
+ }
+
DWARFDIE die = GetDIE(label.symbol_id);
if (!die.IsValid())
return llvm::createStringError(
@@ -2520,11 +2639,13 @@ SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) {
// Label was created using a declaration DIE. Need to fetch the definition
// to resolve the function call.
if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) {
- auto definition = FindFunctionDefinition(label);
- if (!definition)
- return llvm::createStringError("failed to find definition DIE");
+ auto die_or_err = FindFunctionDefinition(label, die);
+ if (!die_or_err)
+ return llvm::joinErrors(
+ llvm::createStringError("failed to find definition DIE:"),
+ die_or_err.takeError());
- die = std::move(definition);
+ die = std::move(*die_or_err);
}
SymbolContextList sc_list;
@@ -4502,9 +4623,8 @@ void SymbolFileDWARF::GetCompileOptions(
}
}
-std::pair<uint32_t, uint32_t> SymbolFileDWARF::GetDwoFileCounts() {
- uint32_t total_dwo_count = 0;
- uint32_t loaded_dwo_count = 0;
+DWOStats SymbolFileDWARF::GetDwoStats() {
+ DWOStats stats;
DWARFDebugInfo &info = DebugInfo();
const size_t num_cus = info.GetNumUnits();
@@ -4517,16 +4637,21 @@ std::pair<uint32_t, uint32_t> SymbolFileDWARF::GetDwoFileCounts() {
if (!dwarf_cu->GetDWOId().has_value())
continue;
- total_dwo_count++;
+ stats.dwo_file_count++;
// If we have a DWO symbol file, that means we were able to successfully
// load it.
SymbolFile *dwo_symfile =
dwarf_cu->GetDwoSymbolFile(/*load_all_debug_info=*/false);
if (dwo_symfile) {
- loaded_dwo_count++;
+ stats.loaded_dwo_file_count++;
}
+
+ // Check if this unit has a DWO load error, false by default.
+ const Status &dwo_error = dwarf_cu->GetDwoError();
+ if (dwo_error.Fail())
+ stats.dwo_error_count++;
}
- return {loaded_dwo_count, total_dwo_count};
+ return stats;
}