[Lldb-commits] [lldb] r141428 - in /lldb/trunk: include/lldb/Breakpoint/BreakpointResolverName.h include/lldb/Target/CPPLanguageRuntime.h include/lldb/Target/ObjCLanguageRuntime.h source/API/SBTarget.cpp source/Breakpoint/BreakpointResolverName.cpp source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h source/Target/CPPLanguageRuntime.cpp test/python_api/target/TestTargetAPI.py

Jim Ingham jingham at apple.com
Fri Oct 7 15:23:45 PDT 2011


Author: jingham
Date: Fri Oct  7 17:23:45 2011
New Revision: 141428

URL: http://llvm.org/viewvc/llvm-project?rev=141428&view=rev
Log:
Move the responsibility for translating the various eFunctionNameType lookups to the 
SymbolFIle (it was done mostly in the BreakpointResolverName resolver before.)  Then
tailor our searches to the way the indexed maps are laid out.  This removes a bunch 
of test case failures using indexed dSYM's.

Modified:
    lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
    lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h
    lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
    lldb/trunk/source/API/SBTarget.cpp
    lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
    lldb/trunk/source/Target/CPPLanguageRuntime.cpp
    lldb/trunk/test/python_api/target/TestTargetAPI.py

Modified: lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h (original)
+++ lldb/trunk/include/lldb/Breakpoint/BreakpointResolverName.h Fri Oct  7 17:23:45 2011
@@ -72,14 +72,6 @@
 
 protected:
     ConstString m_func_name;
-    // "m_basename_filter" is used to filter results after searching for
-    // "m_func_name" first. This is used when we are asked to set a breakpoint 
-    // at "foo::bar::baz" (C++ function in namespace or in a class). For 
-    // "foo::bar::baz" we will place "baz" into m_func_name and search for all
-    // matching basename and methods that match "baz", then we will filter the
-    // results by checking if the demangled name contains "m_basename_filter"
-    // which would be set to "foo::bar::baz".
-    std::string m_basename_filter;  
     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.
     RegularExpression m_regex;

Modified: lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/CPPLanguageRuntime.h Fri Oct  7 17:23:45 2011
@@ -42,6 +42,15 @@
     virtual bool
     GetObjectDescription (Stream &str, Value &value, ExecutionContextScope *exe_scope);
     
+    static bool
+    IsCPPMangledName(const char *name);
+    
+    static bool
+    IsPossibleCPPCall (const char *name, const char *&base_name_start, const char *&base_name_end);
+
+    static bool
+    StripNamespacesFromVariableName (const char *name, const char *&base_name_start, const char *&base_name_end);
+
 protected:
     //------------------------------------------------------------------
     // Classes that inherit from CPPLanguageRuntime can see and modify these

Modified: lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h (original)
+++ lldb/trunk/include/lldb/Target/ObjCLanguageRuntime.h Fri Oct  7 17:23:45 2011
@@ -102,7 +102,25 @@
     static bool
     IsPossibleObjCMethodName (const char *name)
     {
-        return (name && (name[0] == '+' || name[0] == '-') && name[1] == '[');
+        if (!name)
+            return false;
+        bool starts_right = (name[0] == '+' || name[0] == '-') && name[1] == '[';
+        bool ends_right = (name[strlen(name) - 1] == ']');
+        return (starts_right && ends_right);
+    }
+    
+    static bool
+    IsPossibleObjCSelector (const char *name)
+    {
+        if (!name)
+            return false;
+            
+        if (strchr(name, ':') == NULL)
+            return true;
+        else if (name[strlen(name) - 1] == ':')
+            return true;
+        else
+            return false;
     }
     
 protected:

Modified: lldb/trunk/source/API/SBTarget.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTarget.cpp?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTarget.cpp (original)
+++ lldb/trunk/source/API/SBTarget.cpp Fri Oct  7 17:23:45 2011
@@ -588,11 +588,11 @@
         {
             FileSpecList module_spec_list;
             module_spec_list.Append (FileSpec (module_name, false));
-            *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
+            *sb_bp = m_opaque_sp->CreateBreakpoint (&module_spec_list, NULL, symbol_name, eFunctionNameTypeAuto, false);
         }
         else
         {
-            *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeFull | eFunctionNameTypeBase, false);
+            *sb_bp = m_opaque_sp->CreateBreakpoint (NULL, NULL, symbol_name, eFunctionNameTypeAuto, false);
         }
     }
     

