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.
git-svn-id: https://llvm.org/svn/llvm-project/llvdb/trunk@141428 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/lldb/Breakpoint/BreakpointResolverName.h b/include/lldb/Breakpoint/BreakpointResolverName.h
index cf69231..2732f47 100644
--- a/include/lldb/Breakpoint/BreakpointResolverName.h
+++ b/include/lldb/Breakpoint/BreakpointResolverName.h
@@ -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;
diff --git a/include/lldb/Target/CPPLanguageRuntime.h b/include/lldb/Target/CPPLanguageRuntime.h
index 474b0ba..e2da738 100644
--- a/include/lldb/Target/CPPLanguageRuntime.h
+++ b/include/lldb/Target/CPPLanguageRuntime.h
@@ -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
diff --git a/include/lldb/Target/ObjCLanguageRuntime.h b/include/lldb/Target/ObjCLanguageRuntime.h
index d1b12cc..9507409 100644
--- a/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/include/lldb/Target/ObjCLanguageRuntime.h
@@ -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:
diff --git a/source/API/SBTarget.cpp b/source/API/SBTarget.cpp
index 28bb109..dff7007 100644
--- a/source/API/SBTarget.cpp
+++ b/source/API/SBTarget.cpp
@@ -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);
}
}
diff --git a/source/Breakpoint/BreakpointResolverName.cpp b/source/Breakpoint/BreakpointResolverName.cpp
index 4288909..9df1dd7 100644
--- a/source/Breakpoint/BreakpointResolverName.cpp
+++ b/source/Breakpoint/BreakpointResolverName.cpp
@@ -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
diff --git a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index 909f6aa..81da55a 100644
--- a/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -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;
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index e25acbb..5204d07 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -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)
{
- DWARFDebugInfo* info = DebugInfo();
- if (info == NULL)
- return 0;
-
- const uint32_t sc_list_initial_size = sc_list.GetSize();
SymbolContext sc;
- sc.module_sp = m_obj_file->GetModule();
- assert (sc.module_sp);
- DWARFCompileUnit* dwarf_cu = NULL;
- const size_t num_matches = die_offsets.size();
- for (size_t i=0; i<num_matches; ++i)
+ DWARFDebugInfo* info = DebugInfo();
+ bool resolved_it = false;
+
+ if (info == NULL)
+ return resolved_it;
+
+ DWARFDebugInfoEntry *die = info->GetDIEPtrWithCompileUnitHint (die_offset, &dwarf_cu);
+
+ // 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;
+
+ 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;
- }
-
-
- const DWARFDebugInfoEntry* inlined_die = NULL;
- if (die->Tag() == DW_TAG_inlined_subroutine)
- {
- // 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;
- }
- }
- if (die->Tag() == DW_TAG_subprogram)
- {
- if (GetFunction (dwarf_cu, die, sc))
- {
- 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 (die->Tag() == DW_TAG_subprogram)
+ break;
}
}
- return sc_list.GetSize() - sc_list_initial_size;
+ assert (die->Tag() == DW_TAG_subprogram);
+ if (GetFunction (dwarf_cu, die, sc))
+ {
+ 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);
+ resolved_it = true;
+ }
+ }
+
+ return resolved_it;
}
-
-
void
SymbolFileDWARF::FindFunctions (const ConstString &name,
const NameToDIE &name_to_die,
@@ -2216,65 +2204,78 @@
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;
-
- while ((die = die->GetParent()) != NULL)
- {
- if (die->Tag() == DW_TAG_subprogram)
- break;
- }
- }
- assert (die->Tag() == DW_TAG_subprogram);
- if (GetFunction (dwarf_cu, die, sc))
- {
- 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);
- }
- }
+ 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;
+
+ 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))
+ {
+ 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)
+ {
+ printf ("name: \"%s\" didn't match full name: \"%s\".\n", partial_name, demangled);
+ return false;
+ }
+ }
+ }
+ }
+
+ return true;
+}
uint32_t
SymbolFileDWARF::FindFunctions (const ConstString &name,
@@ -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
{
diff --git a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 0f21e8e..134e734 100644
--- a/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -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,
diff --git a/source/Target/CPPLanguageRuntime.cpp b/source/Target/CPPLanguageRuntime.cpp
index d80ed21..22fbd84 100644
--- a/source/Target/CPPLanguageRuntime.cpp
+++ b/source/Target/CPPLanguageRuntime.cpp
@@ -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);
+}
diff --git a/test/python_api/target/TestTargetAPI.py b/test/python_api/target/TestTargetAPI.py
index 81d250b..e0cfa47 100644
--- a/test/python_api/target/TestTargetAPI.py
+++ b/test/python_api/target/TestTargetAPI.py
@@ -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)