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
38 changes: 36 additions & 2 deletions lldb/include/lldb/Core/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,15 @@ class Module : public std::enable_shared_from_this<Module>,
const ModuleFunctionSearchOptions &options,
SymbolContextList &sc_list);

/// Find functions by a vector of lookup infos.
///
/// If the function is an inlined function, it will have a block,
/// representing the inlined function, and the function will be the
/// containing function. If it is not inlined, then the block will be NULL.
void FindFunctions(const std::vector<LookupInfo> &lookup_infos,
Copy link
Contributor

@felipepiovezan felipepiovezan Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should never use const vector& as a parameter inside LLVM, favouring llvm::ArrayRef instead, as it works with more kinds of containers and, more importantly, it works with a single element of the value type.

const CompilerDeclContext &parent_decl_ctx,
const ModuleFunctionSearchOptions &options,
SymbolContextList &sc_list);
/// Find functions by name.
///
/// If the function is an inlined function, it will have a block,
Expand Down Expand Up @@ -917,8 +926,29 @@ class Module : public std::enable_shared_from_this<Module>,
public:
LookupInfo() = default;

LookupInfo(ConstString name, lldb::FunctionNameType name_type_mask,
lldb::LanguageType language);
/// Creates a vector of lookup infos for function name resolution.
///
/// \param[in] name
/// The function name to search for. This can be a simple name like
/// "foo" or a qualified name like "Class::method".
///
/// \param[in] name_type_mask
/// A bitmask specifying what types of names to search for
/// (e.g., eFunctionNameTypeFull, eFunctionNameTypeBase,
/// eFunctionNameTypeMethod, eFunctionNameTypeAuto). Multiple types
/// can be combined with bitwise OR.
///
/// \param[in] lang_type
/// The language to create lookups for. If eLanguageTypeUnknown is
/// passed, creates one LookupInfo for each language plugin currently
/// available in LLDB. If a specific language is provided, creates only
// a single LookupInfo for that language.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I am a bit late to the party, but I think this is odd from an interface point of view. We could probably have two overloads: one which takes a LanguageType, and returns a single LookupInfo, and one which doesn't take a LanguageType, and returns a vector of LookupInfo.

As it stands, we are making all clients of this function handle vector types, which feels wrong, as it creates more code paths to check for (e.g. check that the vector is not empty, and check that the vector contains a single element). By having the specialized signature, we define all these runtime checks away.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess the existence of the "unknown enum" makes it annoying to have this different API.... :(

///
/// \return
/// A vector of LookupInfo objects, one per relevant language.
static std::vector<LookupInfo>
MakeLookupInfos(ConstString name, lldb::FunctionNameType name_type_mask,
lldb::LanguageType lang_type);

ConstString GetName() const { return m_name; }

Expand Down Expand Up @@ -959,6 +989,10 @@ class Module : public std::enable_shared_from_this<Module>,
/// If \b true, then demangled names that match will need to contain
/// "m_name" in order to be considered a match
bool m_match_name_after_lookup = false;

private:
LookupInfo(ConstString name, lldb::FunctionNameType name_type_mask,
lldb::LanguageType lang_type);
};