Modified: lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp (original)
+++ lldb/trunk/source/Breakpoint/BreakpointResolverName.cpp Fri Oct  7 17:23:45 2011
@@ -30,55 +30,14 @@
     bool skip_prologue
 ) :
     BreakpointResolver (bkpt, BreakpointResolver::NameResolver),
-    m_func_name (),
-    m_basename_filter (),
+    m_func_name (func_name),
     m_func_name_type_mask (func_name_type_mask),
     m_class_name (),
     m_regex (),
     m_match_type (type),
     m_skip_prologue (skip_prologue)
 {
-    if (func_name_type_mask == eFunctionNameTypeAuto)
-    {
-        if ((::strchr (func_name, '(' ) != NULL) ||
-            (::strstr (func_name, "-[") == func_name) || 
-            (::strstr (func_name, "+[") == func_name))
-        {
-            // We have a name that contains an open parens, or starts with 
-            // "+[" or "-[", so this looks like a complete function prototype
-            m_func_name_type_mask = eFunctionNameTypeFull;
-        }
-        else
-        {
-            // We don't have a full function name, but we might have a partial
-            // function basename with namespaces or classes
-            if (::strstr (func_name, "::") != NULL)
-            {
-                // Keep the full name in "m_basename_filter"
-                m_basename_filter = func_name;
-                // Now set "m_func_name" to just the function basename
-                m_func_name.SetCString(m_basename_filter.c_str() + m_basename_filter.rfind("::") + 2);
-                // We have a name with a double colon which means we have a
-                // function name that is a C++ method or a function in a C++ 
-                // namespace
-                m_func_name_type_mask = eFunctionNameTypeBase | eFunctionNameTypeMethod;
-            }
-            else if (::strstr (func_name, ":") != NULL)
-            {
-                // Single colon => selector
-                m_func_name_type_mask = eFunctionNameTypeSelector;
-            }
-            else
-            {
-                // just a  basename by default
-                m_func_name_type_mask = eFunctionNameTypeBase;
-            }
-        }
-    }
 
-    if (!m_func_name)
-        m_func_name.SetCString(func_name);
-    
     if (m_match_type == Breakpoint::Regexp)
     {
         if (!m_regex.Compile (m_func_name.AsCString()))
@@ -178,7 +137,7 @@
                 
                 if (num_functions == 0 && !filter_by_cu)
                 {
-                    if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull))
+                    if (m_func_name_type_mask & (eFunctionNameTypeBase | eFunctionNameTypeFull | eFunctionNameTypeAuto))
                         context.module_sp->FindSymbolsWithNameAndType (m_func_name, eSymbolTypeCode, sym_list);
                 }
             }
@@ -217,68 +176,7 @@
             }
         }
     }
-                
-
-    if (!m_basename_filter.empty())
-    {
-        // Filter out any matches whose names don't contain the basename filter
-        const char *basename_filter = m_basename_filter.c_str();
-        if (func_list.GetSize())
-        {
-            bool remove = false;
-            for (i = 0; i < func_list.GetSize(); remove = false)
-            {
-                if (func_list.GetContextAtIndex(i, sc) == false)
-                    remove = true;
-                else if (sc.function == NULL)
-                    remove = true;
-                else
-                {
-                    const InlineFunctionInfo* inlined_info = NULL;
-                    
-                    if (sc.block)
-                        inlined_info = sc.block->GetInlinedFunctionInfo();
 
-                    if (inlined_info)
-                    {
-                        if (::strstr (inlined_info->GetName().AsCString(), basename_filter) == NULL)
-                            remove = true;
-                    }
-                    else if (::strstr (sc.function->GetName().AsCString(), basename_filter) == NULL)
-                        remove = true;
-                }
-
-                if (remove)
-                {
-                    func_list.RemoveContextAtIndex(i);
-                    continue;
-                }
-                i++;
-            }
-        }
-
-        if (sym_list.GetSize())
-        {
-            bool remove = false;
-            for (i = 0; i < sym_list.GetSize(); remove = false)
-            {
-                if (sym_list.GetContextAtIndex(i, sc) == false)
-                    remove = true;
-                else if (sc.symbol == NULL)
-                    remove = true;
-                else if (::strstr (sc.symbol->GetName().AsCString(), basename_filter) == NULL)
-                    remove = true;
-
-                if (remove)
-                {
-                    sym_list.RemoveContextAtIndex(i);
-                    continue;
-                }
-                i++;
-            }
-        }
-    }
-    
     // Remove any duplicates between the funcion list and the symbol list
     if (func_list.GetSize())
     {
@@ -395,10 +293,8 @@
 {
     if (m_match_type == Breakpoint::Regexp)
         s->Printf("regex = '%s'", m_regex.GetText());
-    else if (m_basename_filter.empty())
-        s->Printf("name = '%s'", m_func_name.AsCString());
     else
-        s->Printf("name = '%s'", m_basename_filter.c_str());
+        s->Printf("name = '%s'", m_func_name.AsCString());
 }
 
 void

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h Fri Oct  7 17:23:45 2011
@@ -652,6 +652,19 @@
             return die_offsets.size();
         }
 
