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.

llvm-svn: 141428
This commit is contained in:
Jim Ingham 2011-10-07 22:23:45 +00:00
parent dccc2b2277
commit 4cda6e058b
10 changed files with 457 additions and 286 deletions

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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

View File

@ -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;

View File

@ -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)
{
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 @@ 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;
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 @@ 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
{

View File

@ -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,

View File

@ -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);
}

View File

@ -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)