/// Get a unique hash for this module.
Expand Down
14 changes: 14 additions & 0 deletions lldb/include/lldb/Symbol/SymbolContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,20 @@ class SymbolContext {

lldb::LanguageType GetLanguage() const;

/// Compares the two symbol contexts, considering that the symbol may or may
/// not be present. If both symbols are present, compare them, if one of the
/// symbols is not present, consider the symbol contexts as equal as long as
/// the other fields are equal.
///
/// This function exists because SymbolContexts are often created without the
/// symbol, which is filled in later on, after its creation.
static bool CompareConsideringPossiblyNullSymbol(const SymbolContext &lhs,
const SymbolContext &rhs);

/// Compares the two symbol contexts, except for the symbol field.
static bool CompareWithoutSymbol(const SymbolContext &lhs,
const SymbolContext &rhs);

/// Find a block that defines the function represented by this symbol
/// context.
///
Expand Down
4 changes: 4 additions & 0 deletions lldb/include/lldb/Symbol/SymbolFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,10 @@ class SymbolFile : public PluginInterface {
virtual void FindFunctions(const Module::LookupInfo &lookup_info,
const CompilerDeclContext &parent_decl_ctx,
bool include_inlines, SymbolContextList &sc_list);
virtual void
FindFunctions(const std::vector<Module::LookupInfo> &lookup_infos,
const CompilerDeclContext &parent_decl_ctx,
bool include_inlines, SymbolContextList &sc_list);
virtual void FindFunctions(const RegularExpression &regex,
bool include_inlines, SymbolContextList &sc_list);

Expand Down
33 changes: 22 additions & 11 deletions lldb/source/Breakpoint/BreakpointResolverName.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -218,19 +218,22 @@ StructuredData::ObjectSP BreakpointResolverName::SerializeToStructuredData() {

void BreakpointResolverName::AddNameLookup(ConstString name,
FunctionNameType name_type_mask) {

Module::LookupInfo lookup(name, name_type_mask, m_language);
m_lookups.emplace_back(lookup);
std::vector<Module::LookupInfo> infos =
Module::LookupInfo::MakeLookupInfos(name, name_type_mask, m_language);
llvm::append_range(m_lookups, infos);

auto add_variant_funcs = [&](Language *lang) {
for (Language::MethodNameVariant variant :
lang->GetMethodNameVariants(name)) {
// FIXME: Should we be adding variants that aren't of type Full?
if (variant.GetType() & lldb::eFunctionNameTypeFull) {
Module::LookupInfo variant_lookup(name, variant.GetType(),
lang->GetLanguageType());
variant_lookup.SetLookupName(variant.GetName());
m_lookups.emplace_back(variant_lookup);
std::vector<Module::LookupInfo> variant_lookups =
Module::LookupInfo::MakeLookupInfos(name, variant.GetType(),
lang->GetLanguageType());
llvm::for_each(variant_lookups, [&](auto &variant_lookup) {
variant_lookup.SetLookupName(variant.GetName());
});
llvm::append_range(m_lookups, variant_lookups);
}
}
return IterationAction::Continue;
Expand Down Expand Up @@ -401,14 +404,22 @@ void BreakpointResolverName::GetDescription(Stream *s) {
if (m_match_type == Breakpoint::Regexp)
s->Printf("regex = '%s'", m_regex.GetText().str().c_str());
else {
size_t num_names = m_lookups.size();
if (num_names == 1)
s->Printf("name = '%s'", m_lookups[0].GetName().GetCString());
// Since there may be many lookups objects for the same name breakpoint (one
// per language available), unique them by name, and operate on those unique
// names.
std::vector<ConstString> unique_lookups;
for (auto &lookup : m_lookups) {
if (!llvm::is_contained(unique_lookups, lookup.GetName()))
unique_lookups.push_back(lookup.GetName());
}
if (unique_lookups.size() == 1)
s->Printf("name = '%s'", unique_lookups[0].GetCString());
else {
size_t num_names = unique_lookups.size();
s->Printf("names = {");
for (size_t i = 0; i < num_names; i++) {
s->Printf("%s'%s'", (i == 0 ? "" : ", "),
m_lookups[i].GetName().GetCString());
unique_lookups[i].GetCString());
}
s->Printf("}");
}
Expand Down
90 changes: 58 additions & 32 deletions lldb/source/Core/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -643,26 +643,13 @@ void Module::FindCompileUnits(const FileSpec &path,

Module::LookupInfo::LookupInfo(ConstString name,
FunctionNameType name_type_mask,
LanguageType language)
: m_name(name), m_lookup_name(name), m_language(language) {
LanguageType lang_type)
: m_name(name), m_lookup_name(name), m_language(lang_type) {
std::optional<ConstString> basename;

std::vector<Language *> languages;
{
std::vector<LanguageType> lang_types;
if (language != eLanguageTypeUnknown)
lang_types.push_back(language);
else
lang_types = {eLanguageTypeObjC, eLanguageTypeC_plus_plus};

for (LanguageType lang_type : lang_types) {
if (Language *lang = Language::FindPlugin(lang_type))
languages.push_back(lang);
}
}
Language *lang = Language::FindPlugin(lang_type);

if (name_type_mask & eFunctionNameTypeAuto) {
for (Language *lang : languages) {
if (lang) {
auto info = lang->GetFunctionNameInfo(name);
if (info.first != eFunctionNameTypeNone) {
m_name_type_mask |= info.first;
Expand All @@ -679,7 +666,7 @@ Module::LookupInfo::LookupInfo(ConstString name,

} else {
m_name_type_mask = name_type_mask;
for (Language *lang : languages) {
if (lang) {
auto info = lang->GetFunctionNameInfo(name);
if (info.first & m_name_type_mask) {
// If the user asked for FunctionNameTypes that aren't possible,
Expand All @@ -688,14 +675,12 @@ Module::LookupInfo::LookupInfo(ConstString name,
// ObjC)
m_name_type_mask &= info.first;
basename = info.second;
break;
}
// Still try and get a basename in case someone specifies a name type mask
// of eFunctionNameTypeFull and a name like "A::func"
if (name_type_mask & eFunctionNameTypeFull &&
info.first != eFunctionNameTypeNone && !basename && info.second) {
} else if (name_type_mask & eFunctionNameTypeFull &&
info.first != eFunctionNameTypeNone && !basename &&
info.second) {
// Still try and get a basename in case someone specifies a name type
// mask of eFunctionNameTypeFull and a name like "A::func"
basename = info.second;
break;
}
}
}
Expand All @@ -711,6 +696,36 @@ Module::LookupInfo::LookupInfo(ConstString name,
}
}

std::vector<Module::LookupInfo>
Module::LookupInfo::MakeLookupInfos(ConstString name,
lldb::FunctionNameType name_type_mask,
lldb::LanguageType lang_type) {
std::vector<LanguageType> lang_types;
if (lang_type != eLanguageTypeUnknown) {
lang_types.push_back(lang_type);
} else {
// If the language type was not specified, look up in every language
// available.
Language::ForEach([&](Language *lang) {
auto lang_type = lang->GetLanguageType();
if (!llvm::is_contained(lang_types, lang_type))
lang_types.push_back(lang_type);
return IterationAction::Continue;
});

if (lang_types.empty())
lang_types = {eLanguageTypeObjC, eLanguageTypeC_plus_plus};
}

std::vector<Module::LookupInfo> infos;
infos.reserve(lang_types.size());
for (LanguageType lang_type : lang_types) {
Module::LookupInfo info(name, name_type_mask, lang_type);
infos.push_back(info);
Comment on lines +723 to +724
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we emplace_back and do the creation inline?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm apparently we can't because LookupInfo's constructor is private so vector can't access it.

}
return infos;
}

bool Module::LookupInfo::NameMatchesLookupInfo(
ConstString function_name, LanguageType language_type) const {
// We always keep unnamed symbols
Expand Down Expand Up @@ -824,18 +839,29 @@ void Module::FindFunctions(const Module::LookupInfo &lookup_info,
}
}

void Module::FindFunctions(const std::vector<Module::LookupInfo> &lookup_infos,
const CompilerDeclContext &parent_decl_ctx,
const ModuleFunctionSearchOptions &options,
SymbolContextList &sc_list) {
for (auto &lookup_info : lookup_infos)
FindFunctions(lookup_info, parent_decl_ctx, options, sc_list);
}

void Module::FindFunctions(ConstString name,
const CompilerDeclContext &parent_decl_ctx,
FunctionNameType name_type_mask,
const ModuleFunctionSearchOptions &options,
SymbolContextList &sc_list) {
const size_t old_size = sc_list.GetSize();
LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
FindFunctions(lookup_info, parent_decl_ctx, options, sc_list);
if (name_type_mask & eFunctionNameTypeAuto) {
const size_t new_size = sc_list.GetSize();
if (old_size < new_size)
lookup_info.Prune(sc_list, old_size);
std::vector<LookupInfo> lookup_infos =
LookupInfo::MakeLookupInfos(name, name_type_mask, eLanguageTypeUnknown);
for (auto &lookup_info : lookup_infos) {
const size_t old_size = sc_list.GetSize();
FindFunctions(lookup_info, parent_decl_ctx, options, sc_list);
if (name_type_mask & eFunctionNameTypeAuto) {
const size_t new_size = sc_list.GetSize();
if (old_size < new_size)
lookup_info.Prune(sc_list, old_size);
}
}
}

Expand Down
48 changes: 26 additions & 22 deletions lldb/source/Core/ModuleList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -453,21 +453,22 @@ void ModuleList::FindFunctions(ConstString name,
FunctionNameType name_type_mask,
const ModuleFunctionSearchOptions &options,
SymbolContextList &sc_list) const {
const size_t old_size = sc_list.GetSize();

if (name_type_mask & eFunctionNameTypeAuto) {
Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);

std::vector<Module::LookupInfo> lookup_infos =
Module::LookupInfo::MakeLookupInfos(name, name_type_mask,
eLanguageTypeUnknown);
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
for (const ModuleSP &module_sp : m_modules) {
module_sp->FindFunctions(lookup_info, CompilerDeclContext(), options,
sc_list);
}

const size_t new_size = sc_list.GetSize();
for (const auto &lookup_info : lookup_infos) {
const size_t old_size = sc_list.GetSize();
for (const ModuleSP &module_sp : m_modules) {
module_sp->FindFunctions(lookup_info, CompilerDeclContext(), options,
sc_list);
}

if (old_size < new_size)
lookup_info.Prune(sc_list, old_size);
const size_t new_size = sc_list.GetSize();
if (old_size < new_size)
lookup_info.Prune(sc_list, old_size);
}
} else {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
for (const ModuleSP &module_sp : m_modules) {
Expand All @@ -480,21 +481,24 @@ void ModuleList::FindFunctions(ConstString name,
void ModuleList::FindFunctionSymbols(ConstString name,
lldb::FunctionNameType name_type_mask,
SymbolContextList &sc_list) {
const size_t old_size = sc_list.GetSize();

if (name_type_mask & eFunctionNameTypeAuto) {
Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown);
std::vector<Module::LookupInfo> lookup_infos =
Module::LookupInfo::MakeLookupInfos(name, name_type_mask,
eLanguageTypeUnknown);

std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
for (const ModuleSP &module_sp : m_modules) {
module_sp->FindFunctionSymbols(lookup_info.GetLookupName(),
lookup_info.GetNameTypeMask(), sc_list);
}
for (const auto &lookup_info : lookup_infos) {
const size_t old_size = sc_list.GetSize();
for (const ModuleSP &module_sp : m_modules) {
module_sp->FindFunctionSymbols(lookup_info.GetLookupName(),
lookup_info.GetNameTypeMask(), sc_list);
}

const size_t new_size = sc_list.GetSize();
const size_t new_size = sc_list.GetSize();

if (old_size < new_size)
lookup_info.Prune(sc_list, old_size);
if (old_size < new_size)
lookup_info.Prune(sc_list, old_size);
}
} else {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
for (const ModuleSP &module_sp : m_modules) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ void SymbolFileBreakpad::FindFunctions(
sc.comp_unit = cu_sp.get();
sc.function = func_sp.get();
sc.module_sp = func_sp->CalculateSymbolContextModule();
sc_list.Append(sc);
sc_list.AppendIfUnique(sc, /*merge_symbol_into_function=*/true);
}
}
}
Expand Down
8 changes: 8 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,14 @@ void DWARFIndex::GetNamespacesWithParents(
});
}

void DWARFIndex::GetFunctions(
const std::vector<Module::LookupInfo> &lookup_infos, SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
for (auto &lookup_info : lookup_infos)
GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
}

IterationAction DWARFIndex::ProcessNamespaceDieMatchParents(
const CompilerDeclContext &parent_decl_ctx, DWARFDIE die,
llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
Expand Down
5 changes: 5 additions & 0 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ class DWARFIndex {
const CompilerDeclContext &parent_decl_ctx,
llvm::function_ref<IterationAction(DWARFDIE die)> callback) = 0;
virtual void
GetFunctions(const std::vector<Module::LookupInfo> &lookup_infos,
SymbolFileDWARF &dwarf,
const CompilerDeclContext &parent_decl_ctx,
llvm::function_ref<IterationAction(DWARFDIE die)> callback);
virtual void
GetFunctions(const RegularExpression &regex,
llvm::function_ref<IterationAction(DWARFDIE die)> callback) = 0;

Expand Down
Loading
Loading