+        size_t 
+        FindByName (const char *name, DIEArray &die_offsets)
+        {
+            Pair kv_pair;
+            size_t old_size = die_offsets.size();
+            if (Find (name, kv_pair))
+            {
+                die_offsets.swap(kv_pair.value);
+                return die_offsets.size() - old_size;
+            }
+            return 0;
+        }
+        
     protected:
         const lldb_private::DataExtractor &m_data;
         const lldb_private::DataExtractor &m_string_table;

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=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Fri Oct  7 17:23:45 2011
@@ -43,6 +43,7 @@
 #include "lldb/Symbol/VariableList.h"
 
 #include "lldb/Target/ObjCLanguageRuntime.h"
+#include "lldb/Target/CPPLanguageRuntime.h"
 
 #include "DWARFCompileUnit.h"
 #include "DWARFDebugAbbrev.h"
@@ -1655,14 +1656,19 @@
 {
     sc.Clear();
     // Check if the symbol vendor already knows about this compile unit?
-    sc.module_sp = m_obj_file->GetModule();
     sc.comp_unit = GetCompUnitForDWARFCompUnit(curr_cu, UINT32_MAX);
 
     sc.function = sc.comp_unit->FindFunctionByUID (func_die->GetOffset()).get();
     if (sc.function == NULL)
         sc.function = ParseCompileUnitFunction(sc, curr_cu, func_die);
-
-    return sc.function != NULL;
+        
+    if (sc.function)
+    {        
+        sc.module_sp = sc.function->CalculateSymbolContextModule();
+        return true;
+    }
+    
+    return false;
 }
 
 uint32_t
@@ -1969,11 +1975,13 @@
     if (m_apple_names_ap.get())
     {
         const char *name_cstr = name.GetCString();
-        DWARFMappedHash::MemoryTable::Pair kv_pair;
-        if (m_apple_names_ap->Find (name_cstr, kv_pair))
-        {
-            die_offsets.swap(kv_pair.value);
-        }
+        const char *base_name_start;
+        const char *base_name_end = NULL;
+        
+        if (!CPPLanguageRuntime::StripNamespacesFromVariableName(name_cstr, base_name_start, base_name_end))
+            base_name_start = name_cstr;
+            
+        m_apple_names_ap->FindByName (base_name_start, die_offsets);
     }
     else
     {
@@ -2080,96 +2088,76 @@
     return variables.GetSize() - original_size;
 }
 
