diff options
-rw-r--r-- | lldb/include/lldb/Breakpoint/BreakpointResolverName.h | 22 | ||||
-rw-r--r-- | lldb/include/lldb/Core/Module.h | 92 | ||||
-rw-r--r-- | lldb/source/Breakpoint/BreakpointResolverName.cpp | 62 | ||||
-rw-r--r-- | lldb/source/Core/Module.cpp | 329 | ||||
-rw-r--r-- | lldb/source/Core/ModuleList.cpp | 79 |
5 files changed, 311 insertions, 273 deletions
diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h index 7a9a4f25142..a11359dd009 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h +++ b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h @@ -18,6 +18,7 @@ // Other libraries and framework includes // Project includes #include "lldb/Breakpoint/BreakpointResolver.h" +#include "lldb/Core/Module.h" namespace lldb_private { @@ -100,26 +101,7 @@ public: protected: BreakpointResolverName(const BreakpointResolverName &rhs); - struct LookupInfo - { - ConstString name; - ConstString lookup_name; - uint32_t name_type_mask; // See FunctionNameType - bool match_name_after_lookup; - - LookupInfo () : - name(), - lookup_name(), - name_type_mask (0), - match_name_after_lookup (false) - { - } - - void - Prune (SymbolContextList &sc_list, - size_t start_idx) const; - }; - std::vector<LookupInfo> m_lookups; + std::vector<Module::LookupInfo> m_lookups; ConstString m_class_name; RegularExpression m_regex; Breakpoint::MatchType m_match_type; diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 819d7110526..2a5ab0667b7 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -1094,13 +1094,91 @@ public: /// set to true to indicate any matches will need to be checked /// to make sure they contain \a name. //------------------------------------------------------------------ - static void - PrepareForFunctionNameLookup (const ConstString &name, - uint32_t name_type_mask, - lldb::LanguageType language, - ConstString &lookup_name, - uint32_t &lookup_name_type_mask, - bool &match_name_after_lookup); + + //---------------------------------------------------------------------- + /// @class LookupInfo Module.h "lldb/Core/Module.h" + /// @brief A class that encapsulates name lookup information. + /// + /// Users can type a wide variety of partial names when setting + /// breakpoints by name or when looking for functions by name. + /// SymbolVendor and SymbolFile objects are only required to implement + /// name lookup for function basenames and for fully mangled names. + /// This means if the user types in a partial name, we must reduce this + /// to a name lookup that will work with all SymbolFile objects. So we + /// might reduce a name lookup to look for a basename, and then prune + /// out any results that don't match. + /// + /// The "m_name" member variable represents the name as it was typed + /// by the user. "m_lookup_name" will be the name we actually search + /// for through the symbol or objects files. Lanaguage is included in + /// case we need to filter results by language at a later date. The + /// "m_name_type_mask" member variable tells us what kinds of names we + /// are looking for and can help us prune out unwanted results. + /// + /// Function lookups are done in Module.cpp, ModuleList.cpp and in + /// BreakpointResolverName.cpp and they all now use this class to do + /// lookups correctly. + //---------------------------------------------------------------------- + class LookupInfo + { + public: + LookupInfo() : + m_name(), + m_lookup_name(), + m_language(lldb::eLanguageTypeUnknown), + m_name_type_mask(0), + m_match_name_after_lookup(false) + { + } + + LookupInfo(const ConstString &name, uint32_t name_type_mask, lldb::LanguageType language); + + const ConstString & + GetName() const + { + return m_name; + } + + void + SetName(const ConstString &name) + { + m_name = name; + } + + const ConstString & + GetLookupName() const + { + return m_lookup_name; + } + + void + SetLookupName(const ConstString &name) + { + m_lookup_name = name; + } + + uint32_t + GetNameTypeMask() const + { + return m_name_type_mask; + } + + void + SetNameTypeMask(uint32_t mask) + { + m_name_type_mask = mask; + } + + void + Prune(SymbolContextList &sc_list, size_t start_idx) const; + + protected: + ConstString m_name; ///< What the user originally typed + ConstString m_lookup_name; ///< The actual name will lookup when calling in the object or symbol file + lldb::LanguageType m_language; ///< Limit matches to only be for this language + uint32_t m_name_type_mask; ///< One or more bits from lldb::FunctionNameType that indicate what kind of names we are looking for + bool m_match_name_after_lookup; ///< If \b true, then demangled names that match will need to contain "m_name" in order to be considered a match + }; protected: //------------------------------------------------------------------ diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp index 573edc683ef..dfa09c2342f 100644 --- a/lldb/source/Breakpoint/BreakpointResolverName.cpp +++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp @@ -22,6 +22,7 @@ #include "lldb/Symbol/Symbol.h" #include "lldb/Symbol/SymbolContext.h" #include "Plugins/Language/ObjC/ObjCLanguage.h" +#include "Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" using namespace lldb; using namespace lldb_private; @@ -121,11 +122,10 @@ BreakpointResolverName::BreakpointResolverName m_language (eLanguageTypeUnknown), m_skip_prologue (skip_prologue) { - LookupInfo lookup; - lookup.name.SetCString(method); - lookup.lookup_name = lookup.name; - lookup.name_type_mask = eFunctionNameTypeMethod; - lookup.match_name_after_lookup = false; + Module::LookupInfo lookup; + lookup.SetName(ConstString(method)); + lookup.SetLookupName(lookup.GetName()); + lookup.SetNameTypeMask(eFunctionNameTypeMethod); m_lookups.push_back (lookup); } @@ -152,47 +152,20 @@ BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_ty objc_method.GetFullNames(objc_names, true); for (ConstString objc_name : objc_names) { - LookupInfo lookup; - lookup.name = name; - lookup.lookup_name = objc_name; - lookup.name_type_mask = eFunctionNameTypeFull; - lookup.match_name_after_lookup = false; + Module::LookupInfo lookup; + lookup.SetName(name); + lookup.SetLookupName(objc_name); + lookup.SetNameTypeMask(eFunctionNameTypeFull); m_lookups.push_back (lookup); } } else { - LookupInfo lookup; - lookup.name = name; - Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, m_language, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup); + Module::LookupInfo lookup(name, name_type_mask, m_language); m_lookups.push_back (lookup); } } -void -BreakpointResolverName::LookupInfo::Prune (SymbolContextList &sc_list, size_t start_idx) const -{ - if (match_name_after_lookup && name) - { - SymbolContext sc; - size_t i = start_idx; - while (i < sc_list.GetSize()) - { - if (!sc_list.GetContextAtIndex(i, sc)) - break; - ConstString full_name (sc.GetFunctionName()); - if (full_name && ::strstr(full_name.GetCString(), name.GetCString()) == nullptr) - { - sc_list.RemoveContextAtIndex(i); - } - else - { - ++i; - } - } - } -} - // FIXME: Right now we look at the module level, and call the module's "FindFunctions". // Greg says he will add function tables, maybe at the CompileUnit level to accelerate function // lookup. At that point, we should switch the depth to CompileUnit, and look in these tables. @@ -230,16 +203,17 @@ BreakpointResolverName::SearchCallback(SearchFilter &filter, case Breakpoint::Exact: if (context.module_sp) { - for (const LookupInfo &lookup : m_lookups) + for (const auto &lookup : m_lookups) { const size_t start_func_idx = func_list.GetSize(); - context.module_sp->FindFunctions(lookup.lookup_name, + context.module_sp->FindFunctions(lookup.GetLookupName(), nullptr, - lookup.name_type_mask, + lookup.GetNameTypeMask(), include_symbols, include_inlines, append, func_list); + const size_t end_func_idx = func_list.GetSize(); if (start_func_idx < end_func_idx) @@ -387,15 +361,15 @@ BreakpointResolverName::GetDescription (Stream *s) { size_t num_names = m_lookups.size(); if (num_names == 1) - s->Printf("name = '%s'", m_lookups[0].name.GetCString()); + s->Printf("name = '%s'", m_lookups[0].GetName().GetCString()); else { s->Printf("names = {"); - for (size_t i = 0; i < num_names - 1; i++) + for (size_t i = 0; i < num_names; i++) { - s->Printf ("'%s', ", m_lookups[i].name.GetCString()); + s->Printf ("%s'%s'", (i == 0 ? "" : ", "), m_lookups[i].GetName().GetCString()); } - s->Printf ("'%s'}", m_lookups[num_names - 1].name.GetCString()); + s->Printf ("}"); } } if (m_language != eLanguageTypeUnknown) diff --git a/lldb/source/Core/Module.cpp b/lldb/source/Core/Module.cpp index cd984baa886..5fe39abda18 100644 --- a/lldb/source/Core/Module.cpp +++ b/lldb/source/Core/Module.cpp @@ -734,6 +734,186 @@ Module::FindCompileUnits (const FileSpec &path, return sc_list.GetSize() - start_size; } +Module::LookupInfo::LookupInfo(const ConstString &name, uint32_t name_type_mask, lldb::LanguageType language) : + m_name(name), + m_lookup_name(), + m_language(language), + m_name_type_mask(0), + m_match_name_after_lookup(false) +{ + const char *name_cstr = name.GetCString(); + llvm::StringRef basename; + llvm::StringRef context; + + if (name_type_mask & eFunctionNameTypeAuto) + { + if (CPlusPlusLanguage::IsCPPMangledName (name_cstr)) + m_name_type_mask = eFunctionNameTypeFull; + else if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCMethodName (name_cstr)) + m_name_type_mask = eFunctionNameTypeFull; + else if (Language::LanguageIsC(language)) + { + m_name_type_mask = eFunctionNameTypeFull; + } + else + { + if ((language == eLanguageTypeUnknown || + Language::LanguageIsObjC(language)) && + ObjCLanguage::IsPossibleObjCSelector(name_cstr)) + m_name_type_mask |= eFunctionNameTypeSelector; + + CPlusPlusLanguage::MethodName cpp_method (name); + basename = cpp_method.GetBasename(); + if (basename.empty()) + { + if (CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename)) + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); + else + m_name_type_mask |= eFunctionNameTypeFull; + } + else + { + m_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); + } + } + } + else + { + m_name_type_mask = name_type_mask; + if (name_type_mask & eFunctionNameTypeMethod || name_type_mask & eFunctionNameTypeBase) + { + // If they've asked for a CPP method or function name and it can't be that, we don't + // even need to search for CPP methods or names. + CPlusPlusLanguage::MethodName cpp_method (name); + if (cpp_method.IsValid()) + { + basename = cpp_method.GetBasename(); + + if (!cpp_method.GetQualifiers().empty()) + { + // There is a "const" or other qualifier following the end of the function parens, + // this can't be a eFunctionNameTypeBase + m_name_type_mask &= ~(eFunctionNameTypeBase); + if (m_name_type_mask == eFunctionNameTypeNone) + return; + } + } + else + { + // If the CPP method parser didn't manage to chop this up, try to fill in the base name if we can. + // If a::b::c is passed in, we need to just look up "c", and then we'll filter the result later. + CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename); + } + } + + if (name_type_mask & eFunctionNameTypeSelector) + { + if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) + { + m_name_type_mask &= ~(eFunctionNameTypeSelector); + if (m_name_type_mask == eFunctionNameTypeNone) + return; + } + } + + // Still try and get a basename in case someone specifies a name type mask of + // eFunctionNameTypeFull and a name like "A::func" + if (basename.empty()) + { + if (name_type_mask & eFunctionNameTypeFull) + { + CPlusPlusLanguage::MethodName cpp_method (name); + basename = cpp_method.GetBasename(); + if (basename.empty()) + CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename); + } + } + } + + if (!basename.empty()) + { + // The name supplied was a partial C++ path like "a::count". In this case we want to do a + // lookup on the basename "count" and then make sure any matching results contain "a::count" + // so that it would match "b::a::count" and "a::count". This is why we set "match_name_after_lookup" + // to true + m_lookup_name.SetString(basename); + m_match_name_after_lookup = true; + } + else + { + // The name is already correct, just use the exact name as supplied, and we won't need + // to check if any matches contain "name" + m_lookup_name = name; + m_match_name_after_lookup = false; + } + +} + +void +Module::LookupInfo::Prune(SymbolContextList &sc_list, size_t start_idx) const +{ + if (m_match_name_after_lookup && m_name) + { + SymbolContext sc; + size_t i = start_idx; + while (i < sc_list.GetSize()) + { + if (!sc_list.GetContextAtIndex(i, sc)) + break; + ConstString full_name(sc.GetFunctionName()); + if (full_name && ::strstr(full_name.GetCString(), m_name.GetCString()) == nullptr) + { + sc_list.RemoveContextAtIndex(i); + } + else + { + ++i; + } + } + } + + // If we have only full name matches we might have tried to set breakpoint on "func" + // and specified eFunctionNameTypeFull, but we might have found "a::func()", + // "a::b::func()", "c::func()", "func()" and "func". Only "func()" and "func" should + // end up matching. + if (m_name_type_mask == eFunctionNameTypeFull) + { + SymbolContext sc; + size_t i = start_idx; + while (i < sc_list.GetSize()) + { + if (!sc_list.GetContextAtIndex(i, sc)) + break; + ConstString full_name(sc.GetFunctionName()); + CPlusPlusLanguage::MethodName cpp_method(full_name); + if (cpp_method.IsValid()) + { + if (cpp_method.GetContext().empty()) + { + if (cpp_method.GetBasename().compare(m_name.GetStringRef()) != 0) + { + sc_list.RemoveContextAtIndex(i); + continue; + } + } + else + { + std::string qualified_name = cpp_method.GetScopeQualifiedName(); + if (qualified_name.compare(m_name.GetCString()) != 0) + { + sc_list.RemoveContextAtIndex(i); + continue; + } + } + } + ++i; + } + } +} + + size_t Module::FindFunctions (const ConstString &name, const CompilerDeclContext *parent_decl_ctx, @@ -753,21 +933,13 @@ Module::FindFunctions (const ConstString &name, if (name_type_mask & eFunctionNameTypeAuto) { - ConstString lookup_name; - uint32_t lookup_name_type_mask = 0; - bool match_name_after_lookup = false; - Module::PrepareForFunctionNameLookup (name, - name_type_mask, - eLanguageTypeUnknown, // TODO: add support - lookup_name, - lookup_name_type_mask, - match_name_after_lookup); - + LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); + if (symbols) { - symbols->FindFunctions(lookup_name, + symbols->FindFunctions(lookup_info.GetLookupName(), parent_decl_ctx, - lookup_name_type_mask, + lookup_info.GetNameTypeMask(), include_inlines, append, sc_list); @@ -777,30 +949,14 @@ Module::FindFunctions (const ConstString &name, { Symtab *symtab = symbols->GetSymtab(); if (symtab) - symtab->FindFunctionSymbols(lookup_name, lookup_name_type_mask, sc_list); + symtab->FindFunctionSymbols(lookup_info.GetLookupName(), lookup_info.GetNameTypeMask(), sc_list); } } - if (match_name_after_lookup) - { - SymbolContext sc; - size_t i = old_size; - while (i < sc_list.GetSize()) - { - if (sc_list.GetContextAtIndex(i, sc)) - { - const char *func_name = sc.GetFunctionName().GetCString(); - if (func_name && strstr(func_name, name.GetCString()) == nullptr) - { - // Remove the current context - sc_list.RemoveContextAtIndex(i); - // Don't increment i and continue in the loop - continue; - } - } - ++i; - } - } + const size_t new_size = sc_list.GetSize(); + + if (old_size < new_size) + lookup_info.Prune (sc_list, old_size); } else { @@ -1728,113 +1884,6 @@ Module::GetVersion (uint32_t *versions, uint32_t num_versions) return 0; } -void -Module::PrepareForFunctionNameLookup (const ConstString &name, - uint32_t name_type_mask, - LanguageType language, - ConstString &lookup_name, - uint32_t &lookup_name_type_mask, - bool &match_name_after_lookup) -{ - const char *name_cstr = name.GetCString(); - lookup_name_type_mask = eFunctionNameTypeNone; - match_name_after_lookup = false; - - llvm::StringRef basename; - llvm::StringRef context; - - if (name_type_mask & eFunctionNameTypeAuto) - { - if (CPlusPlusLanguage::IsCPPMangledName (name_cstr)) - lookup_name_type_mask = eFunctionNameTypeFull; - else if ((language == eLanguageTypeUnknown || - Language::LanguageIsObjC(language)) && - ObjCLanguage::IsPossibleObjCMethodName (name_cstr)) - lookup_name_type_mask = eFunctionNameTypeFull; - else if (Language::LanguageIsC(language)) - { - lookup_name_type_mask = eFunctionNameTypeFull; - } - else - { - if ((language == eLanguageTypeUnknown || - Language::LanguageIsObjC(language)) && - ObjCLanguage::IsPossibleObjCSelector(name_cstr)) - lookup_name_type_mask |= eFunctionNameTypeSelector; - - CPlusPlusLanguage::MethodName cpp_method (name); - basename = cpp_method.GetBasename(); - if (basename.empty()) - { - if (CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename)) - lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); - else - lookup_name_type_mask |= eFunctionNameTypeFull; - } - else - { - lookup_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase); - } - } - } - else - { - lookup_name_type_mask = name_type_mask; - if (lookup_name_type_mask & eFunctionNameTypeMethod || name_type_mask & eFunctionNameTypeBase) - { - // If they've asked for a CPP method or function name and it can't be that, we don't - // even need to search for CPP methods or names. - CPlusPlusLanguage::MethodName cpp_method (name); - if (cpp_method.IsValid()) - { - basename = cpp_method.GetBasename(); - - if (!cpp_method.GetQualifiers().empty()) - { - // There is a "const" or other qualifier following the end of the function parens, - // this can't be a eFunctionNameTypeBase - lookup_name_type_mask &= ~(eFunctionNameTypeBase); - if (lookup_name_type_mask == eFunctionNameTypeNone) - return; - } - } - else - { - // If the CPP method parser didn't manage to chop this up, try to fill in the base name if we can. - // If a::b::c is passed in, we need to just look up "c", and then we'll filter the result later. - CPlusPlusLanguage::ExtractContextAndIdentifier (name_cstr, context, basename); - } - } - - if (lookup_name_type_mask & eFunctionNameTypeSelector) - { - if (!ObjCLanguage::IsPossibleObjCSelector(name_cstr)) - { - lookup_name_type_mask &= ~(eFunctionNameTypeSelector); - if (lookup_name_type_mask == eFunctionNameTypeNone) - return; - } - } - } - - if (!basename.empty()) - { - // The name supplied was a partial C++ path like "a::count". In this case we want to do a - // lookup on the basename "count" and then make sure any matching results contain "a::count" - // so that it would match "b::a::count" and "a::count". This is why we set "match_name_after_lookup" - // to true - lookup_name.SetString(basename); - match_name_after_lookup = true; - } - else - { - // The name is already correct, just use the exact name as supplied, and we won't need - // to check if any matches contain "name" - lookup_name = name; - match_name_after_lookup = false; - } -} - ModuleSP Module::CreateJITModule (const lldb::ObjectFileJITDelegateSP &delegate_sp) { diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp index ea5d72ecb54..bfd53e7d1c2 100644 --- a/lldb/source/Core/ModuleList.cpp +++ b/lldb/source/Core/ModuleList.cpp @@ -344,48 +344,25 @@ ModuleList::FindFunctions (const ConstString &name, if (name_type_mask & eFunctionNameTypeAuto) { - ConstString lookup_name; - uint32_t lookup_name_type_mask = 0; - bool match_name_after_lookup = false; - Module::PrepareForFunctionNameLookup (name, name_type_mask, - eLanguageTypeUnknown, // TODO: add support - lookup_name, - lookup_name_type_mask, - match_name_after_lookup); + Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { - (*pos)->FindFunctions(lookup_name, + (*pos)->FindFunctions(lookup_info.GetLookupName(), nullptr, - lookup_name_type_mask, + lookup_info.GetNameTypeMask(), include_symbols, include_inlines, true, sc_list); } - if (match_name_after_lookup) - { - SymbolContext sc; - size_t i = old_size; - while (i < sc_list.GetSize()) - { - if (sc_list.GetContextAtIndex(i, sc)) - { - const char *func_name = sc.GetFunctionName().GetCString(); - if (func_name != nullptr && strstr(func_name, name.GetCString()) == nullptr) - { - // Remove the current context - sc_list.RemoveContextAtIndex(i); - // Don't increment i and continue in the loop - continue; - } - } - ++i; - } - } + const size_t new_size = sc_list.GetSize(); + + if (old_size < new_size) + lookup_info.Prune (sc_list, old_size); } else { @@ -408,44 +385,22 @@ ModuleList::FindFunctionSymbols (const ConstString &name, if (name_type_mask & eFunctionNameTypeAuto) { - ConstString lookup_name; - uint32_t lookup_name_type_mask = 0; - bool match_name_after_lookup = false; - Module::PrepareForFunctionNameLookup (name, name_type_mask, - eLanguageTypeUnknown, // TODO: add support - lookup_name, - lookup_name_type_mask, - match_name_after_lookup); + Module::LookupInfo lookup_info(name, name_type_mask, eLanguageTypeUnknown); std::lock_guard<std::recursive_mutex> guard(m_modules_mutex); collection::const_iterator pos, end = m_modules.end(); for (pos = m_modules.begin(); pos != end; ++pos) { - (*pos)->FindFunctionSymbols (lookup_name, - lookup_name_type_mask, - sc_list); - } - - if (match_name_after_lookup) - { - SymbolContext sc; - size_t i = old_size; - while (i < sc_list.GetSize()) - { - if (sc_list.GetContextAtIndex(i, sc)) - { - const char *func_name = sc.GetFunctionName().GetCString(); - if (func_name != nullptr && strstr(func_name, name.GetCString()) == nullptr) - { - // Remove the current context - sc_list.RemoveContextAtIndex(i); - // Don't increment i and continue in the loop - continue; - } - } - ++i; - } + (*pos)->FindFunctionSymbols (lookup_info.GetLookupName(), + lookup_info.GetNameTypeMask(), + sc_list); } + + + const size_t new_size = sc_list.GetSize(); + + if (old_size < new_size) + lookup_info.Prune (sc_list, old_size); } else { |