From 87a26cef46aace78ac5901861478a3b7ca19a384 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 15 Nov 2024 01:59:36 +0000 Subject: [PATCH 01/38] [lldb][Expression] Encode Module and DIE UIDs into function AsmLabels --- lldb/include/lldb/Core/Module.h | 4 +- lldb/include/lldb/Expression/Expression.h | 25 +++++++ lldb/include/lldb/Symbol/SymbolFile.h | 14 ++++ lldb/include/lldb/Symbol/TypeSystem.h | 16 ++++ lldb/source/Core/Module.cpp | 19 ++++- lldb/source/Expression/Expression.cpp | 16 ++++ lldb/source/Expression/IRExecutionUnit.cpp | 74 +++++++++++++++++++ .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 21 +++++- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 41 ++++++++++ .../SymbolFile/DWARF/SymbolFileDWARF.h | 3 + .../TypeSystem/Clang/TypeSystemClang.cpp | 56 ++++++++++++++ .../TypeSystem/Clang/TypeSystemClang.h | 6 ++ lldb/unittests/Symbol/TestTypeSystemClang.cpp | 24 ++++++ 13 files changed, 312 insertions(+), 7 deletions(-) diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 8bb55c95773bc..3991a12997541 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -86,7 +86,8 @@ struct ModuleFunctionSearchOptions { /// /// The module will parse more detailed information as more queries are made. class Module : public std::enable_shared_from_this, - public SymbolContextScope { + public SymbolContextScope, + public UserID { public: class LookupInfo; // Static functions that can track the lifetime of module objects. This is @@ -97,6 +98,7 @@ class Module : public std::enable_shared_from_this, // using the "--global" (-g for short). static size_t GetNumberAllocatedModules(); + static Module *GetAllocatedModuleWithUID(lldb::user_id_t uid); static Module *GetAllocatedModuleAtIndex(size_t idx); static std::recursive_mutex &GetAllocationModuleCollectionMutex(); diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 8de9364436ccf..f32878c9bf876 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -96,6 +96,31 @@ class Expression { ///invalid. }; +/// Holds parsed information about a function call label that +/// LLDB attaches as an AsmLabel to function AST nodes it parses +/// from debug-info. +/// +/// The format being: +/// +/// ::: +/// +/// The label string needs to stay valid for the entire lifetime +/// of this object. +struct FunctionCallLabel { + llvm::StringRef m_lookup_name; + lldb::user_id_t m_module_id; + + /// Mostly for debuggability. + lldb::user_id_t m_die_id; +}; + +/// LLDB attaches this prefix to mangled names of functions that it get called +/// from JITted expressions. +inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func"; + +bool consumeFunctionCallLabelPrefix(llvm::StringRef &name); +bool hasFunctionCallLabelPrefix(llvm::StringRef name); + } // namespace lldb_private #endif // LLDB_EXPRESSION_EXPRESSION_H diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index e95f95553c17c..6aca276fc85b6 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -18,6 +18,7 @@ #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/SourceModule.h" +#include "lldb/Symbol/SymbolContext.h" #include "lldb/Symbol/Type.h" #include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/TypeSystem.h" @@ -328,6 +329,19 @@ class SymbolFile : public PluginInterface { GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector &mangled_names); + /// Resolves the function DIE identified by \c lookup_name within + /// this SymbolFile. + /// + /// \param[in,out] sc_list The resolved functions will be appended to this + /// list. + /// + /// \param[in] lookup_name The UID of the function DIE to resolve. + /// + virtual llvm::Error FindAndResolveFunction(SymbolContextList &sc_list, + llvm::StringRef lookup_name) { + return llvm::createStringError("Not implemented"); + } + virtual void GetTypes(lldb_private::SymbolContextScope *sc_scope, lldb::TypeClass type_mask, lldb_private::TypeList &type_list) = 0; diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index cb1f0130b548d..742c09251ea2f 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -548,6 +548,22 @@ class TypeSystem : public PluginInterface, bool GetHasForcefullyCompletedTypes() const { return m_has_forcefully_completed_types; } + + /// Returns the components of the specified function call label. + /// + /// The format of \c label is described in \c FunctionCallLabel. + /// The label prefix is not one of the components. + virtual llvm::Expected> + splitFunctionCallLabel(llvm::StringRef label) const { + return llvm::createStringError("Not implemented."); + } + + // Decodes the function label into a \c FunctionCallLabel. + virtual llvm::Expected + makeFunctionCallLabel(llvm::StringRef label) const { + return llvm::createStringError("Not implemented."); + } + protected: SymbolFile *m_sym_file = nullptr; /// Used for reporting statistics. diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index 90997dada3666..edd79aff5d065 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -121,6 +121,15 @@ size_t Module::GetNumberAllocatedModules() { return GetModuleCollection().size(); } +Module *Module::GetAllocatedModuleWithUID(lldb::user_id_t uid) { + std::lock_guard guard( + GetAllocationModuleCollectionMutex()); + for (Module *mod : GetModuleCollection()) + if (mod->GetID() == uid) + return mod; + return nullptr; +} + Module *Module::GetAllocatedModuleAtIndex(size_t idx) { std::lock_guard guard( GetAllocationModuleCollectionMutex()); @@ -130,8 +139,11 @@ Module *Module::GetAllocatedModuleAtIndex(size_t idx) { return nullptr; } +// TODO: needs a mutex +static lldb::user_id_t g_unique_id = 1; + Module::Module(const ModuleSpec &module_spec) - : m_unwind_table(*this), m_file_has_changed(false), + : UserID(g_unique_id++), m_unwind_table(*this), m_file_has_changed(false), m_first_file_changed_log(false) { // Scope for locker below... { @@ -236,7 +248,8 @@ Module::Module(const ModuleSpec &module_spec) Module::Module(const FileSpec &file_spec, const ArchSpec &arch, ConstString object_name, lldb::offset_t object_offset, const llvm::sys::TimePoint<> &object_mod_time) - : m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)), + : UserID(g_unique_id++), + m_mod_time(FileSystem::Instance().GetModificationTime(file_spec)), m_arch(arch), m_file(file_spec), m_object_name(object_name), m_object_offset(object_offset), m_object_mod_time(object_mod_time), m_unwind_table(*this), m_file_has_changed(false), @@ -257,7 +270,7 @@ Module::Module(const FileSpec &file_spec, const ArchSpec &arch, } Module::Module() - : m_unwind_table(*this), m_file_has_changed(false), + : UserID(g_unique_id++), m_unwind_table(*this), m_file_has_changed(false), m_first_file_changed_log(false) { std::lock_guard guard( GetAllocationModuleCollectionMutex()); diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index 93f585edfce3d..e19c804caa3c6 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -10,6 +10,10 @@ #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/Target.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" + using namespace lldb_private; Expression::Expression(Target &target) @@ -26,3 +30,15 @@ Expression::Expression(ExecutionContextScope &exe_scope) m_jit_end_addr(LLDB_INVALID_ADDRESS) { assert(m_target_wp.lock()); } + +bool lldb_private::consumeFunctionCallLabelPrefix(llvm::StringRef &name) { + // On Darwin mangled names get a '_' prefix. + name.consume_front("_"); + return name.consume_front(FunctionCallLabelPrefix); +} + +bool lldb_private::hasFunctionCallLabelPrefix(llvm::StringRef name) { + // On Darwin mangled names get a '_' prefix. + name.consume_front("_"); + return name.starts_with(FunctionCallLabelPrefix); +} diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 6f812b91a8b1d..a9ea244889cce 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -13,6 +13,7 @@ #include "llvm/IR/DiagnosticInfo.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" +#include "llvm/Support/Error.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/raw_ostream.h" @@ -20,6 +21,7 @@ #include "lldb/Core/Disassembler.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" +#include "lldb/Expression/Expression.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/ObjectFileJIT.h" #include "lldb/Host/HostInfo.h" @@ -36,6 +38,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" +#include "lldb/lldb-defines.h" #include @@ -771,6 +774,63 @@ class LoadAddressResolver { lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS; }; +/// Returns address of the function referred to by the special function call +/// label \c label. +/// +/// \param[in] label Function call label encoding the unique location of the +/// function to look up. +/// Assumes that the \c FunctionCallLabelPrefix has been +/// stripped from the front of the label. +static llvm::Expected +ResolveFunctionCallLabel(llvm::StringRef name, + const lldb_private::SymbolContext &sc, + bool &symbol_was_missing_weak) { + symbol_was_missing_weak = false; + + if (!sc.target_sp) + return llvm::createStringError("target not available."); + + auto ts_or_err = sc.target_sp->GetScratchTypeSystemForLanguage( + lldb::eLanguageTypeC_plus_plus); + if (!ts_or_err || !*ts_or_err) + return llvm::joinErrors( + llvm::createStringError( + "failed to find scratch C++ TypeSystem for current target."), + ts_or_err.takeError()); + + auto ts_sp = *ts_or_err; + + auto label_or_err = ts_sp->makeFunctionCallLabel(name); + if (!label_or_err) + return llvm::joinErrors( + llvm::createStringError("failed to create FunctionCallLabel from: %s", + name.data()), + label_or_err.takeError()); + + const auto &label = *label_or_err; + + Module *module = Module::GetAllocatedModuleWithUID(label.m_module_id); + + if (!module) + return llvm::createStringError( + llvm::formatv("failed to find module by UID {0}", label.m_module_id)); + + auto *symbol_file = module->GetSymbolFile(); + if (!symbol_file) + return llvm::createStringError( + llvm::formatv("no SymbolFile found on module {0:x}.", module)); + + SymbolContextList sc_list; + if (auto err = + symbol_file->FindAndResolveFunction(sc_list, label.m_lookup_name)) + return llvm::joinErrors( + llvm::createStringError("failed to resolve function by UID"), + std::move(err)); + + LoadAddressResolver resolver(*sc.target_sp, symbol_was_missing_weak); + return resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS); +} + lldb::addr_t IRExecutionUnit::FindInSymbols(const std::vector &names, const lldb_private::SymbolContext &sc, @@ -906,6 +966,20 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols( lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name, bool &missing_weak) { + if (hasFunctionCallLabelPrefix(name.GetStringRef())) { + if (auto addr_or_err = ResolveFunctionCallLabel(name.GetStringRef(), + m_sym_ctx, missing_weak)) { + return *addr_or_err; + } else { + LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), addr_or_err.takeError(), + "Failed to resolve function call label {1}: {0}", + name.GetStringRef()); + return LLDB_INVALID_ADDRESS; + } + } + + // TODO: do we still need the following lookups? + std::vector candidate_C_names; std::vector candidate_CPlusPlus_names; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index e58e28a260ab0..6bf3b91c900c9 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -24,6 +24,7 @@ #include "Plugins/Language/ObjC/ObjCLanguage.h" #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/Expression.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" @@ -249,12 +250,26 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram, return cv_quals; } -static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) { +static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { char const *name = die.GetMangledName(/*substitute_name_allowed*/ false); if (!name) - return {}; + return std::nullopt; - return name; + auto module_sp = die.GetModule(); + if (!module_sp) + return std::nullopt; + + lldb::user_id_t module_id = module_sp->GetID(); + if (module_id == LLDB_INVALID_UID) + return std::nullopt; + + const auto die_id = die.GetID(); + if (die_id == LLDB_INVALID_UID) + return std::nullopt; + + return llvm::formatv("{0}:{1}:{2:x}:{3:x}", FunctionCallLabelPrefix, name, + module_id, die_id) + .str(); } TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 41ab8d1b75b34..552a675c833c7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2475,6 +2475,47 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, return false; } +llvm::Error +SymbolFileDWARF::FindAndResolveFunction(SymbolContextList &sc_list, + llvm::StringRef lookup_name) { + std::lock_guard guard(GetModuleMutex()); + + DWARFDIE die; + 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 true; + + // 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. + die = entry; + return false; + }); + + if (!die.IsValid()) + return llvm::createStringError( + llvm::formatv("failed to find definition DIE for '{0}'", lookup_name)); + + if (!ResolveFunction(die, false, sc_list)) + return llvm::createStringError("failed to resolve function DIE"); + + if (sc_list.IsEmpty()) + return llvm::createStringError("no definition DIE found"); + + if (sc_list.GetSize() > 1) + return llvm::createStringError( + "found %d functions for %s but expected only 1", sc_list.GetSize(), + lookup_name.data()); + + return llvm::Error::success(); +} + bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx, const DWARFDIE &die, bool only_root_namespaces) { diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 56d8ccbd97e46..94463fa2dc2e3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -436,6 +436,9 @@ class SymbolFileDWARF : public SymbolFileCommon { DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die, DIEArray &&variable_dies); + llvm::Error FindAndResolveFunction(SymbolContextList &sc_list, + llvm::StringRef lookup_name) override; + // Given a die_offset, figure out the symbol context representing that die. bool ResolveFunction(const DWARFDIE &die, bool include_inlines, SymbolContextList &sc_list); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 836f9feebb27a..3d33c9728b8af 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -60,6 +60,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Expression/Expression.h" #include "lldb/Host/StreamFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" @@ -9055,6 +9056,13 @@ ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) { if (!mc || !mc->shouldMangleCXXName(nd)) return {}; + if (const auto *label = nd->getAttr()) { + if (auto components_or_err = splitFunctionCallLabel(label->getLabel())) + return ConstString((*components_or_err)[0]); + else + llvm::consumeError(components_or_err.takeError()); + } + llvm::SmallVector buf; llvm::raw_svector_ostream llvm_ostrm(buf); if (llvm::isa(nd)) { @@ -9777,3 +9785,51 @@ void TypeSystemClang::LogCreation() const { LLDB_LOG(log, "Created new TypeSystem for (ASTContext*){0:x} '{1}'", &getASTContext(), getDisplayName()); } + +// Expected format is: +// $__lldb_func::: +llvm::Expected> +TypeSystemClang::splitFunctionCallLabel(llvm::StringRef label) const { + if (!consumeFunctionCallLabelPrefix(label)) + return llvm::createStringError( + "expected function call label prefix not found in %s", label.data()); + if (!label.consume_front(":")) + return llvm::createStringError( + "incorrect format: expected ':' as the first character."); + + llvm::SmallVector components; + label.split(components, ":"); + + if (components.size() != 3) + return llvm::createStringError( + "incorrect format: too many label subcomponents."); + + return components; +} + +llvm::Expected +TypeSystemClang::makeFunctionCallLabel(llvm::StringRef label) const { + auto components_or_err = splitFunctionCallLabel(label); + if (!components_or_err) + return llvm::joinErrors( + llvm::createStringError("Failed to decode function call label"), + components_or_err.takeError()); + + const auto &components = *components_or_err; + + llvm::StringRef module_label = components[1]; + llvm::StringRef die_label = components[2]; + + lldb::user_id_t module_id = 0; + if (module_label.consumeInteger(0, module_id)) + return llvm::createStringError( + llvm::formatv("failed to parse module ID from '{0}'.", components[1])); + + lldb::user_id_t die_id; + if (die_label.consumeInteger(/*Radix=*/0, die_id)) + return llvm::createStringError( + llvm::formatv("failed to parse DIE ID from '{0}'.", components[2])); + + return FunctionCallLabel{/*.m_lookup_name =*/components[0], + /*.m_module_id =*/module_id, /*.m_die_id =*/die_id}; +} diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index de66bb68c6a4c..4e92a452af815 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -1098,6 +1098,12 @@ class TypeSystemClang : public TypeSystem { lldb::opaque_compiler_type_t type, Stream &s, lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override; + llvm::Expected> + splitFunctionCallLabel(llvm::StringRef label) const override; + + llvm::Expected + makeFunctionCallLabel(llvm::StringRef label) const override; + static void DumpTypeName(const CompilerType &type); static clang::EnumDecl *GetAsEnumDecl(const CompilerType &type); diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index 57857676c7df9..228ee2ed9b6ea 100644 --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -869,7 +869,11 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) { CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U); FunctionDecl *func = m_ast->CreateFunctionDeclaration( TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None, +<<<<<<< HEAD false, /*asm_label=*/{}); +======= + false, std::nullopt); +>>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -900,7 +904,11 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) { // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine. FunctionDecl *func = m_ast->CreateFunctionDeclaration( TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None, +<<<<<<< HEAD false, /*asm_label=*/{}); +======= + false, std::nullopt); +>>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -938,7 +946,11 @@ TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) { bool is_attr_used = false; bool is_artificial = false; m_ast->AddMethodToCXXRecordType( +<<<<<<< HEAD t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, +======= + t.GetOpaqueQualType(), class_name, std::nullopt, function_type, +>>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); @@ -975,7 +987,11 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { CompilerType function_type = m_ast->CreateFunctionType( return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( +<<<<<<< HEAD t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, +======= + t.GetOpaqueQualType(), class_name, std::nullopt, function_type, +>>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -987,7 +1003,11 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { m_ast->CreateFunctionType(return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( +<<<<<<< HEAD t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, +======= + t.GetOpaqueQualType(), class_name, std::nullopt, function_type, +>>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -1098,7 +1118,11 @@ TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) { m_ast->CreateFunctionType(return_type, param_types, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( +<<<<<<< HEAD t.GetOpaqueQualType(), "myFunc", /*asm_label=*/{}, function_type, +======= + t.GetOpaqueQualType(), "myFunc", std::nullopt, function_type, +>>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); From 818cf2287f8f7ef79af92de8d955ed1397e7ca74 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 21 Jul 2025 12:15:24 +0100 Subject: [PATCH 02/38] fixup! add quotes --- lldb/source/Expression/IRExecutionUnit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index a9ea244889cce..40635d0829168 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -972,7 +972,7 @@ lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name, return *addr_or_err; } else { LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), addr_or_err.takeError(), - "Failed to resolve function call label {1}: {0}", + "Failed to resolve function call label '{1}': {0}", name.GetStringRef()); return LLDB_INVALID_ADDRESS; } From 53a43aaf5b83b9416af2f2a6bb5960e2e499b4f9 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 11:43:17 +0100 Subject: [PATCH 03/38] fixup! create literal AsmLabels --- lldb/include/lldb/Expression/Expression.h | 3 --- lldb/source/Expression/Expression.cpp | 12 ------------ lldb/source/Expression/IRExecutionUnit.cpp | 2 +- .../Plugins/TypeSystem/Clang/TypeSystemClang.cpp | 2 +- 4 files changed, 2 insertions(+), 17 deletions(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index f32878c9bf876..9044d26cf6670 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -118,9 +118,6 @@ struct FunctionCallLabel { /// from JITted expressions. inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func"; -bool consumeFunctionCallLabelPrefix(llvm::StringRef &name); -bool hasFunctionCallLabelPrefix(llvm::StringRef name); - } // namespace lldb_private #endif // LLDB_EXPRESSION_EXPRESSION_H diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index e19c804caa3c6..f85a3284d7eda 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -30,15 +30,3 @@ Expression::Expression(ExecutionContextScope &exe_scope) m_jit_end_addr(LLDB_INVALID_ADDRESS) { assert(m_target_wp.lock()); } - -bool lldb_private::consumeFunctionCallLabelPrefix(llvm::StringRef &name) { - // On Darwin mangled names get a '_' prefix. - name.consume_front("_"); - return name.consume_front(FunctionCallLabelPrefix); -} - -bool lldb_private::hasFunctionCallLabelPrefix(llvm::StringRef name) { - // On Darwin mangled names get a '_' prefix. - name.consume_front("_"); - return name.starts_with(FunctionCallLabelPrefix); -} diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 40635d0829168..9a545c40eacd0 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -966,7 +966,7 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols( lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name, bool &missing_weak) { - if (hasFunctionCallLabelPrefix(name.GetStringRef())) { + if (name.GetStringRef().starts_with(FunctionCallLabelPrefix)) { if (auto addr_or_err = ResolveFunctionCallLabel(name.GetStringRef(), m_sym_ctx, missing_weak)) { return *addr_or_err; diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 3d33c9728b8af..94beb4af97335 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9790,7 +9790,7 @@ void TypeSystemClang::LogCreation() const { // $__lldb_func::: llvm::Expected> TypeSystemClang::splitFunctionCallLabel(llvm::StringRef label) const { - if (!consumeFunctionCallLabelPrefix(label)) + if (!label.consume_front(FunctionCallLabelPrefix)) return llvm::createStringError( "expected function call label prefix not found in %s", label.data()); if (!label.consume_front(":")) From 5078c8523e1a20189e53b9ed1dbc6d7b08032c0d Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 12:02:49 +0100 Subject: [PATCH 04/38] fixup! move to new FindModule API; make module UID atomic --- lldb/include/lldb/Core/Module.h | 1 - lldb/include/lldb/Core/ModuleList.h | 8 ++++++++ lldb/source/Core/Module.cpp | 12 +----------- lldb/source/Core/ModuleList.cpp | 14 ++++++++++++++ lldb/source/Expression/IRExecutionUnit.cpp | 8 ++++---- 5 files changed, 27 insertions(+), 16 deletions(-) diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 3991a12997541..8513e147ee523 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -98,7 +98,6 @@ class Module : public std::enable_shared_from_this, // using the "--global" (-g for short). static size_t GetNumberAllocatedModules(); - static Module *GetAllocatedModuleWithUID(lldb::user_id_t uid); static Module *GetAllocatedModuleAtIndex(size_t idx); static std::recursive_mutex &GetAllocationModuleCollectionMutex(); diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index d5e291f3380a8..6ecdcf10fa85f 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -352,6 +352,14 @@ class ModuleList { // UUID values is very efficient and accurate. lldb::ModuleSP FindModule(const UUID &uuid) const; + /// Find a module by LLDB-specific unique identifier. + /// + /// \param[in] uid The UID of the module assigned to it on construction. + /// + /// \returns ModuleSP of module with \c uid. Returns nullptr if no such + /// module could be found. + lldb::ModuleSP FindModule(lldb::user_id_t uid) const; + /// Finds the first module whose file specification matches \a module_spec. lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const; diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index edd79aff5d065..f27a95de484df 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -121,15 +121,6 @@ size_t Module::GetNumberAllocatedModules() { return GetModuleCollection().size(); } -Module *Module::GetAllocatedModuleWithUID(lldb::user_id_t uid) { - std::lock_guard guard( - GetAllocationModuleCollectionMutex()); - for (Module *mod : GetModuleCollection()) - if (mod->GetID() == uid) - return mod; - return nullptr; -} - Module *Module::GetAllocatedModuleAtIndex(size_t idx) { std::lock_guard guard( GetAllocationModuleCollectionMutex()); @@ -139,8 +130,7 @@ Module *Module::GetAllocatedModuleAtIndex(size_t idx) { return nullptr; } -// TODO: needs a mutex -static lldb::user_id_t g_unique_id = 1; +static std::atomic g_unique_id = 1; Module::Module(const ModuleSpec &module_spec) : UserID(g_unique_id++), m_unwind_table(*this), m_file_has_changed(false), diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index d2e5be8c79b17..e3dfa799ebb65 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -584,6 +584,20 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const { return module_sp; } +ModuleSP ModuleList::FindModule(lldb::user_id_t uid) const { + ModuleSP module_sp; + ForEach([&](const ModuleSP &m) { + if (m->GetID() == uid) { + module_sp = m; + return true; + } + + return false; + }); + + return module_sp; +} + void ModuleList::FindTypes(Module *search_first, const TypeQuery &query, TypeResults &results) const { std::lock_guard guard(m_modules_mutex); diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 9a545c40eacd0..e7387dc2b3bf9 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -809,16 +809,16 @@ ResolveFunctionCallLabel(llvm::StringRef name, const auto &label = *label_or_err; - Module *module = Module::GetAllocatedModuleWithUID(label.m_module_id); + auto module_sp = sc.target_sp->GetImages().FindModule(label.m_module_id); - if (!module) + if (!module_sp) return llvm::createStringError( llvm::formatv("failed to find module by UID {0}", label.m_module_id)); - auto *symbol_file = module->GetSymbolFile(); + auto *symbol_file = module_sp->GetSymbolFile(); if (!symbol_file) return llvm::createStringError( - llvm::formatv("no SymbolFile found on module {0:x}.", module)); + llvm::formatv("no SymbolFile found on module {0:x}.", module_sp.get())); SymbolContextList sc_list; if (auto err = From 6741c7b4d27ce82f589b828916e033943515093f Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 12:16:22 +0100 Subject: [PATCH 05/38] fixup! rename FunctionCallLabel members --- lldb/include/lldb/Expression/Expression.h | 21 +++++++++++++------ lldb/source/Expression/IRExecutionUnit.cpp | 6 +++--- .../TypeSystem/Clang/TypeSystemClang.cpp | 6 ++---- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 9044d26cf6670..0f2281790a055 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -102,16 +102,25 @@ class Expression { /// /// The format being: /// -/// ::: +/// ::: /// /// The label string needs to stay valid for the entire lifetime /// of this object. struct FunctionCallLabel { - llvm::StringRef m_lookup_name; - lldb::user_id_t m_module_id; - - /// Mostly for debuggability. - lldb::user_id_t m_die_id; + /// Name to use when searching for the function symbol in + /// \c module_id. For most function calls this will be a + /// mangled name. In cases where a mangled name can't be used, + /// this will be the function name. + llvm::StringRef lookup_name; + + /// Unique identifier of the lldb_private::Module + /// which contains the symbol identified by \c symbol_id. + lldb::user_id_t module_id; + + /// Unique identifier of the function symbol on which to + /// perform the function call. For example, for DWARF this would + /// be the DIE UID. + lldb::user_id_t symbol_id; }; /// LLDB attaches this prefix to mangled names of functions that it get called diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index e7387dc2b3bf9..33f34831126ac 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -809,11 +809,11 @@ ResolveFunctionCallLabel(llvm::StringRef name, const auto &label = *label_or_err; - auto module_sp = sc.target_sp->GetImages().FindModule(label.m_module_id); + auto module_sp = sc.target_sp->GetImages().FindModule(label.module_id); if (!module_sp) return llvm::createStringError( - llvm::formatv("failed to find module by UID {0}", label.m_module_id)); + llvm::formatv("failed to find module by UID {0}", label.module_id)); auto *symbol_file = module_sp->GetSymbolFile(); if (!symbol_file) @@ -822,7 +822,7 @@ ResolveFunctionCallLabel(llvm::StringRef name, SymbolContextList sc_list; if (auto err = - symbol_file->FindAndResolveFunction(sc_list, label.m_lookup_name)) + symbol_file->FindAndResolveFunction(sc_list, label.lookup_name)) return llvm::joinErrors( llvm::createStringError("failed to resolve function by UID"), std::move(err)); diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 94beb4af97335..cf6cc2053f8ed 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9786,8 +9786,6 @@ void TypeSystemClang::LogCreation() const { &getASTContext(), getDisplayName()); } -// Expected format is: -// $__lldb_func::: llvm::Expected> TypeSystemClang::splitFunctionCallLabel(llvm::StringRef label) const { if (!label.consume_front(FunctionCallLabelPrefix)) @@ -9830,6 +9828,6 @@ TypeSystemClang::makeFunctionCallLabel(llvm::StringRef label) const { return llvm::createStringError( llvm::formatv("failed to parse DIE ID from '{0}'.", components[2])); - return FunctionCallLabel{/*.m_lookup_name =*/components[0], - /*.m_module_id =*/module_id, /*.m_die_id =*/die_id}; + return FunctionCallLabel{/*.lookup_name=*/components[0], + /*.module_id=*/module_id, /*.symbol_id=*/die_id}; } From 96cbb48bfe43b22e0002d99243666fb77b265750 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 12:29:44 +0100 Subject: [PATCH 06/38] fixup! remove unused headers --- lldb/source/Expression/Expression.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index f85a3284d7eda..93f585edfce3d 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -10,10 +10,6 @@ #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/Target.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Error.h" - using namespace lldb_private; Expression::Expression(Target &target) From 65f8706b5a9d68f1f33508340c4204c86bd45391 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 12:41:58 +0100 Subject: [PATCH 07/38] fixup! move FunctionCallLabel APIs into Expression component --- lldb/include/lldb/Expression/Expression.h | 11 ++++ lldb/include/lldb/Symbol/TypeSystem.h | 15 ------ lldb/source/Expression/Expression.cpp | 50 +++++++++++++++++++ lldb/source/Expression/IRExecutionUnit.cpp | 12 +---- .../TypeSystem/Clang/TypeSystemClang.cpp | 48 +----------------- .../TypeSystem/Clang/TypeSystemClang.h | 6 --- 6 files changed, 64 insertions(+), 78 deletions(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 0f2281790a055..35d7d71f6b253 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -127,6 +127,17 @@ struct FunctionCallLabel { /// from JITted expressions. inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func"; +/// Returns the components of the specified function call label. +/// +/// The format of \c label is described in \c FunctionCallLabel. +/// The label prefix is not one of the components. +llvm::Expected> +splitFunctionCallLabel(llvm::StringRef label); + +// Decodes the function label into a \c FunctionCallLabel. +llvm::Expected +makeFunctionCallLabel(llvm::StringRef label); + } // namespace lldb_private #endif // LLDB_EXPRESSION_EXPRESSION_H diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 742c09251ea2f..40bd59056a5df 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -549,21 +549,6 @@ class TypeSystem : public PluginInterface, return m_has_forcefully_completed_types; } - /// Returns the components of the specified function call label. - /// - /// The format of \c label is described in \c FunctionCallLabel. - /// The label prefix is not one of the components. - virtual llvm::Expected> - splitFunctionCallLabel(llvm::StringRef label) const { - return llvm::createStringError("Not implemented."); - } - - // Decodes the function label into a \c FunctionCallLabel. - virtual llvm::Expected - makeFunctionCallLabel(llvm::StringRef label) const { - return llvm::createStringError("Not implemented."); - } - protected: SymbolFile *m_sym_file = nullptr; /// Used for reporting statistics. diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index 93f585edfce3d..f55e8b1f8e485 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -10,6 +10,10 @@ #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/Target.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Error.h" + using namespace lldb_private; Expression::Expression(Target &target) @@ -26,3 +30,49 @@ Expression::Expression(ExecutionContextScope &exe_scope) m_jit_end_addr(LLDB_INVALID_ADDRESS) { assert(m_target_wp.lock()); } + +llvm::Expected> +lldb_private::splitFunctionCallLabel(llvm::StringRef label) { + if (!label.consume_front(FunctionCallLabelPrefix)) + return llvm::createStringError( + "expected function call label prefix not found in %s", label.data()); + if (!label.consume_front(":")) + return llvm::createStringError( + "incorrect format: expected ':' as the first character."); + + llvm::SmallVector components; + label.split(components, ":"); + + if (components.size() != 3) + return llvm::createStringError( + "incorrect format: too many label subcomponents."); + + return components; +} + +llvm::Expected +lldb_private::makeFunctionCallLabel(llvm::StringRef label) { + auto components_or_err = splitFunctionCallLabel(label); + if (!components_or_err) + return llvm::joinErrors( + llvm::createStringError("Failed to decode function call label"), + components_or_err.takeError()); + + const auto &components = *components_or_err; + + llvm::StringRef module_label = components[1]; + llvm::StringRef die_label = components[2]; + + lldb::user_id_t module_id = 0; + if (module_label.consumeInteger(0, module_id)) + return llvm::createStringError( + llvm::formatv("failed to parse module ID from '{0}'.", components[1])); + + lldb::user_id_t die_id; + if (die_label.consumeInteger(/*Radix=*/0, die_id)) + return llvm::createStringError( + llvm::formatv("failed to parse DIE ID from '{0}'.", components[2])); + + return FunctionCallLabel{/*.lookup_name=*/components[0], + /*.module_id=*/module_id, /*.symbol_id=*/die_id}; +} diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 33f34831126ac..56a01d7003c50 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -790,17 +790,7 @@ ResolveFunctionCallLabel(llvm::StringRef name, if (!sc.target_sp) return llvm::createStringError("target not available."); - auto ts_or_err = sc.target_sp->GetScratchTypeSystemForLanguage( - lldb::eLanguageTypeC_plus_plus); - if (!ts_or_err || !*ts_or_err) - return llvm::joinErrors( - llvm::createStringError( - "failed to find scratch C++ TypeSystem for current target."), - ts_or_err.takeError()); - - auto ts_sp = *ts_or_err; - - auto label_or_err = ts_sp->makeFunctionCallLabel(name); + auto label_or_err = makeFunctionCallLabel(name); if (!label_or_err) return llvm::joinErrors( llvm::createStringError("failed to create FunctionCallLabel from: %s", diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index cf6cc2053f8ed..c81a8b8651c41 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9056,6 +9056,8 @@ ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) { if (!mc || !mc->shouldMangleCXXName(nd)) return {}; + // We have a LLDB FunctionCallLabel instead of an ordinary mangled name. + // Extract the mangled name out of this label. if (const auto *label = nd->getAttr()) { if (auto components_or_err = splitFunctionCallLabel(label->getLabel())) return ConstString((*components_or_err)[0]); @@ -9785,49 +9787,3 @@ void TypeSystemClang::LogCreation() const { LLDB_LOG(log, "Created new TypeSystem for (ASTContext*){0:x} '{1}'", &getASTContext(), getDisplayName()); } - -llvm::Expected> -TypeSystemClang::splitFunctionCallLabel(llvm::StringRef label) const { - if (!label.consume_front(FunctionCallLabelPrefix)) - return llvm::createStringError( - "expected function call label prefix not found in %s", label.data()); - if (!label.consume_front(":")) - return llvm::createStringError( - "incorrect format: expected ':' as the first character."); - - llvm::SmallVector components; - label.split(components, ":"); - - if (components.size() != 3) - return llvm::createStringError( - "incorrect format: too many label subcomponents."); - - return components; -} - -llvm::Expected -TypeSystemClang::makeFunctionCallLabel(llvm::StringRef label) const { - auto components_or_err = splitFunctionCallLabel(label); - if (!components_or_err) - return llvm::joinErrors( - llvm::createStringError("Failed to decode function call label"), - components_or_err.takeError()); - - const auto &components = *components_or_err; - - llvm::StringRef module_label = components[1]; - llvm::StringRef die_label = components[2]; - - lldb::user_id_t module_id = 0; - if (module_label.consumeInteger(0, module_id)) - return llvm::createStringError( - llvm::formatv("failed to parse module ID from '{0}'.", components[1])); - - lldb::user_id_t die_id; - if (die_label.consumeInteger(/*Radix=*/0, die_id)) - return llvm::createStringError( - llvm::formatv("failed to parse DIE ID from '{0}'.", components[2])); - - return FunctionCallLabel{/*.lookup_name=*/components[0], - /*.module_id=*/module_id, /*.symbol_id=*/die_id}; -} diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 4e92a452af815..de66bb68c6a4c 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -1098,12 +1098,6 @@ class TypeSystemClang : public TypeSystem { lldb::opaque_compiler_type_t type, Stream &s, lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) override; - llvm::Expected> - splitFunctionCallLabel(llvm::StringRef label) const override; - - llvm::Expected - makeFunctionCallLabel(llvm::StringRef label) const override; - static void DumpTypeName(const CompilerType &type); static clang::EnumDecl *GetAsEnumDecl(const CompilerType &type); From 3e27e98e94abeaa3bab948a899f688f15efbee27 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 12:54:20 +0100 Subject: [PATCH 08/38] fixup! adjust TypeSystemClang::DeclGetMangledName --- .../TypeSystem/Clang/TypeSystemClang.cpp | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index c81a8b8651c41..ad26e0f5d2cbf 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9045,6 +9045,21 @@ ConstString TypeSystemClang::DeclGetName(void *opaque_decl) { return ConstString(); } +static ConstString +ExtractMangledNameFromFunctionCallLabel(llvm::StringRef label) { + auto components_or_err = splitFunctionCallLabel(label); + if (!components_or_err) { + llvm::consumeError(components_or_err.takeError()); + return {}; + } + + llvm::StringRef mangled = (*components_or_err)[0]; + if (Mangled::IsMangledName(mangled)) + return ConstString(mangled); + + return {}; +} + ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) { clang::NamedDecl *nd = llvm::dyn_cast_or_null( static_cast(opaque_decl)); @@ -9056,14 +9071,12 @@ ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) { if (!mc || !mc->shouldMangleCXXName(nd)) return {}; - // We have a LLDB FunctionCallLabel instead of an ordinary mangled name. + // We have an LLDB FunctionCallLabel instead of an ordinary mangled name. // Extract the mangled name out of this label. - if (const auto *label = nd->getAttr()) { - if (auto components_or_err = splitFunctionCallLabel(label->getLabel())) - return ConstString((*components_or_err)[0]); - else - llvm::consumeError(components_or_err.takeError()); - } + if (const auto *label = nd->getAttr()) + if (ConstString mangled = + ExtractMangledNameFromFunctionCallLabel(label->getLabel())) + return mangled; llvm::SmallVector buf; llvm::raw_svector_ostream llvm_ostrm(buf); From 76ae694c1eeaceb956c3919efebc86cef524fc38 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 15:08:30 +0100 Subject: [PATCH 09/38] fixup! move label encoding/decoding into FunctionCallLabel structure --- lldb/include/lldb/Expression/Expression.h | 19 +++++++++++++++---- lldb/source/Expression/Expression.cpp | 8 +++++++- lldb/source/Expression/IRExecutionUnit.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 7 ++++--- 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 35d7d71f6b253..83d3dc75620ba 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -121,6 +121,21 @@ struct FunctionCallLabel { /// perform the function call. For example, for DWARF this would /// be the DIE UID. lldb::user_id_t symbol_id; + + /// Decodes the specified function \c label into a \c FunctionCallLabel. + static llvm::Expected fromString(llvm::StringRef label); + + /// Encode this FunctionCallLabel into it's string representation. + /// + /// The representation roundtrips through \c fromString: + /// \code{.cpp} + /// llvm::StringRef encoded = "$__lldb_func:_Z3foov:0x0:0x0"; + /// FunctionCallLabel label = *fromString(label); + /// + /// assert (label.toString() == encoded); + /// assert (*fromString(label.toString()) == label); + /// \endcode + std::string toString() const; }; /// LLDB attaches this prefix to mangled names of functions that it get called @@ -134,10 +149,6 @@ inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func"; llvm::Expected> splitFunctionCallLabel(llvm::StringRef label); -// Decodes the function label into a \c FunctionCallLabel. -llvm::Expected -makeFunctionCallLabel(llvm::StringRef label); - } // namespace lldb_private #endif // LLDB_EXPRESSION_EXPRESSION_H diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index f55e8b1f8e485..1ea18dce772ba 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -51,7 +51,7 @@ lldb_private::splitFunctionCallLabel(llvm::StringRef label) { } llvm::Expected -lldb_private::makeFunctionCallLabel(llvm::StringRef label) { +lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) { auto components_or_err = splitFunctionCallLabel(label); if (!components_or_err) return llvm::joinErrors( @@ -76,3 +76,9 @@ lldb_private::makeFunctionCallLabel(llvm::StringRef label) { return FunctionCallLabel{/*.lookup_name=*/components[0], /*.module_id=*/module_id, /*.symbol_id=*/die_id}; } + +std::string lldb_private::FunctionCallLabel::toString() const { + return llvm::formatv("{0}:{1}:{2:x}:{3:x}", FunctionCallLabelPrefix, + lookup_name, module_id, symbol_id) + .str(); +} diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 56a01d7003c50..a1d8f30f373eb 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -790,7 +790,7 @@ ResolveFunctionCallLabel(llvm::StringRef name, if (!sc.target_sp) return llvm::createStringError("target not available."); - auto label_or_err = makeFunctionCallLabel(name); + auto label_or_err = FunctionCallLabel::fromString(name); if (!label_or_err) return llvm::joinErrors( llvm::createStringError("failed to create FunctionCallLabel from: %s", diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 6bf3b91c900c9..999632edbbbe8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -267,9 +267,10 @@ static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { if (die_id == LLDB_INVALID_UID) return std::nullopt; - return llvm::formatv("{0}:{1}:{2:x}:{3:x}", FunctionCallLabelPrefix, name, - module_id, die_id) - .str(); + return FunctionCallLabel{/*.lookup_name=*/name, + /*module_id=*/module_id, + /*symbol_id=*/die_id} + .toString(); } TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, From 1e6e9c012b7bd895c858ec71f029cece8755aae0 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 15:25:16 +0100 Subject: [PATCH 10/38] fixup! make mangled name last component in label; remove need for splitting helper --- lldb/include/lldb/Expression/Expression.h | 26 ++++++++----------- lldb/source/Expression/Expression.cpp | 25 +++++++++++------- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 8 +++--- .../TypeSystem/Clang/TypeSystemClang.cpp | 8 +++--- 4 files changed, 35 insertions(+), 32 deletions(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 83d3dc75620ba..7dce9aa21e5d2 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -102,17 +102,11 @@ class Expression { /// /// The format being: /// -/// ::: +/// ::: /// /// The label string needs to stay valid for the entire lifetime /// of this object. struct FunctionCallLabel { - /// Name to use when searching for the function symbol in - /// \c module_id. For most function calls this will be a - /// mangled name. In cases where a mangled name can't be used, - /// this will be the function name. - llvm::StringRef lookup_name; - /// Unique identifier of the lldb_private::Module /// which contains the symbol identified by \c symbol_id. lldb::user_id_t module_id; @@ -122,6 +116,15 @@ struct FunctionCallLabel { /// be the DIE UID. lldb::user_id_t symbol_id; + /// Name to use when searching for the function symbol in + /// \c module_id. For most function calls this will be a + /// mangled name. In cases where a mangled name can't be used, + /// this will be the function name. + /// + /// NOTE: kept as last element so we don't have to worry about + /// ':' in the mangled name when parsing the label. + llvm::StringRef lookup_name; + /// Decodes the specified function \c label into a \c FunctionCallLabel. static llvm::Expected fromString(llvm::StringRef label); @@ -129,7 +132,7 @@ struct FunctionCallLabel { /// /// The representation roundtrips through \c fromString: /// \code{.cpp} - /// llvm::StringRef encoded = "$__lldb_func:_Z3foov:0x0:0x0"; + /// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov"; /// FunctionCallLabel label = *fromString(label); /// /// assert (label.toString() == encoded); @@ -142,13 +145,6 @@ struct FunctionCallLabel { /// from JITted expressions. inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func"; -/// Returns the components of the specified function call label. -/// -/// The format of \c label is described in \c FunctionCallLabel. -/// The label prefix is not one of the components. -llvm::Expected> -splitFunctionCallLabel(llvm::StringRef label); - } // namespace lldb_private #endif // LLDB_EXPRESSION_EXPRESSION_H diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index 1ea18dce772ba..dc2d6bf520f05 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -31,8 +31,12 @@ Expression::Expression(ExecutionContextScope &exe_scope) assert(m_target_wp.lock()); } -llvm::Expected> -lldb_private::splitFunctionCallLabel(llvm::StringRef label) { +/// Returns the components of the specified function call label. +/// +/// The format of \c label is described in \c FunctionCallLabel. +/// The label prefix is not one of the components. +static llvm::Expected> +splitFunctionCallLabel(llvm::StringRef label) { if (!label.consume_front(FunctionCallLabelPrefix)) return llvm::createStringError( "expected function call label prefix not found in %s", label.data()); @@ -60,25 +64,26 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) { const auto &components = *components_or_err; - llvm::StringRef module_label = components[1]; - llvm::StringRef die_label = components[2]; + llvm::StringRef module_label = components[0]; + llvm::StringRef die_label = components[1]; lldb::user_id_t module_id = 0; if (module_label.consumeInteger(0, module_id)) return llvm::createStringError( - llvm::formatv("failed to parse module ID from '{0}'.", components[1])); + llvm::formatv("failed to parse module ID from '{0}'.", components[0])); lldb::user_id_t die_id; if (die_label.consumeInteger(/*Radix=*/0, die_id)) return llvm::createStringError( - llvm::formatv("failed to parse DIE ID from '{0}'.", components[2])); + llvm::formatv("failed to parse DIE ID from '{0}'.", components[1])); - return FunctionCallLabel{/*.lookup_name=*/components[0], - /*.module_id=*/module_id, /*.symbol_id=*/die_id}; + return FunctionCallLabel{/*.module_id=*/module_id, + /*.symbol_id=*/die_id, + /*.lookup_name=*/components[2]}; } std::string lldb_private::FunctionCallLabel::toString() const { - return llvm::formatv("{0}:{1}:{2:x}:{3:x}", FunctionCallLabelPrefix, - lookup_name, module_id, symbol_id) + return llvm::formatv("{0}:{1:x}:{2:x}:{3}", FunctionCallLabelPrefix, + module_id, symbol_id, lookup_name) .str(); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 999632edbbbe8..938d52f7d6b0b 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -267,9 +267,11 @@ static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { if (die_id == LLDB_INVALID_UID) return std::nullopt; - return FunctionCallLabel{/*.lookup_name=*/name, - /*module_id=*/module_id, - /*symbol_id=*/die_id} + return FunctionCallLabel{ + /*module_id=*/module_id, + /*symbol_id=*/die_id, + /*.lookup_name=*/name + } .toString(); } diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index ad26e0f5d2cbf..ab5f4138187ed 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -9047,13 +9047,13 @@ ConstString TypeSystemClang::DeclGetName(void *opaque_decl) { static ConstString ExtractMangledNameFromFunctionCallLabel(llvm::StringRef label) { - auto components_or_err = splitFunctionCallLabel(label); - if (!components_or_err) { - llvm::consumeError(components_or_err.takeError()); + auto label_or_err = FunctionCallLabel::fromString(label); + if (!label_or_err) { + llvm::consumeError(label_or_err.takeError()); return {}; } - llvm::StringRef mangled = (*components_or_err)[0]; + llvm::StringRef mangled = label_or_err->lookup_name; if (Mangled::IsMangledName(mangled)) return ConstString(mangled); From 73768e663f0cc09a08199f2ded1fcf4a79dc5209 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 15:44:13 +0100 Subject: [PATCH 11/38] fixup! rebase on latest ModuleList changes --- lldb/source/Core/ModuleList.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index e3dfa799ebb65..01f46b62b57bd 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -589,10 +589,10 @@ ModuleSP ModuleList::FindModule(lldb::user_id_t uid) const { ForEach([&](const ModuleSP &m) { if (m->GetID() == uid) { module_sp = m; - return true; + return IterationAction::Stop; } - return false; + return IterationAction::Continue; }); return module_sp; From 6eb12d95bf7b381078b713c24110d5fc5a1e39d1 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 15:44:54 +0100 Subject: [PATCH 12/38] fixup! remove mention of mangled name from FunctionCallLabel doc --- lldb/include/lldb/Expression/Expression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 7dce9aa21e5d2..4dc74b13fa8f9 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -102,7 +102,7 @@ class Expression { /// /// The format being: /// -/// ::: +/// ::: /// /// The label string needs to stay valid for the entire lifetime /// of this object. From de9c994a8fbbcebfd9517007dcfa8b20b1273534 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 16:35:47 +0100 Subject: [PATCH 13/38] fixup! add format_provider for FunctionCallLabel --- lldb/include/lldb/Expression/Expression.h | 8 ++++++++ lldb/source/Expression/Expression.cpp | 9 ++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 4dc74b13fa8f9..a6c49bcc10ad0 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -13,6 +13,7 @@ #include #include +#include "llvm/Support/FormatProviders.h" #include "lldb/Expression/ExpressionTypeSystemHelper.h" #include "lldb/lldb-forward.h" @@ -147,4 +148,11 @@ inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func"; } // namespace lldb_private +namespace llvm { +template <> struct format_provider { + static void format(const lldb_private::FunctionCallLabel &label, + raw_ostream &OS, StringRef Style); +}; +} // namespace llvm + #endif // LLDB_EXPRESSION_EXPRESSION_H diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index dc2d6bf520f05..251904fbc7dcb 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -10,8 +10,8 @@ #include "lldb/Target/ExecutionContextScope.h" #include "lldb/Target/Target.h" -#include "llvm/ADT/StringRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" using namespace lldb_private; @@ -87,3 +87,10 @@ std::string lldb_private::FunctionCallLabel::toString() const { module_id, symbol_id, lookup_name) .str(); } + +void llvm::format_provider::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); +} From 308d33d4aacec2f5a5462b7c9fbfbd18e63504fd Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Mon, 28 Jul 2025 16:36:12 +0100 Subject: [PATCH 14/38] fixup! only do name lookup for declaration DIE cases --- lldb/include/lldb/Symbol/SymbolFile.h | 12 ++-- lldb/source/Expression/IRExecutionUnit.cpp | 3 +- .../SymbolFile/DWARF/SymbolFileDWARF.cpp | 61 +++++++++++-------- .../SymbolFile/DWARF/SymbolFileDWARF.h | 4 +- 4 files changed, 46 insertions(+), 34 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 6aca276fc85b6..45798f667cb22 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -329,16 +329,18 @@ class SymbolFile : public PluginInterface { GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector &mangled_names); - /// Resolves the function DIE identified by \c lookup_name within - /// this SymbolFile. + /// Resolves the function corresponding to the specified LLDB function + /// call \c label. /// /// \param[in,out] sc_list The resolved functions will be appended to this /// list. /// - /// \param[in] lookup_name The UID of the function DIE to resolve. + /// \param[in] label The FunctionCallLabel to be resolved. /// - virtual llvm::Error FindAndResolveFunction(SymbolContextList &sc_list, - llvm::StringRef lookup_name) { + /// \returns An llvm::Error if the specified \c label couldn't be resolved. + /// Returns \c llvm::ErrorSuccess otherwise. + virtual llvm::Error ResolveFunctionCallLabel(SymbolContextList &sc_list, + const FunctionCallLabel &label) { return llvm::createStringError("Not implemented"); } diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index a1d8f30f373eb..ef119f6875870 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -811,8 +811,7 @@ ResolveFunctionCallLabel(llvm::StringRef name, llvm::formatv("no SymbolFile found on module {0:x}.", module_sp.get())); SymbolContextList sc_list; - if (auto err = - symbol_file->FindAndResolveFunction(sc_list, label.lookup_name)) + if (auto err = symbol_file->ResolveFunctionCallLabel(sc_list, label)) return llvm::joinErrors( llvm::createStringError("failed to resolve function by UID"), std::move(err)); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 552a675c833c7..c0a74c871c68f 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2476,42 +2476,53 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, } llvm::Error -SymbolFileDWARF::FindAndResolveFunction(SymbolContextList &sc_list, - llvm::StringRef lookup_name) { +SymbolFileDWARF::ResolveFunctionCallLabel(SymbolContextList &sc_list, + const FunctionCallLabel &label) { std::lock_guard guard(GetModuleMutex()); - DWARFDIE die; - Module::LookupInfo info(ConstString(lookup_name), lldb::eFunctionNameTypeFull, - lldb::eLanguageTypeUnknown); + DWARFDIE die = GetDIE(label.symbol_id); + if (!die.IsValid()) + return llvm::createStringError( + llvm::formatv("invalid DIE ID in {0}", label)); - m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) { - if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) - return true; + // 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)) { + Module::LookupInfo info(ConstString(label.lookup_name), + lldb::eFunctionNameTypeFull, + lldb::eLanguageTypeUnknown); - // 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. - die = entry; - return false; - }); + m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) { + if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) + return true; - if (!die.IsValid()) - return llvm::createStringError( - llvm::formatv("failed to find definition DIE for '{0}'", lookup_name)); + // 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. + die = entry; + return false; + }); - if (!ResolveFunction(die, false, sc_list)) - return llvm::createStringError("failed to resolve function DIE"); + if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) + return llvm::createStringError( + llvm::formatv("failed to find definition DIE for {0}", label)); + } + + if (!ResolveFunction(die, /*include_inlines=*/false, sc_list)) + return llvm::createStringError( + llvm::formatv("failed to resolve function for {0}", label)); if (sc_list.IsEmpty()) - return llvm::createStringError("no definition DIE found"); + return llvm::createStringError( + llvm::formatv("failed to find function for {0}", label)); if (sc_list.GetSize() > 1) return llvm::createStringError( - "found %d functions for %s but expected only 1", sc_list.GetSize(), - lookup_name.data()); + llvm::formatv("found {0} functions for {1} but expected only 1", + sc_list.GetSize(), label)); return llvm::Error::success(); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 94463fa2dc2e3..93b5b58ac0929 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -436,8 +436,8 @@ class SymbolFileDWARF : public SymbolFileCommon { DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die, DIEArray &&variable_dies); - llvm::Error FindAndResolveFunction(SymbolContextList &sc_list, - llvm::StringRef lookup_name) override; + llvm::Error ResolveFunctionCallLabel(SymbolContextList &sc_list, + const FunctionCallLabel &label) override; // Given a die_offset, figure out the symbol context representing that die. bool ResolveFunction(const DWARFDIE &die, bool include_inlines, From 7408359c4f7d22e23e03533177b147c5259deb8d Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Tue, 29 Jul 2025 12:08:45 +0100 Subject: [PATCH 15/38] fixup! add tests; account for ':' in mangled name; adjust error messages --- lldb/source/Expression/Expression.cpp | 25 ++-- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 10 +- lldb/unittests/Expression/CMakeLists.txt | 1 + lldb/unittests/Expression/ExpressionTest.cpp | 109 ++++++++++++++++++ 4 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 lldb/unittests/Expression/ExpressionTest.cpp diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index 251904fbc7dcb..a57bcbe97e117 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -39,17 +39,23 @@ static llvm::Expected> splitFunctionCallLabel(llvm::StringRef label) { if (!label.consume_front(FunctionCallLabelPrefix)) return llvm::createStringError( - "expected function call label prefix not found in %s", label.data()); + "expected function call label prefix not found."); if (!label.consume_front(":")) return llvm::createStringError( - "incorrect format: expected ':' as the first character."); + "expected ':' as the first character after prefix."); - llvm::SmallVector components; - label.split(components, ":"); + auto sep1 = label.find_first_of(":"); + if (sep1 == llvm::StringRef::npos) + return llvm::createStringError("no ':' separator found."); - if (components.size() != 3) - return llvm::createStringError( - "incorrect format: too many label subcomponents."); + auto sep2 = label.find_first_of(":", sep1 + 1); + if (sep2 == llvm::StringRef::npos) + return llvm::createStringError("only single ':' separator found."); + + llvm::SmallVector components; + components.push_back(label.slice(0, sep1)); + components.push_back(label.slice(sep1 + 1, sep2)); + components.push_back(label.slice(sep2 + 1, llvm::StringRef::npos)); return components; } @@ -59,7 +65,8 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) { auto components_or_err = splitFunctionCallLabel(label); if (!components_or_err) return llvm::joinErrors( - llvm::createStringError("Failed to decode function call label"), + llvm::createStringError("failed to split function call label '%s'", + label.data()), components_or_err.takeError()); const auto &components = *components_or_err; @@ -75,7 +82,7 @@ lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) { lldb::user_id_t die_id; if (die_label.consumeInteger(/*Radix=*/0, die_id)) return llvm::createStringError( - llvm::formatv("failed to parse DIE ID from '{0}'.", components[1])); + llvm::formatv("failed to parse symbol ID from '{0}'.", components[1])); return FunctionCallLabel{/*.module_id=*/module_id, /*.symbol_id=*/die_id, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 938d52f7d6b0b..e76b599fd5f9c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -255,7 +255,15 @@ static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { if (!name) return std::nullopt; - auto module_sp = die.GetModule(); + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (!dwarf) + return std::nullopt; + + ObjectFile *main_obj = dwarf->GetMainObjectFile(); + if (!main_obj) + return std::nullopt; + + auto module_sp = main_obj->GetModule(); if (!module_sp) return std::nullopt; diff --git a/lldb/unittests/Expression/CMakeLists.txt b/lldb/unittests/Expression/CMakeLists.txt index 533cdc673e6d1..4c58b3c5e3922 100644 --- a/lldb/unittests/Expression/CMakeLists.txt +++ b/lldb/unittests/Expression/CMakeLists.txt @@ -4,6 +4,7 @@ add_lldb_unittest(ExpressionTests DiagnosticManagerTest.cpp DWARFExpressionTest.cpp CppModuleConfigurationTest.cpp + ExpressionTest.cpp LINK_LIBS lldbCore diff --git a/lldb/unittests/Expression/ExpressionTest.cpp b/lldb/unittests/Expression/ExpressionTest.cpp new file mode 100644 index 0000000000000..542ce5005d7d9 --- /dev/null +++ b/lldb/unittests/Expression/ExpressionTest.cpp @@ -0,0 +1,109 @@ +//===-- ExpressionTest.cpp ------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "gmock/gmock.h" +#include "gtest/gtest.h" + +#include "TestingSupport/TestUtilities.h" +#include "lldb/Expression/Expression.h" +#include "llvm/Testing/Support/Error.h" + +using namespace lldb_private; + +struct LabelTestCase { + llvm::StringRef encoded; + FunctionCallLabel label; + llvm::SmallVector error_pattern; +}; + +static LabelTestCase g_label_test_cases[] = { + // Failure modes + {"0x0:0x0:_Z3foov", + {}, + {"failed to split function call label '0x0:0x0:_Z3foov'", + "expected function call label prefix not found."}}, + {"$__lldb_func0x0:0x0:_Z3foov", + {}, + {"failed to split function call label '$__lldb_func0x0:0x0:_Z3foov'", + "expected ':' as the first character after prefix."}}, + {"$__lldb_func:", + {}, + {"failed to split function call label '$__lldb_func:'", + "no ':' separator found."}}, + {"$__lldb_func:0x0:0x0", + {}, + {"failed to split function call label '$__lldb_func:0x0:0x0'", + "only single ':' separator found."}}, + {"$__lldb_func:abc:0x0:_Z3foov", + {}, + {"failed to parse module ID from 'abc'."}}, + {"$__lldb_func:-1:0x0:_Z3foov", + {}, + {"failed to parse module ID from '-1'."}}, + {"$__lldb_func:0x0:abc:_Z3foov", + {}, + {"failed to parse symbol ID from 'abc'."}}, + {"$__lldb_func:0x5:-1:_Z3foov", + {}, + {"failed to parse symbol ID from '-1'."}}, + {"$__lldb_func:0x0:0x0:_Z3foov", + { + /*.module_id=*/0x0, + /*.symbol_id=*/0x0, + /*.lookup_name=*/"_Z3foov", + }, + {}}, + {"$__lldb_func:0x0:0x0:abc:def:::a", + { + /*.module_id=*/0x0, + /*.symbol_id=*/0x0, + /*.lookup_name=*/"abc:def:::a", + }, + {}}, + {"$__lldb_func:0xd2:0xf0:$__lldb_func", + { + /*.module_id=*/0xd2, + /*.symbol_id=*/0xf0, + /*.lookup_name=*/"$__lldb_func", + }, + {}}, +}; + +struct ExpressionTestFixture : public testing::TestWithParam {}; + +TEST_P(ExpressionTestFixture, FunctionCallLabel) { + const auto &[encoded, label, errors] = GetParam(); + + auto decoded_or_err = FunctionCallLabel::fromString(encoded); + if (!errors.empty()) { + EXPECT_THAT_EXPECTED( + decoded_or_err, + llvm::FailedWithMessageArray(testing::ElementsAreArray(errors))); + return; + } + + EXPECT_THAT_EXPECTED(decoded_or_err, llvm::Succeeded()); + + auto label_str = label.toString(); + EXPECT_EQ(decoded_or_err->toString(), encoded); + EXPECT_EQ(label_str, encoded); + + EXPECT_EQ(decoded_or_err->module_id, label.module_id); + EXPECT_EQ(decoded_or_err->symbol_id, label.symbol_id); + EXPECT_EQ(decoded_or_err->lookup_name, label.lookup_name); + + auto roundtrip_or_err = FunctionCallLabel::fromString(label_str); + EXPECT_THAT_EXPECTED(roundtrip_or_err, llvm::Succeeded()); + + EXPECT_EQ(roundtrip_or_err->module_id, label.module_id); + EXPECT_EQ(roundtrip_or_err->symbol_id, label.symbol_id); + EXPECT_EQ(roundtrip_or_err->lookup_name, label.lookup_name); +} + +INSTANTIATE_TEST_SUITE_P(FunctionCallLabelTest, ExpressionTestFixture, + testing::ValuesIn(g_label_test_cases)); From 75c5cd01cfddac4a412391f9dcf1901a573fdd11 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 10:11:05 +0100 Subject: [PATCH 16/38] fixup! drop \01 mangling prefix when searching using IR function name --- lldb/source/Expression/IRInterpreter.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lldb/source/Expression/IRInterpreter.cpp b/lldb/source/Expression/IRInterpreter.cpp index fa74e8828a574..91404831aeb9b 100644 --- a/lldb/source/Expression/IRInterpreter.cpp +++ b/lldb/source/Expression/IRInterpreter.cpp @@ -259,7 +259,9 @@ class InterpreterStackFrame { break; case Value::FunctionVal: if (const Function *constant_func = dyn_cast(constant)) { - lldb_private::ConstString name(constant_func->getName()); + lldb_private::ConstString name( + llvm::GlobalValue::dropLLVMManglingEscape( + constant_func->getName())); bool missing_weak = false; lldb::addr_t addr = m_execution_unit.FindSymbol(name, missing_weak); if (addr == LLDB_INVALID_ADDRESS) From cc7d462b4ab9c21918c09a3f95377bef4de91f68 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 10:13:44 +0100 Subject: [PATCH 17/38] fixup! search .o files when searching for module by UID --- lldb/include/lldb/Core/ModuleList.h | 8 ------ lldb/source/Core/ModuleList.cpp | 14 --------- lldb/source/Expression/IRExecutionUnit.cpp | 33 ++++++++++++++++++++-- 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 6ecdcf10fa85f..d5e291f3380a8 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -352,14 +352,6 @@ class ModuleList { // UUID values is very efficient and accurate. lldb::ModuleSP FindModule(const UUID &uuid) const; - /// Find a module by LLDB-specific unique identifier. - /// - /// \param[in] uid The UID of the module assigned to it on construction. - /// - /// \returns ModuleSP of module with \c uid. Returns nullptr if no such - /// module could be found. - lldb::ModuleSP FindModule(lldb::user_id_t uid) const; - /// Finds the first module whose file specification matches \a module_spec. lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const; diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 01f46b62b57bd..d2e5be8c79b17 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -584,20 +584,6 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const { return module_sp; } -ModuleSP ModuleList::FindModule(lldb::user_id_t uid) const { - ModuleSP module_sp; - ForEach([&](const ModuleSP &m) { - if (m->GetID() == uid) { - module_sp = m; - return IterationAction::Stop; - } - - return IterationAction::Continue; - }); - - return module_sp; -} - void ModuleList::FindTypes(Module *search_first, const TypeQuery &query, TypeResults &results) const { std::lock_guard guard(m_modules_mutex); diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index ef119f6875870..128e1beb76991 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -774,6 +774,36 @@ class LoadAddressResolver { lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS; }; +/// Find a module by LLDB-specific unique identifier. +/// +/// \param[in] uid The UID of the module assigned to it on construction. +/// +/// \returns ModuleSP of module with \c uid. Returns nullptr if no such +/// module could be found. +static lldb::ModuleSP FindDebugModule(lldb::user_id_t uid, + const ModuleList &modules) { + lldb::ModuleSP module_sp; + modules.ForEach([&](const lldb::ModuleSP &m) { + if (m->GetID() == uid) { + module_sp = m; + return IterationAction::Stop; + } + + auto *sym = m->GetSymbolFile(); + if (!sym) + return IterationAction::Continue; + + auto debug_modules = sym->GetDebugInfoModules(); + module_sp = FindDebugModule(uid, debug_modules); + if (module_sp) + return IterationAction::Stop; + + return IterationAction::Continue; + }); + + return module_sp; +} + /// Returns address of the function referred to by the special function call /// label \c label. /// @@ -799,8 +829,7 @@ ResolveFunctionCallLabel(llvm::StringRef name, const auto &label = *label_or_err; - auto module_sp = sc.target_sp->GetImages().FindModule(label.module_id); - + auto module_sp = FindDebugModule(label.module_id, sc.target_sp->GetImages()); if (!module_sp) return llvm::createStringError( llvm::formatv("failed to find module by UID {0}", label.module_id)); From 0ce95bd4c1c59b48fe11d3b3b62d71e9f6809897 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 10:15:14 +0100 Subject: [PATCH 18/38] fixup! revert whitespace change --- lldb/include/lldb/Symbol/TypeSystem.h | 1 - 1 file changed, 1 deletion(-) diff --git a/lldb/include/lldb/Symbol/TypeSystem.h b/lldb/include/lldb/Symbol/TypeSystem.h index 40bd59056a5df..cb1f0130b548d 100644 --- a/lldb/include/lldb/Symbol/TypeSystem.h +++ b/lldb/include/lldb/Symbol/TypeSystem.h @@ -548,7 +548,6 @@ class TypeSystem : public PluginInterface, bool GetHasForcefullyCompletedTypes() const { return m_has_forcefully_completed_types; } - protected: SymbolFile *m_sym_file = nullptr; /// Used for reporting statistics. From 5789808305dd377a807fef5496d241059f8a2a3e Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 10:26:42 +0100 Subject: [PATCH 19/38] fixup! remove stale comment --- lldb/source/Expression/IRExecutionUnit.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 128e1beb76991..448a3cb649c0d 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -809,8 +809,6 @@ static lldb::ModuleSP FindDebugModule(lldb::user_id_t uid, /// /// \param[in] label Function call label encoding the unique location of the /// function to look up. -/// Assumes that the \c FunctionCallLabelPrefix has been -/// stripped from the front of the label. static llvm::Expected ResolveFunctionCallLabel(llvm::StringRef name, const lldb_private::SymbolContext &sc, From 6973ac27c406070a516b7788b8b59ac7465e6490 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 11:50:23 +0100 Subject: [PATCH 20/38] fixup! implement SymbolFileDWARFDebugMap::ResolveFunctionCallLabel --- lldb/include/lldb/Core/ModuleList.h | 8 +++++++ lldb/source/Core/ModuleList.cpp | 14 +++++++++++ lldb/source/Expression/IRExecutionUnit.cpp | 2 +- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 24 +++++++++++++------ .../DWARF/SymbolFileDWARFDebugMap.cpp | 11 +++++++++ .../DWARF/SymbolFileDWARFDebugMap.h | 3 +++ 6 files changed, 54 insertions(+), 8 deletions(-) diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index d5e291f3380a8..6ecdcf10fa85f 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -352,6 +352,14 @@ class ModuleList { // UUID values is very efficient and accurate. lldb::ModuleSP FindModule(const UUID &uuid) const; + /// Find a module by LLDB-specific unique identifier. + /// + /// \param[in] uid The UID of the module assigned to it on construction. + /// + /// \returns ModuleSP of module with \c uid. Returns nullptr if no such + /// module could be found. + lldb::ModuleSP FindModule(lldb::user_id_t uid) const; + /// Finds the first module whose file specification matches \a module_spec. lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const; diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index d2e5be8c79b17..01f46b62b57bd 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -584,6 +584,20 @@ ModuleSP ModuleList::FindModule(const UUID &uuid) const { return module_sp; } +ModuleSP ModuleList::FindModule(lldb::user_id_t uid) const { + ModuleSP module_sp; + ForEach([&](const ModuleSP &m) { + if (m->GetID() == uid) { + module_sp = m; + return IterationAction::Stop; + } + + return IterationAction::Continue; + }); + + return module_sp; +} + void ModuleList::FindTypes(Module *search_first, const TypeQuery &query, TypeResults &results) const { std::lock_guard guard(m_modules_mutex); diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 448a3cb649c0d..90d087553b35b 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -827,7 +827,7 @@ ResolveFunctionCallLabel(llvm::StringRef name, const auto &label = *label_or_err; - auto module_sp = FindDebugModule(label.module_id, sc.target_sp->GetImages()); + auto module_sp = sc.target_sp->GetImages().FindModule(label.module_id); if (!module_sp) return llvm::createStringError( llvm::formatv("failed to find module by UID {0}", label.module_id)); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index e76b599fd5f9c..f1a8433842bab 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -259,15 +259,25 @@ static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { if (!dwarf) return std::nullopt; - ObjectFile *main_obj = dwarf->GetMainObjectFile(); - if (!main_obj) - return std::nullopt; + auto get_module_id = [&](SymbolFile *sym) { + if (!sym) + return LLDB_INVALID_UID; - auto module_sp = main_obj->GetModule(); - if (!module_sp) - return std::nullopt; + auto *obj = sym->GetMainObjectFile(); + if (!obj) + return LLDB_INVALID_UID; + + auto module_sp = obj->GetModule(); + if (!module_sp) + return LLDB_INVALID_UID; + + return module_sp->GetID(); + }; + + lldb::user_id_t module_id = get_module_id(dwarf->GetDebugMapSymfile()); + if (module_id == LLDB_INVALID_UID) + module_id = get_module_id(dwarf); - lldb::user_id_t module_id = module_sp->GetID(); if (module_id == LLDB_INVALID_UID) return std::nullopt; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index dd94f0b36f2b2..b532e4d8c83e1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1602,3 +1602,14 @@ void SymbolFileDWARFDebugMap::GetCompileOptions( return IterationAction::Continue; }); } + +llvm::Error SymbolFileDWARFDebugMap::ResolveFunctionCallLabel( + SymbolContextList &sc_list, const FunctionCallLabel &label) { + const uint64_t oso_idx = GetOSOIndexFromUserID(label.symbol_id); + SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); + if (!oso_dwarf) + return llvm::createStringError(llvm::formatv( + "couldn't find symbol file for {0} in debug-map.", label)); + + return oso_dwarf->ResolveFunctionCallLabel(sc_list, label); +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index f074b17082e62..31a2889cf3ff6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -144,6 +144,9 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon { void GetCompileOptions(std::unordered_map &args) override; + llvm::Error ResolveFunctionCallLabel(SymbolContextList &sc_list, + const FunctionCallLabel &label) override; + protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; From e43310a51b8ac37cf0cb2bd8c92c25ae16a8a305 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 12:38:48 +0100 Subject: [PATCH 21/38] fixup! add test for when definition is in different Module than declaration --- .../cpp/expr-definition-in-dylib/Makefile | 6 ++++++ .../TestExprDefinitionInDylib.py | 19 +++++++++++++++++++ .../lang/cpp/expr-definition-in-dylib/lib.cpp | 5 +++++ .../lang/cpp/expr-definition-in-dylib/lib.h | 8 ++++++++ .../cpp/expr-definition-in-dylib/main.cpp | 6 ++++++ 5 files changed, 44 insertions(+) create mode 100644 lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile create mode 100644 lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py create mode 100644 lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp create mode 100644 lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h create mode 100644 lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile b/lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile new file mode 100644 index 0000000000000..82daeb1dd3f90 --- /dev/null +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/Makefile @@ -0,0 +1,6 @@ +CXX_SOURCES := main.cpp + +DYLIB_CXX_SOURCES := lib.cpp +DYLIB_NAME := lib + +include Makefile.rules diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py new file mode 100644 index 0000000000000..3a89eb01b3932 --- /dev/null +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py @@ -0,0 +1,19 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprDefinitionInDylibTestCase(TestBase): + def test(self): + """ + Tests that we can call functions whose definition + is in a different LLDB module than it's declaration. + """ + self.build() + + lldbutil.run_to_source_breakpoint( + self, "return", lldb.SBFileSpec("main.cpp") + ) + + self.expect_expr("f.method()", result_value="-72", result_type="int") diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp new file mode 100644 index 0000000000000..c4336d7b69be4 --- /dev/null +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp @@ -0,0 +1,5 @@ +#include "lib.h" + +int Foo::method() { + return -72; +} diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h new file mode 100644 index 0000000000000..9568db2166ec4 --- /dev/null +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.h @@ -0,0 +1,8 @@ +#ifndef LIB_H_IN +#define LIB_H_IN + +struct Foo { + int method(); +}; + +#endif // LIB_H_IN diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp b/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp new file mode 100644 index 0000000000000..2fddb2b7b3e74 --- /dev/null +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/main.cpp @@ -0,0 +1,6 @@ +#include "lib.h" + +int main() { + Foo f; + return f.method(); +} From e8146d7457ddd599f1326cafe33883a2c3bbc37b Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 12:39:07 +0100 Subject: [PATCH 22/38] fixup! clang-format --- lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp index c4336d7b69be4..ad148cebb00d1 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp @@ -1,5 +1,3 @@ #include "lib.h" -int Foo::method() { - return -72; -} +int Foo::method() { return -72; } From e4129ce205d6d397e461ee2c400c3649dbaaa6b7 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 12:51:45 +0100 Subject: [PATCH 23/38] fixup! python format --- .../cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py index 3a89eb01b3932..13480001dd82f 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py @@ -12,8 +12,6 @@ def test(self): """ self.build() - lldbutil.run_to_source_breakpoint( - self, "return", lldb.SBFileSpec("main.cpp") - ) + lldbutil.run_to_source_breakpoint(self, "return", lldb.SBFileSpec("main.cpp")) self.expect_expr("f.method()", result_value="-72", result_type="int") From 36b39a4483eb279367d50598547b1060472d0be4 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 12:54:00 +0100 Subject: [PATCH 24/38] fixup! clang-format --- .../Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index f1a8433842bab..4b386ac2093a7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -285,11 +285,9 @@ static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { if (die_id == LLDB_INVALID_UID) return std::nullopt; - return FunctionCallLabel{ - /*module_id=*/module_id, - /*symbol_id=*/die_id, - /*.lookup_name=*/name - } + return FunctionCallLabel{/*module_id=*/module_id, + /*symbol_id=*/die_id, + /*.lookup_name=*/name} .toString(); } From e882765006208691a0c8f233718ab5d1ae71b73e Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 13:09:41 +0100 Subject: [PATCH 25/38] fixup! mark test NO_DEBUG_INFO_TESTCASE --- .../cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py index 13480001dd82f..84559155f3c4b 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py @@ -5,6 +5,8 @@ class ExprDefinitionInDylibTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + def test(self): """ Tests that we can call functions whose definition From a8a98902ded0dbf0632855f0bf24d2ff70fb4fda Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 13:10:11 +0100 Subject: [PATCH 26/38] fixup! fallback to name lookup if definition is in separate module from declaration --- lldb/source/Expression/IRExecutionUnit.cpp | 35 +++++++++++----------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 90d087553b35b..cea5ca90d7315 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -806,11 +806,8 @@ static lldb::ModuleSP FindDebugModule(lldb::user_id_t uid, /// Returns address of the function referred to by the special function call /// label \c label. -/// -/// \param[in] label Function call label encoding the unique location of the -/// function to look up. static llvm::Expected -ResolveFunctionCallLabel(llvm::StringRef name, +ResolveFunctionCallLabel(const FunctionCallLabel &label, const lldb_private::SymbolContext &sc, bool &symbol_was_missing_weak) { symbol_was_missing_weak = false; @@ -818,15 +815,6 @@ ResolveFunctionCallLabel(llvm::StringRef name, if (!sc.target_sp) return llvm::createStringError("target not available."); - auto label_or_err = FunctionCallLabel::fromString(name); - if (!label_or_err) - return llvm::joinErrors( - llvm::createStringError("failed to create FunctionCallLabel from: %s", - name.data()), - label_or_err.takeError()); - - const auto &label = *label_or_err; - auto module_sp = sc.target_sp->GetImages().FindModule(label.module_id); if (!module_sp) return llvm::createStringError( @@ -983,19 +971,30 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols( lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name, bool &missing_weak) { if (name.GetStringRef().starts_with(FunctionCallLabelPrefix)) { - if (auto addr_or_err = ResolveFunctionCallLabel(name.GetStringRef(), - m_sym_ctx, missing_weak)) { + auto label_or_err = FunctionCallLabel::fromString(name); + if (!label_or_err) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), label_or_err.takeError(), + "failed to create FunctionCallLabel from '{0}': {1}", + name.GetStringRef()); + return LLDB_INVALID_ADDRESS; + } + + if (auto addr_or_err = + ResolveFunctionCallLabel(*label_or_err, m_sym_ctx, missing_weak)) { return *addr_or_err; } else { LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), addr_or_err.takeError(), "Failed to resolve function call label '{1}': {0}", name.GetStringRef()); - return LLDB_INVALID_ADDRESS; + + // Fall back to lookup by name despite error in resolving the label. + // May happen in practice if the definition of a function lives in + // a different lldb_private::Module than it's declaration. Meaning + // we couldn't pin-point it using the information encoded in the label. + name.SetString(label_or_err->lookup_name); } } - // TODO: do we still need the following lookups? - std::vector candidate_C_names; std::vector candidate_CPlusPlus_names; From a5b2e26ba6d1af1d6a8c5787d3d05c093ac3cbf3 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 16:17:28 +0100 Subject: [PATCH 27/38] fixup! register dylib in test Otherwise executable fails to launch on linux --- .../TestExprDefinitionInDylib.py | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py index 84559155f3c4b..1eddd265eab93 100644 --- a/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py @@ -14,6 +14,19 @@ def test(self): """ self.build() - lldbutil.run_to_source_breakpoint(self, "return", lldb.SBFileSpec("main.cpp")) + target = self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + self.assertTrue(target, VALID_TARGET) + + env = self.registerSharedLibrariesWithTarget(target, ["lib"]) + + breakpoint = lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", line_number("main.cpp", "return") + ) + + process = target.LaunchSimple(None, env, self.get_process_working_directory()) + + self.assertIsNotNone( + lldbutil.get_one_thread_stopped_at_breakpoint_id(self.process(), breakpoint) + ) self.expect_expr("f.method()", result_value="-72", result_type="int") From 5aa13329d31fa5e1d16376b588578db188928099 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 15:34:01 +0100 Subject: [PATCH 28/38] fixup! fix typo --- lldb/include/lldb/Expression/Expression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index a6c49bcc10ad0..086aa1406a1c6 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -129,7 +129,7 @@ struct FunctionCallLabel { /// Decodes the specified function \c label into a \c FunctionCallLabel. static llvm::Expected fromString(llvm::StringRef label); - /// Encode this FunctionCallLabel into it's string representation. + /// Encode this FunctionCallLabel into its string representation. /// /// The representation roundtrips through \c fromString: /// \code{.cpp} From 98d2c4bd96cb181680ac7be6ff37adc030d45767 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 15:42:03 +0100 Subject: [PATCH 29/38] fixup! SymbolContextList -> SymbolContext --- lldb/include/lldb/Symbol/SymbolFile.h | 9 +++------ lldb/source/Expression/IRExecutionUnit.cpp | 9 ++++++--- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 13 +++++-------- .../Plugins/SymbolFile/DWARF/SymbolFileDWARF.h | 4 ++-- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp | 6 +++--- .../SymbolFile/DWARF/SymbolFileDWARFDebugMap.h | 4 ++-- 6 files changed, 21 insertions(+), 24 deletions(-) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 45798f667cb22..bbc615d9fdc38 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -332,15 +332,12 @@ class SymbolFile : public PluginInterface { /// Resolves the function corresponding to the specified LLDB function /// call \c label. /// - /// \param[in,out] sc_list The resolved functions will be appended to this - /// list. - /// /// \param[in] label The FunctionCallLabel to be resolved. /// /// \returns An llvm::Error if the specified \c label couldn't be resolved. - /// Returns \c llvm::ErrorSuccess otherwise. - virtual llvm::Error ResolveFunctionCallLabel(SymbolContextList &sc_list, - const FunctionCallLabel &label) { + /// Returns the resolved function (as a SymbolContext) otherwise. + virtual llvm::Expected + ResolveFunctionCallLabel(const FunctionCallLabel &label) { return llvm::createStringError("Not implemented"); } diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index cea5ca90d7315..870b71eee3c7c 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -825,11 +825,14 @@ ResolveFunctionCallLabel(const FunctionCallLabel &label, return llvm::createStringError( llvm::formatv("no SymbolFile found on module {0:x}.", module_sp.get())); - SymbolContextList sc_list; - if (auto err = symbol_file->ResolveFunctionCallLabel(sc_list, label)) + auto sc_or_err = symbol_file->ResolveFunctionCallLabel(label); + if (!sc_or_err) return llvm::joinErrors( llvm::createStringError("failed to resolve function by UID"), - std::move(err)); + sc_or_err.takeError()); + + SymbolContextList sc_list; + sc_list.Append(*sc_or_err); LoadAddressResolver resolver(*sc.target_sp, symbol_was_missing_weak); return resolver.Resolve(sc_list).value_or(LLDB_INVALID_ADDRESS); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index c0a74c871c68f..874fbf7c160b8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2475,9 +2475,8 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, return false; } -llvm::Error -SymbolFileDWARF::ResolveFunctionCallLabel(SymbolContextList &sc_list, - const FunctionCallLabel &label) { +llvm::Expected +SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) { std::lock_guard guard(GetModuleMutex()); DWARFDIE die = GetDIE(label.symbol_id); @@ -2511,6 +2510,7 @@ SymbolFileDWARF::ResolveFunctionCallLabel(SymbolContextList &sc_list, llvm::formatv("failed to find definition DIE for {0}", label)); } + SymbolContextList sc_list; if (!ResolveFunction(die, /*include_inlines=*/false, sc_list)) return llvm::createStringError( llvm::formatv("failed to resolve function for {0}", label)); @@ -2519,12 +2519,9 @@ SymbolFileDWARF::ResolveFunctionCallLabel(SymbolContextList &sc_list, return llvm::createStringError( llvm::formatv("failed to find function for {0}", label)); - if (sc_list.GetSize() > 1) - return llvm::createStringError( - llvm::formatv("found {0} functions for {1} but expected only 1", - sc_list.GetSize(), label)); + assert(sc_list.GetSize() == 1); - return llvm::Error::success(); + return sc_list[0]; } bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 93b5b58ac0929..3ec538da8cf77 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -436,8 +436,8 @@ class SymbolFileDWARF : public SymbolFileCommon { DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die, DIEArray &&variable_dies); - llvm::Error ResolveFunctionCallLabel(SymbolContextList &sc_list, - const FunctionCallLabel &label) override; + llvm::Expected + ResolveFunctionCallLabel(const 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 b532e4d8c83e1..9d7452a1988fa 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1603,13 +1603,13 @@ void SymbolFileDWARFDebugMap::GetCompileOptions( }); } -llvm::Error SymbolFileDWARFDebugMap::ResolveFunctionCallLabel( - SymbolContextList &sc_list, const FunctionCallLabel &label) { +llvm::Expected SymbolFileDWARFDebugMap::ResolveFunctionCallLabel( + const FunctionCallLabel &label) { const uint64_t oso_idx = GetOSOIndexFromUserID(label.symbol_id); SymbolFileDWARF *oso_dwarf = GetSymbolFileByOSOIndex(oso_idx); if (!oso_dwarf) return llvm::createStringError(llvm::formatv( "couldn't find symbol file for {0} in debug-map.", label)); - return oso_dwarf->ResolveFunctionCallLabel(sc_list, label); + return oso_dwarf->ResolveFunctionCallLabel(label); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index 31a2889cf3ff6..e1f1df23951c6 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -144,8 +144,8 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon { void GetCompileOptions(std::unordered_map &args) override; - llvm::Error ResolveFunctionCallLabel(SymbolContextList &sc_list, - const FunctionCallLabel &label) override; + llvm::Expected + ResolveFunctionCallLabel(const FunctionCallLabel &label) override; protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; From 2a0b79940994fd0ec85e352625b944b6bc611736 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 16:16:33 +0100 Subject: [PATCH 30/38] fixup! simplify label parsing --- lldb/source/Expression/Expression.cpp | 60 ++++++-------------- lldb/unittests/Expression/ExpressionTest.cpp | 39 ++++++++----- 2 files changed, 43 insertions(+), 56 deletions(-) diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index a57bcbe97e117..796851ff15ca3 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -11,6 +11,7 @@ #include "lldb/Target/Target.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" @@ -31,62 +32,35 @@ Expression::Expression(ExecutionContextScope &exe_scope) assert(m_target_wp.lock()); } -/// Returns the components of the specified function call label. -/// -/// The format of \c label is described in \c FunctionCallLabel. -/// The label prefix is not one of the components. -static llvm::Expected> -splitFunctionCallLabel(llvm::StringRef label) { - if (!label.consume_front(FunctionCallLabelPrefix)) - return llvm::createStringError( - "expected function call label prefix not found."); - if (!label.consume_front(":")) - return llvm::createStringError( - "expected ':' as the first character after prefix."); - - auto sep1 = label.find_first_of(":"); - if (sep1 == llvm::StringRef::npos) - return llvm::createStringError("no ':' separator found."); - - auto sep2 = label.find_first_of(":", sep1 + 1); - if (sep2 == llvm::StringRef::npos) - return llvm::createStringError("only single ':' separator found."); - - llvm::SmallVector components; - components.push_back(label.slice(0, sep1)); - components.push_back(label.slice(sep1 + 1, sep2)); - components.push_back(label.slice(sep2 + 1, llvm::StringRef::npos)); - - return components; -} - llvm::Expected lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) { - auto components_or_err = splitFunctionCallLabel(label); - if (!components_or_err) - return llvm::joinErrors( - llvm::createStringError("failed to split function call label '%s'", - label.data()), - components_or_err.takeError()); + llvm::SmallVector components; + label.split(components, ":", /*MaxSplit=*/3); + + if (components.size() != 4) + return llvm::createStringError("malformed function call label."); - const auto &components = *components_or_err; + 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[0]; - llvm::StringRef die_label = components[1]; + llvm::StringRef module_label = components[1]; + llvm::StringRef die_label = components[2]; lldb::user_id_t module_id = 0; - if (module_label.consumeInteger(0, module_id)) + if (!llvm::to_integer(module_label, module_id)) return llvm::createStringError( - llvm::formatv("failed to parse module ID from '{0}'.", components[0])); + llvm::formatv("failed to parse module ID from '{0}'.", module_label)); lldb::user_id_t die_id; - if (die_label.consumeInteger(/*Radix=*/0, die_id)) + if (!llvm::to_integer(die_label, die_id)) return llvm::createStringError( - llvm::formatv("failed to parse symbol ID from '{0}'.", components[1])); + llvm::formatv("failed to parse symbol ID from '{0}'.", die_label)); return FunctionCallLabel{/*.module_id=*/module_id, /*.symbol_id=*/die_id, - /*.lookup_name=*/components[2]}; + /*.lookup_name=*/components[3]}; } std::string lldb_private::FunctionCallLabel::toString() const { diff --git a/lldb/unittests/Expression/ExpressionTest.cpp b/lldb/unittests/Expression/ExpressionTest.cpp index 542ce5005d7d9..12f6dd515fd11 100644 --- a/lldb/unittests/Expression/ExpressionTest.cpp +++ b/lldb/unittests/Expression/ExpressionTest.cpp @@ -23,34 +23,47 @@ struct LabelTestCase { static LabelTestCase g_label_test_cases[] = { // Failure modes - {"0x0:0x0:_Z3foov", + {"bar:0x0:0x0:_Z3foov", {}, - {"failed to split function call label '0x0:0x0:_Z3foov'", - "expected function call label prefix not found."}}, - {"$__lldb_func0x0:0x0:_Z3foov", + {"expected function call label prefix '$__lldb_func' but found 'bar' " + "instead."}}, + {"$__lldb_func :0x0:0x0:_Z3foov", {}, - {"failed to split function call label '$__lldb_func0x0:0x0:_Z3foov'", - "expected ':' as the first character after prefix."}}, - {"$__lldb_func:", + {"expected function call label prefix '$__lldb_func' but found " + "'$__lldb_func ' instead."}}, + {"$__lldb_funcc:0x0:0x0:_Z3foov", {}, - {"failed to split function call label '$__lldb_func:'", - "no ':' separator found."}}, - {"$__lldb_func:0x0:0x0", - {}, - {"failed to split function call label '$__lldb_func:0x0:0x0'", - "only single ':' separator found."}}, + {"expected function call label prefix '$__lldb_func' but found " + "'$__lldb_funcc' instead."}}, + {"", {}, {"malformed function call label."}}, + {"foo", {}, {"malformed function call label."}}, + {"$__lldb_func", {}, {"malformed function call label."}}, + {"$__lldb_func:", {}, {"malformed function call label."}}, + {"$__lldb_func:0x0:0x0", {}, {"malformed function call label."}}, {"$__lldb_func:abc:0x0:_Z3foov", {}, {"failed to parse module ID from 'abc'."}}, {"$__lldb_func:-1:0x0:_Z3foov", {}, {"failed to parse module ID from '-1'."}}, + {"$__lldb_func:0x0invalid:0x0:_Z3foov", + {}, + {"failed to parse module ID from '0x0invalid'."}}, + {"$__lldb_func:0x0 :0x0:_Z3foov", + {}, + {"failed to parse module ID from '0x0 '."}}, {"$__lldb_func:0x0:abc:_Z3foov", {}, {"failed to parse symbol ID from 'abc'."}}, {"$__lldb_func:0x5:-1:_Z3foov", {}, {"failed to parse symbol ID from '-1'."}}, + {"$__lldb_func:0x5:0x0invalid:_Z3foov", + {}, + {"failed to parse symbol ID from '0x0invalid'."}}, + {"$__lldb_func:0x5:0x0 :_Z3foov", + {}, + {"failed to parse symbol ID from '0x0 '."}}, {"$__lldb_func:0x0:0x0:_Z3foov", { /*.module_id=*/0x0, From e080b6d5461e5eae9341c7458a92416c33346ae8 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 16:45:37 +0100 Subject: [PATCH 31/38] fixup! remove unused function --- lldb/source/Expression/IRExecutionUnit.cpp | 30 ---------------------- 1 file changed, 30 deletions(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 870b71eee3c7c..b50f5dcc0c61e 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -774,36 +774,6 @@ class LoadAddressResolver { lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS; }; -/// Find a module by LLDB-specific unique identifier. -/// -/// \param[in] uid The UID of the module assigned to it on construction. -/// -/// \returns ModuleSP of module with \c uid. Returns nullptr if no such -/// module could be found. -static lldb::ModuleSP FindDebugModule(lldb::user_id_t uid, - const ModuleList &modules) { - lldb::ModuleSP module_sp; - modules.ForEach([&](const lldb::ModuleSP &m) { - if (m->GetID() == uid) { - module_sp = m; - return IterationAction::Stop; - } - - auto *sym = m->GetSymbolFile(); - if (!sym) - return IterationAction::Continue; - - auto debug_modules = sym->GetDebugInfoModules(); - module_sp = FindDebugModule(uid, debug_modules); - if (module_sp) - return IterationAction::Stop; - - return IterationAction::Continue; - }); - - return module_sp; -} - /// Returns address of the function referred to by the special function call /// label \c label. static llvm::Expected From 24fbf6c4666eb22dba61d4d5a88ec95726df10b4 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 16:46:29 +0100 Subject: [PATCH 32/38] fixup! add TODO --- lldb/source/Expression/IRExecutionUnit.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index b50f5dcc0c61e..6f16196373dbc 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -968,6 +968,9 @@ lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name, } } + // TODO: now with function call labels, do we still need to + // generate alternate manglings? + std::vector candidate_C_names; std::vector candidate_CPlusPlus_names; From fa0b004bac72ef50d0ccfdeb0835d6a4e3763413 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 17:39:16 +0100 Subject: [PATCH 33/38] fixup! fix docs --- lldb/include/lldb/Expression/Expression.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 086aa1406a1c6..20067f469895b 100644 --- a/lldb/include/lldb/Expression/Expression.h +++ b/lldb/include/lldb/Expression/Expression.h @@ -142,7 +142,7 @@ struct FunctionCallLabel { std::string toString() const; }; -/// LLDB attaches this prefix to mangled names of functions that it get called +/// LLDB attaches this prefix to mangled names of functions that get called /// from JITted expressions. inline constexpr llvm::StringRef FunctionCallLabelPrefix = "$__lldb_func"; From edd781de6f718814e6fe32d41fe294b0b88c3c54 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Wed, 30 Jul 2025 23:09:57 +0100 Subject: [PATCH 34/38] fixup! no need for std::optional (cherry picked from commit 7aeed0f42b364ac4272f3cb7b526fcb6dbc38d33) --- .../SymbolFile/DWARF/DWARFASTParserClang.cpp | 10 ++++---- lldb/unittests/Symbol/TestTypeSystemClang.cpp | 24 ------------------- 2 files changed, 5 insertions(+), 29 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 4b386ac2093a7..781c1c6c5745d 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -250,14 +250,14 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram, return cv_quals; } -static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { +static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) { char const *name = die.GetMangledName(/*substitute_name_allowed*/ false); if (!name) - return std::nullopt; + return {}; SymbolFileDWARF *dwarf = die.GetDWARF(); if (!dwarf) - return std::nullopt; + return {}; auto get_module_id = [&](SymbolFile *sym) { if (!sym) @@ -279,11 +279,11 @@ static std::optional MakeLLDBFuncAsmLabel(const DWARFDIE &die) { module_id = get_module_id(dwarf); if (module_id == LLDB_INVALID_UID) - return std::nullopt; + return {}; const auto die_id = die.GetID(); if (die_id == LLDB_INVALID_UID) - return std::nullopt; + return {}; return FunctionCallLabel{/*module_id=*/module_id, /*symbol_id=*/die_id, diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index 228ee2ed9b6ea..57857676c7df9 100644 --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -869,11 +869,7 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) { CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U); FunctionDecl *func = m_ast->CreateFunctionDeclaration( TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None, -<<<<<<< HEAD false, /*asm_label=*/{}); -======= - false, std::nullopt); ->>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -904,11 +900,7 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) { // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine. FunctionDecl *func = m_ast->CreateFunctionDeclaration( TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None, -<<<<<<< HEAD false, /*asm_label=*/{}); -======= - false, std::nullopt); ->>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -946,11 +938,7 @@ TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) { bool is_attr_used = false; bool is_artificial = false; m_ast->AddMethodToCXXRecordType( -<<<<<<< HEAD t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, -======= - t.GetOpaqueQualType(), class_name, std::nullopt, function_type, ->>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); @@ -987,11 +975,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { CompilerType function_type = m_ast->CreateFunctionType( return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( -<<<<<<< HEAD t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, -======= - t.GetOpaqueQualType(), class_name, std::nullopt, function_type, ->>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -1003,11 +987,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { m_ast->CreateFunctionType(return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( -<<<<<<< HEAD t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, -======= - t.GetOpaqueQualType(), class_name, std::nullopt, function_type, ->>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -1118,11 +1098,7 @@ TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) { m_ast->CreateFunctionType(return_type, param_types, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( -<<<<<<< HEAD t.GetOpaqueQualType(), "myFunc", /*asm_label=*/{}, function_type, -======= - t.GetOpaqueQualType(), "myFunc", std::nullopt, function_type, ->>>>>>> 382395408c4b ([lldb][Expression] Encode Module and DIE UIDs into function AsmLabels) lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); From f1e3ce118911757ecb0f379fa1c43c574f4462e4 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Thu, 31 Jul 2025 08:33:17 +0100 Subject: [PATCH 35/38] fixup! add tests for TypeSystemClang::DeclGetMangledName --- lldb/unittests/Symbol/TestTypeSystemClang.cpp | 116 ++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index 57857676c7df9..eb0780d068d36 100644 --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/ExprCXX.h" +#include "llvm/IR/GlobalValue.h" #include "gtest/gtest.h" using namespace clang; @@ -1116,3 +1117,118 @@ TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) { EXPECT_EQ(method_it->getParamDecl(0)->getDeclContext(), *method_it); EXPECT_EQ(method_it->getParamDecl(1)->getDeclContext(), *method_it); } + +TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) { + // Tests TypeSystemClang::DeclGetMangledName for constructors/destructors + // with and without AsmLabels. + + llvm::StringRef class_name = "S"; + CompilerType t = clang_utils::createRecord(*m_ast, class_name); + m_ast->StartTagDeclarationDefinition(t); + + CompilerType return_type = m_ast->GetBasicType(lldb::eBasicTypeVoid); + const bool is_virtual = false; + const bool is_static = false; + const bool is_inline = false; + const bool is_explicit = true; + const bool is_attr_used = false; + const bool is_artificial = false; + + CompilerType function_type = + m_ast->CreateFunctionType(return_type, {}, + /*variadic=*/false, /*quals*/ 0U); + auto *ctor_nolabel = m_ast->AddMethodToCXXRecordType( + t.GetOpaqueQualType(), "S", /*asm_label=*/{}, function_type, + lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, + is_explicit, is_attr_used, is_artificial); + + auto *dtor_nolabel = m_ast->AddMethodToCXXRecordType( + t.GetOpaqueQualType(), "~S", /*asm_label=*/{}, function_type, + lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, + is_explicit, is_attr_used, is_artificial); + + auto *ctor = m_ast->AddMethodToCXXRecordType( + t.GetOpaqueQualType(), "S", /*asm_label=*/"$__lldb_func:0x0:0x0:S", + function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, + is_inline, is_explicit, is_attr_used, is_artificial); + + auto *dtor = m_ast->AddMethodToCXXRecordType( + t.GetOpaqueQualType(), "~S", /*asm_label=*/"$__lldb_func:0x0:0x0:~S", + function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, + is_inline, is_explicit, is_attr_used, is_artificial); + + m_ast->CompleteTagDeclarationDefinition(t); + + ASSERT_TRUE(ctor_nolabel); + ASSERT_TRUE(dtor_nolabel); + ASSERT_TRUE(ctor); + ASSERT_TRUE(dtor); + + ASSERT_STREQ(m_ast->DeclGetMangledName(ctor_nolabel).GetCString(), + "_ZN1SC1Ev"); + ASSERT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(), + "_ZN1SD1Ev"); + ASSERT_STREQ(m_ast->DeclGetMangledName(ctor).GetCString(), + "\01$__lldb_func:0x0:0x0:S"); + ASSERT_STREQ(m_ast->DeclGetMangledName(dtor).GetCString(), + "\01$__lldb_func:0x0:0x0:~S"); +} + +struct AsmLabelTestCase { + llvm::StringRef mangled; + llvm::StringRef expected; +}; + +class TestTypeSystemClangAsmLabel + : public testing::TestWithParam { +public: + SubsystemRAII subsystems; + + void SetUp() override { + m_holder = + std::make_unique("test ASTContext"); + m_ast = m_holder->GetAST(); + } + + void TearDown() override { + m_ast = nullptr; + m_holder.reset(); + } + +protected: + TypeSystemClang *m_ast = nullptr; + std::unique_ptr m_holder; +}; + +static AsmLabelTestCase g_asm_label_test_cases[] = { + {/*mangled=*/"$__lldb_func:0x0:0x0:_Z3foov", + /*expected=*/"_Z3foov"}, + {/*mangled=*/"$__lldb_func:0x0:0x0:foo", + /*expected=*/"$__lldb_func:0x0:0x0:foo"}, + {/*mangled=*/"foo", + /*expected=*/"foo"}, + {/*mangled=*/"_Z3foov", + /*expected=*/"_Z3foov"}, + {/*mangled=*/"$__lldb_func:", + /*expected=*/"$__lldb_func:"}, +}; + +TEST_P(TestTypeSystemClangAsmLabel, DeclGetMangledName) { + const auto &[mangled, expected] = GetParam(); + + CompilerType int_type = m_ast->GetBasicType(lldb::eBasicTypeInt); + clang::TranslationUnitDecl *TU = m_ast->GetTranslationUnitDecl(); + + // Prepare the declarations/types we need for the template. + CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U); + FunctionDecl *func = m_ast->CreateFunctionDeclaration( + TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None, + false, /*asm_label=*/mangled); + + ASSERT_EQ(llvm::GlobalValue::dropLLVMManglingEscape( + m_ast->DeclGetMangledName(func).GetStringRef()), + expected); +} + +INSTANTIATE_TEST_SUITE_P(AsmLabelTests, TestTypeSystemClangAsmLabel, + testing::ValuesIn(g_asm_label_test_cases)); From eabbf72939aa2ed745a6b1d16d073163dfb618fb Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Thu, 31 Jul 2025 10:24:52 +0100 Subject: [PATCH 36/38] fixup! fix mangled name test --- lldb/unittests/Symbol/TestTypeSystemClang.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index eb0780d068d36..739f5376ebe1e 100644 --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -1168,10 +1168,14 @@ TEST_F(TestTypeSystemClang, AsmLabel_CtorDtor) { "_ZN1SC1Ev"); ASSERT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(), "_ZN1SD1Ev"); - ASSERT_STREQ(m_ast->DeclGetMangledName(ctor).GetCString(), - "\01$__lldb_func:0x0:0x0:S"); - ASSERT_STREQ(m_ast->DeclGetMangledName(dtor).GetCString(), - "\01$__lldb_func:0x0:0x0:~S"); + ASSERT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape( + m_ast->DeclGetMangledName(ctor).GetStringRef()) + .data(), + "$__lldb_func:0x0:0x0:S"); + ASSERT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape( + m_ast->DeclGetMangledName(dtor).GetStringRef()) + .data(), + "$__lldb_func:0x0:0x0:~S"); } struct AsmLabelTestCase { From 1f6059c425187626c3b7aa3bf8b69a938b1672fe Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Thu, 31 Jul 2025 13:34:52 +0100 Subject: [PATCH 37/38] fixup! fix LLDB_LOG_ERROR argument error --- lldb/source/Expression/IRExecutionUnit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index 6f16196373dbc..5e40df282e7b0 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -947,7 +947,7 @@ lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name, auto label_or_err = FunctionCallLabel::fromString(name); if (!label_or_err) { LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), label_or_err.takeError(), - "failed to create FunctionCallLabel from '{0}': {1}", + "failed to create FunctionCallLabel from '{1}': {0}", name.GetStringRef()); return LLDB_INVALID_ADDRESS; } From 9269af7095ac7bf9b3eaee6c2e5852c740a6f285 Mon Sep 17 00:00:00 2001 From: Michael Buch Date: Fri, 1 Aug 2025 00:09:41 +0100 Subject: [PATCH 38/38] fixup! fix after rebase --- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 3b3fad6c517c3..a3ba061424cc1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -2494,7 +2494,7 @@ SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) { m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) { if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) - return true; + return IterationAction::Continue; // We don't check whether the specification DIE for this function // corresponds to the declaration DIE because the declaration might be in @@ -2503,7 +2503,7 @@ SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) { // rely on the mangled name within the module to be enough to find us the // unique definition. die = entry; - return false; + return IterationAction::Stop; }); if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0))