-
-uint32_t
-SymbolFileDWARF::ResolveFunctions (const DIEArray &die_offsets,
-                                   SymbolContextList& sc_list,
-                                   const ConstString &name,
-                                   uint32_t name_type_mask)
+bool
+SymbolFileDWARF::ResolveFunction (dw_offset_t die_offset,
+                                  DWARFCompileUnit *&dwarf_cu,
+                                  SymbolContextList& sc_list)
 {
+    SymbolContext sc;
+    
     DWARFDebugInfo* info = DebugInfo();
+    bool resolved_it = false;
+    
     if (info == NULL)
-        return 0;
+        return resolved_it;
+        
+    DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
     
-    const uint32_t sc_list_initial_size = sc_list.GetSize();
-    SymbolContext sc;
-    sc.module_sp = m_obj_file->GetModule();
-    assert (sc.module_sp);
+    // If we were passed a die that is not a function, just return false...
+    if (die->Tag() != DW_TAG_subprogram && die->Tag() != DW_TAG_inlined_subroutine)
+        return false;
     
-    DWARFCompileUnit* dwarf_cu = NULL;
-    const size_t num_matches = die_offsets.size();
-    for (size_t i=0; i<num_matches; ++i)
+    const DWARFDebugInfoEntry* inlined_die = NULL;
+    if (die->Tag() == DW_TAG_inlined_subroutine)
     {
-        const dw_offset_t die_offset = die_offsets[i];
-        const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+        inlined_die = die;
         
-        // If we aren't doing full names, 
-        if ((name_type_mask & eFunctionNameTypeFull) == 0)
+        while ((die = die->GetParent()) != NULL)
         {
-            const char *name_cstr = name.GetCString();
-            if (ObjCLanguageRuntime::IsPossibleObjCMethodName(name_cstr))
-                continue;
+            if (die->Tag() == DW_TAG_subprogram)
+                break;
         }
-        
-
-        const DWARFDebugInfoEntry* inlined_die = NULL;
-        if (die->Tag() == DW_TAG_inlined_subroutine)
+    }
+    assert (die->Tag() == DW_TAG_subprogram);
+    if (GetFunction (dwarf_cu, die, sc))
+    {
+        Address addr;
+        // Parse all blocks if needed
+        if (inlined_die)
         {
-            // We only are looking for selectors, which disallows anything inlined
-            if (name_type_mask == eFunctionNameTypeSelector)
-                continue;
-        
-            inlined_die = die;
-            
-            while ((die = die->GetParent()) != NULL)
-            {
-                if (die->Tag() == DW_TAG_subprogram)
-                    break;
-            }
+            sc.block = sc.function->GetBlock (true).FindBlockByID (inlined_die->GetOffset());
+            assert (sc.block != NULL);
+            if (sc.block->GetStartAddress (addr) == false)
+                addr.Clear();
         }
-        if (die->Tag() == DW_TAG_subprogram)
+        else 
+        {
+            sc.block = NULL;
+            addr = sc.function->GetAddressRange().GetBaseAddress();
+        }
+
+        if (addr.IsValid())
         {
-            if (GetFunction (dwarf_cu, die, sc))
+        
+            // We found the function, so we should find the line table
+            // and line table entry as well
+            LineTable *line_table = sc.comp_unit->GetLineTable();
+            if (line_table == NULL)
             {
-                Address addr;
-                // Parse all blocks if needed
-                if (inlined_die)
-                {
-                    sc.block = sc.function->GetBlock (true).FindBlockByID (inlined_die->GetOffset());
-                    assert (sc.block != NULL);
-                    if (sc.block->GetStartAddress (addr) == false)
-                        addr.Clear();
-                }
-                else 
-                {
-                    sc.block = NULL;
-                    addr = sc.function->GetAddressRange().GetBaseAddress();
-                }
-                
-                if (addr.IsValid())
-                {
-                    
-                    // We found the function, so we should find the line table
-                    // and line table entry as well
-                    LineTable *line_table = sc.comp_unit->GetLineTable();
-                    if (line_table == NULL)
-                    {
-                        if (ParseCompileUnitLineTable(sc))
-                            line_table = sc.comp_unit->GetLineTable();
-                    }
-                    if (line_table != NULL)
-                        line_table->FindLineEntryByAddress (addr, sc.line_entry);
-                    
-                    sc_list.Append(sc);
-                }
+                if (ParseCompileUnitLineTable(sc))
+                    line_table = sc.comp_unit->GetLineTable();
             }
+            if (line_table != NULL)
+                line_table->FindLineEntryByAddress (addr, sc.line_entry);
+
+            sc_list.Append(sc);
+            resolved_it = true;
         }
     }
-    return sc_list.GetSize() - sc_list_initial_size;
+    
+    return resolved_it;
 }
 
