FindFunctions now works again with mangled names.

<rdar://problem/28147057> 

llvm-svn: 294990
This commit is contained in:
Greg Clayton 2017-02-13 21:34:58 +00:00
parent b74485dfaa
commit 5d0c114630
5 changed files with 158 additions and 20 deletions

View File

@ -0,0 +1,5 @@
LEVEL = ../../make
CXX_SOURCES := main.cpp
include $(LEVEL)/Makefile.rules

View File

@ -0,0 +1,65 @@
"""
Test SBTarget APIs.
"""
from __future__ import print_function
import unittest2
import os
import time
import re
import lldb
from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
class TestNameLookup(TestBase):
mydir = TestBase.compute_mydir(__file__)
@add_test_categories(['pyapi'])
def test_target(self):
"""Exercise SBTarget.FindFunctions() with various name masks.
A previous regression caused mangled names to not be able to be looked up.
This test verifies that using a mangled name with eFunctionNameTypeFull works
and that using a function basename with eFunctionNameTypeFull works for all
C++ functions that are at the global namespace level."""
self.build();
exe = os.path.join(os.getcwd(), 'a.out')
# Create a target by the debugger.
target = self.dbg.CreateTarget(exe)
self.assertTrue(target, VALID_TARGET)
exe_module = target.FindModule(target.GetExecutable())
c_name_to_symbol = {}
cpp_name_to_symbol = {}
mangled_to_symbol = {}
num_symbols = exe_module.GetNumSymbols();
for i in range(num_symbols):
symbol = exe_module.GetSymbolAtIndex(i);
name = symbol.GetName()
if 'unique_function_name' in name:
mangled = symbol.GetMangledName()
if mangled:
mangled_to_symbol[mangled] = symbol
if name:
cpp_name_to_symbol[name] = symbol
elif name:
c_name_to_symbol[name] = symbol
# Make sure each mangled name turns up exactly one match when looking up
# functions by full name and using the mangled name as the name in the
# lookup
for mangled in mangled_to_symbol.keys():
symbol_contexts = target.FindFunctions(mangled, lldb.eFunctionNameTypeFull)
self.assertTrue(symbol_contexts.GetSize() == 1)
for symbol_context in symbol_contexts:
self.assertTrue(symbol_context.GetFunction().IsValid())
self.assertTrue(symbol_context.GetSymbol().IsValid())

View File

@ -0,0 +1,54 @@
#include <stdio.h>
extern "C" int unique_function_name(int i)
{
return puts(__PRETTY_FUNCTION__);
}
int unique_function_name()
{
return puts(__PRETTY_FUNCTION__);
}
int unique_function_name(float f)
{
return puts(__PRETTY_FUNCTION__);
}
namespace e
{
int unique_function_name()
{
return puts(__PRETTY_FUNCTION__);
}
namespace g
{
int unique_function_name()
{
return puts(__PRETTY_FUNCTION__);
}
}
}
class g
{
public:
int unique_function_name()
{
return puts(__PRETTY_FUNCTION__);
}
int unique_function_name(int i)
{
return puts(__PRETTY_FUNCTION__);
}
};
int main (int argc, char const *argv[])
{
g g;
g.unique_function_name();
g.unique_function_name(argc);
return 0;
}

View File

@ -719,10 +719,10 @@ Module::LookupInfo::LookupInfo(const ConstString &name, uint32_t name_type_mask,
}
// Still try and get a basename in case someone specifies a name type mask
// of
// eFunctionNameTypeFull and a name like "A::func"
// of eFunctionNameTypeFull and a name like "A::func"
if (basename.empty()) {
if (name_type_mask & eFunctionNameTypeFull) {
if (name_type_mask & eFunctionNameTypeFull &&
!CPlusPlusLanguage::IsCPPMangledName(name_cstr)) {
CPlusPlusLanguage::MethodName cpp_method(name);
basename = cpp_method.GetBasename();
if (basename.empty())
@ -770,30 +770,39 @@ void Module::LookupInfo::Prune(SymbolContextList &sc_list,
}
// If we have only full name matches we might have tried to set breakpoint on
// "func"
// and specified eFunctionNameTypeFull, but we might have found "a::func()",
// "a::b::func()", "c::func()", "func()" and "func". Only "func()" and "func"
// should
// end up matching.
// "func" and specified eFunctionNameTypeFull, but we might have found
// "a::func()", "a::b::func()", "c::func()", "func()" and "func". Only
// "func()" and "func" should end up matching.
if (m_name_type_mask == eFunctionNameTypeFull) {
SymbolContext sc;
size_t i = start_idx;
while (i < sc_list.GetSize()) {
if (!sc_list.GetContextAtIndex(i, sc))
break;
// Make sure the mangled and demangled names don't match before we try
// to pull anything out
ConstString mangled_name(sc.GetFunctionName(Mangled::ePreferMangled));
ConstString full_name(sc.GetFunctionName());
CPlusPlusLanguage::MethodName cpp_method(full_name);
if (cpp_method.IsValid()) {
if (cpp_method.GetContext().empty()) {
if (cpp_method.GetBasename().compare(m_name.GetStringRef()) != 0) {
sc_list.RemoveContextAtIndex(i);
continue;
}
} else {
std::string qualified_name = cpp_method.GetScopeQualifiedName();
if (qualified_name.compare(m_name.GetCString()) != 0) {
sc_list.RemoveContextAtIndex(i);
continue;
if (mangled_name != m_name && full_name != m_name)
{
CPlusPlusLanguage::MethodName cpp_method(full_name);
if (cpp_method.IsValid()) {
if (cpp_method.GetContext().empty()) {
if (cpp_method.GetBasename().compare(m_name.GetStringRef()) != 0) {
sc_list.RemoveContextAtIndex(i);
continue;
}
} else {
std::string qualified_name;
llvm::StringRef anon_prefix("(anonymous namespace)");
if (cpp_method.GetContext() == anon_prefix)
qualified_name = cpp_method.GetBasename().str();
else
qualified_name = cpp_method.GetScopeQualifiedName();
if (qualified_name.compare(m_name.GetCString()) != 0) {
sc_list.RemoveContextAtIndex(i);
continue;
}
}
}
}

View File

@ -328,6 +328,11 @@ void Symtab::InitNameIndexes() {
} else {
// No context for this function so this has to be a basename
m_basename_to_index.Append(entry);
// If there is no context (no namespaces or class scopes that
// come before the function name) then this also could be a
// fullname.
if (cxx_method.GetContext().empty())
m_name_to_index.Append(entry);
}
}
}