[Lldb-commits] [lldb] r178608 - <rdar://problem/13506727>
Greg Clayton
gclayton at apple.com
Tue Apr 2 19:00:15 PDT 2013
Author: gclayton
Date: Tue Apr 2 21:00:15 2013
New Revision: 178608
URL: http://llvm.org/viewvc/llvm-project?rev=178608&view=rev
Log:
<rdar://problem/13506727>
Symbol table function names should support lookups like symbols with debug info.
To fix this I:
- Gutted the way FindFunctions is used, there used to be way too much smarts only in the DWARF plug-in
- Made it more efficient by chopping the name up once and using simpler queries so that SymbolFile and Symtab plug-ins don't need to do as much
- Filter the results at a higher level
- Make the lldb_private::Symtab able to chop up C++ mangled names and make as much sense out of them as possible and also be able to search by basename, fullname, method name, and selector name.
Modified:
lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
lldb/trunk/include/lldb/Core/Module.h
lldb/trunk/include/lldb/Symbol/SymbolContext.h
lldb/trunk/include/lldb/Symbol/Symtab.h
lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h
lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
lldb/trunk/source/Core/Module.cpp
lldb/trunk/source/Core/ModuleList.cpp
lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp
lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/trunk/source/Symbol/SymbolContext.cpp
lldb/trunk/source/Symbol/Symtab.cpp
lldb/trunk/source/Target/CPPLanguageRuntime.cpp
Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h Tue Apr 2 21:00:15 2013
@@ -86,13 +86,33 @@ public:
}
protected:
- std::vector<ConstString> m_func_names;
- uint32_t m_func_name_type_mask; // See FunctionNameType
- ConstString m_class_name; // FIXME: Not used yet. The idea would be to stop on methods of this class.
+ 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;
+ ConstString m_class_name;
RegularExpression m_regex;
Breakpoint::MatchType m_match_type;
bool m_skip_prologue;
+ void
+ AddNameLookup (const ConstString &name, uint32_t name_type_mask);
private:
DISALLOW_COPY_AND_ASSIGN(BreakpointResolverName);
};
Modified: lldb/trunk/include/lldb/Core/Module.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/Module.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/Module.h (original)
+++ lldb/trunk/include/lldb/Core/Module.h Tue Apr 2 21:00:15 2013
@@ -882,6 +882,56 @@ public:
bool
RemapSourceFile (const char *path, std::string &new_path) const;
+
+ //------------------------------------------------------------------
+ /// Prepare to do a function name lookup.
+ ///
+ /// Looking up functions by name can be a tricky thing. LLDB requires
+ /// that accelerator tables contain full names for functions as well
+ /// as function basenames which include functions, class methods and
+ /// class functions. When the user requests that an action use a
+ /// function by name, we are sometimes asked to automatically figure
+ /// out what a name could possibly map to. A user might request a
+ /// breakpoint be set on "count". If no options are supplied to limit
+ /// the scope of where to search for count, we will by default match
+ /// any function names named "count", all class and instance methods
+ /// named "count" (no matter what the namespace or contained context)
+ /// and any selectors named "count". If a user specifies "a::b" we
+ /// will search for the basename "b", and then prune the results that
+ /// don't match "a::b" (note that "c::a::b" and "d::e::a::b" will
+ /// match a query of "a::b".
+ ///
+ /// @param[in] name
+ /// The user supplied name to use in the lookup
+ ///
+ /// @param[in] name_type_mask
+ /// The mask of bits from lldb::FunctionNameType enumerations
+ /// that tell us what kind of name we are looking for.
+ ///
+ /// @param[out] lookup_name
+ /// The actual name that will be used when calling
+ /// SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols()
+ ///
+ /// @param[out] lookup_name_type_mask
+ /// The actual name mask that should be used in the calls to
+ /// SymbolVendor::FindFunctions() or Symtab::FindFunctionSymbols()
+ ///
+ /// @param[out] match_name_after_lookup
+ /// A boolean that indicates if we need to iterate through any
+ /// match results obtained from SymbolVendor::FindFunctions() or
+ /// Symtab::FindFunctionSymbols() to see if the name contains
+ /// \a name. For example if \a name is "a::b", this function will
+ /// return a \a lookup_name of "b", with \a match_name_after_lookup
+ /// 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,
+ ConstString &lookup_name,
+ uint32_t &lookup_name_type_mask,
+ bool &match_name_after_lookup);
+
protected:
//------------------------------------------------------------------
// Member Variables
Modified: lldb/trunk/include/lldb/Symbol/SymbolContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/SymbolContext.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/SymbolContext.h (original)
+++ lldb/trunk/include/lldb/Symbol/SymbolContext.h Tue Apr 2 21:00:15 2013
@@ -461,6 +461,19 @@ public:
bool
GetContextAtIndex(size_t idx, SymbolContext& sc) const;
+ //------------------------------------------------------------------
+ /// Get accessor for the last symbol context in the list.
+ ///
+ /// @param[out] sc
+ /// A reference to the symbol context to fill in.
+ ///
+ /// @return
+ /// Returns \b true if \a sc was filled in, \b false if the
+ /// list is empty.
+ //------------------------------------------------------------------
+ bool
+ GetLastContext(SymbolContext& sc) const;
+
bool
RemoveContextAtIndex (size_t idx);
//------------------------------------------------------------------
Modified: lldb/trunk/include/lldb/Symbol/Symtab.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Symbol/Symtab.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Symbol/Symtab.h (original)
+++ lldb/trunk/include/lldb/Symbol/Symtab.h Tue Apr 2 21:00:15 2013
@@ -107,6 +107,8 @@ protected:
collection m_symbols;
std::vector<uint32_t> m_addr_indexes;
UniqueCStringMap<uint32_t> m_name_to_index;
+ UniqueCStringMap<uint32_t> m_basename_to_index;
+ UniqueCStringMap<uint32_t> m_method_to_index;
UniqueCStringMap<uint32_t> m_selector_to_index;
mutable Mutex m_mutex; // Provide thread safety for this symbol table
bool m_addr_indexes_computed:1,
Modified: lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h Tue Apr 2 21:00:15 2013
@@ -25,6 +25,93 @@ class CPPLanguageRuntime :
public LanguageRuntime
{
public:
+
+ class MethodName
+ {
+ public:
+ enum Type
+ {
+ eTypeInvalid,
+ eTypeUnknownMethod,
+ eTypeClassMethod,
+ eTypeInstanceMethod
+ };
+
+ MethodName () :
+ m_full(),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ MethodName (const ConstString &s) :
+ m_full(s),
+ m_basename(),
+ m_context(),
+ m_arguments(),
+ m_qualifiers(),
+ m_type (eTypeInvalid),
+ m_parsed (false),
+ m_parse_error (false)
+ {
+ }
+
+ void
+ Clear();
+
+ bool
+ IsValid () const
+ {
+ if (m_parse_error)
+ return false;
+ if (m_type == eTypeInvalid)
+ return false;
+ return (bool)m_full;
+ }
+
+ Type
+ GetType () const
+ {
+ return m_type;
+ }
+
+ const ConstString &
+ GetFullName () const
+ {
+ return m_full;
+ }
+
+ const ConstString &
+ GetBasename ();
+
+ llvm::StringRef
+ GetContext ();
+
+ llvm::StringRef
+ GetArguments ();
+
+ llvm::StringRef
+ GetQualifiers ();
+
+ protected:
+ void
+ Parse();
+
+ ConstString m_full; // Full name: "lldb::SBTarget::GetBreakpointAtIndex(unsigned int) const"
+ ConstString m_basename; // Basename: "GetBreakpointAtIndex"
+ llvm::StringRef m_context; // Decl context: "lldb::SBTarget"
+ llvm::StringRef m_arguments; // Arguments: "(unsigned int)"
+ llvm::StringRef m_qualifiers; // Qualifiers: "const"
+ Type m_type;
+ bool m_parsed;
+ bool m_parse_error;
+ };
+
virtual
~CPPLanguageRuntime();
Modified: lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp Tue Apr 2 21:00:15 2013
@@ -27,16 +27,12 @@
using namespace lldb;
using namespace lldb_private;
-BreakpointResolverName::BreakpointResolverName
-(
- Breakpoint *bkpt,
- const char *func_name,
- uint32_t func_name_type_mask,
- Breakpoint::MatchType type,
- bool skip_prologue
-) :
+BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
+ const char *name_cstr,
+ uint32_t name_type_mask,
+ Breakpoint::MatchType type,
+ bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
- m_func_name_type_mask (func_name_type_mask),
m_class_name (),
m_regex (),
m_match_type (type),
@@ -45,22 +41,17 @@ BreakpointResolverName::BreakpointResolv
if (m_match_type == Breakpoint::Regexp)
{
- if (!m_regex.Compile (func_name))
+ if (!m_regex.Compile (name_cstr))
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
if (log)
- log->Warning ("function name regexp: \"%s\" did not compile.", func_name);
+ log->Warning ("function name regexp: \"%s\" did not compile.", name_cstr);
}
}
else
{
- const bool append = true;
- ObjCLanguageRuntime::MethodName objc_name(func_name, false);
- if (objc_name.IsValid(false))
- objc_name.GetFullNames(m_func_names, append);
- else
- m_func_names.push_back(ConstString(func_name));
+ AddNameLookup (ConstString(name_cstr), name_type_mask);
}
}
@@ -70,18 +61,12 @@ BreakpointResolverName::BreakpointResolv
uint32_t name_type_mask,
bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
- m_func_name_type_mask (name_type_mask),
m_match_type (Breakpoint::Exact),
m_skip_prologue (skip_prologue)
{
- const bool append = true;
for (size_t i = 0; i < num_names; i++)
{
- ObjCLanguageRuntime::MethodName objc_name(names[i], false);
- if (objc_name.IsValid(false))
- objc_name.GetFullNames(m_func_names, append);
- else
- m_func_names.push_back (ConstString (names[i]));
+ AddNameLookup (ConstString (names[i]), name_type_mask);
}
}
@@ -90,28 +75,18 @@ BreakpointResolverName::BreakpointResolv
uint32_t name_type_mask,
bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
- m_func_name_type_mask (name_type_mask),
m_match_type (Breakpoint::Exact),
m_skip_prologue (skip_prologue)
{
- size_t num_names = names.size();
- const bool append = true;
- for (size_t i = 0; i < num_names; i++)
+ for (const std::string& name : names)
{
- ObjCLanguageRuntime::MethodName objc_name(names[i].c_str(), false);
- if (objc_name.IsValid(false))
- objc_name.GetFullNames(m_func_names, append);
- else
- m_func_names.push_back (ConstString (names[i].c_str()));
+ AddNameLookup (ConstString (name.c_str(), name.size()), name_type_mask);
}
}
-BreakpointResolverName::BreakpointResolverName
-(
- Breakpoint *bkpt,
- RegularExpression &func_regex,
- bool skip_prologue
-) :
+BreakpointResolverName::BreakpointResolverName (Breakpoint *bkpt,
+ RegularExpression &func_regex,
+ bool skip_prologue) :
BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
m_class_name (NULL),
m_regex (func_regex),
@@ -134,13 +109,71 @@ BreakpointResolverName::BreakpointResolv
m_match_type (type),
m_skip_prologue (skip_prologue)
{
- m_func_names.push_back(ConstString(method));
+ LookupInfo lookup;
+ lookup.name.SetCString(method);
+ lookup.lookup_name = lookup.name;
+ lookup.name_type_mask = eFunctionNameTypeMethod;
+ lookup.match_name_after_lookup = false;
+ m_lookups.push_back (lookup);
}
BreakpointResolverName::~BreakpointResolverName ()
{
}
+void
+BreakpointResolverName::AddNameLookup (const ConstString &name, uint32_t name_type_mask)
+{
+ ObjCLanguageRuntime::MethodName objc_method(name.GetCString(), false);
+ if (objc_method.IsValid(false))
+ {
+ std::vector<ConstString> objc_names;
+ 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;
+ m_lookups.push_back (lookup);
+ }
+ }
+ else
+ {
+ LookupInfo lookup;
+ lookup.name = name;
+ Module::PrepareForFunctionNameLookup(lookup.name, name_type_mask, lookup.lookup_name, lookup.name_type_mask, lookup.match_name_after_lookup);
+ 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()) == NULL)
+ {
+ 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.
@@ -159,7 +192,6 @@ BreakpointResolverName::SearchCallback
uint32_t i;
bool new_location;
- SymbolContext sc;
Address break_addr;
assert (m_breakpoint != NULL);
@@ -182,22 +214,29 @@ BreakpointResolverName::SearchCallback
case Breakpoint::Exact:
if (context.module_sp)
{
- size_t num_names = m_func_names.size();
- for (int j = 0; j < num_names; j++)
+ for (const LookupInfo &lookup : m_lookups)
{
- size_t num_functions = context.module_sp->FindFunctions (m_func_names[j],
- NULL,
- m_func_name_type_mask,
- include_symbols,
- include_inlines,
- append,
- func_list);
+ const size_t start_func_idx = func_list.GetSize();
+ context.module_sp->FindFunctions (lookup.lookup_name,
+ NULL,
+ lookup.name_type_mask,
+ include_symbols,
+ include_inlines,
+ append,
+ func_list);
+ const size_t end_func_idx = func_list.GetSize();
+
+ if (start_func_idx < end_func_idx)
+ lookup.Prune (func_list, start_func_idx);
// If the search filter specifies a Compilation Unit, then we don't need to bother to look in plain
// symbols, since all the ones from a set compilation unit will have been found above already.
-
- if (num_functions == 0 && !filter_by_cu)
+ else if (!filter_by_cu)
{
- context.module_sp->FindFunctionSymbols (m_func_names[j], m_func_name_type_mask, sym_list);
+ const size_t start_symbol_idx = sym_list.GetSize();
+ context.module_sp->FindFunctionSymbols (lookup.lookup_name, lookup.name_type_mask, sym_list);
+ const size_t end_symbol_idx = sym_list.GetSize();
+ if (start_symbol_idx < end_symbol_idx)
+ lookup.Prune (func_list, start_symbol_idx);
}
}
}
@@ -239,6 +278,7 @@ BreakpointResolverName::SearchCallback
}
// Remove any duplicates between the funcion list and the symbol list
+ SymbolContext sc;
if (func_list.GetSize())
{
for (i = 0; i < func_list.GetSize(); i++)
@@ -356,17 +396,17 @@ BreakpointResolverName::GetDescription (
s->Printf("regex = '%s'", m_regex.GetText());
else
{
- size_t num_names = m_func_names.size();
+ size_t num_names = m_lookups.size();
if (num_names == 1)
- s->Printf("name = '%s'", m_func_names[0].AsCString());
+ s->Printf("name = '%s'", m_lookups[0].name.GetCString());
else
{
s->Printf("names = {");
for (size_t i = 0; i < num_names - 1; i++)
{
- s->Printf ("'%s', ", m_func_names[i].AsCString());
+ s->Printf ("'%s', ", m_lookups[i].name.GetCString());
}
- s->Printf ("'%s'}", m_func_names[num_names - 1].AsCString());
+ s->Printf ("'%s'}", m_lookups[num_names - 1].name.GetCString());
}
}
}
Modified: lldb/trunk/source/Core/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/Module.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Core/Module.cpp (original)
+++ lldb/trunk/source/Core/Module.cpp Tue Apr 2 21:00:15 2013
@@ -29,6 +29,8 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolVendor.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
+#include "lldb/Target/ObjCLanguageRuntime.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
@@ -589,42 +591,83 @@ Module::FindFunctions (const ConstString
if (!append)
sc_list.Clear();
- const size_t start_size = sc_list.GetSize();
+ const size_t old_size = sc_list.GetSize();
// Find all the functions (not symbols, but debug information functions...
SymbolVendor *symbols = GetSymbolVendor ();
- if (symbols)
- symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
-
- // Now check our symbol table for symbols that are code symbols if requested
- if (include_symbols)
+
+ if (name_type_mask & eFunctionNameTypeAuto)
{
- ObjectFile *objfile = GetObjectFile();
- if (objfile)
+ ConstString lookup_name;
+ uint32_t lookup_name_type_mask = 0;
+ bool match_name_after_lookup = false;
+ Module::PrepareForFunctionNameLookup (name,
+ name_type_mask,
+ lookup_name,
+ lookup_name_type_mask,
+ match_name_after_lookup);
+
+ if (symbols)
+ symbols->FindFunctions(lookup_name,
+ namespace_decl,
+ lookup_name_type_mask,
+ include_inlines,
+ append,
+ sc_list);
+
+ // Now check our symbol table for symbols that are code symbols if requested
+ if (include_symbols)
{
- Symtab *symtab = objfile->GetSymtab();
- if (symtab)
+ ObjectFile *objfile = GetObjectFile();
+ if (objfile)
{
- std::vector<uint32_t> symbol_indexes;
- symtab->FindAllSymbolsWithNameAndType (name, eSymbolTypeAny, Symtab::eDebugAny, Symtab::eVisibilityAny, symbol_indexes);
- const size_t num_matches = symbol_indexes.size();
- if (num_matches)
+ Symtab *symtab = objfile->GetSymtab();
+ if (symtab)
+ symtab->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 bool merge_symbol_into_function = true;
- SymbolContext sc(this);
- for (size_t i=0; i<num_matches; i++)
+ const char *func_name = sc.GetFunctionName().GetCString();
+ if (func_name && strstr (func_name, name.GetCString()) == NULL)
{
- sc.symbol = symtab->SymbolAtIndex(symbol_indexes[i]);
- SymbolType sym_type = sc.symbol->GetType();
- if (sc.symbol && (sym_type == eSymbolTypeCode ||
- sym_type == eSymbolTypeResolver))
- sc_list.AppendIfUnique (sc, merge_symbol_into_function);
+ // Remove the current context
+ sc_list.RemoveContextAtIndex(i);
+ // Don't increment i and continue in the loop
+ continue;
}
}
+ ++i;
}
}
+
}
- return sc_list.GetSize() - start_size;
+ else
+ {
+ if (symbols)
+ symbols->FindFunctions(name, namespace_decl, name_type_mask, include_inlines, append, sc_list);
+
+ // Now check our symbol table for symbols that are code symbols if requested
+ if (include_symbols)
+ {
+ ObjectFile *objfile = GetObjectFile();
+ if (objfile)
+ {
+ Symtab *symtab = objfile->GetSymtab();
+ if (symtab)
+ symtab->FindFunctionSymbols(name, name_type_mask, sc_list);
+ }
+ }
+ }
+
+ return sc_list.GetSize() - old_size;
}
size_t
@@ -1347,3 +1390,78 @@ Module::GetVersion (uint32_t *versions,
}
return 0;
}
+
+void
+Module::PrepareForFunctionNameLookup (const ConstString &name,
+ uint32_t name_type_mask,
+ 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;
+ const char *base_name_start = NULL;
+ const char *base_name_end = NULL;
+
+ if (name_type_mask & eFunctionNameTypeAuto)
+ {
+ if (CPPLanguageRuntime::IsCPPMangledName (name_cstr))
+ lookup_name_type_mask = eFunctionNameTypeFull;
+ else if (ObjCLanguageRuntime::IsPossibleObjCMethodName (name_cstr))
+ lookup_name_type_mask = eFunctionNameTypeFull;
+ else
+ {
+ if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
+ lookup_name_type_mask |= eFunctionNameTypeSelector;
+
+ if (CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
+ 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.
+ if (!CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
+ {
+ lookup_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase);
+ if (lookup_name_type_mask == eFunctionNameTypeNone)
+ return;
+ }
+ }
+
+ if (lookup_name_type_mask & eFunctionNameTypeSelector)
+ {
+ if (!ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
+ {
+ lookup_name_type_mask &= ~(eFunctionNameTypeSelector);
+ if (lookup_name_type_mask == eFunctionNameTypeNone)
+ return;
+ }
+ }
+ }
+
+ if (base_name_start &&
+ base_name_end &&
+ base_name_start != name_cstr &&
+ base_name_start < base_name_end)
+ {
+ // 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.SetCStringWithLength(base_name_start, base_name_end - base_name_start);
+ 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;
+ }
+}
\ No newline at end of file
Modified: lldb/trunk/source/Core/ModuleList.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/ModuleList.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Core/ModuleList.cpp (original)
+++ lldb/trunk/source/Core/ModuleList.cpp Tue Apr 2 21:00:15 2013
@@ -337,14 +337,64 @@ ModuleList::FindFunctions (const ConstSt
if (!append)
sc_list.Clear();
- Mutex::Locker locker(m_modules_mutex);
- collection::const_iterator pos, end = m_modules.end();
- for (pos = m_modules.begin(); pos != end; ++pos)
+ const size_t old_size = sc_list.GetSize();
+
+ if (name_type_mask & eFunctionNameTypeAuto)
{
- (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
+ ConstString lookup_name;
+ uint32_t lookup_name_type_mask = 0;
+ bool match_name_after_lookup = false;
+ Module::PrepareForFunctionNameLookup (name, name_type_mask,
+ lookup_name,
+ lookup_name_type_mask,
+ match_name_after_lookup);
+
+ Mutex::Locker locker(m_modules_mutex);
+ collection::const_iterator pos, end = m_modules.end();
+ for (pos = m_modules.begin(); pos != end; ++pos)
+ {
+ (*pos)->FindFunctions (lookup_name,
+ NULL,
+ lookup_name_type_mask,
+ 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 && strstr (func_name, name.GetCString()) == NULL)
+ {
+ // Remove the current context
+ sc_list.RemoveContextAtIndex(i);
+ // Don't increment i and continue in the loop
+ continue;
+ }
+ }
+ ++i;
+ }
+ }
+
}
+ else
+ {
- return sc_list.GetSize();
+ Mutex::Locker locker(m_modules_mutex);
+ collection::const_iterator pos, end = m_modules.end();
+ for (pos = m_modules.begin(); pos != end; ++pos)
+ {
+ (*pos)->FindFunctions (name, NULL, name_type_mask, include_symbols, include_inlines, true, sc_list);
+ }
+ }
+ return sc_list.GetSize() - old_size;
}
size_t
Modified: lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp (original)
+++ lldb/trunk/source/Expression/ClangExpressionDeclMap.cpp Tue Apr 2 21:00:15 2013
@@ -3116,7 +3116,7 @@ ClangExpressionDeclMap::FindExternalVisi
// instance methods for eFunctionNameTypeBase.
target->GetImages().FindFunctions(name,
- eFunctionNameTypeBase,
+ eFunctionNameTypeFull,
include_symbols,
include_inlines,
append,
Modified: lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp (original)
+++ lldb/trunk/source/Interpreter/CommandObjectRegexCommand.cpp Tue Apr 2 21:00:15 2013
@@ -35,8 +35,8 @@ CommandObjectRegexCommand::CommandObject
) :
CommandObjectRaw (interpreter, name, help, syntax),
m_max_matches (max_matches),
- m_entries (),
- m_completion_type_mask (completion_type_mask)
+ m_completion_type_mask (completion_type_mask),
+ m_entries ()
{
}
Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Tue Apr 2 21:00:15 2013
@@ -3322,6 +3322,9 @@ SymbolFileDWARF::FindFunctions (const Co
"SymbolFileDWARF::FindFunctions (name = '%s')",
name.AsCString());
+ // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
+ assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
+
Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_LOOKUPS));
if (log)
@@ -3347,59 +3350,16 @@ SymbolFileDWARF::FindFunctions (const Co
// Remember how many sc_list are in the list before we search in case
// we are appending the results to a variable list.
- const uint32_t original_size = sc_list.GetSize();
-
const char *name_cstr = name.GetCString();
- uint32_t effective_name_type_mask = eFunctionNameTypeNone;
- const char *base_name_start = name_cstr;
- const char *base_name_end = name_cstr + strlen(name_cstr);
-
- if (name_type_mask & eFunctionNameTypeAuto)
- {
- if (CPPLanguageRuntime::IsCPPMangledName (name_cstr))
- effective_name_type_mask = eFunctionNameTypeFull;
- else if (ObjCLanguageRuntime::IsPossibleObjCMethodName (name_cstr))
- effective_name_type_mask = eFunctionNameTypeFull;
- else
- {
- if (ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
- effective_name_type_mask |= eFunctionNameTypeSelector;
-
- if (CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
- effective_name_type_mask |= (eFunctionNameTypeMethod | eFunctionNameTypeBase);
- }
- }
- else
- {
- effective_name_type_mask = name_type_mask;
- if (effective_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.
- if (!CPPLanguageRuntime::IsPossibleCPPCall(name_cstr, base_name_start, base_name_end))
- {
- effective_name_type_mask &= ~(eFunctionNameTypeMethod | eFunctionNameTypeBase);
- if (effective_name_type_mask == eFunctionNameTypeNone)
- return 0;
- }
- }
-
- if (effective_name_type_mask & eFunctionNameTypeSelector)
- {
- if (!ObjCLanguageRuntime::IsPossibleObjCSelector(name_cstr))
- {
- effective_name_type_mask &= ~(eFunctionNameTypeSelector);
- if (effective_name_type_mask == eFunctionNameTypeNone)
- return 0;
- }
- }
- }
-
+
+ const uint32_t original_size = sc_list.GetSize();
+
DWARFDebugInfo* info = DebugInfo();
if (info == NULL)
return 0;
DWARFCompileUnit *dwarf_cu = NULL;
+ std::set<const DWARFDebugInfoEntry *> resolved_dies;
if (m_using_apple_tables)
{
if (m_apple_names_ap.get())
@@ -3409,7 +3369,7 @@ SymbolFileDWARF::FindFunctions (const Co
uint32_t num_matches = 0;
- if (effective_name_type_mask & eFunctionNameTypeFull)
+ if (name_type_mask & eFunctionNameTypeFull)
{
// If they asked for the full name, match what they typed. At some point we may
// want to canonicalize this (strip double spaces, etc. For now, we just add all the
@@ -3427,7 +3387,11 @@ SymbolFileDWARF::FindFunctions (const Co
if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
continue;
- ResolveFunction (dwarf_cu, die, sc_list);
+ if (resolved_dies.find(die) == resolved_dies.end())
+ {
+ if (ResolveFunction (dwarf_cu, die, sc_list))
+ resolved_dies.insert(die);
+ }
}
else
{
@@ -3436,87 +3400,116 @@ SymbolFileDWARF::FindFunctions (const Co
}
}
}
- else
- {
- if (effective_name_type_mask & eFunctionNameTypeSelector)
- {
- if (namespace_decl && *namespace_decl)
- return 0; // no selectors in namespaces
-
- num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
- // Now make sure these are actually ObjC methods. In this case we can simply look up the name,
- // and if it is an ObjC method name, we're good.
+
+ if (name_type_mask & eFunctionNameTypeSelector)
+ {
+ if (namespace_decl && *namespace_decl)
+ return 0; // no selectors in namespaces
- for (uint32_t i = 0; i < num_matches; i++)
+ num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
+ // Now make sure these are actually ObjC methods. In this case we can simply look up the name,
+ // and if it is an ObjC method name, we're good.
+
+ for (uint32_t i = 0; i < num_matches; i++)
+ {
+ const dw_offset_t die_offset = die_offsets[i];
+ const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ if (die)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
- if (die)
+ const char *die_name = die->GetName(this, dwarf_cu);
+ if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
{
- const char *die_name = die->GetName(this, dwarf_cu);
- if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
+ if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+ continue;
+
+ if (resolved_dies.find(die) == resolved_dies.end())
{
- if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
- continue;
-
- ResolveFunction (dwarf_cu, die, sc_list);
+ if (ResolveFunction (dwarf_cu, die, sc_list))
+ resolved_dies.insert(die);
}
}
- else
- {
- GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
- }
}
- die_offsets.clear();
+ else
+ {
+ GetObjectFile()->GetModule()->ReportError ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
+ die_offset, name_cstr);
+ }
}
+ die_offsets.clear();
+ }
+
+ if (((name_type_mask & eFunctionNameTypeMethod) && !namespace_decl) || name_type_mask & eFunctionNameTypeBase)
+ {
+ // The apple_names table stores just the "base name" of C++ methods in the table. So we have to
+ // extract the base name, look that up, and if there is any other information in the name we were
+ // passed in we have to post-filter based on that.
+
+ // FIXME: Arrange the logic above so that we don't calculate the base name twice:
+ num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
- if (effective_name_type_mask & eFunctionNameTypeMethod
- || effective_name_type_mask & eFunctionNameTypeBase)
+ for (uint32_t i = 0; i < num_matches; i++)
{
- if ((effective_name_type_mask & eFunctionNameTypeMethod) &&
- (namespace_decl && *namespace_decl))
- return 0; // no methods in namespaces
-
- // The apple_names table stores just the "base name" of C++ methods in the table. So we have to
- // extract the base name, look that up, and if there is any other information in the name we were
- // passed in we have to post-filter based on that.
-
- // FIXME: Arrange the logic above so that we don't calculate the base name twice:
- std::string base_name(base_name_start, base_name_end - base_name_start);
- num_matches = m_apple_names_ap->FindByName (base_name.c_str(), die_offsets);
-
- for (uint32_t i = 0; i < num_matches; i++)
+ const dw_offset_t die_offset = die_offsets[i];
+ const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+ if (die)
{
- const dw_offset_t die_offset = die_offsets[i];
- const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
- if (die)
+ if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
+ continue;
+
+ if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
+ continue;
+
+ // If we get to here, the die is good, and we should add it:
+ if (resolved_dies.find(die) == resolved_dies.end())
+ if (ResolveFunction (dwarf_cu, die, sc_list))
{
- if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
- continue;
-
- if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
- continue;
-
- if (!FunctionDieMatchesPartialName(die,
- dwarf_cu,
- effective_name_type_mask,
- name_cstr,
- base_name_start,
- base_name_end))
- continue;
-
- // If we get to here, the die is good, and we should add it:
- ResolveFunction (dwarf_cu, die, sc_list);
+ bool keep_die = true;
+ if ((name_type_mask & (eFunctionNameTypeBase|eFunctionNameTypeMethod)) != (eFunctionNameTypeBase|eFunctionNameTypeMethod))
+ {
+ // We are looking for either basenames or methods, so we need to
+ // trim out the ones we won't want by looking at the type
+ SymbolContext sc;
+ if (sc_list.GetLastContext(sc))
+ {
+ if (sc.block)
+ {
+ // We have an inlined function
+ }
+ else if (sc.function)
+ {
+ Type *type = sc.function->GetType();
+
+ clang::DeclContext* decl_ctx = GetClangDeclContextContainingTypeUID (type->GetID());
+ if (decl_ctx->isRecord())
+ {
+ if (name_type_mask & eFunctionNameTypeBase)
+ {
+ sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+ keep_die = false;
+ }
+ }
+ else
+ {
+ if (name_type_mask & eFunctionNameTypeMethod)
+ {
+ sc_list.RemoveContextAtIndex(sc_list.GetSize()-1);
+ keep_die = false;
+ }
+ }
+ }
+ }
+ }
+ if (keep_die)
+ resolved_dies.insert(die);
}
- else
- {
- GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
- die_offset, name_cstr);
- }
}
- die_offsets.clear();
+ else
+ {
+ GetObjectFile()->GetModule()->ReportErrorIfModifyDetected ("the DWARF debug information has been modified (.apple_names accelerator table had bad die 0x%8.8x for '%s')",
+ die_offset, name_cstr);
+ }
}
+ die_offsets.clear();
}
}
}
@@ -3530,14 +3523,12 @@ SymbolFileDWARF::FindFunctions (const Co
if (name_type_mask & eFunctionNameTypeFull)
FindFunctions (name, m_function_fullname_index, sc_list);
- std::string base_name(base_name_start, base_name_end - base_name_start);
- ConstString base_name_const(base_name.c_str());
DIEArray die_offsets;
DWARFCompileUnit *dwarf_cu = NULL;
- if (effective_name_type_mask & eFunctionNameTypeBase)
+ if (name_type_mask & eFunctionNameTypeBase)
{
- uint32_t num_base = m_function_basename_index.Find(base_name_const, die_offsets);
+ uint32_t num_base = m_function_basename_index.Find(name, die_offsets);
for (uint32_t i = 0; i < num_base; i++)
{
const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
@@ -3549,27 +3540,23 @@ SymbolFileDWARF::FindFunctions (const Co
if (namespace_decl && !DIEIsInNamespace (namespace_decl, dwarf_cu, die))
continue;
- if (!FunctionDieMatchesPartialName(die,
- dwarf_cu,
- eFunctionNameTypeBase,
- name_cstr,
- base_name_start,
- base_name_end))
- continue;
-
// If we get to here, the die is good, and we should add it:
- ResolveFunction (dwarf_cu, die, sc_list);
+ if (resolved_dies.find(die) == resolved_dies.end())
+ {
+ if (ResolveFunction (dwarf_cu, die, sc_list))
+ resolved_dies.insert(die);
+ }
}
}
die_offsets.clear();
}
- if (effective_name_type_mask & eFunctionNameTypeMethod)
+ if (name_type_mask & eFunctionNameTypeMethod)
{
if (namespace_decl && *namespace_decl)
return 0; // no methods in namespaces
- uint32_t num_base = m_function_method_index.Find(base_name_const, die_offsets);
+ uint32_t num_base = m_function_method_index.Find(name, die_offsets);
{
for (uint32_t i = 0; i < num_base; i++)
{
@@ -3579,23 +3566,19 @@ SymbolFileDWARF::FindFunctions (const Co
if (!include_inlines && die->Tag() == DW_TAG_inlined_subroutine)
continue;
- if (!FunctionDieMatchesPartialName(die,
- dwarf_cu,
- eFunctionNameTypeMethod,
- name_cstr,
- base_name_start,
- base_name_end))
- continue;
-
// If we get to here, the die is good, and we should add it:
- ResolveFunction (dwarf_cu, die, sc_list);
+ if (resolved_dies.find(die) == resolved_dies.end())
+ {
+ if (ResolveFunction (dwarf_cu, die, sc_list))
+ resolved_dies.insert(die);
+ }
}
}
}
die_offsets.clear();
}
- if ((effective_name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
+ if ((name_type_mask & eFunctionNameTypeSelector) && (!namespace_decl || !*namespace_decl))
{
FindFunctions (name, m_function_selector_index, sc_list);
}
Modified: lldb/trunk/source/Symbol/SymbolContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/SymbolContext.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/SymbolContext.cpp (original)
+++ lldb/trunk/source/Symbol/SymbolContext.cpp Tue Apr 2 21:00:15 2013
@@ -1056,6 +1056,17 @@ SymbolContextList::GetContextAtIndex(siz
}
bool
+SymbolContextList::GetLastContext(SymbolContext& sc) const
+{
+ if (!m_symbol_contexts.empty())
+ {
+ sc = m_symbol_contexts.back();
+ return true;
+ }
+ return false;
+}
+
+bool
SymbolContextList::RemoveContextAtIndex (size_t idx)
{
if (idx < m_symbol_contexts.size())
Modified: lldb/trunk/source/Symbol/Symtab.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Symbol/Symtab.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Symbol/Symtab.cpp (original)
+++ lldb/trunk/source/Symbol/Symtab.cpp Tue Apr 2 21:00:15 2013
@@ -16,6 +16,7 @@
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/Symtab.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
#include "lldb/Target/ObjCLanguageRuntime.h"
using namespace lldb;
@@ -263,9 +264,9 @@ Symtab::InitNameIndexes()
m_name_indexes_computed = true;
Timer scoped_timer (__PRETTY_FUNCTION__, "%s", __PRETTY_FUNCTION__);
// Create the name index vector to be able to quickly search by name
- const size_t count = m_symbols.size();
+ const size_t num_symbols = m_symbols.size();
#if 1
- m_name_to_index.Reserve (count);
+ m_name_to_index.Reserve (num_symbols);
#else
// TODO: benchmark this to see if we save any memory. Otherwise we
// will always keep the memory reserved in the vector unless we pull
@@ -288,7 +289,12 @@ Symtab::InitNameIndexes()
NameToIndexMap::Entry entry;
- for (entry.value = 0; entry.value < count; ++entry.value)
+ // The "const char *" in "class_contexts" must come from a ConstString::GetCString()
+ std::set<const char *> class_contexts;
+ UniqueCStringMap<uint32_t> mangled_name_to_index;
+ std::vector<const char *> symbol_contexts(num_symbols, NULL);
+
+ for (entry.value = 0; entry.value<num_symbols; ++entry.value)
{
const Symbol *symbol = &m_symbols[entry.value];
@@ -303,8 +309,66 @@ Symtab::InitNameIndexes()
const Mangled &mangled = symbol->GetMangled();
entry.cstring = mangled.GetMangledName().GetCString();
if (entry.cstring && entry.cstring[0])
+ {
m_name_to_index.Append (entry);
-
+
+ const SymbolType symbol_type = symbol->GetType();
+ if (symbol_type == eSymbolTypeCode || symbol_type == eSymbolTypeResolver)
+ {
+ if (entry.cstring[0] == '_' && entry.cstring[1] == 'Z' &&
+ (entry.cstring[2] != 'T' && // avoid virtual table, VTT structure, typeinfo structure, and typeinfo name
+ entry.cstring[2] != 'G' && // avoid guard variables
+ entry.cstring[2] != 'Z')) // named local entities (if we eventually handle eSymbolTypeData, we will want this back)
+ {
+ CPPLanguageRuntime::MethodName cxx_method (mangled.GetDemangledName());
+ entry.cstring = cxx_method.GetBasename ().GetCString();
+ if (entry.cstring && entry.cstring[0])
+ {
+ // ConstString objects permanently store the string in the pool so calling
+ // GetCString() on the value gets us a const char * that will never go away
+ const char *const_context = ConstString(cxx_method.GetContext()).GetCString();
+
+ if (entry.cstring[0] == '~' || !cxx_method.GetQualifiers().empty())
+ {
+ // The first character of the demangled basename is '~' which
+ // means we have a class destructor. We can use this information
+ // to help us know what is a class and what isn't.
+ if (class_contexts.find(const_context) == class_contexts.end())
+ class_contexts.insert(const_context);
+ m_method_to_index.Append (entry);
+ }
+ else
+ {
+ if (const_context && const_context[0])
+ {
+ if (class_contexts.find(const_context) != class_contexts.end())
+ {
+ // The current decl context is in our "class_contexts" which means
+ // this is a method on a class
+ m_method_to_index.Append (entry);
+ }
+ else
+ {
+ // We don't know if this is a function basename or a method,
+ // so put it into a temporary collection so once we are done
+ // we can look in class_contexts to see if each entry is a class
+ // or just a function and will put any remaining items into
+ // m_method_to_index or m_basename_to_index as needed
+ mangled_name_to_index.Append (entry);
+ symbol_contexts[entry.value] = const_context;
+ }
+ }
+ else
+ {
+ // No context for this function so this has to be a basename
+ m_basename_to_index.Append(entry);
+ }
+ }
+ }
+ }
+ }
+ }
+
entry.cstring = mangled.GetDemangledName().GetCString();
if (entry.cstring && entry.cstring[0])
m_name_to_index.Append (entry);
@@ -326,15 +390,64 @@ Symtab::InitNameIndexes()
}
}
+
+ size_t count;
+ if (!mangled_name_to_index.IsEmpty())
+ {
+ count = mangled_name_to_index.GetSize();
+ for (size_t i=0; i<count; ++i)
+ {
+ if (mangled_name_to_index.GetValueAtIndex(i, entry.value))
+ {
+ entry.cstring = mangled_name_to_index.GetCStringAtIndex(i);
+ if (symbol_contexts[entry.value] && class_contexts.find(symbol_contexts[entry.value]) != class_contexts.end())
+ {
+ m_method_to_index.Append (entry);
+ }
+ else
+ {
+ // If we got here, we have something that had a context (was inside a namespace or class)
+ // yet we don't know if the entry
+ m_method_to_index.Append (entry);
+ m_basename_to_index.Append (entry);
+ }
+ }
+ }
+ }
m_name_to_index.Sort();
m_name_to_index.SizeToFit();
m_selector_to_index.Sort();
m_selector_to_index.SizeToFit();
+ m_basename_to_index.Sort();
+ m_basename_to_index.SizeToFit();
+ m_method_to_index.Sort();
+ m_method_to_index.SizeToFit();
+
+// static StreamFile a ("/tmp/a.txt");
+//
+// count = m_basename_to_index.GetSize();
+// if (count)
+// {
+// for (size_t i=0; i<count; ++i)
+// {
+// if (m_basename_to_index.GetValueAtIndex(i, entry.value))
+// a.Printf ("%s BASENAME\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
+// }
+// }
+// count = m_method_to_index.GetSize();
+// if (count)
+// {
+// for (size_t i=0; i<count; ++i)
+// {
+// if (m_method_to_index.GetValueAtIndex(i, entry.value))
+// a.Printf ("%s METHOD\n", m_symbols[entry.value].GetMangled().GetName().GetCString());
+// }
+// }
}
}
void
-Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
+Symtab::AppendSymbolNamesToMap (const IndexCollection &indexes,
bool add_demangled,
bool add_mangled,
NameToIndexMap &name_to_index_map) const
@@ -1009,6 +1122,7 @@ Symtab::SymbolIndicesToSymbolContextList
// No need to protect this call using m_mutex all other method calls are
// already thread safe.
+ const bool merge_symbol_into_function = true;
size_t num_indices = symbol_indexes.size();
if (num_indices > 0)
{
@@ -1018,7 +1132,7 @@ Symtab::SymbolIndicesToSymbolContextList
{
sc.symbol = SymbolAtIndex (symbol_indexes[i]);
if (sc.symbol)
- sc_list.Append (sc);
+ sc_list.AppendIfUnique(sc, merge_symbol_into_function);
}
}
}
@@ -1031,11 +1145,53 @@ Symtab::FindFunctionSymbols (const Const
{
size_t count = 0;
std::vector<uint32_t> symbol_indexes;
- if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeAuto))
+
+ const char *name_cstr = name.GetCString();
+
+ // eFunctionNameTypeAuto should be pre-resolved by a call to Module::PrepareForFunctionNameLookup()
+ assert ((name_type_mask & eFunctionNameTypeAuto) == 0);
+
+ if (name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
{
FindAllSymbolsWithNameAndType (name, eSymbolTypeCode, symbol_indexes);
}
+ if (name_type_mask & eFunctionNameTypeBase)
+ {
+ // From mangled names we can't tell what is a basename and what
+ // is a method name, so we just treat them the same
+ if (!m_name_indexes_computed)
+ InitNameIndexes();
+
+ if (!m_basename_to_index.IsEmpty())
+ {
+ const UniqueCStringMap<uint32_t>::Entry *match;
+ for (match = m_basename_to_index.FindFirstValueForName(name_cstr);
+ match != NULL;
+ match = m_basename_to_index.FindNextValueForName(match))
+ {
+ symbol_indexes.push_back(match->value);
+ }
+ }
+ }
+
+ if (name_type_mask & eFunctionNameTypeMethod)
+ {
+ if (!m_name_indexes_computed)
+ InitNameIndexes();
+
+ if (!m_method_to_index.IsEmpty())
+ {
+ const UniqueCStringMap<uint32_t>::Entry *match;
+ for (match = m_method_to_index.FindFirstValueForName(name_cstr);
+ match != NULL;
+ match = m_method_to_index.FindNextValueForName(match))
+ {
+ symbol_indexes.push_back(match->value);
+ }
+ }
+ }
+
if (name_type_mask & eFunctionNameTypeSelector)
{
if (!m_name_indexes_computed)
@@ -1044,7 +1200,7 @@ Symtab::FindFunctionSymbols (const Const
if (!m_selector_to_index.IsEmpty())
{
const UniqueCStringMap<uint32_t>::Entry *match;
- for (match = m_selector_to_index.FindFirstValueForName(name.AsCString());
+ for (match = m_selector_to_index.FindFirstValueForName(name_cstr);
match != NULL;
match = m_selector_to_index.FindNextValueForName(match))
{
Modified: lldb/trunk/source/Target/CPPLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/CPPLanguageRuntime.cpp?rev=178608&r1=178607&r2=178608&view=diff
==============================================================================
--- lldb/trunk/source/Target/CPPLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/CPPLanguageRuntime.cpp Tue Apr 2 21:00:15 2013
@@ -190,65 +190,65 @@ CPPLanguageRuntime::IsCPPMangledName (co
bool
CPPLanguageRuntime::StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end)
{
- if (base_name_end == NULL)
- base_name_end = name + strlen (name);
+ if (base_name_end == NULL)
+ base_name_end = name + strlen (name);
- const char *last_colon = NULL;
- for (const char *ptr = base_name_end; ptr != name; ptr--)
+ const char *last_colon = NULL;
+ for (const char *ptr = base_name_end; ptr != name; ptr--)
{
- if (*ptr == ':')
+ if (*ptr == ':')
{
- last_colon = ptr;
- break;
+ last_colon = ptr;
+ break;
}
}
-
- if (last_colon == NULL)
+
+ if (last_colon == NULL)
{
- base_name_start = name;
- return true;
+ base_name_start = name;
+ return true;
}
-
- // Can't have a C++ name that begins with a single ':', nor contains an internal single ':'
- if (last_colon == name)
- return false;
- else if (last_colon[-1] != ':')
- return false;
- else
+
+ // Can't have a C++ name that begins with a single ':', nor contains an internal single ':'
+ if (last_colon == name)
+ return false;
+ else if (last_colon[-1] != ':')
+ return false;
+ else
{
- // FIXME: should check if there is
- base_name_start = last_colon + 1;
- return true;
+ // FIXME: should check if there is
+ base_name_start = last_colon + 1;
+ return true;
}
}
bool
CPPLanguageRuntime::IsPossibleCPPCall (const char *name, const char *&base_name_start, const char *&base_name_end)
{
if (!name)
- return false;
+ return false;
// For now, I really can't handle taking template names apart, so if you
// have < or > I'll say "could be CPP but leave the base_name empty which
// means I couldn't figure out what to use for that.
// FIXME: Do I need to do more sanity checking here?
-
+
if (strchr(name, '>') != NULL || strchr (name, '>') != NULL)
- return true;
-
+ return true;
+
size_t name_len = strlen (name);
-
+
if (name[name_len - 1] == ')')
{
// We've got arguments.
base_name_end = strchr (name, '(');
if (base_name_end == NULL)
- return false;
-
+ return false;
+
// FIXME: should check that this parenthesis isn't a template specialized
// on a function type or something gross like that...
}
else
base_name_end = name + strlen (name);
-
+
return StripNamespacesFromVariableName (name, base_name_start, base_name_end);
}
@@ -267,3 +267,156 @@ CPPLanguageRuntime::FindEquivalentNames(
return count;
}
+
+void
+CPPLanguageRuntime::MethodName::Clear()
+{
+ m_full.Clear();
+ m_basename.Clear();
+ m_context = llvm::StringRef();
+ m_arguments = llvm::StringRef();
+ m_qualifiers = llvm::StringRef();
+ m_type = eTypeInvalid;
+ m_parsed = false;
+ m_parse_error = false;
+}
+
+bool
+ReverseFindMatchingChars (const llvm::StringRef &s,
+ const llvm::StringRef &left_right_chars,
+ size_t &left_pos,
+ size_t &right_pos,
+ size_t pos = llvm::StringRef::npos)
+{
+ assert (left_right_chars.size() == 2);
+ left_pos = llvm::StringRef::npos;
+ const char left_char = left_right_chars[0];
+ const char right_char = left_right_chars[1];
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos || s[pos] == left_char)
+ return false;
+ right_pos = pos;
+ uint32_t depth = 1;
+ while (pos > 0 && depth > 0)
+ {
+ pos = s.find_last_of(left_right_chars, pos);
+ if (pos == llvm::StringRef::npos)
+ return false;
+ if (s[pos] == left_char)
+ {
+ if (--depth == 0)
+ {
+ left_pos = pos;
+ return left_pos < right_pos;
+ }
+ }
+ else if (s[pos] == right_char)
+ {
+ ++depth;
+ }
+ }
+ return false;
+}
+
+void
+CPPLanguageRuntime::MethodName::Parse()
+{
+ if (!m_parsed && m_full)
+ {
+// ConstString mangled;
+// m_full.GetMangledCounterpart(mangled);
+// printf ("\n parsing = '%s'\n", m_full.GetCString());
+// if (mangled)
+// printf (" mangled = '%s'\n", mangled.GetCString());
+ m_parse_error = false;
+ m_parsed = true;
+ llvm::StringRef full (m_full.GetCString());
+
+ size_t arg_start, arg_end;
+ llvm::StringRef parens("()", 2);
+ if (ReverseFindMatchingChars (full, parens, arg_start, arg_end))
+ {
+ m_arguments = full.substr(arg_start, arg_end - arg_start + 1);
+ if (arg_end + 1 < full.size())
+ m_qualifiers = full.substr(arg_end + 1);
+ if (arg_start > 0)
+ {
+ size_t basename_end = arg_start;
+ size_t context_end = llvm::StringRef::npos;
+ if (basename_end > 0 && full[basename_end-1] == '>')
+ {
+ // TODO: handle template junk...
+ // Templated function
+ size_t template_start, template_end;
+ llvm::StringRef lt_gt("<>", 2);
+ if (ReverseFindMatchingChars (full, lt_gt, template_start, template_end, basename_end))
+ context_end = full.rfind(':', template_start);
+ }
+ if (context_end == llvm::StringRef::npos)
+ context_end = full.rfind(':', basename_end);
+
+ if (context_end == llvm::StringRef::npos)
+ m_basename.SetString(full.substr(0, basename_end));
+ else
+ {
+ m_context = full.substr(0, context_end - 1);
+ const size_t basename_begin = context_end + 1;
+ m_basename.SetString(full.substr(basename_begin, basename_end - basename_begin));
+ }
+ m_type = eTypeUnknownMethod;
+ }
+ else
+ {
+ m_parse_error = true;
+ return;
+ }
+
+// if (!m_context.empty())
+// printf (" context = '%s'\n", m_context.str().c_str());
+// if (m_basename)
+// printf (" basename = '%s'\n", m_basename.GetCString());
+// if (!m_arguments.empty())
+// printf (" arguments = '%s'\n", m_arguments.str().c_str());
+// if (!m_qualifiers.empty())
+// printf ("qualifiers = '%s'\n", m_qualifiers.str().c_str());
+ }
+ else
+ {
+ m_parse_error = true;
+// printf ("error: didn't find matching parens for arguments\n");
+ }
+ }
+}
+
+const ConstString &
+CPPLanguageRuntime::MethodName::GetBasename ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_basename;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetContext ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_context;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetArguments ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_arguments;
+}
+
+llvm::StringRef
+CPPLanguageRuntime::MethodName::GetQualifiers ()
+{
+ if (!m_parsed)
+ Parse();
+ return m_qualifiers;
+}
+
More information about the lldb-commits
mailing list