-
-
 void
 SymbolFileDWARF::FindFunctions (const ConstString &name, 
                                 const NameToDIE &name_to_die,
@@ -2216,66 +2204,79 @@
     if (num_matches)
     {
         SymbolContext sc;
-        sc.module_sp = m_obj_file->GetModule();
 
         DWARFCompileUnit* dwarf_cu = NULL;
-        const DWARFDebugInfoEntry* die = NULL;
-        DWARFDebugInfo* debug_info = DebugInfo();
         for (size_t i=0; i<num_matches; ++i)
         {
             const dw_offset_t die_offset = die_offsets[i];
-            die = debug_info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
-            const DWARFDebugInfoEntry* inlined_die = NULL;
-            if (die->Tag() == DW_TAG_inlined_subroutine)
-            {
-                inlined_die = die;
+            ResolveFunction (die_offset, dwarf_cu, sc_list);
+        }
+    }
+}
+
+bool
+SymbolFileDWARF::FunctionDieMatchesPartialName (const DWARFDebugInfoEntry* die,
+                                                const DWARFCompileUnit *dwarf_cu,
+                                                uint32_t name_type_mask, 
+                                                const char *partial_name,
+                                                const char *base_name_start,
+                                                const char *base_name_end)
+{
+    // If we are looking only for methods, throw away all the ones that aren't in C++ classes:
+    if (name_type_mask == eFunctionNameTypeMethod
+        || name_type_mask == eFunctionNameTypeBase)
+    {
+            clang::DeclContext *containing_decl_ctx = GetClangDeclContextContainingDIEOffset(die->GetOffset());
+            if (!containing_decl_ctx)
+                return false;
                 
-                while ((die = die->GetParent()) != NULL)
-                {
-                    if (die->Tag() == DW_TAG_subprogram)
-                        break;
-                }
-            }
-            assert (die->Tag() == DW_TAG_subprogram);
-            if (GetFunction (dwarf_cu, die, sc))
+            bool is_cxx_method = (containing_decl_ctx->getDeclKind() == clang::Decl::CXXRecord);
+
+            if (!is_cxx_method && name_type_mask == eFunctionNameTypeMethod)
+                return false;
+            if (is_cxx_method && name_type_mask == eFunctionNameTypeBase)
+                return false;
+    }
+
+    // Now we need to check whether the name we got back for this type matches the extra specifications
+    // that were in the name we're looking up:
+    if (base_name_start != partial_name || *base_name_end != '\0')
+    {
+        // First see if the stuff to the left matches the full name.  To do that let's see if
+        // we can pull out the mips linkage name attribute:
+        
+        Mangled best_name;
+
+        DWARFDebugInfoEntry::Attributes attributes;
+        die->GetAttributes(this, dwarf_cu, NULL, attributes);
+        uint32_t idx = attributes.FindAttributeIndex(DW_AT_MIPS_linkage_name);
+        if (idx != UINT32_MAX)
+        {
+            DWARFFormValue form_value;
+            if (attributes.ExtractFormValueAtIndex(this, idx, form_value))
             {
-                Address addr;
-                // Parse all blocks if needed
-                if (inlined_die)
-                {
-                    sc.block = sc.function->GetBlock (true).FindBlockByID (inlined_die->GetOffset());
-                    assert (sc.block != NULL);
-                    if (sc.block->GetStartAddress (addr) == false)
-                        addr.Clear();
-                }
-                else 
-                {
-                    sc.block = NULL;
-                    addr = sc.function->GetAddressRange().GetBaseAddress();
-                }
-                
-                if (addr.IsValid())
+                const char *name = form_value.AsCString(&get_debug_str_data());
+                best_name.SetValue (name, true);
+            } 
+        }
+        if (best_name)
+        {
+            const char *demangled = best_name.GetDemangledName().GetCString();
+            if (demangled)
+            {
+                std::string name_no_parens(partial_name, base_name_end - partial_name);
+                if (strstr (demangled, name_no_parens.c_str()) == NULL)
                 {
-                    
-                    // We found the function, so we should find the line table
-                    // and line table entry as well
-                    LineTable *line_table = sc.comp_unit->GetLineTable();
-                    if (line_table == NULL)
-                    {
-                        if (ParseCompileUnitLineTable(sc))
-                            line_table = sc.comp_unit->GetLineTable();
-                    }
-                    if (line_table != NULL)
-                        line_table->FindLineEntryByAddress (addr, sc.line_entry);
-                    
-                    sc_list.Append(sc);
+                    printf ("name: \"%s\" didn't match full name: \"%s\".\n", partial_name, demangled);
+                    return false;
                 }
             }
         }
     }
+    
+    return true;
 }
 
