summaryrefslogtreecommitdiff
path: root/lldb/source/Plugins/SymbolFile/DWARF
diff options
context:
space:
mode:
authorMingming Liu <mingmingl@google.com>2025-09-10 15:25:31 -0700
committerGitHub <noreply@github.com>2025-09-10 15:25:31 -0700
commit1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch)
tree57f4b1f313c8cf74eed8819870f39c36ea263c68 /lldb/source/Plugins/SymbolFile/DWARF
parent898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff)
parentb8cefcb601ddaa18482555c4ff363c01a270c2fe (diff)
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF')
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp18
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp185
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h15
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp4
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h2
5 files changed, 183 insertions, 41 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
index a429ea848b7f..5ffb4423969c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -252,7 +252,7 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram,
}
static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
- char const *name = die.GetMangledName(/*substitute_name_allowed*/ false);
+ const char *name = die.GetMangledName(/*substitute_name_allowed*/ false);
if (!name)
return {};
@@ -286,7 +286,9 @@ static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) {
if (die_id == LLDB_INVALID_UID)
return {};
- return FunctionCallLabel{/*module_id=*/module_id,
+ // Note, discriminator is added by Clang during mangling.
+ return FunctionCallLabel{/*discriminator=*/{},
+ /*module_id=*/module_id,
/*symbol_id=*/die_id,
/*.lookup_name=*/name}
.toString();
@@ -2230,6 +2232,18 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die,
for (DelayedAddObjCClassProperty &property : delayed_properties)
property.Finalize();
}
+ } else if (Language::LanguageIsObjC(
+ static_cast<LanguageType>(die.GetAttributeValueAsUnsigned(
+ DW_AT_APPLE_runtime_class, eLanguageTypeUnknown)))) {
+ /// The forward declaration was C++ but the definition is Objective-C.
+ /// We currently don't handle such situations. In such cases, keep the
+ /// forward declaration without a definition to avoid violating Clang AST
+ /// invariants.
+ LLDB_LOG(GetLog(LLDBLog::Expressions),
+ "WARNING: Type completion aborted because forward declaration for "
+ "'{0}' is C++ while definition is Objective-C.",
+ llvm::StringRef(die.GetName()));
+ return {};
}
if (!bases.empty()) {
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;
}
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index d7db8a3c0869..85306d8b4fb5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -283,10 +283,11 @@ public:
bool GetSeparateDebugInfo(StructuredData::Dictionary &d, bool errors_only,
bool load_all_debug_info = false) override;
- // Gets a pair of loaded and total dwo file counts.
- // For split-dwarf files, this reports the counts for successfully loaded DWO
- // CUs and total DWO CUs. For non-split-dwarf files, this reports 0 for both.
- std::pair<uint32_t, uint32_t> GetDwoFileCounts() override;
+ /// Gets statistics about dwo files associated with this symbol file.
+ /// For split-dwarf files, this reports the counts for successfully loaded DWO
+ /// CUs, total DWO CUs, and the number of DWO CUs with loading errors.
+ /// For non-split-dwarf files, this reports 0 for all.
+ DWOStats GetDwoStats() override;
DWARFContext &GetDWARFContext() { return m_context; }
@@ -378,7 +379,9 @@ private:
/// SymbolFile.
///
/// \returns A valid definition DIE on success.
- DWARFDIE FindFunctionDefinition(const FunctionCallLabel &label);
+ llvm::Expected<DWARFDIE>
+ FindFunctionDefinition(const FunctionCallLabel &label,
+ const DWARFDIE &declaration);
protected:
SymbolFileDWARF(const SymbolFileDWARF &) = delete;
@@ -445,7 +448,7 @@ protected:
DIEArray &&variable_dies);
llvm::Expected<SymbolContext>
- ResolveFunctionCallLabel(const FunctionCallLabel &label) override;
+ ResolveFunctionCallLabel(FunctionCallLabel &label) override;
// Given a die_offset, figure out the symbol context representing that die.
bool ResolveFunction(const DWARFDIE &die, bool include_inlines,
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
index 9d7452a1988f..8b8229a7020c 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp
@@ -1603,8 +1603,8 @@ void SymbolFileDWARFDebugMap::GetCompileOptions(
});
}
-llvm::Expected<SymbolContext> SymbolFileDWARFDebugMap::ResolveFunctionCallLabel(
- const FunctionCallLabel &label) {
+llvm::Expected<SymbolContext>
+SymbolFileDWARFDebugMap::ResolveFunctionCallLabel(FunctionCallLabel &label) {
const uint64_t oso_idx = GetOSOIndexFromUserID(label.symbol_id);
SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx);
if (!oso_dwarf)
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
index e1f1df23951c..bce1ed2671af 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h
@@ -145,7 +145,7 @@ public:
GetCompileOptions(std::unordered_map<lldb::CompUnitSP, Args> &args) override;
llvm::Expected<SymbolContext>
- ResolveFunctionCallLabel(const FunctionCallLabel &label) override;
+ ResolveFunctionCallLabel(FunctionCallLabel &label) override;
protected:
enum { kHaveInitializedOSOs = (1 << 0), kNumFlags };