diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp')
| -rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 185 |
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; } |