-
 uint32_t
 SymbolFileDWARF::FindFunctions (const ConstString &name, 
                                 uint32_t name_type_mask, 
@@ -2299,18 +2300,134 @@
     // If we aren't appending the results to this list, then clear the list
     if (!append)
         sc_list.Clear();
+        
+    // If name is empty then we won't find anything.
+    if (name.IsEmpty())
+        return 0;
 
     // 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;
+            }
+        }
+    }
+    
+    DWARFDebugInfo* info = DebugInfo();
+    if (info == NULL)
+        return 0;
+
     if (m_apple_names_ap.get())
     {
-        const char *name_cstr = name.GetCString();
-        DWARFMappedHash::MemoryTable::Pair kv_pair;
-        if (m_apple_names_ap->Find (name_cstr, kv_pair))
-            ResolveFunctions (kv_pair.value, sc_list, name, name_type_mask);
+        DIEArray die_offsets;
+
+        uint32_t num_matches = 0;
+            
+        if (effective_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
+            // dies that we find by exact match.
+            DWARFCompileUnit *dwarf_cu = NULL;
+            num_matches = m_apple_names_ap->FindByName (name_cstr, die_offsets);
+            for (uint32_t i = 0; i < num_matches; i++)
+                ResolveFunction (die_offsets[i], dwarf_cu, sc_list);
+        }
+        else
+        {                
+            DWARFCompileUnit* dwarf_cu = NULL;
+            
+            if (effective_name_type_mask & eFunctionNameTypeSelector)
+            {
+                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 DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (die_offsets[i], &dwarf_cu);
+                    assert (die);
+                    
+                    const char *die_name = die->GetName(this, dwarf_cu);
+                    if (ObjCLanguageRuntime::IsPossibleObjCMethodName(die_name))
+                        ResolveFunction (die_offsets[i], dwarf_cu, sc_list);
+                }
+                die_offsets.clear();
+            }
+            
+            if (effective_name_type_mask & eFunctionNameTypeMethod
+                || effective_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:
+                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++)
+                {
+                    dw_offset_t offset = die_offsets[i];
+                    const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (offset, &dwarf_cu);
+                    assert (die);
+                    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 (offset, dwarf_cu, sc_list);
+                }
+                die_offsets.clear();
+            }
+        }
     }
     else
     {
@@ -2319,24 +2436,73 @@
         if (!m_indexed)
             Index ();
 
-        if (name_type_mask & eFunctionNameTypeBase)
-            FindFunctions (name, m_function_basename_index, sc_list);
-
         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)
+        {
+            uint32_t num_base = m_function_basename_index.Find(base_name_const, die_offsets);
+            {
+              for (uint32_t i = 0; i < num_base; i++)
+              {
+                dw_offset_t offset = die_offsets[i];
+                const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (offset, &dwarf_cu);
+                assert (die);
+                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 (offset, dwarf_cu, sc_list);
+              }
+            }
+            die_offsets.clear();
+        }
+        
         if (name_type_mask & eFunctionNameTypeMethod)
-            FindFunctions (name, m_function_method_index, sc_list);
+        {
+            uint32_t num_base = m_function_method_index.Find(base_name_const, die_offsets);
+            {
+              for (uint32_t i = 0; i < num_base; i++)
+              {
+                dw_offset_t offset = die_offsets[i];
+                const DWARFDebugInfoEntry* die = info->GetDIEPtrWithCompileUnitHint (offset, &dwarf_cu);
+                assert (die);
+                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 (offset, dwarf_cu, sc_list);
+              }
+            }
+            die_offsets.clear();
+        }
 
         if (name_type_mask & eFunctionNameTypeSelector)
+        {
             FindFunctions (name, m_function_selector_index, sc_list);
+        }
+        
     }
 
     // Return the number of variable that were appended to the list
     return sc_list.GetSize() - original_size;
 }
 
