summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointResolverName.h8
-rw-r--r--lldb/include/lldb/Target/CPPLanguageRuntime.h9
-rw-r--r--lldb/include/lldb/Target/ObjCLanguageRuntime.h20
-rw-r--r--lldb/source/API/SBTarget.cpp4
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverName.cpp110
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h13
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp456
-rw-r--r--lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h18
-rw-r--r--lldb/source/Target/CPPLanguageRuntime.cpp78
-rw-r--r--lldb/test/python_api/target/TestTargetAPI.py3
10 files changed, 445 insertions, 274 deletions
diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
index cf69231824a..2732f478279 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointResolverName.h
@@ -72,14 +72,6 @@ public:
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/lldb/include/lldb/Target/CPPLanguageRuntime.h b/lldb/include/lldb/Target/CPPLanguageRuntime.h
index 474b0ba8c06..e2da738fcbd 100644
--- a/lldb/include/lldb/Target/CPPLanguageRuntime.h
+++ b/lldb/include/lldb/Target/CPPLanguageRuntime.h
@@ -42,6 +42,15 @@ public:
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/lldb/include/lldb/Target/ObjCLanguageRuntime.h b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
index d1b12cccb22..95074095795 100644
--- a/lldb/include/lldb/Target/ObjCLanguageRuntime.h
+++ b/lldb/include/lldb/Target/ObjCLanguageRuntime.h
@@ -102,7 +102,25 @@ public:
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/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 28bb109108f..dff70079881 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -588,11 +588,11 @@ SBTarget::BreakpointCreateByName (const char *symbol_name, const char *module_na
{
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/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp
index 42889091a97..9df1dd73334 100644
--- a/lldb/source/Breakpoint/BreakpointResolverName.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -30,55 +30,14 @@ BreakpointResolverName::BreakpointResolverName
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 @@ BreakpointResolverName::SearchCallback
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 @@ BreakpointResolverName::SearchCallback
}
}
}
-
-
- 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 @@ BreakpointResolverName::GetDescription (Stream *s)
{
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/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
index 909f6aaeb3e..81da55a13b2 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/HashedNameToDIE.h
@@ -652,6 +652,19 @@ struct DWARFMappedHash
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/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
index e25acbb28f9..5204d070ff5 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ b/lldb/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 @@ SymbolFileDWARF::GetFunction (DWARFCompileUnit* curr_cu, const DWARFDebugInfoEnt
{
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 @@ SymbolFileDWARF::FindGlobalVariables (const ConstString &name, bool append, uint
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 @@ SymbolFileDWARF::FindGlobalVariables(const RegularExpression& regex, bool append
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;
+ }
+ }
+ 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();
}
-
- const DWARFDebugInfoEntry* inlined_die = NULL;
- if (die->Tag() == DW_TAG_inlined_subroutine)
+ if (addr.IsValid())
{
- // We only are looking for selectors, which disallows anything inlined
- if (name_type_mask == eFunctionNameTypeSelector)
- continue;
- inlined_die = die;
-
- while ((die = die->GetParent()) != 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 (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 (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 @@ SymbolFileDWARF::ParseFunctions (const DIEArray &die_offsets,
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 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
// 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 @@ SymbolFileDWARF::FindFunctions (const ConstString &name,
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 @@ SymbolFileDWARF::FindFunctions(const RegularExpression& regex, bool append, Symb
// 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 @@ SymbolFileDWARF::FindTypes(const SymbolContext& sc, const ConstString &name, boo
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 @@ SymbolFileDWARF::FindNamespace (const SymbolContext& sc,
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 @@ SymbolFileDWARF::FindDefinitionTypeForDIE (DWARFCompileUnit* cu,
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/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
index 0f21e8e6e44..134e734a877 100644
--- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -322,11 +322,19 @@ protected:
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/lldb/source/Target/CPPLanguageRuntime.cpp b/lldb/source/Target/CPPLanguageRuntime.cpp
index d80ed210440..22fbd8479b5 100644
--- a/lldb/source/Target/CPPLanguageRuntime.cpp
+++ b/lldb/source/Target/CPPLanguageRuntime.cpp
@@ -40,3 +40,81 @@ CPPLanguageRuntime::GetObjectDescription (Stream &str, Value &value, ExecutionCo
// 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/lldb/test/python_api/target/TestTargetAPI.py b/lldb/test/python_api/target/TestTargetAPI.py
index 81d250b497f..e0cfa477238 100644
--- a/lldb/test/python_api/target/TestTargetAPI.py
+++ b/lldb/test/python_api/target/TestTargetAPI.py
@@ -120,6 +120,9 @@ class TargetAPITestCase(TestBase):
# 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)
OpenPOWER on IntegriCloud