diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index b8805819485bd..2953c1b63b3dc 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1084,22 +1084,13 @@ def AVRSignal : InheritableAttr, TargetSpecificAttr { def AsmLabel : InheritableAttr { let Spellings = [CustomKeyword<"asm">, CustomKeyword<"__asm__">]; let Args = [ - // Label specifies the mangled name for the decl. - StringArgument<"Label">, - - // IsLiteralLabel specifies whether the label is literal (i.e. suppresses - // the global C symbol prefix) or not. If not, the mangle-suppression prefix - // ('\01') is omitted from the decl name at the LLVM IR level. - // - // Non-literal labels are used by some external AST sources like LLDB. - BoolArgument<"IsLiteralLabel", /*optional=*/0, /*fake=*/1> - ]; + // Label specifies the mangled name for the decl. + StringArgument<"Label">, ]; let SemaHandler = 0; let Documentation = [AsmLabelDocs]; - let AdditionalMembers = -[{ + let AdditionalMembers = [{ bool isEquivalent(AsmLabelAttr *Other) const { - return getLabel() == Other->getLabel() && getIsLiteralLabel() == Other->getIsLiteralLabel(); + return getLabel() == Other->getLabel(); } }]; } diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 9652fdbc4e125..0bfb51c11f0a5 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -161,9 +161,9 @@ void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) { if (const AsmLabelAttr *ALA = D->getAttr()) { // If we have an asm name, then we use it as the mangling. - // If the label isn't literal, or if this is an alias for an LLVM intrinsic, + // If the label is an alias for an LLVM intrinsic, // do not add a "\01" prefix. - if (!ALA->getIsLiteralLabel() || ALA->getLabel().starts_with("llvm.")) { + if (ALA->getLabel().starts_with("llvm.")) { Out << ALA->getLabel(); return; } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index af7beb07bba83..55a6a93061d85 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -8951,9 +8951,7 @@ NamedDecl *Sema::ActOnVariableDeclarator( } } - NewVD->addAttr(AsmLabelAttr::Create(Context, Label, - /*IsLiteralLabel=*/true, - SE->getStrTokenLoc(0))); + NewVD->addAttr(AsmLabelAttr::Create(Context, Label, SE->getStrTokenLoc(0))); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap::iterator I = ExtnameUndeclaredIdentifiers.find(NewVD->getIdentifier()); @@ -11254,9 +11252,8 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (Expr *E = D.getAsmLabel()) { // The parser guarantees this is a string. StringLiteral *SE = cast(E); - NewFD->addAttr(AsmLabelAttr::Create(Context, SE->getString(), - /*IsLiteralLabel=*/true, - SE->getStrTokenLoc(0))); + NewFD->addAttr( + AsmLabelAttr::Create(Context, SE->getString(), SE->getStrTokenLoc(0))); } else if (!ExtnameUndeclaredIdentifiers.empty()) { llvm::DenseMap::iterator I = ExtnameUndeclaredIdentifiers.find(NewFD->getIdentifier()); @@ -21737,8 +21734,8 @@ void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, LookupOrdinaryName); AttributeCommonInfo Info(AliasName, SourceRange(AliasNameLoc), AttributeCommonInfo::Form::Pragma()); - AsmLabelAttr *Attr = AsmLabelAttr::CreateImplicit( - Context, AliasName->getName(), /*IsLiteralLabel=*/true, Info); + AsmLabelAttr *Attr = + AsmLabelAttr::CreateImplicit(Context, AliasName->getName(), Info); // If a declaration that: // 1) declares a function or a variable diff --git a/clang/unittests/AST/DeclTest.cpp b/clang/unittests/AST/DeclTest.cpp index 4d418a6dfd0ae..bd894caec61d8 100644 --- a/clang/unittests/AST/DeclTest.cpp +++ b/clang/unittests/AST/DeclTest.cpp @@ -131,7 +131,6 @@ TEST(Decl, AsmLabelAttr) { StringRef Code = R"( struct S { void f() {} - void g() {} }; )"; auto AST = @@ -144,11 +143,8 @@ TEST(Decl, AsmLabelAttr) { const auto *DeclS = selectFirst("d", match(cxxRecordDecl().bind("d"), Ctx)); NamedDecl *DeclF = *DeclS->method_begin(); - NamedDecl *DeclG = *(++DeclS->method_begin()); - // Attach asm labels to the decls: one literal, and one not. - DeclF->addAttr(AsmLabelAttr::Create(Ctx, "foo", /*LiteralLabel=*/true)); - DeclG->addAttr(AsmLabelAttr::Create(Ctx, "goo", /*LiteralLabel=*/false)); + DeclF->addAttr(AsmLabelAttr::Create(Ctx, "foo")); // Mangle the decl names. std::string MangleF, MangleG; @@ -156,14 +152,11 @@ TEST(Decl, AsmLabelAttr) { ItaniumMangleContext::create(Ctx, Diags)); { llvm::raw_string_ostream OS_F(MangleF); - llvm::raw_string_ostream OS_G(MangleG); MC->mangleName(DeclF, OS_F); - MC->mangleName(DeclG, OS_G); } ASSERT_EQ(MangleF, "\x01" "foo"); - ASSERT_EQ(MangleG, "goo"); } TEST(Decl, MangleDependentSizedArray) { diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 679c7b6160720..597359c48c43b 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -88,7 +88,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 diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h index 5c21e6c1fc3a9..1109572e27d21 100644 --- a/lldb/include/lldb/Core/ModuleList.h +++ b/lldb/include/lldb/Core/ModuleList.h @@ -18,6 +18,7 @@ #include "lldb/Utility/Status.h" #include "lldb/lldb-enumerations.h" #include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" #include "lldb/lldb-types.h" #include "llvm/ADT/DenseSet.h" @@ -374,6 +375,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; @@ -530,8 +539,9 @@ class ModuleList { /// be non-null. /// /// This function is thread-safe. - void ForEach(std::function const - &callback) const; + void + ForEach(std::function const + &callback) const; void ClearModuleDependentCaches(); diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h index 8de9364436ccf..20067f469895b 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" @@ -96,6 +97,62 @@ 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 { + /// 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; + + /// 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); + + /// Encode this FunctionCallLabel into its string representation. + /// + /// The representation roundtrips through \c fromString: + /// \code{.cpp} + /// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov"; + /// 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 get called +/// from JITted expressions. +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/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 20e2d87ad252c..b527e0d20beac 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -349,6 +349,18 @@ class SymbolFile : public PluginInterface { GetMangledNamesForFunction(const std::string &scope_qualified_name, std::vector &mangled_names); + /// Resolves the function corresponding to the specified LLDB function + /// call \c label. + /// + /// \param[in] label The FunctionCallLabel to be resolved. + /// + /// \returns An llvm::Error if the specified \c label couldn't be resolved. + /// Returns the resolved function (as a SymbolContext) otherwise. + virtual llvm::Expected + ResolveFunctionCallLabel(const FunctionCallLabel &label) { + 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/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp index 38231a8e993c7..93b16f60845fd 100644 --- a/lldb/source/Commands/CommandCompletions.cpp +++ b/lldb/source/Commands/CommandCompletions.cpp @@ -570,7 +570,7 @@ void CommandCompletions::ModuleUUIDs(CommandInterpreter &interpreter, lldb::eDescriptionLevelInitial); request.TryCompleteCurrentArg(module->GetUUID().GetAsString(), strm.GetString()); - return true; + return IterationAction::Continue; }); } diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index b25b586f97c6a..731aa6688d275 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -135,8 +135,10 @@ Module *Module::GetAllocatedModuleAtIndex(size_t idx) { return nullptr; } +static std::atomic 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... { @@ -241,7 +243,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), @@ -262,7 +265,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/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index 85e3c4357daff..2f5428d27252f 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -832,6 +832,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); @@ -1343,12 +1357,12 @@ bool ModuleList::LoadScriptingResourcesInTarget(Target *target, } void ModuleList::ForEach( - std::function const &callback) const { + std::function const &callback) + const { std::lock_guard guard(m_modules_mutex); for (const auto &module_sp : m_modules) { assert(module_sp != nullptr); - // If the callback returns false, then stop iterating and break out - if (!callback(module_sp)) + if (callback(module_sp) == IterationAction::Stop) break; } } diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp index 93f585edfce3d..796851ff15ca3 100644 --- a/lldb/source/Expression/Expression.cpp +++ b/lldb/source/Expression/Expression.cpp @@ -10,6 +10,11 @@ #include "lldb/Target/ExecutionContextScope.h" #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" + using namespace lldb_private; Expression::Expression(Target &target) @@ -26,3 +31,47 @@ Expression::Expression(ExecutionContextScope &exe_scope) m_jit_end_addr(LLDB_INVALID_ADDRESS) { assert(m_target_wp.lock()); } + +llvm::Expected +lldb_private::FunctionCallLabel::fromString(llvm::StringRef label) { + llvm::SmallVector components; + label.split(components, ":", /*MaxSplit=*/3); + + if (components.size() != 4) + return llvm::createStringError("malformed function call label."); + + if (components[0] != FunctionCallLabelPrefix) + return llvm::createStringError(llvm::formatv( + "expected function call label prefix '{0}' but found '{1}' instead.", + FunctionCallLabelPrefix, components[0])); + + llvm::StringRef module_label = components[1]; + llvm::StringRef die_label = components[2]; + + lldb::user_id_t module_id = 0; + if (!llvm::to_integer(module_label, module_id)) + return llvm::createStringError( + llvm::formatv("failed to parse module ID from '{0}'.", module_label)); + + lldb::user_id_t die_id; + if (!llvm::to_integer(die_label, die_id)) + return llvm::createStringError( + llvm::formatv("failed to parse symbol ID from '{0}'.", die_label)); + + return FunctionCallLabel{/*.module_id=*/module_id, + /*.symbol_id=*/die_id, + /*.lookup_name=*/components[3]}; +} + +std::string lldb_private::FunctionCallLabel::toString() const { + return llvm::formatv("{0}:{1:x}:{2:x}:{3}", FunctionCallLabelPrefix, + 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); +} diff --git a/lldb/source/Expression/IRExecutionUnit.cpp b/lldb/source/Expression/IRExecutionUnit.cpp index d2f39ce737bd2..e9a5e026d79ed 100644 --- a/lldb/source/Expression/IRExecutionUnit.cpp +++ b/lldb/source/Expression/IRExecutionUnit.cpp @@ -15,6 +15,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" @@ -23,6 +24,7 @@ #include "lldb/Core/JITSection.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" @@ -39,6 +41,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" +#include "lldb/lldb-defines.h" #include @@ -739,7 +742,7 @@ void IRExecutionUnit::CollectCandidateCPlusPlusNames( class LoadAddressResolver { public: - LoadAddressResolver(Target *target, bool &symbol_was_missing_weak) + LoadAddressResolver(Target &target, bool &symbol_was_missing_weak) : m_target(target), m_symbol_was_missing_weak(symbol_was_missing_weak) {} std::optional Resolve(SymbolContextList &sc_list) { @@ -761,11 +764,11 @@ class LoadAddressResolver { // First try the symbol. if (candidate_sc.symbol) { - load_address = candidate_sc.symbol->ResolveCallableAddress(*m_target); + load_address = candidate_sc.symbol->ResolveCallableAddress(m_target); if (load_address == LLDB_INVALID_ADDRESS) { Address addr = candidate_sc.symbol->GetAddress(); - load_address = m_target->GetProcessSP() - ? addr.GetLoadAddress(m_target) + load_address = m_target.GetProcessSP() + ? addr.GetLoadAddress(&m_target) : addr.GetFileAddress(); } } @@ -773,8 +776,8 @@ class LoadAddressResolver { // If that didn't work, try the function. if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) { Address addr = candidate_sc.function->GetAddress(); - load_address = m_target->GetProcessSP() ? addr.GetLoadAddress(m_target) - : addr.GetFileAddress(); + load_address = m_target.GetProcessSP() ? addr.GetLoadAddress(&m_target) + : addr.GetFileAddress(); } // We found a load address. @@ -805,11 +808,45 @@ class LoadAddressResolver { } private: - Target *m_target; + Target &m_target; bool &m_symbol_was_missing_weak; 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. +static llvm::Expected +ResolveFunctionCallLabel(const FunctionCallLabel &label, + 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 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)); + + auto *symbol_file = module_sp->GetSymbolFile(); + if (!symbol_file) + return llvm::createStringError( + llvm::formatv("no SymbolFile found on module {0:x}.", module_sp.get())); + + auto sc_or_err = symbol_file->ResolveFunctionCallLabel(label); + if (!sc_or_err) + return llvm::joinErrors( + llvm::createStringError("failed to resolve function by UID:"), + 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); +} + lldb::addr_t IRExecutionUnit::FindInSymbols(const std::vector &names, const lldb_private::SymbolContext &sc, @@ -829,7 +866,7 @@ IRExecutionUnit::FindInSymbols(const std::vector &names, for (size_t i = 0; i < m_preferred_modules.GetSize(); ++i) non_local_images.Remove(m_preferred_modules.GetModuleAtIndex(i)); - LoadAddressResolver resolver(target, symbol_was_missing_weak); + LoadAddressResolver resolver(*target, symbol_was_missing_weak); ModuleFunctionSearchOptions function_options; function_options.include_symbols = true; @@ -954,6 +991,34 @@ lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols( lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name, bool &missing_weak) { + if (name.GetStringRef().starts_with(FunctionCallLabelPrefix)) { + 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 '{1}': {0}", + 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()); + + // 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: now with function call labels, do we still need to + // generate alternate manglings? + std::vector candidate_C_names; std::vector candidate_CPlusPlus_names; 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) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 97690717e5535..16f4916a090e7 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1990,7 +1990,7 @@ void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context, const bool is_artificial = false; CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType( - copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr, + copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", /*asm_label=*/{}, method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp index 7fe76a6f0d8ff..a5cee5d324325 100644 --- a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp +++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp @@ -23,10 +23,10 @@ lldb::ModuleSP GetPreferredAsanModule(const Target &target) { target.GetImages().ForEach([&](const lldb::ModuleSP &m) { if (pattern.match(m->GetFileSpec().GetFilename().GetStringRef())) { module = m; - return false; + return IterationAction::Stop; } - return true; + return IterationAction::Continue; }); return module; diff --git a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp index f8207ee6e679c..3846d879a07f3 100644 --- a/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.cpp @@ -172,14 +172,14 @@ static ModuleSP findRuntime(Process &process, RuntimeKind runtime_kind) { if (runtime_kind == RuntimeKind::Swift && image && IsModuleSwiftRuntime(process, *image)) { runtime_image = image; - return false; + return IterationAction::Stop; } if (runtime_kind == RuntimeKind::ObjC && objc_runtime->IsModuleObjCLibrary(image)) { runtime_image = image; - return false; + return IterationAction::Stop; } - return true; + return IterationAction::Continue; }); if (!runtime_image && runtime_kind == RuntimeKind::Swift) { @@ -187,9 +187,9 @@ static ModuleSP findRuntime(Process &process, RuntimeKind runtime_kind) { process.GetTarget().GetImages().ForEach([&](const ModuleSP &image) { if (image && IsStaticSwiftRuntime(*image)) { runtime_image = image; - return false; + return IterationAction::Stop; } - return true; + return IterationAction::Continue; }); } return runtime_image; @@ -200,9 +200,9 @@ ModuleSP SwiftLanguageRuntime::FindConcurrencyModule(Process &process) { process.GetTarget().GetImages().ForEach([&](const ModuleSP &candidate) { if (candidate && IsModuleSwiftConcurrency(process, *candidate)) { concurrency_module = candidate; - return false; + return IterationAction::Stop; } - return true; + return IterationAction::Continue; }); if (concurrency_module) return concurrency_module; @@ -211,9 +211,9 @@ ModuleSP SwiftLanguageRuntime::FindConcurrencyModule(Process &process) { process.GetTarget().GetImages().ForEach([&](const ModuleSP &candidate) { if (candidate && IsStaticSwiftConcurrency(*candidate)) { concurrency_module = candidate; - return false; + return IterationAction::Stop; } - return true; + return IterationAction::Continue; }); return concurrency_module; } @@ -361,14 +361,15 @@ void SwiftLanguageRuntime::ProcessModulesToAdd() { // Add all defered modules to reflection context that were added to // the target since this SwiftLanguageRuntime was created. - modules_to_add_snapshot.ForEach([&](const ModuleSP &module_sp) -> bool { - if (module_sp) { - AddModuleToReflectionContext(module_sp); - progress.Increment(++completion, - module_sp->GetFileSpec().GetFilename().GetString()); - } - return true; - }); + modules_to_add_snapshot.ForEach( + [&](const ModuleSP &module_sp) -> IterationAction { + if (module_sp) { + AddModuleToReflectionContext(module_sp); + progress.Increment( + ++completion, module_sp->GetFileSpec().GetFilename().GetString()); + } + return IterationAction::Continue; + }); } SwiftMetadataCache *SwiftLanguageRuntime::GetSwiftMetadataCache() { diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 14dfdec6a6f62..73c23ab24404b 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -5265,17 +5265,17 @@ llvm::Error ProcessGDBRemote::LoadModules() { loaded_modules.Remove(removed_modules); m_process->GetTarget().ModulesDidUnload(removed_modules, false); - new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool { + new_modules.ForEach([&target](const lldb::ModuleSP module_sp) { lldb_private::ObjectFile *obj = module_sp->GetObjectFile(); if (!obj) - return true; + return IterationAction::Continue; if (obj->GetType() != ObjectFile::Type::eTypeExecutable) - return true; + return IterationAction::Continue; lldb::ModuleSP module_copy_sp = module_sp; target.SetExecutableModule(module_copy_sp, eLoadDependentsNo); - return false; + return IterationAction::Stop; }); loaded_modules.AppendIfNeeded(new_modules); diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp index ef3c00e2857df..ad714698a394d 100644 --- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp +++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp @@ -405,7 +405,7 @@ void ProcessMinidump::BuildMemoryRegions() { to_add.back().SetName(module_sp->GetFileSpec().GetPath().c_str()); } } - return true; + return IterationAction::Continue; }); m_memory_regions->insert(m_memory_regions->end(), to_add.begin(), to_add.end()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp index 4bfbb4d81f5da..a5f83e137eb83 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/Module.h" #include "lldb/Symbol/Function.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/Support/DJB.h" using namespace lldb; @@ -117,11 +118,11 @@ HasImplementationFlag(const llvm::AppleAcceleratorTable::Entry &entry) { (*Flags & llvm::dwarf::AcceleratorTable::DW_FLAG_type_implementation); } -void AppleDWARFIndex::SearchFor(const llvm::AppleAcceleratorTable &table, - llvm::StringRef name, - llvm::function_ref callback, - std::optional search_for_tag, - std::optional search_for_qualhash) { +void AppleDWARFIndex::SearchFor( + const llvm::AppleAcceleratorTable &table, llvm::StringRef name, + llvm::function_ref callback, + std::optional search_for_tag, + std::optional search_for_qualhash) { auto converted_cb = DIERefCallback(callback, name); for (const auto &entry : table.equal_range(name)) { if (search_for_qualhash && @@ -129,13 +130,14 @@ void AppleDWARFIndex::SearchFor(const llvm::AppleAcceleratorTable &table, continue; if (search_for_tag && !EntryHasMatchingTag(entry, *search_for_tag)) continue; - if (!converted_cb(entry)) + if (converted_cb(entry) == IterationAction::Stop) break; } } void AppleDWARFIndex::GetGlobalVariables( - ConstString basename, llvm::function_ref callback) { + ConstString basename, + llvm::function_ref callback) { if (!m_apple_names_up) return; SearchFor(*m_apple_names_up, basename, callback); @@ -143,7 +145,7 @@ void AppleDWARFIndex::GetGlobalVariables( void AppleDWARFIndex::GetGlobalVariables( const RegularExpression ®ex, - llvm::function_ref callback) { + llvm::function_ref callback) { if (!m_apple_names_up) return; @@ -152,12 +154,12 @@ void AppleDWARFIndex::GetGlobalVariables( for (const auto &entry : m_apple_names_up->entries()) if (std::optional name = entry.readName(); name && Mangled(*name).NameMatches(regex)) - if (!converted_cb(entry.BaseEntry)) + if (converted_cb(entry.BaseEntry) == IterationAction::Stop) return; } void AppleDWARFIndex::GetGlobalVariables( - DWARFUnit &cu, llvm::function_ref callback) { + DWARFUnit &cu, llvm::function_ref callback) { if (!m_apple_names_up) return; @@ -171,13 +173,14 @@ void AppleDWARFIndex::GetGlobalVariables( DIERefCallbackImpl converted_cb = DIERefCallback(callback); for (auto entry : m_apple_names_up->entries()) { if (is_in_range(entry.BaseEntry.getDIESectionOffset())) - if (!converted_cb(entry.BaseEntry)) + if (converted_cb(entry.BaseEntry) == IterationAction::Stop) return; } } void AppleDWARFIndex::GetObjCMethods( - ConstString class_name, llvm::function_ref callback) { + ConstString class_name, + llvm::function_ref callback) { if (!m_apple_objc_up) return; SearchFor(*m_apple_objc_up, class_name, callback); @@ -185,7 +188,7 @@ void AppleDWARFIndex::GetObjCMethods( void AppleDWARFIndex::GetCompleteObjCClass( ConstString class_name, bool must_be_implementation, - llvm::function_ref callback) { + llvm::function_ref callback) { if (!m_apple_types_up) return; @@ -205,12 +208,13 @@ void AppleDWARFIndex::GetCompleteObjCClass( if (must_be_implementation) return; for (DIERef ref : decl_dies) - if (!converted_cb(ref)) + if (converted_cb(ref) == IterationAction::Stop) return; } void AppleDWARFIndex::GetTypes( - ConstString name, llvm::function_ref callback) { + ConstString name, + llvm::function_ref callback) { if (!m_apple_types_up) return; SearchFor(*m_apple_types_up, name, callback); @@ -218,7 +222,7 @@ void AppleDWARFIndex::GetTypes( void AppleDWARFIndex::GetTypes( const DWARFDeclContext &context, - llvm::function_ref callback) { + llvm::function_ref callback) { if (!m_apple_types_up) return; @@ -237,7 +241,7 @@ void AppleDWARFIndex::GetTypes( if (log) m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()"); SearchFor(*m_apple_types_up, expected_name, callback, expected_tag, - expected_qualname_hash); + expected_qualname_hash); return; } @@ -266,7 +270,8 @@ void AppleDWARFIndex::GetTypes( } void AppleDWARFIndex::GetNamespaces( - ConstString name, llvm::function_ref callback) { + ConstString name, + llvm::function_ref callback) { if (!m_apple_namespaces_up) return; SearchFor(*m_apple_namespaces_up, name, callback); @@ -275,7 +280,7 @@ void AppleDWARFIndex::GetNamespaces( void AppleDWARFIndex::GetFunctions( const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) { + llvm::function_ref callback) { if (!m_apple_names_up) return; @@ -288,14 +293,15 @@ void AppleDWARFIndex::GetFunctions( ReportInvalidDIERef(die_ref, name); continue; } - if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, callback)) + if (ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, callback) == + IterationAction::Stop) return; } } void AppleDWARFIndex::GetFunctions( const RegularExpression ®ex, - llvm::function_ref callback) { + llvm::function_ref callback) { return GetGlobalVariables(regex, callback); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h index 73de75b583bd4..6da0cce565a29 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/AppleDWARFIndex.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_APPLEDWARFINDEX_H #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" namespace lldb_private::plugin { @@ -41,32 +42,37 @@ class AppleDWARFIndex : public DWARFIndex { void Preload() override {} - void - GetGlobalVariables(ConstString basename, - llvm::function_ref callback) override; - void - GetGlobalVariables(const RegularExpression ®ex, - llvm::function_ref callback) override; - void - GetGlobalVariables(DWARFUnit &cu, - llvm::function_ref callback) override; - void GetObjCMethods(ConstString class_name, - llvm::function_ref callback) override; + void GetGlobalVariables( + ConstString basename, + llvm::function_ref callback) override; + void GetGlobalVariables( + const RegularExpression ®ex, + llvm::function_ref callback) override; + void GetGlobalVariables( + DWARFUnit &cu, + llvm::function_ref callback) override; + void GetObjCMethods( + ConstString class_name, + llvm::function_ref callback) override; void GetCompleteObjCClass( ConstString class_name, bool must_be_implementation, - llvm::function_ref callback) override; - void GetTypes(ConstString name, - llvm::function_ref callback) override; - void GetTypes(const DWARFDeclContext &context, - llvm::function_ref callback) override; - void GetNamespaces(ConstString name, - llvm::function_ref callback) override; - void GetFunctions(const Module::LookupInfo &lookup_info, - SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) override; - void GetFunctions(const RegularExpression ®ex, - llvm::function_ref callback) override; + llvm::function_ref callback) override; + void + GetTypes(ConstString name, + llvm::function_ref callback) override; + void + GetTypes(const DWARFDeclContext &context, + llvm::function_ref callback) override; + void GetNamespaces( + ConstString name, + llvm::function_ref callback) override; + void GetFunctions( + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref callback) override; + void GetFunctions( + const RegularExpression ®ex, + llvm::function_ref callback) override; void Dump(Stream &s) override; @@ -88,9 +94,10 @@ class AppleDWARFIndex : public DWARFIndex { /// each match. If `search_for_tag` is provided, ignore entries whose tag is /// not `search_for_tag`. If `search_for_qualhash` is provided, ignore entries /// whose qualified name hash does not match `search_for_qualhash`. - /// If `callback` returns false for an entry, the search is interrupted. + /// If `callback` returns `IterationAction::Stop` for an entry, the search is + /// interrupted. void SearchFor(const llvm::AppleAcceleratorTable &table, llvm::StringRef name, - llvm::function_ref callback, + llvm::function_ref callback, std::optional search_for_tag = std::nullopt, std::optional search_for_qualhash = std::nullopt); }; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 95580198be9f3..c91cea64ddeee 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -26,6 +26,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/CompilerType.h" @@ -40,6 +41,7 @@ #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/StreamString.h" +#include "lldb/lldb-private-enumerations.h" #include "clang/AST/CXXInheritance.h" #include "clang/AST/Decl.h" @@ -254,6 +256,47 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram, return cv_quals; } +static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) { + char const *name = die.GetMangledName(/*substitute_name_allowed*/ false); + if (!name) + return {}; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (!dwarf) + return {}; + + auto get_module_id = [&](SymbolFile *sym) { + if (!sym) + return LLDB_INVALID_UID; + + 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); + + if (module_id == LLDB_INVALID_UID) + return {}; + + const auto die_id = die.GetID(); + if (die_id == LLDB_INVALID_UID) + return {}; + + return FunctionCallLabel{/*module_id=*/module_id, + /*symbol_id=*/die_id, + /*.lookup_name=*/name} + .toString(); +} + TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, const DWARFDIE &die, Log *log) { @@ -1319,7 +1362,7 @@ std::pair DWARFASTParserClang::ParseCXXMethod( clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), - attrs.mangled_name, clang_type, accessibility, attrs.is_virtual, + MakeLLDBFuncAsmLabel(die), clang_type, accessibility, attrs.is_virtual, is_static, attrs.is_inline, attrs.is_explicit, is_attr_used, attrs.is_artificial); @@ -1472,7 +1515,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, GetOwningClangModule(die), name, clang_type, attrs.storage, - attrs.is_inline); + attrs.is_inline, MakeLLDBFuncAsmLabel(die)); std::free(name_buf); if (has_template_params) { @@ -1482,7 +1525,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type, - attrs.storage, attrs.is_inline); + attrs.storage, attrs.is_inline, /*asm_label=*/{}); clang::FunctionTemplateDecl *func_template_decl = m_ast.CreateFunctionTemplateDecl( containing_decl_ctx, GetOwningClangModule(die), @@ -1494,20 +1537,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, lldbassert(function_decl); if (function_decl) { - // Attach an asm() label to the FunctionDecl. - // This ensures that clang::CodeGen emits function calls - // using symbols that are mangled according to the DW_AT_linkage_name. - // If we didn't do this, the external symbols wouldn't exactly - // match the mangled name LLDB knows about and the IRExecutionUnit - // would have to fall back to searching object files for - // approximately matching function names. The motivating - // example is generating calls to ABI-tagged template functions. - // This is done separately for member functions in - // AddMethodToCXXRecordType. - if (attrs.mangled_name) - function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( - m_ast.getASTContext(), attrs.mangled_name, /*literal=*/false)); - LinkDeclContextToDIE(function_decl, die); const clang::FunctionProtoType *function_prototype( @@ -2313,7 +2342,7 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, if (class_name) { dwarf->GetObjCMethods(class_name, [&](DWARFDIE method_die) { method_die.ResolveType(); - return true; + return IterationAction::Continue; }); for (DelayedAddObjCClassProperty &property : delayed_properties) diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp index 30c890d6d0138..64a8005308454 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.cpp @@ -16,6 +16,7 @@ #include "lldb/Core/Mangled.h" #include "lldb/Core/Module.h" #include "lldb/Target/Language.h" +#include "lldb/lldb-private-enumerations.h" using namespace lldb_private; using namespace lldb; @@ -23,10 +24,10 @@ using namespace lldb_private::plugin::dwarf; DWARFIndex::~DWARFIndex() = default; -bool DWARFIndex::ProcessFunctionDIE( +IterationAction DWARFIndex::ProcessFunctionDIE( const Module::LookupInfo &lookup_info, DWARFDIE die, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) { + llvm::function_ref callback) { llvm::StringRef name = lookup_info.GetLookupName().GetStringRef(); FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); @@ -43,7 +44,7 @@ bool DWARFIndex::ProcessFunctionDIE( if (!lookup_info.NameMatchesLookupInfo(name_to_match_against, lookup_info.GetLanguageType())) - return true; + return IterationAction::Continue; } // Exit early if we're searching exclusively for methods or selectors and @@ -51,12 +52,12 @@ bool DWARFIndex::ProcessFunctionDIE( uint32_t looking_for_nonmethods = name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector); if (!looking_for_nonmethods && parent_decl_ctx.IsValid()) - return true; + return IterationAction::Continue; // Otherwise, we need to also check that the context matches. If it does not // match, we do nothing. if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) - return true; + return IterationAction::Continue; // In case of a full match, we just insert everything we find. if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name) @@ -79,25 +80,26 @@ bool DWARFIndex::ProcessFunctionDIE( return callback(die); } - return true; + return IterationAction::Continue; } DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl( - const DWARFIndex &index, llvm::function_ref callback, + const DWARFIndex &index, + llvm::function_ref callback, llvm::StringRef name) : m_index(index), m_dwarf(*llvm::cast( index.m_module.GetSymbolFile()->GetBackingSymbolFile())), m_callback(callback), m_name(name) {} -bool DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const { +IterationAction DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const { if (DWARFDIE die = m_dwarf.GetDIE(ref)) return m_callback(die); m_index.ReportInvalidDIERef(ref, m_name); - return true; + return IterationAction::Continue; } -bool DWARFIndex::DIERefCallbackImpl::operator()( +IterationAction DWARFIndex::DIERefCallbackImpl::operator()( const llvm::AppleAcceleratorTable::Entry &entry) const { return this->operator()(DIERef(std::nullopt, DIERef::Section::DebugInfo, *entry.getDIESectionOffset())); @@ -112,42 +114,43 @@ void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const { void DWARFIndex::GetFullyQualifiedType( const DWARFDeclContext &context, - llvm::function_ref callback) { + llvm::function_ref callback) { GetTypes(context, [&](DWARFDIE die) { return GetFullyQualifiedTypeImpl(context, die, callback); }); } -bool DWARFIndex::GetFullyQualifiedTypeImpl( +IterationAction DWARFIndex::GetFullyQualifiedTypeImpl( const DWARFDeclContext &context, DWARFDIE die, - llvm::function_ref callback) { + llvm::function_ref callback) { DWARFDeclContext dwarf_decl_ctx = die.GetDWARFDeclContext(); if (dwarf_decl_ctx == context) return callback(die); - return true; + return IterationAction::Continue; } void DWARFIndex::GetTypesWithQuery( - TypeQuery &query, llvm::function_ref callback) { + TypeQuery &query, + llvm::function_ref callback) { GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) { return ProcessTypeDIEMatchQuery(query, die, callback); }); } -bool DWARFIndex::ProcessTypeDIEMatchQuery( +IterationAction DWARFIndex::ProcessTypeDIEMatchQuery( TypeQuery &query, DWARFDIE die, - llvm::function_ref callback) { + llvm::function_ref callback) { // Check the language, but only if we have a language filter. if (query.HasLanguage() && !query.LanguageMatches(SymbolFileDWARF::GetLanguageFamily(*die.GetCU()))) - return true; // Keep iterating over index types, language mismatch. + return IterationAction::Continue; // Since mangled names are unique, we only need to check if the names are // the same. if (query.GetSearchByMangledName()) { if (die.GetMangledName(/*substitute_name_allowed=*/false) != query.GetTypeBasename().GetStringRef()) - return true; // Keep iterating over index types, mangled name mismatch. + return IterationAction::Continue; return callback(die); } @@ -158,22 +161,22 @@ bool DWARFIndex::ProcessTypeDIEMatchQuery( die_context = die.GetTypeLookupContext(); if (!query.ContextMatches(die_context)) - return true; + return IterationAction::Continue; return callback(die); } void DWARFIndex::GetNamespacesWithParents( ConstString name, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) { + llvm::function_ref callback) { GetNamespaces(name, [&](DWARFDIE die) { return ProcessNamespaceDieMatchParents(parent_decl_ctx, die, callback); }); } -bool DWARFIndex::ProcessNamespaceDieMatchParents( +IterationAction DWARFIndex::ProcessNamespaceDieMatchParents( const CompilerDeclContext &parent_decl_ctx, DWARFDIE die, - llvm::function_ref callback) { + llvm::function_ref callback) { if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) - return true; + return IterationAction::Continue; return callback(die); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h index 15d85033434e7..be73255aaf141 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFIndex.h @@ -16,6 +16,7 @@ #include "lldb/Core/Module.h" #include "lldb/Target/Statistics.h" +#include "lldb/lldb-private-enumerations.h" namespace lldb_private::plugin { namespace dwarf { @@ -32,60 +33,61 @@ class DWARFIndex { /// Finds global variables with the given base name. Any additional filtering /// (e.g., to only retrieve variables from a given context) should be done by /// the consumer. - virtual void - GetGlobalVariables(ConstString basename, - llvm::function_ref callback) = 0; + virtual void GetGlobalVariables( + ConstString basename, + llvm::function_ref callback) = 0; - virtual void - GetGlobalVariables(const RegularExpression ®ex, - llvm::function_ref callback) = 0; + virtual void GetGlobalVariables( + const RegularExpression ®ex, + llvm::function_ref callback) = 0; /// \a cu must be the skeleton unit if possible, not GetNonSkeletonUnit(). + virtual void GetGlobalVariables( + DWARFUnit &cu, + llvm::function_ref callback) = 0; + virtual void GetObjCMethods( + ConstString class_name, + llvm::function_ref callback) = 0; + virtual void GetCompleteObjCClass( + ConstString class_name, bool must_be_implementation, + llvm::function_ref callback) = 0; virtual void - GetGlobalVariables(DWARFUnit &cu, - llvm::function_ref callback) = 0; - virtual void - GetObjCMethods(ConstString class_name, - llvm::function_ref callback) = 0; + GetTypes(ConstString name, + llvm::function_ref callback) = 0; virtual void - GetCompleteObjCClass(ConstString class_name, bool must_be_implementation, - llvm::function_ref callback) = 0; - virtual void GetTypes(ConstString name, - llvm::function_ref callback) = 0; - virtual void GetTypes(const DWARFDeclContext &context, - llvm::function_ref callback) = 0; + GetTypes(const DWARFDeclContext &context, + llvm::function_ref callback) = 0; /// Finds all DIEs whose fully qualified name matches `context`. A base /// implementation is provided, and it uses the entire CU to check the DIE /// parent hierarchy. Specializations should override this if they are able /// to provide a faster implementation. - virtual void - GetFullyQualifiedType(const DWARFDeclContext &context, - llvm::function_ref callback); + virtual void GetFullyQualifiedType( + const DWARFDeclContext &context, + llvm::function_ref callback); virtual void GetNamespaces(ConstString name, - llvm::function_ref callback) = 0; + llvm::function_ref callback) = 0; /// Get type DIEs meeting requires of \a query. /// in its decl parent chain as subset. A base implementation is provided, /// Specializations should override this if they are able to provide a faster /// implementation. virtual void GetTypesWithQuery(TypeQuery &query, - llvm::function_ref callback); + llvm::function_ref callback); /// Get namespace DIEs whose base name match \param name with \param /// parent_decl_ctx in its decl parent chain. A base implementation /// is provided. Specializations should override this if they are able to /// provide a faster implementation. - virtual void - GetNamespacesWithParents(ConstString name, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback); + virtual void GetNamespacesWithParents( + ConstString name, const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref callback); virtual void GetFunctions(const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) = 0; + llvm::function_ref callback) = 0; virtual void GetFunctions(const RegularExpression ®ex, - llvm::function_ref callback) = 0; + llvm::function_ref callback) = 0; virtual void Dump(Stream &s) = 0; @@ -101,26 +103,29 @@ class DWARFIndex { /// the function given by "die" matches search criteria given by /// "parent_decl_ctx" and "name_type_mask", it calls the callback with the /// given die. - bool ProcessFunctionDIE(const Module::LookupInfo &lookup_info, DWARFDIE die, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback); + IterationAction ProcessFunctionDIE( + const Module::LookupInfo &lookup_info, DWARFDIE die, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref callback); class DIERefCallbackImpl { public: - DIERefCallbackImpl(const DWARFIndex &index, - llvm::function_ref callback, - llvm::StringRef name); - bool operator()(DIERef ref) const; - bool operator()(const llvm::AppleAcceleratorTable::Entry &entry) const; + DIERefCallbackImpl( + const DWARFIndex &index, + llvm::function_ref callback, + llvm::StringRef name); + IterationAction operator()(DIERef ref) const; + IterationAction + operator()(const llvm::AppleAcceleratorTable::Entry &entry) const; private: const DWARFIndex &m_index; SymbolFileDWARF &m_dwarf; - const llvm::function_ref m_callback; + const llvm::function_ref m_callback; const llvm::StringRef m_name; }; DIERefCallbackImpl - DIERefCallback(llvm::function_ref callback, + DIERefCallback(llvm::function_ref callback, llvm::StringRef name = {}) const { return DIERefCallbackImpl(*this, callback, name); } @@ -129,17 +134,17 @@ class DWARFIndex { /// Implementation of `GetFullyQualifiedType` to check a single entry, /// shareable with derived classes. - bool - GetFullyQualifiedTypeImpl(const DWARFDeclContext &context, DWARFDIE die, - llvm::function_ref callback); + IterationAction GetFullyQualifiedTypeImpl( + const DWARFDeclContext &context, DWARFDIE die, + llvm::function_ref callback); /// Check if the type \a die can meet the requirements of \a query. - bool - ProcessTypeDIEMatchQuery(TypeQuery &query, DWARFDIE die, - llvm::function_ref callback); - bool ProcessNamespaceDieMatchParents( + IterationAction ProcessTypeDIEMatchQuery( + TypeQuery &query, DWARFDIE die, + llvm::function_ref callback); + IterationAction ProcessNamespaceDieMatchParents( const CompilerDeclContext &parent_decl_ctx, DWARFDIE die, - llvm::function_ref callback); + llvm::function_ref callback); }; } // namespace dwarf } // namespace lldb_private::plugin diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp index ff1a76b1dd1dc..fa5baf1a0eeb1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/Module.h" #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/ADT/Sequence.h" #include @@ -151,17 +152,17 @@ DWARFDIE DebugNamesDWARFIndex::GetDIE(const DebugNames::Entry &entry) const { return DWARFDIE(); } -bool DebugNamesDWARFIndex::ProcessEntry( +IterationAction DebugNamesDWARFIndex::ProcessEntry( const DebugNames::Entry &entry, - llvm::function_ref callback) { + llvm::function_ref callback) { DWARFDIE die = GetDIE(entry); if (!die) - return true; + return IterationAction::Continue; // Clang used to erroneously emit index entries for declaration DIEs in case // when the definition is in a type unit (llvm.org/pr77696). if (die.IsStructUnionOrClass() && die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0)) - return true; + return IterationAction::Continue; return callback(die); } @@ -177,13 +178,14 @@ void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error, } void DebugNamesDWARFIndex::GetGlobalVariables( - ConstString basename, llvm::function_ref callback) { + ConstString basename, + llvm::function_ref callback) { for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(basename.GetStringRef())) { if (entry.tag() != DW_TAG_variable) continue; - if (!ProcessEntry(entry, callback)) + if (ProcessEntry(entry, callback) == IterationAction::Stop) return; } @@ -192,7 +194,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables( void DebugNamesDWARFIndex::GetGlobalVariables( const RegularExpression ®ex, - llvm::function_ref callback) { + llvm::function_ref callback) { for (const DebugNames::NameIndex &ni: *m_debug_names_up) { for (DebugNames::NameTableEntry nte: ni) { Mangled mangled_name(nte.getString()); @@ -205,7 +207,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables( if (entry_or->tag() != DW_TAG_variable) continue; - if (!ProcessEntry(*entry_or, callback)) + if (ProcessEntry(*entry_or, callback) == IterationAction::Stop) return; } MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); @@ -216,7 +218,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables( } void DebugNamesDWARFIndex::GetGlobalVariables( - DWARFUnit &cu, llvm::function_ref callback) { + DWARFUnit &cu, llvm::function_ref callback) { uint64_t cu_offset = cu.GetOffset(); bool found_entry_for_cu = false; for (const DebugNames::NameIndex &ni : *m_debug_names_up) { @@ -241,7 +243,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables( continue; found_entry_for_cu = true; - if (!ProcessEntry(*entry_or, callback)) + if (ProcessEntry(*entry_or, callback) == IterationAction::Stop) return; } MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); @@ -255,7 +257,7 @@ void DebugNamesDWARFIndex::GetGlobalVariables( void DebugNamesDWARFIndex::GetCompleteObjCClass( ConstString class_name, bool must_be_implementation, - llvm::function_ref callback) { + llvm::function_ref callback) { // Keep a list of incomplete types as fallback for when we don't find the // complete type. std::vector incomplete_types; @@ -281,7 +283,7 @@ void DebugNamesDWARFIndex::GetCompleteObjCClass( } for (DWARFDIE die : incomplete_types) - if (!callback(die)) + if (callback(die) == IterationAction::Stop) return; m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback); @@ -327,7 +329,7 @@ getParentChain(Entry entry, void DebugNamesDWARFIndex::GetFullyQualifiedType( const DWARFDeclContext &context, - llvm::function_ref callback) { + llvm::function_ref callback) { if (context.GetSize() == 0) return; @@ -356,15 +358,15 @@ void DebugNamesDWARFIndex::GetFullyQualifiedType( if (!parent_chain) { // Fallback: use the base class implementation. - if (!ProcessEntry(entry, [&](DWARFDIE die) { + if (ProcessEntry(entry, [&](DWARFDIE die) { return GetFullyQualifiedTypeImpl(context, die, callback); - })) + }) == IterationAction::Stop) return; continue; } if (SameParentChain(parent_names, *parent_chain)) { - if (!ProcessEntry(entry, callback)) + if (ProcessEntry(entry, callback) == IterationAction::Stop) return; } } @@ -454,11 +456,12 @@ bool DebugNamesDWARFIndex::WithinParentChain( } void DebugNamesDWARFIndex::GetTypes( - ConstString name, llvm::function_ref callback) { + ConstString name, + llvm::function_ref callback) { for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name.GetStringRef())) { if (isType(entry.tag())) { - if (!ProcessEntry(entry, callback)) + if (ProcessEntry(entry, callback) == IterationAction::Stop) return; } } @@ -468,11 +471,11 @@ void DebugNamesDWARFIndex::GetTypes( void DebugNamesDWARFIndex::GetTypes( const DWARFDeclContext &context, - llvm::function_ref callback) { + llvm::function_ref callback) { auto name = context[0].name; for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) { if (entry.tag() == context[0].tag) { - if (!ProcessEntry(entry, callback)) + if (ProcessEntry(entry, callback) == IterationAction::Stop) return; } } @@ -481,13 +484,14 @@ void DebugNamesDWARFIndex::GetTypes( } void DebugNamesDWARFIndex::GetNamespaces( - ConstString name, llvm::function_ref callback) { + ConstString name, + llvm::function_ref callback) { for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name.GetStringRef())) { llvm::dwarf::Tag entry_tag = entry.tag(); if (entry_tag == DW_TAG_namespace || entry_tag == DW_TAG_imported_declaration) { - if (!ProcessEntry(entry, callback)) + if (ProcessEntry(entry, callback) == IterationAction::Stop) return; } } @@ -518,7 +522,8 @@ DebugNamesDWARFIndex::GetTypeQueryParentContexts(TypeQuery &query) { } void DebugNamesDWARFIndex::GetTypesWithQuery( - TypeQuery &query, llvm::function_ref callback) { + TypeQuery &query, + llvm::function_ref callback) { ConstString name = query.GetTypeBasename(); std::vector query_context = query.GetContextRef(); @@ -543,20 +548,20 @@ void DebugNamesDWARFIndex::GetTypesWithQuery( getParentChain(entry); if (!parent_chain) { // Fallback: use the base class implementation. - if (!ProcessEntry(entry, [&](DWARFDIE die) { + if (ProcessEntry(entry, [&](DWARFDIE die) { return ProcessTypeDIEMatchQuery(query, die, callback); - })) + }) == IterationAction::Stop) return; continue; } if (WithinParentChain(parent_contexts, *parent_chain)) { - if (!ProcessEntry(entry, [&](DWARFDIE die) { - // After .debug_names filtering still sending to base class for - // further filtering before calling the callback. + if (ProcessEntry(entry, [&](DWARFDIE die) { + // After .debug_names filtering still sending to base + // class for further filtering before calling the + // callback. return ProcessTypeDIEMatchQuery(query, die, callback); - })) - // If the callback returns false, we're done. + }) == IterationAction::Stop) return; } } @@ -565,7 +570,7 @@ void DebugNamesDWARFIndex::GetTypesWithQuery( void DebugNamesDWARFIndex::GetNamespacesWithParents( ConstString name, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) { + llvm::function_ref callback) { std::vector parent_contexts = parent_decl_ctx.GetCompilerContext(); llvm::SmallVector parent_named_contexts; @@ -581,22 +586,22 @@ void DebugNamesDWARFIndex::GetNamespacesWithParents( getParentChain(entry); if (!parent_chain) { // Fallback: use the base class implementation. - if (!ProcessEntry(entry, [&](DWARFDIE die) { + if (ProcessEntry(entry, [&](DWARFDIE die) { return ProcessNamespaceDieMatchParents(parent_decl_ctx, die, callback); - })) + }) == IterationAction::Stop) return; continue; } if (WithinParentChain(parent_named_contexts, *parent_chain)) { - if (!ProcessEntry(entry, [&](DWARFDIE die) { - // After .debug_names filtering still sending to base class for - // further filtering before calling the callback. + if (ProcessEntry(entry, [&](DWARFDIE die) { + // After .debug_names filtering still sending to + // base class for further filtering before calling + // the callback. return ProcessNamespaceDieMatchParents(parent_decl_ctx, die, callback); - })) - // If the callback returns false, we're done. + }) == IterationAction::Stop) return; } } @@ -607,7 +612,7 @@ void DebugNamesDWARFIndex::GetNamespacesWithParents( void DebugNamesDWARFIndex::GetFunctions( const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) { + llvm::function_ref callback) { ConstString name = lookup_info.GetLookupName(); std::set seen; for (const DebugNames::Entry &entry : @@ -617,12 +622,12 @@ void DebugNamesDWARFIndex::GetFunctions( continue; if (DWARFDIE die = GetDIE(entry)) { - if (!ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, - [&](DWARFDIE die) { - if (!seen.insert(die.GetDIE()).second) - return true; - return callback(die); - })) + if (ProcessFunctionDIE(lookup_info, die, parent_decl_ctx, + [&](DWARFDIE die) { + if (!seen.insert(die.GetDIE()).second) + return IterationAction::Continue; + return callback(die); + }) == IterationAction::Stop) return; } } @@ -632,7 +637,7 @@ void DebugNamesDWARFIndex::GetFunctions( void DebugNamesDWARFIndex::GetFunctions( const RegularExpression ®ex, - llvm::function_ref callback) { + llvm::function_ref callback) { for (const DebugNames::NameIndex &ni: *m_debug_names_up) { for (DebugNames::NameTableEntry nte: ni) { if (!regex.Execute(nte.getString())) @@ -645,7 +650,7 @@ void DebugNamesDWARFIndex::GetFunctions( if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine) continue; - if (!ProcessEntry(*entry_or, callback)) + if (ProcessEntry(*entry_or, callback) == IterationAction::Stop) return; } MaybeLogLookupError(entry_or.takeError(), ni, nte.getString()); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h index ab6cde12623f6..5ebd4f6deb5d4 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h @@ -13,6 +13,7 @@ #include "Plugins/SymbolFile/DWARF/ManualDWARFIndex.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h" #include "lldb/Utility/ConstString.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/DebugInfo/DWARF/DWARFAcceleratorTable.h" #include @@ -26,44 +27,48 @@ class DebugNamesDWARFIndex : public DWARFIndex { void Preload() override { m_fallback.Preload(); } - void - GetGlobalVariables(ConstString basename, - llvm::function_ref callback) override; - void - GetGlobalVariables(const RegularExpression ®ex, - llvm::function_ref callback) override; - void - GetGlobalVariables(DWARFUnit &cu, - llvm::function_ref callback) override; - void - GetObjCMethods(ConstString class_name, - llvm::function_ref callback) override {} + void GetGlobalVariables( + ConstString basename, + llvm::function_ref callback) override; + void GetGlobalVariables( + const RegularExpression ®ex, + llvm::function_ref callback) override; + void GetGlobalVariables( + DWARFUnit &cu, + llvm::function_ref callback) override; + void GetObjCMethods( + ConstString class_name, + llvm::function_ref callback) override {} void GetCompleteObjCClass( ConstString class_name, bool must_be_implementation, - llvm::function_ref callback) override; + llvm::function_ref callback) override; /// Uses DWARF5's IDX_parent fields, when available, to speed up this query. void GetFullyQualifiedType( const DWARFDeclContext &context, - llvm::function_ref callback) override; - void GetTypes(ConstString name, - llvm::function_ref callback) override; - void GetTypes(const DWARFDeclContext &context, - llvm::function_ref callback) override; - void GetNamespaces(ConstString name, - llvm::function_ref callback) override; + llvm::function_ref callback) override; + void + GetTypes(ConstString name, + llvm::function_ref callback) override; void - GetTypesWithQuery(TypeQuery &query, - llvm::function_ref callback) override; + GetTypes(const DWARFDeclContext &context, + llvm::function_ref callback) override; + void GetNamespaces( + ConstString name, + llvm::function_ref callback) override; + void GetTypesWithQuery( + TypeQuery &query, + llvm::function_ref callback) override; void GetNamespacesWithParents( ConstString name, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) override; - void GetFunctions(const Module::LookupInfo &lookup_info, - SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) override; - void GetFunctions(const RegularExpression ®ex, - llvm::function_ref callback) override; + llvm::function_ref callback) override; + void GetFunctions( + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref callback) override; + void GetFunctions( + const RegularExpression ®ex, + llvm::function_ref callback) override; void Dump(Stream &s) override; @@ -117,8 +122,9 @@ class DebugNamesDWARFIndex : public DWARFIndex { std::optional GetForeignTypeUnit(const DebugNames::Entry &entry) const; - bool ProcessEntry(const DebugNames::Entry &entry, - llvm::function_ref callback); + IterationAction + ProcessEntry(const DebugNames::Entry &entry, + llvm::function_ref callback); /// Returns true if `parent_entries` have identical names to `parent_names`. bool SameParentChain(llvm::ArrayRef parent_names, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp index 62f70dcd51f96..7a778d3cd6877 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.cpp @@ -21,6 +21,7 @@ #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/Timer.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/Support/FormatVariadic.h" #include "llvm/Support/ThreadPool.h" #include @@ -413,7 +414,8 @@ void ManualDWARFIndex::IndexUnitImpl(DWARFUnit &unit, } void ManualDWARFIndex::GetGlobalVariables( - ConstString basename, llvm::function_ref callback) { + ConstString basename, + llvm::function_ref callback) { Index(); m_set.globals.Find(basename, DIERefCallback(callback, basename.GetStringRef())); @@ -421,19 +423,21 @@ void ManualDWARFIndex::GetGlobalVariables( void ManualDWARFIndex::GetGlobalVariables( const RegularExpression ®ex, - llvm::function_ref callback) { + llvm::function_ref callback) { Index(); m_set.globals.Find(regex, DIERefCallback(callback, regex.GetText())); } void ManualDWARFIndex::GetGlobalVariables( - DWARFUnit &unit, llvm::function_ref callback) { + DWARFUnit &unit, + llvm::function_ref callback) { Index(); m_set.globals.FindAllEntriesForUnit(unit, DIERefCallback(callback)); } void ManualDWARFIndex::GetObjCMethods( - ConstString class_name, llvm::function_ref callback) { + ConstString class_name, + llvm::function_ref callback) { Index(); m_set.objc_class_selectors.Find( class_name, DIERefCallback(callback, class_name.GetStringRef())); @@ -441,21 +445,22 @@ void ManualDWARFIndex::GetObjCMethods( void ManualDWARFIndex::GetCompleteObjCClass( ConstString class_name, bool must_be_implementation, - llvm::function_ref callback) { + llvm::function_ref callback) { Index(); m_set.types.Find(class_name, DIERefCallback(callback, class_name.GetStringRef())); } void ManualDWARFIndex::GetTypes( - ConstString name, llvm::function_ref callback) { + ConstString name, + llvm::function_ref callback) { Index(); m_set.types.Find(name, DIERefCallback(callback, name.GetStringRef())); } void ManualDWARFIndex::GetTypes( const DWARFDeclContext &context, - llvm::function_ref callback) { + llvm::function_ref callback) { Index(); auto name = context[0].name; m_set.types.Find(ConstString(name), @@ -463,7 +468,8 @@ void ManualDWARFIndex::GetTypes( } void ManualDWARFIndex::GetNamespaces( - ConstString name, llvm::function_ref callback) { + ConstString name, + llvm::function_ref callback) { Index(); m_set.namespaces.Find(name, DIERefCallback(callback, name.GetStringRef())); } @@ -471,7 +477,7 @@ void ManualDWARFIndex::GetNamespaces( void ManualDWARFIndex::GetFunctions( const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) { + llvm::function_ref callback) { Index(); ConstString name = lookup_info.GetLookupName(); FunctionNameType name_type_mask = lookup_info.GetNameTypeMask(); @@ -482,7 +488,7 @@ void ManualDWARFIndex::GetFunctions( [&](DWARFDIE die) { if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) - return true; + return IterationAction::Continue; return callback(die); }, name.GetStringRef()))) @@ -494,7 +500,7 @@ void ManualDWARFIndex::GetFunctions( [&](DWARFDIE die) { if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die)) - return true; + return IterationAction::Continue; return callback(die); }, name.GetStringRef()))) @@ -517,7 +523,7 @@ void ManualDWARFIndex::GetFunctions( void ManualDWARFIndex::GetFunctions( const RegularExpression ®ex, - llvm::function_ref callback) { + llvm::function_ref callback) { Index(); if (!m_set.function_basenames.Find(regex, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h index 04627b0ad91e6..0b5b2f3e84309 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/ManualDWARFIndex.h @@ -12,6 +12,7 @@ #include "Plugins/SymbolFile/DWARF/DWARFIndex.h" #include "Plugins/SymbolFile/DWARF/ManualDWARFIndexSet.h" #include "Plugins/SymbolFile/DWARF/NameToDIE.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/ADT/DenseSet.h" namespace lldb_private::plugin { @@ -30,32 +31,37 @@ class ManualDWARFIndex : public DWARFIndex { void Preload() override { Index(); } - void - GetGlobalVariables(ConstString basename, - llvm::function_ref callback) override; - void - GetGlobalVariables(const RegularExpression ®ex, - llvm::function_ref callback) override; - void - GetGlobalVariables(DWARFUnit &unit, - llvm::function_ref callback) override; - void GetObjCMethods(ConstString class_name, - llvm::function_ref callback) override; + void GetGlobalVariables( + ConstString basename, + llvm::function_ref callback) override; + void GetGlobalVariables( + const RegularExpression ®ex, + llvm::function_ref callback) override; + void GetGlobalVariables( + DWARFUnit &unit, + llvm::function_ref callback) override; + void GetObjCMethods( + ConstString class_name, + llvm::function_ref callback) override; void GetCompleteObjCClass( ConstString class_name, bool must_be_implementation, - llvm::function_ref callback) override; - void GetTypes(ConstString name, - llvm::function_ref callback) override; - void GetTypes(const DWARFDeclContext &context, - llvm::function_ref callback) override; - void GetNamespaces(ConstString name, - llvm::function_ref callback) override; - void GetFunctions(const Module::LookupInfo &lookup_info, - SymbolFileDWARF &dwarf, - const CompilerDeclContext &parent_decl_ctx, - llvm::function_ref callback) override; - void GetFunctions(const RegularExpression ®ex, - llvm::function_ref callback) override; + llvm::function_ref callback) override; + void + GetTypes(ConstString name, + llvm::function_ref callback) override; + void + GetTypes(const DWARFDeclContext &context, + llvm::function_ref callback) override; + void GetNamespaces( + ConstString name, + llvm::function_ref callback) override; + void GetFunctions( + const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf, + const CompilerDeclContext &parent_decl_ctx, + llvm::function_ref callback) override; + void GetFunctions( + const RegularExpression ®ex, + llvm::function_ref callback) override; void Dump(Stream &s) override; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp index 44d90648700cf..b34fda5740924 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.cpp @@ -16,6 +16,7 @@ #include "lldb/Utility/RegularExpression.h" #include "lldb/Utility/Stream.h" #include "lldb/Utility/StreamString.h" +#include "lldb/lldb-private-enumerations.h" #include using namespace lldb; @@ -31,26 +32,29 @@ void NameToDIE::Insert(ConstString name, const DIERef &die_ref) { m_map.Append(name, die_ref); } -bool NameToDIE::Find(ConstString name, - llvm::function_ref callback) const { +bool NameToDIE::Find( + ConstString name, + llvm::function_ref callback) const { for (const auto &entry : m_map.equal_range(name)) - if (!callback(entry.value)) + if (callback(entry.value) == IterationAction::Stop) return false; return true; } -bool NameToDIE::Find(const RegularExpression ®ex, - llvm::function_ref callback) const { +bool NameToDIE::Find( + const RegularExpression ®ex, + llvm::function_ref callback) const { for (const auto &entry : m_map) if (regex.Execute(entry.cstring.GetCString())) { - if (!callback(entry.value)) + if (callback(entry.value) == IterationAction::Stop) return false; } return true; } void NameToDIE::FindAllEntriesForUnit( - DWARFUnit &s_unit, llvm::function_ref callback) const { + DWARFUnit &s_unit, + llvm::function_ref callback) const { const DWARFUnit &ns_unit = s_unit.GetNonSkeletonUnit(); const uint32_t size = m_map.GetSize(); for (uint32_t i = 0; i < size; ++i) { @@ -59,7 +63,7 @@ void NameToDIE::FindAllEntriesForUnit( ns_unit.GetDebugSection() == die_ref.section() && ns_unit.GetOffset() <= die_ref.die_offset() && die_ref.die_offset() < ns_unit.GetNextUnitOffset()) { - if (!callback(die_ref)) + if (callback(die_ref) == IterationAction::Stop) return; } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h index 90eac1fa37338..9f9b631f178ee 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/NameToDIE.h @@ -15,6 +15,7 @@ #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Core/dwarf.h" #include "lldb/lldb-defines.h" +#include "lldb/lldb-private-enumerations.h" namespace lldb_private::plugin { namespace dwarf { @@ -35,15 +36,15 @@ class NameToDIE { void Finalize(); bool Find(ConstString name, - llvm::function_ref callback) const; + llvm::function_ref callback) const; bool Find(const RegularExpression ®ex, - llvm::function_ref callback) const; + llvm::function_ref callback) const; /// \a unit must be the skeleton unit if possible, not GetNonSkeletonUnit(). - void - FindAllEntriesForUnit(DWARFUnit &unit, - llvm::function_ref callback) const; + void FindAllEntriesForUnit( + DWARFUnit &unit, + llvm::function_ref callback) const; void ForEach(std::function const diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index ce4d472e411f6..00920221d78fe 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -75,6 +75,7 @@ #include "ManualDWARFIndex.h" #include "SymbolFileDWARFDebugMap.h" #include "SymbolFileDWARFDwo.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h" @@ -1675,7 +1676,8 @@ SymbolFileDWARF::GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu) { } void SymbolFileDWARF::GetObjCMethods( - ConstString class_name, llvm::function_ref callback) { + ConstString class_name, + llvm::function_ref callback) { m_index->GetObjCMethods(class_name, callback); } @@ -2367,11 +2369,11 @@ void SymbolFileDWARF::FindGlobalVariables( assert(sc.module_sp); if (die.Tag() != DW_TAG_variable && die.Tag() != DW_TAG_member) - return true; + return IterationAction::Continue; auto *dwarf_cu = llvm::dyn_cast(die.GetCU()); if (!dwarf_cu) - return true; + return IterationAction::Continue; sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); if (parent_decl_ctx) { @@ -2386,7 +2388,7 @@ void SymbolFileDWARF::FindGlobalVariables( if (!actual_parent_decl_ctx || (actual_parent_decl_ctx != parent_decl_ctx && !parent_decl_ctx.IsContainedInLookup(actual_parent_decl_ctx))) - return true; + return IterationAction::Continue; } } @@ -2400,7 +2402,10 @@ void SymbolFileDWARF::FindGlobalVariables( variables.RemoveVariableAtIndex(pruned_idx); } - return variables.GetSize() - original_size < max_matches; + if (variables.GetSize() - original_size < max_matches) + return IterationAction::Continue; + + return IterationAction::Stop; }); // Return the number of variable that were appended to the list @@ -2440,12 +2445,15 @@ void SymbolFileDWARF::FindGlobalVariables(const RegularExpression ®ex, DWARFCompileUnit *dwarf_cu = llvm::dyn_cast(die.GetCU()); if (!dwarf_cu) - return true; + return IterationAction::Continue; sc.comp_unit = GetCompUnitForDWARFCompUnit(*dwarf_cu); ParseAndAppendGlobalVariable(sc, die, variables); - return variables.GetSize() - original_size < max_matches; + if (variables.GetSize() - original_size < max_matches) + return IterationAction::Continue; + + return IterationAction::Stop; }); } @@ -2494,6 +2502,61 @@ bool SymbolFileDWARF::ResolveFunction(const DWARFDIE &orig_die, return false; } +DWARFDIE +SymbolFileDWARF::FindFunctionDefinition(const FunctionCallLabel &label) { + DWARFDIE definition; + Module::LookupInfo info(ConstString(label.lookup_name), + lldb::eFunctionNameTypeFull, + lldb::eLanguageTypeUnknown); + + m_index->GetFunctions(info, *this, {}, [&](DWARFDIE entry) { + if (entry.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) + return IterationAction::Continue; + + // We don't check whether the specification DIE for this function + // corresponds to the declaration DIE because the declaration might be in + // a type-unit but the definition in the compile-unit (and it's + // specifcation would point to the declaration in the compile-unit). We + // rely on the mangled name within the module to be enough to find us the + // unique definition. + definition = entry; + return IterationAction::Stop; + }); + + return definition; +} + +llvm::Expected +SymbolFileDWARF::ResolveFunctionCallLabel(const FunctionCallLabel &label) { + std::lock_guard guard(GetModuleMutex()); + + DWARFDIE die = GetDIE(label.symbol_id); + if (!die.IsValid()) + return llvm::createStringError( + llvm::formatv("invalid DIE ID in {0}", label)); + + // Label was created using a declaration DIE. Need to fetch the definition + // to resolve the function call. + if (die.GetAttributeValueAsUnsigned(llvm::dwarf::DW_AT_declaration, 0)) { + auto definition = FindFunctionDefinition(label); + if (!definition) + return llvm::createStringError("failed to find definition DIE"); + + die = std::move(definition); + } + + SymbolContextList sc_list; + if (!ResolveFunction(die, /*include_inlines=*/false, sc_list)) + return llvm::createStringError("failed to resolve function"); + + if (sc_list.IsEmpty()) + return llvm::createStringError("failed to find function"); + + assert(sc_list.GetSize() == 1); + + return sc_list[0]; +} + bool SymbolFileDWARF::DIEInDeclContext(const CompilerDeclContext &decl_ctx, const DWARFDIE &die, bool only_root_namespaces) { @@ -2558,7 +2621,7 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info, m_index->GetFunctions(lookup_info, *this, parent_decl_ctx, [&](DWARFDIE die) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); - return true; + return IterationAction::Continue; }); // With -gsimple-template-names, a templated type's DW_AT_name will not // contain the template parameters. Try again stripping '<' and anything @@ -2575,7 +2638,7 @@ void SymbolFileDWARF::FindFunctions(const Module::LookupInfo &lookup_info, [&](DWARFDIE die) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); - return true; + return IterationAction::Continue; }); } } @@ -2611,7 +2674,7 @@ void SymbolFileDWARF::FindFunctions(const RegularExpression ®ex, m_index->GetFunctions(regex, [&](DWARFDIE die) { if (resolved_dies.insert(die.GetDIE()).second) ResolveFunction(die, include_inlines, sc_list); - return true; + return IterationAction::Continue; }); } @@ -2621,13 +2684,16 @@ void SymbolFileDWARF::FindImportedDeclaration( llvm::DenseSet resolved_dies; m_index->GetNamespaces(name, [&](DWARFDIE die) { if (die.Tag() != llvm::dwarf::DW_TAG_imported_declaration) - return true; + return IterationAction::Continue; if (name != die.GetName()) - return true; + return IterationAction::Continue; sc_list.emplace_back(die.GetID(), name, this); - return !find_one; + if (find_one) + return IterationAction::Stop; + + return IterationAction::Continue; }); } @@ -2738,12 +2804,15 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) { auto CompilerTypeBasename = matching_type->GetForwardCompilerType().GetTypeName(true); if (CompilerTypeBasename != query.GetTypeBasename()) - return true; // Keep iterating over index types, basename mismatch. + return IterationAction::Continue; } have_index_match = true; results.InsertUnique(matching_type->shared_from_this()); } - return !results.Done(query); // Keep iterating if we aren't done. + if (!results.Done(query)) + return IterationAction::Continue; + + return IterationAction::Stop; }); if (results.Done(query)) { @@ -2779,7 +2848,10 @@ void SymbolFileDWARF::FindTypes(const TypeQuery &query, TypeResults &results) { if (query.ContextMatches(qualified_context)) if (Type *matching_type = ResolveType(die, true, true)) results.InsertUnique(matching_type->shared_from_this()); - return !results.Done(query); // Keep iterating if we aren't done. + if (!results.Done(query)) + return IterationAction::Continue; + + return IterationAction::Stop; }); if (results.Done(query)) { if (log) { @@ -2832,14 +2904,17 @@ SymbolFileDWARF::FindNamespace(ConstString name, m_index->GetNamespacesWithParents(name, parent_decl_ctx, [&](DWARFDIE die) { if (!DIEInDeclContext(parent_decl_ctx, die, only_root_namespaces)) - return true; // The containing decl contexts don't match + return IterationAction::Continue; DWARFASTParser *dwarf_ast = GetDWARFParser(*die.GetCU()); if (!dwarf_ast) - return true; + return IterationAction::Continue; namespace_decl_ctx = dwarf_ast->GetDeclContextForUIDFromDWARF(die); - return !namespace_decl_ctx.IsValid(); + if (namespace_decl_ctx.IsValid()) + return IterationAction::Stop; + + return IterationAction::Continue; }); if (log && namespace_decl_ctx) { @@ -2969,18 +3044,18 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( // Don't try and resolve the DIE we are looking for with the DIE // itself! if (type_die == die || !IsStructOrClassTag(type_die.Tag())) - return true; + return IterationAction::Continue; if (must_be_implementation) { const bool try_resolving_type = type_die.GetAttributeValueAsUnsigned( DW_AT_APPLE_objc_complete_type, 0); if (!try_resolving_type) - return true; + return IterationAction::Continue; } Type *resolved_type = ResolveType(type_die, false, true); if (!resolved_type || resolved_type == DIE_IS_BEING_PARSED) - return true; + return IterationAction::Continue; DEBUG_PRINTF( "resolved 0x%8.8" PRIx64 " from %s to 0x%8.8" PRIx64 @@ -2992,7 +3067,7 @@ TypeSP SymbolFileDWARF::FindCompleteObjCDefinitionTypeForDIE( if (die) GetDIEToType()[die.GetDIE()] = resolved_type; type_sp = resolved_type->shared_from_this(); - return false; + return IterationAction::Stop; }); return type_sp; } @@ -3083,7 +3158,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { // are looking for a "Foo" type for C, C++, ObjC, or ObjC++. if (type_system && !type_system->SupportsLanguage(GetLanguage(*type_die.GetCU()))) - return true; + return IterationAction::Continue; if (!die_matches(type_die)) { if (log) { @@ -3094,7 +3169,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { DW_TAG_value_to_name(tag), tag, name, type_die.GetOffset(), type_die.GetName()); } - return true; + return IterationAction::Continue; } if (log) { @@ -3108,7 +3183,7 @@ SymbolFileDWARF::FindDefinitionDIE(const DWARFDIE &die) { } result = type_die; - return false; + return IterationAction::Stop; }); return result; } @@ -3337,7 +3412,7 @@ size_t SymbolFileDWARF::ParseVariablesForContext(const SymbolContext &sc) { variables->AddVariableIfUnique(var_sp); ++vars_added; } - return true; + return IterationAction::Continue; }); } return vars_added; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index a4a6505323462..6e1d78519bec7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -240,8 +240,9 @@ class SymbolFileDWARF : public SymbolFileCommon { CompileUnit *GetCompUnitForDWARFCompUnit(DWARFCompileUnit &dwarf_cu); - virtual void GetObjCMethods(ConstString class_name, - llvm::function_ref callback); + virtual void + GetObjCMethods(ConstString class_name, + llvm::function_ref callback); DebugMacrosSP ParseDebugMacros(lldb::offset_t *offset); @@ -392,6 +393,13 @@ class SymbolFileDWARF : public SymbolFileCommon { /// Returns the DWARFIndex for this symbol, if it exists. DWARFIndex *getIndex() { return m_index.get(); } +private: + /// Find the definition DIE for the specified \c label in this + /// SymbolFile. + /// + /// \returns A valid definition DIE on success. + DWARFDIE FindFunctionDefinition(const FunctionCallLabel &label); + protected: SymbolFileDWARF(const SymbolFileDWARF &) = delete; const SymbolFileDWARF &operator=(const SymbolFileDWARF &) = delete; @@ -456,6 +464,9 @@ class SymbolFileDWARF : public SymbolFileCommon { DIEArray MergeBlockAbstractParameters(const DWARFDIE &block_die, DIEArray &&variable_dies); + 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, SymbolContextList &sc_list); diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp index 8e550db1415b0..ab3c3b7aa1aa7 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.cpp @@ -1715,3 +1715,14 @@ void SymbolFileDWARFDebugMap::GetCompileOptions( return IterationAction::Continue; }); } + +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(label); +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h index fe6536ed609f3..297f840125e98 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDebugMap.h @@ -157,6 +157,9 @@ class SymbolFileDWARFDebugMap : public SymbolFileCommon { void GetCompileOptions(std::unordered_map &args) override; + llvm::Expected + ResolveFunctionCallLabel(const FunctionCallLabel &label) override; + protected: enum { kHaveInitializedOSOs = (1 << 0), kNumFlags }; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index 52de3abca4b77..60d87c3fc2559 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -120,7 +120,7 @@ SymbolFileDWARFDwo::GetForwardDeclCompilerTypeToDIE() { void SymbolFileDWARFDwo::GetObjCMethods( lldb_private::ConstString class_name, - llvm::function_ref callback) { + llvm::function_ref callback) { GetBaseSymbolFile().GetObjCMethods(class_name, callback); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 1ab6494f8ef7f..d906e09fe81ab 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -10,6 +10,7 @@ #define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEDWARFDWO_H #include "SymbolFileDWARF.h" +#include "lldb/lldb-private-enumerations.h" #include namespace lldb_private::plugin { @@ -34,8 +35,9 @@ class SymbolFileDWARFDwo : public SymbolFileDWARF { DWARFCompileUnit *GetDWOCompileUnitForHash(uint64_t hash); - void GetObjCMethods(ConstString class_name, - llvm::function_ref callback) override; + void GetObjCMethods( + ConstString class_name, + llvm::function_ref callback) override; llvm::Expected GetTypeSystemForLanguage(lldb::LanguageType language) override; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 702ec5e5c9ea9..8137622842253 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -88,7 +88,7 @@ struct CreateMethodDecl : public TypeVisitorCallbacks { MethodOptions::CompilerGenerated; function_decl = m_clang.AddMethodToCXXRecordType( parent_ty, proc_name, - /*mangled_name=*/nullptr, func_ct, /*access=*/access_type, + /*asm_label=*/{}, func_ct, /*access=*/access_type, /*is_virtual=*/is_virtual, /*is_static=*/is_static, /*is_inline=*/false, /*is_explicit=*/false, /*is_attr_used=*/false, /*is_artificial=*/is_artificial); @@ -903,7 +903,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, if (!function_decl) { function_decl = m_clang.AddMethodToCXXRecordType( parent_opaque_ty, func_name, - /*mangled_name=*/nullptr, func_ct, + /*asm_label=*/{}, func_ct, /*access=*/lldb::AccessType::eAccessPublic, /*is_virtual=*/false, /*is_static=*/false, /*is_inline=*/false, /*is_explicit=*/false, @@ -913,7 +913,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, } else { function_decl = m_clang.CreateFunctionDeclaration( parent, OptionalClangModuleID(), func_name, func_ct, func_storage, - is_inline); + is_inline, /*asm_label=*/{}); CreateFunctionParameters(func_id, *function_decl, param_count); } return function_decl; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 807ee5b30779c..1c575e90bd72c 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -111,9 +111,8 @@ void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, bool is_artificial = (options & MethodOptions::CompilerGenerated) == MethodOptions::CompilerGenerated; m_ast_builder.clang().AddMethodToCXXRecordType( - derived_opaque_ty, name.data(), nullptr, method_ct, - access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false, - is_artificial); + derived_opaque_ty, name.data(), /*asm_label=*/{}, method_ct, access_type, + attrs.isVirtual(), attrs.isStatic(), false, false, false, is_artificial); m_cxx_record_map[derived_opaque_ty].insert({name, method_ct}); } diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 0090d8ff03ab6..8b8eac6e67c01 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -954,7 +954,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { auto decl = m_ast.CreateFunctionDeclaration( decl_context, OptionalClangModuleID(), name, - type->GetForwardCompilerType(), storage, func->hasInlineAttribute()); + type->GetForwardCompilerType(), storage, func->hasInlineAttribute(), + /*asm_label=*/{}); std::vector params; if (std::unique_ptr sig = func->getSignature()) { @@ -1446,7 +1447,7 @@ PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, // TODO: get mangled name for the method. return m_ast.AddMethodToCXXRecordType( record_type.GetOpaqueQualType(), name.c_str(), - /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(), + /*asm_label=*/{}, method_comp_type, access, method.isVirtual(), method.isStatic(), method.hasInlineAttribute(), /*is_explicit*/ false, // FIXME: Need this field in CodeView. /*is_attr_used*/ false, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 7ef34f162cd80..4c51ef190f2b4 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -61,6 +61,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" @@ -2185,7 +2186,7 @@ std::string TypeSystemClang::GetTypeNameForDecl(const NamedDecl *named_decl, FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, llvm::StringRef name, const CompilerType &function_clang_type, - clang::StorageClass storage, bool is_inline) { + clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label) { FunctionDecl *func_decl = nullptr; ASTContext &ast = getASTContext(); if (!decl_ctx) @@ -2206,6 +2207,20 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( func_decl->setConstexprKind(isConstexprSpecified ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified); + + // Attach an asm() label to the FunctionDecl. + // This ensures that clang::CodeGen emits function calls + // using symbols that are mangled according to the DW_AT_linkage_name. + // If we didn't do this, the external symbols wouldn't exactly + // match the mangled name LLDB knows about and the IRExecutionUnit + // would have to fall back to searching object files for + // approximately matching function names. The motivating + // example is generating calls to ABI-tagged template functions. + // This is done separately for member functions in + // AddMethodToCXXRecordType. + if (!asm_label.empty()) + func_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(ast, asm_label)); + SetOwningModule(func_decl, owning_module); decl_ctx->addDecl(func_decl); @@ -7799,7 +7814,7 @@ TypeSystemClang::CreateParameterDeclarations( clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( lldb::opaque_compiler_type_t type, llvm::StringRef name, - const char *mangled_name, const CompilerType &method_clang_type, + llvm::StringRef asm_label, const CompilerType &method_clang_type, lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline, bool is_explicit, bool is_attr_used, bool is_artificial) { if (!type || !method_clang_type.IsValid() || name.empty()) @@ -7934,10 +7949,9 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( if (is_attr_used) cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext())); - if (mangled_name != nullptr) { - cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( - getASTContext(), mangled_name, /*literal=*/false)); - } + if (!asm_label.empty()) + cxx_method_decl->addAttr( + clang::AsmLabelAttr::CreateImplicit(getASTContext(), asm_label)); // Parameters on member function declarations in DWARF generally don't // have names, so we omit them when creating the ParmVarDecls. @@ -9276,6 +9290,21 @@ ConstString TypeSystemClang::DeclGetName(void *opaque_decl) { return ConstString(); } +static ConstString +ExtractMangledNameFromFunctionCallLabel(llvm::StringRef label) { + auto label_or_err = FunctionCallLabel::fromString(label); + if (!label_or_err) { + llvm::consumeError(label_or_err.takeError()); + return {}; + } + + llvm::StringRef mangled = label_or_err->lookup_name; + 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)); @@ -9287,6 +9316,13 @@ ConstString TypeSystemClang::DeclGetMangledName(void *opaque_decl) { if (!mc || !mc->shouldMangleCXXName(nd)) return {}; + // 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 (ConstString mangled = + ExtractMangledNameFromFunctionCallLabel(label->getLabel())) + return mangled; + llvm::SmallVector buf; llvm::raw_svector_ostream llvm_ostrm(buf); if (llvm::isa(nd)) { diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 81c2e8154b122..a82e811e7914a 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -514,7 +514,7 @@ class TypeSystemClang : public TypeSystem { clang::FunctionDecl *CreateFunctionDeclaration( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, llvm::StringRef name, const CompilerType &function_Type, - clang::StorageClass storage, bool is_inline); + clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label); CompilerType CreateFunctionType(const CompilerType &result_type, @@ -1080,7 +1080,7 @@ class TypeSystemClang : public TypeSystem { clang::CXXMethodDecl *AddMethodToCXXRecordType( lldb::opaque_compiler_type_t type, llvm::StringRef name, - const char *mangled_name, const CompilerType &method_type, + llvm::StringRef asm_label, const CompilerType &method_type, lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline, bool is_explicit, bool is_attr_used, bool is_artificial); diff --git a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp index e78ceb1c14889..5eae9d0ea7581 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/SwiftASTContext.cpp @@ -4232,11 +4232,14 @@ void SwiftASTContext::LoadModule(swift::ModuleDecl *swift_module, if (!matching_module_list.IsEmpty()) { matching_module_list.ForEach( [&module_already_loaded, &module_spec, - &framework_name](const ModuleSP &module_sp) -> bool { + &framework_name](const ModuleSP &module_sp) -> IterationAction { module_already_loaded = module_spec.GetFileSpec().GetPath().find( framework_name) != std::string::npos; - return module_already_loaded == - false; // Keep iterating if we didn't find the right module + // Keep iterating if we didn't find the right module + if (!module_already_loaded) + return IterationAction::Continue; + + return IterationAction::Stop; }); } // If we already have this library loaded, don't try and load it again. diff --git a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp index fa667deb6d777..b948d1e61f93a 100644 --- a/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp +++ b/lldb/source/Plugins/TypeSystem/Swift/TypeSystemSwiftTypeRef.cpp @@ -437,21 +437,24 @@ TypeSP TypeSystemSwiftTypeRefForExpressions::LookupClangType( if (m_clang_type_cache.Lookup(key, result)) return result; - auto lookup = [&](const ModuleSP &m) -> bool { + auto lookup = [&](const ModuleSP &m) -> IterationAction { // Don't recursively call into LookupClangTypes() to avoid filling // hundreds of image caches with negative results. result = ::LookupClangType(const_cast(*m), decl_context, ignore_modules); // Cache it in the expression context. - if (result) + if (result) { m_clang_type_cache.Insert(key, result); - return !result; + return IterationAction::Stop; + } + + return IterationAction::Continue; }; // Visit the current module first as a performance optimization heuristic. ModuleSP cur_module = sc.module_sp; if (cur_module) - if (!lookup(cur_module)) + if (lookup(cur_module) == IterationAction::Stop) return result; if (TargetSP target_sp = GetTargetWP().lock()) diff --git a/lldb/source/Target/InstrumentationRuntime.cpp b/lldb/source/Target/InstrumentationRuntime.cpp index 9da06e8e155af..4b531dc3c7597 100644 --- a/lldb/source/Target/InstrumentationRuntime.cpp +++ b/lldb/source/Target/InstrumentationRuntime.cpp @@ -49,10 +49,10 @@ void InstrumentationRuntime::ModulesDidLoad( return; } - module_list.ForEach([this](const lldb::ModuleSP module_sp) -> bool { + module_list.ForEach([this](const lldb::ModuleSP module_sp) { const FileSpec &file_spec = module_sp->GetFileSpec(); if (!file_spec) - return true; // Keep iterating. + return IterationAction::Continue; const RegularExpression &runtime_regex = GetPatternForRuntimeLibrary(); if (runtime_regex.Execute(file_spec.GetFilename().GetCString()) || @@ -62,11 +62,11 @@ void InstrumentationRuntime::ModulesDidLoad( Activate(); if (!IsActive()) SetRuntimeModuleSP({}); // Don't cache module if activation failed. - return false; // Stop iterating, we're done. + return IterationAction::Stop; } } - return true; + return IterationAction::Continue; }); } diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index bf486d0faaffa..bcea249d89349 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -2523,9 +2523,9 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec, ModuleList found_modules; m_images.FindModules(module_spec_copy, found_modules); - found_modules.ForEach([&](const ModuleSP &found_module) -> bool { + found_modules.ForEach([&](const ModuleSP &found_module) { old_modules.push_back(found_module); - return true; + return IterationAction::Continue; }); } diff --git a/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py b/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py index 7c3d09b0ee37e..0ca2f9e52c582 100644 --- a/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py +++ b/lldb/test/API/functionalities/tail_call_frames/cross_dso/TestCrossDSOTailCalls.py @@ -11,7 +11,6 @@ class TestCrossDSOTailCalls(TestBase): @skipIf(compiler="clang", compiler_version=["<", "10.0"]) @skipIf(dwarf_version=["<", "4"]) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") - @expectedFailureAll(archs=["arm$", "arm64", "aarch64"], bugnumber="llvm.org/PR44561") def test_cross_dso_tail_calls(self): self.build() exe = self.getBuildArtifact("a.out") diff --git a/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py b/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py index 180f4d3fb788e..b5de75e30e495 100644 --- a/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py +++ b/lldb/test/API/functionalities/tail_call_frames/cross_object/TestCrossObjectTailCalls.py @@ -11,7 +11,6 @@ class TestCrossObjectTailCalls(TestBase): @skipIf(compiler="clang", compiler_version=["<", "10.0"]) @skipIf(dwarf_version=["<", "4"]) @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr26265") - @expectedFailureAll(archs=["arm$", "arm64", "aarch64"], bugnumber="llvm.org/PR44561") def test_cross_object_tail_calls(self): self.build() exe = self.getBuildArtifact("a.out") 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..02c34b3132722 --- /dev/null +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/TestExprDefinitionInDylib.py @@ -0,0 +1,33 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprDefinitionInDylibTestCase(TestBase): + NO_DEBUG_INFO_TESTCASE = True + + @skipIfWindows + def test(self): + """ + Tests that we can call functions whose definition + is in a different LLDB module than it's declaration. + """ + self.build() + + 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") 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..ad148cebb00d1 --- /dev/null +++ b/lldb/test/API/lang/cpp/expr-definition-in-dylib/lib.cpp @@ -0,0 +1,3 @@ +#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(); +} diff --git a/lldb/unittests/Expression/CMakeLists.txt b/lldb/unittests/Expression/CMakeLists.txt index 20733f2a57525..4c58b3c5e3922 100644 --- a/lldb/unittests/Expression/CMakeLists.txt +++ b/lldb/unittests/Expression/CMakeLists.txt @@ -4,7 +4,7 @@ add_lldb_unittest(ExpressionTests DiagnosticManagerTest.cpp DWARFExpressionTest.cpp CppModuleConfigurationTest.cpp - ClangParserTest.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..12f6dd515fd11 --- /dev/null +++ b/lldb/unittests/Expression/ExpressionTest.cpp @@ -0,0 +1,122 @@ +//===-- 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 + {"bar:0x0:0x0:_Z3foov", + {}, + {"expected function call label prefix '$__lldb_func' but found 'bar' " + "instead."}}, + {"$__lldb_func :0x0:0x0:_Z3foov", + {}, + {"expected function call label prefix '$__lldb_func' but found " + "'$__lldb_func ' instead."}}, + {"$__lldb_funcc:0x0:0x0:_Z3foov", + {}, + {"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, + /*.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)); diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index 71930ab54f409..f2175f6f537a3 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; @@ -869,7 +870,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, - false); + false, /*asm_label=*/{}); TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -900,7 +901,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, - false); + false, /*asm_label=*/{}); TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -938,7 +939,7 @@ TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) { bool is_attr_used = false; bool is_artificial = false; m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), class_name, nullptr, function_type, + t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); @@ -975,7 +976,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { CompilerType function_type = m_ast->CreateFunctionType( return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), class_name, nullptr, function_type, + t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -987,7 +988,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { m_ast->CreateFunctionType(return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), class_name, nullptr, function_type, + t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -1098,7 +1099,7 @@ TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) { m_ast->CreateFunctionType(return_type, param_types, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), "myFunc", nullptr, function_type, + t.GetOpaqueQualType(), "myFunc", /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); @@ -1116,3 +1117,130 @@ 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); + +#ifdef _WIN32 + EXPECT_STREQ(m_ast->DeclGetMangledName(ctor_nolabel).GetCString(), + "??0S@@QEAA@XZ"); + EXPECT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(), + "??_DS@@QEAAXXZ"); +#else + EXPECT_STREQ(m_ast->DeclGetMangledName(ctor_nolabel).GetCString(), + "_ZN1SC1Ev"); + EXPECT_STREQ(m_ast->DeclGetMangledName(dtor_nolabel).GetCString(), + "_ZN1SD1Ev"); +#endif + + EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape( + m_ast->DeclGetMangledName(ctor).GetStringRef()) + .data(), + "$__lldb_func:0x0:0x0:S"); + EXPECT_STREQ(llvm::GlobalValue::dropLLVMManglingEscape( + m_ast->DeclGetMangledName(dtor).GetStringRef()) + .data(), + "$__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)); diff --git a/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp b/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp index c5f811ef4d12e..dd8a0742f6b70 100644 --- a/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp +++ b/lldb/unittests/SymbolFile/DWARF/DWARFDebugNamesIndexTest.cpp @@ -11,6 +11,7 @@ #include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h" #include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h" #include "TestingSupport/Symbol/YAMLModuleTester.h" +#include "lldb/lldb-private-enumerations.h" #include "llvm/ADT/STLExtras.h" #include "gmock/gmock.h" #include "gtest/gtest.h" @@ -28,7 +29,7 @@ check_num_matches(DebugNamesDWARFIndex &index, int expected_num_matches, index.GetFullyQualifiedType(ctx, [&](DWARFDIE die) { num_matches++; - return true; + return IterationAction::Continue; }); ASSERT_EQ(num_matches, expected_num_matches); }