-
 uint32_t
 SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool append, SymbolContextList& sc_list)
 {
@@ -2363,13 +2529,13 @@
     // we are appending the results to a variable list.
     uint32_t original_size = sc_list.GetSize();
 
-    // Index the DWARF if we haven't already
     if (m_apple_names_ap.get())
     {
         FindFunctions (regex, *m_apple_names_ap, sc_list);
     }
     else
     {
+        // Index the DWARF if we haven't already
         if (!m_indexed)
             Index ();
 
@@ -2442,11 +2608,7 @@
     if (m_apple_types_ap.get())
     {
         const char *name_cstr = name.GetCString();
-        DWARFMappedHash::MemoryTable::Pair kv_pair;
-        if (m_apple_types_ap->Find (name_cstr, kv_pair))
-        {
-            die_offsets.swap(kv_pair.value);
-        }
+        m_apple_types_ap->FindByName (name_cstr, die_offsets);
     }
     else
     {
@@ -2518,11 +2680,7 @@
         if (m_apple_namespaces_ap.get())
         {
             const char *name_cstr = name.GetCString();
-            DWARFMappedHash::MemoryTable::Pair kv_pair;
-            if (m_apple_namespaces_ap->Find (name_cstr, kv_pair))
-            {
-                die_offsets.swap(kv_pair.value);
-            }
+            m_apple_namespaces_ap->FindByName (name_cstr, die_offsets);
         }
         else
         {
@@ -3192,11 +3350,7 @@
     if (m_apple_types_ap.get())
     {
         const char *name_cstr = type_name.GetCString();
-        DWARFMappedHash::MemoryTable::Pair kv_pair;
-        if (m_apple_types_ap->Find (name_cstr, kv_pair))
-        {
-            die_offsets.swap(kv_pair.value);
-        }
+        m_apple_types_ap->FindByName (name_cstr, die_offsets);
     }
     else
     {

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Fri Oct  7 17:23:45 2011
@@ -322,11 +322,19 @@
                                 uint32_t& byte_stride,
                                 uint32_t& bit_stride);
 
-    uint32_t                ResolveFunctions (
-                                const DIEArray &die_offsets,
-                                lldb_private::SymbolContextList& sc_list,
-                                const lldb_private::ConstString &name,
-                                uint32_t name_type_mask);
+                            // Given a die_offset, figure out the symbol context representing that die.
+    bool                    ResolveFunction (
+                                dw_offset_t offset,
+                                DWARFCompileUnit *&dwarf_cu,
+                                lldb_private::SymbolContextList& sc_list);
+                                
+    bool                    FunctionDieMatchesPartialName (
+                                const DWARFDebugInfoEntry* die,
+                                const DWARFCompileUnit *dwarf_cu,
+                                uint32_t name_type_mask,
+                                const char *partial_name,
+                                const char *base_name_start,
+                                const char *base_name_end);
 
     void                    FindFunctions(
                                 const lldb_private::ConstString &name, 

Modified: lldb/trunk/source/Target/CPPLanguageRuntime.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/CPPLanguageRuntime.cpp?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/source/Target/CPPLanguageRuntime.cpp (original)
+++ lldb/trunk/source/Target/CPPLanguageRuntime.cpp Fri Oct  7 17:23:45 2011
@@ -40,3 +40,81 @@
     // C++ has no generic way to do this.
     return false;
 }
+
+bool
+CPPLanguageRuntime::IsCPPMangledName (const char *name)
+{
+    // FIXME, we should really run through all the known C++ Language plugins and ask each one if
+    // this is a C++ mangled name, but we can put that off till there is actually more than one
+    // we care about.
+    
+    if (name && name[0] == '_' && name[1] == 'Z')
+        return true;
+    else
+        return false;
+}
+
+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);
+    
+  const char *last_colon = NULL;
+  for (const char *ptr = base_name_end; ptr != name; ptr--)
+    {
+      if (*ptr == ':')
+        {
+          last_colon = ptr;
+          break;
+        }
+    }
+
+  if (last_colon == NULL)
+    {
+      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
+    {
+      // 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;
+    // 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;
+
+    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;
+
+        // 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);
+}

Modified: lldb/trunk/test/python_api/target/TestTargetAPI.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/python_api/target/TestTargetAPI.py?rev=141428&r1=141427&r2=141428&view=diff
==============================================================================
--- lldb/trunk/test/python_api/target/TestTargetAPI.py (original)
+++ lldb/trunk/test/python_api/target/TestTargetAPI.py Fri Oct  7 17:23:45 2011
@@ -120,6 +120,9 @@
         # Now launch the process, and do not stop at entry point.
         process = target.LaunchSimple(None, None, os.getcwd())
         self.assertTrue(process, PROCESS_IS_VALID)
+        # Make sure we hit our breakpoint:
+        thread_list = lldbutil.get_threads_stopped_at_breakpoint (process, breakpoint)
+        self.assertTrue (len(thread_list) == 1)
 
         value_list = target.FindGlobalVariables('my_global_var_of_char_type', 3)
         self.assertTrue(value_list.GetSize() == 1)





More information about the lldb-commits mailing list