Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions lldb/include/lldb/Expression/Expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,15 @@ class Expression {
///
/// The format being:
///
/// <prefix>:<module uid>:<symbol uid>:<name>
/// <prefix>:<discriminator>:<module uid>:<symbol uid>:<name>
///
/// The label string needs to stay valid for the entire lifetime
/// of this object.
struct FunctionCallLabel {
/// Arbitrary string which language plugins can interpret for their
/// own needs.
llvm::StringRef discriminator;

/// Unique identifier of the lldb_private::Module
/// which contains the symbol identified by \c symbol_id.
lldb::user_id_t module_id;
Expand All @@ -133,7 +137,7 @@ struct FunctionCallLabel {
///
/// The representation roundtrips through \c fromString:
/// \code{.cpp}
/// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov";
/// llvm::StringRef encoded = "$__lldb_func:blah:0x0:0x0:_Z3foov";
/// FunctionCallLabel label = *fromString(label);
///
/// assert (label.toString() == encoded);
Expand Down
4 changes: 2 additions & 2 deletions lldb/include/lldb/Symbol/SymbolFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,12 +332,12 @@ class SymbolFile : public PluginInterface {
/// Resolves the function corresponding to the specified LLDB function
/// call \c label.
///
/// \param[in] label The FunctionCallLabel to be resolved.
/// \param[in,out] label The FunctionCallLabel to be resolved.
///
/// \returns An llvm::Error if the specified \c label couldn't be resolved.
/// Returns the resolved function (as a SymbolContext) otherwise.
virtual llvm::Expected<SymbolContext>
ResolveFunctionCallLabel(const FunctionCallLabel &label) {
ResolveFunctionCallLabel(FunctionCallLabel &label) {
return llvm::createStringError("Not implemented");
}

Expand Down
29 changes: 17 additions & 12 deletions lldb/source/Expression/Expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,21 @@ Expression::Expression(ExecutionContextScope &exe_scope)

llvm::Expected<FunctionCallLabel>
lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
llvm::SmallVector<llvm::StringRef, 4> components;
label.split(components, ":", /*MaxSplit=*/3);
llvm::SmallVector<llvm::StringRef, 5> components;
label.split(components, ":", /*MaxSplit=*/4);

if (components.size() != 4)
if (components.size() != 5)
return llvm::createStringError("malformed function call label.");

if (components[0] != FunctionCallLabelPrefix)
return llvm::createStringError(llvm::formatv(
"expected function call label prefix '{0}' but found '{1}' instead.",
FunctionCallLabelPrefix, components[0]));

llvm::StringRef module_label = components[1];
llvm::StringRef die_label = components[2];
llvm::StringRef discriminator = components[1];
llvm::StringRef module_label = components[2];
llvm::StringRef die_label = components[3];
llvm::StringRef lookup_name = components[4];

lldb::user_id_t module_id = 0;
if (!llvm::to_integer(module_label, module_id))
Expand All @@ -58,20 +60,23 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) {
return llvm::createStringError(
llvm::formatv("failed to parse symbol ID from '{0}'.", die_label));

return FunctionCallLabel{/*.module_id=*/module_id,
return FunctionCallLabel{/*.discriminator=*/discriminator,
/*.module_id=*/module_id,
/*.symbol_id=*/die_id,
/*.lookup_name=*/components[3]};
/*.lookup_name=*/lookup_name};
}

std::string lldb_private::FunctionCallLabel::toString() const {
return llvm::formatv("{0}:{1:x}:{2:x}:{3}", FunctionCallLabelPrefix,
module_id, symbol_id, lookup_name)
return llvm::formatv("{0}:{1}:{2:x}:{3:x}:{4}", FunctionCallLabelPrefix,
discriminator, module_id, symbol_id, lookup_name)
.str();
}

void llvm::format_provider<FunctionCallLabel>::format(
const FunctionCallLabel &label, raw_ostream &OS, StringRef Style) {
OS << llvm::formatv("FunctionCallLabel{ module_id: {0:x}, symbol_id: {1:x}, "
"lookup_name: {2} }",
label.module_id, label.symbol_id, label.lookup_name);
OS << llvm::formatv("FunctionCallLabel{ discriminator: {0}, module_id: "
"{1:x}, symbol_id: {2:x}, "
"lookup_name: {3} }",
label.discriminator, label.module_id, label.symbol_id,
label.lookup_name);
}
2 changes: 1 addition & 1 deletion lldb/source/Expression/IRExecutionUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ class LoadAddressResolver {
/// Returns address of the function referred to by the special function call
/// label \c label.
static llvm::Expected<lldb::addr_t>
ResolveFunctionCallLabel(const FunctionCallLabel &label,
ResolveFunctionCallLabel(FunctionCallLabel &label,
const lldb_private::SymbolContext &sc,
bool &symbol_was_missing_weak) {
symbol_was_missing_weak = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};

Expand Down Expand Up @@ -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();
Expand Down
169 changes: 145 additions & 24 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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"
Expand Down Expand Up @@ -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"

Expand Down Expand Up @@ -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(
Expand All @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,9 @@ class SymbolFileDWARF : public SymbolFileCommon {
/// 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;
Expand Down Expand Up @@ -445,7 +447,7 @@ class SymbolFileDWARF : public SymbolFileCommon {
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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon {
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 };
Expand Down
3 changes: 3 additions & 0 deletions lldb/test/API/lang/cpp/abi_tag_structors/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
CXX_SOURCES := main.cpp

include Makefile.rules
Loading
Loading