diff options
author | Siva Chandra <sivachandra@google.com> | 2015-04-09 18:48:34 +0000 |
---|---|---|
committer | Siva Chandra <sivachandra@google.com> | 2015-04-09 18:48:34 +0000 |
commit | 0f404e057501728e819a8955c893fb4b772ba97f (patch) | |
tree | 0f3630849d40921eea8787cb51d442366e2c9c90 | |
parent | 10821e5283fd190c8ff38dcad8b5e2a2fcdc4e5a (diff) | |
download | bcm5719-llvm-0f404e057501728e819a8955c893fb4b772ba97f.tar.gz bcm5719-llvm-0f404e057501728e819a8955c893fb4b772ba97f.zip |
[IRForTarget] Strenghten handling of alternate mangling.
Summary:
This fixes an issue with GCC generated binaries wherein an expression
with method invocations on std::string variables was failing. Such use
cases are tested in TestSTL (albeit, in a test marked with
@unittest2.expectedFailure because of other reasons).
The reason for this particular failure with GCC is that the generated
DWARF for std::basic_string<...> is incomplete, which makes clang not
to use the alternate mangling scheme. GCC correctly generates the name
of basic_string<...>:
DW_AT_name "basic_string<char, std::char_traits<char>, std::allocator<char> >"
It also lists the template parameters of basic_string correctly:
DW_TAG_template_type_parameter
DW_AT_name "_CharT"
DW_AT_type <0x0000009c>
DW_TAG_template_type_parameter
DW_AT_name "_Traits"
DW_AT_type <0x00000609>
DW_TAG_template_type_parameter
DW_AT_name "_Alloc"
DW_AT_type <0x000007fb>
However, it does not list the template parameters of std::char_traits<>.
This makes Clang feel (while parsing the expression) that the string
variable is not actually a basic_string instance, and consequently does
not use the alternate mangling scheme.
Test Plan:
dotest.py -C gcc -p TestSTL
-- See it go past the "for" loop expression successfully.
Reviewers: clayborg, spyffe
Reviewed By: clayborg, spyffe
Subscribers: tberghammer, zturner, lldb-commits
Differential Revision: http://reviews.llvm.org/D8846
llvm-svn: 234522
4 files changed, 79 insertions, 26 deletions
diff --git a/lldb/include/lldb/Target/CPPLanguageRuntime.h b/lldb/include/lldb/Target/CPPLanguageRuntime.h index 43df9e67add..3e51453566b 100644 --- a/lldb/include/lldb/Target/CPPLanguageRuntime.h +++ b/lldb/include/lldb/Target/CPPLanguageRuntime.h @@ -153,6 +153,9 @@ public: static uint32_t FindEquivalentNames(ConstString type_name, std::vector<ConstString>& equivalents); + virtual size_t + GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) = 0; + protected: //------------------------------------------------------------------ // Classes that inherit from CPPLanguageRuntime can see and modify these diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index f5cfb782c48..210ba65f665 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -35,6 +35,7 @@ #include "lldb/Host/Endian.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangASTType.h" +#include "lldb/Target/CPPLanguageRuntime.h" #include <map> @@ -226,44 +227,42 @@ IRForTarget::GetFunctionAddress (llvm::Function *fun, { if (!m_decl_map->GetFunctionInfo (fun_decl, fun_addr)) { - lldb_private::ConstString altnernate_name; + std::vector<lldb_private::ConstString> alternates; bool found_it = m_decl_map->GetFunctionAddress (name, fun_addr); if (!found_it) { - // Check for an alternate mangling for "std::basic_string<char>" - // that is part of the itanium C++ name mangling scheme - const char *name_cstr = name.GetCString(); - if (name_cstr && strncmp(name_cstr, "_ZNKSbIcE", strlen("_ZNKSbIcE")) == 0) + if (log) + log->Printf("Address of function \"%s\" not found.\n", name.GetCString()); + // Check for an alternate mangling for names from the standard library. + // For example, "std::basic_string<...>" has an alternate mangling scheme per + // the Itanium C++ ABI. + lldb::ProcessSP process_sp = m_data_allocator.GetTarget()->GetProcessSP(); + lldb_private::CPPLanguageRuntime *cpp_runtime = process_sp->GetCPPLanguageRuntime(); + if (cpp_runtime && cpp_runtime->GetAlternateManglings(name, alternates)) { - std::string alternate_mangling("_ZNKSs"); - alternate_mangling.append (name_cstr + strlen("_ZNKSbIcE")); - altnernate_name.SetCString(alternate_mangling.c_str()); - found_it = m_decl_map->GetFunctionAddress (altnernate_name, fun_addr); + for (size_t i = 0; i < alternates.size(); ++i) + { + const lldb_private::ConstString &alternate_name = alternates[i]; + if (log) + log->Printf("Looking up address of function \"%s\" with alternate name \"%s\"", + name.GetCString(), alternate_name.GetCString()); + if ((found_it = m_decl_map->GetFunctionAddress (alternate_name, fun_addr))) + { + if (log) + log->Printf("Found address of function \"%s\" with alternate name \"%s\"", + name.GetCString(), alternate_name.GetCString()); + break; + } + } } } if (!found_it) { lldb_private::Mangled mangled_name(name); - lldb_private::Mangled alt_mangled_name(altnernate_name); - if (log) - { - if (alt_mangled_name) - log->Printf("Function \"%s\" (alternate name \"%s\") has no address", - mangled_name.GetName().GetCString(), - alt_mangled_name.GetName().GetCString()); - else - log->Printf("Function \"%s\" had no address", - mangled_name.GetName().GetCString()); - } - if (m_error_stream) { - if (alt_mangled_name) - m_error_stream->Printf("error: call to a function '%s' (alternate name '%s') that is not present in the target\n", - mangled_name.GetName().GetCString(), - alt_mangled_name.GetName().GetCString()); - else if (mangled_name.GetMangledName()) + if (mangled_name.GetMangledName()) m_error_stream->Printf("error: call to a function '%s' ('%s') that is not present in the target\n", mangled_name.GetName().GetCString(), mangled_name.GetMangledName().GetCString()); diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp index 50537eb119f..5712b208855 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.cpp @@ -281,9 +281,43 @@ ItaniumABILanguageRuntime::IsVTableName (const char *name) return false; } +size_t +ItaniumABILanguageRuntime::GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates) +{ + if (!mangled) + return static_cast<size_t>(0); + + alternates.clear(); + const char *mangled_cstr = mangled.AsCString(); + for (typename std::map<ConstString, std::vector<ConstString> >::iterator it = s_alternate_mangling_prefixes.begin(); + it != s_alternate_mangling_prefixes.end(); + ++it) + { + const char *prefix_cstr = it->first.AsCString(); + if (strncmp(mangled_cstr, prefix_cstr, strlen(prefix_cstr)) == 0) + { + const std::vector<ConstString> &alternate_prefixes = it->second; + for (size_t i = 0; i < alternate_prefixes.size(); ++i) + { + std::string alternate_mangling(alternate_prefixes[i].AsCString()); + alternate_mangling.append(mangled_cstr + strlen(prefix_cstr)); + + alternates.push_back(ConstString(alternate_mangling.c_str())); + } + + return alternates.size(); + } + } + + return static_cast<size_t>(0); +} + //------------------------------------------------------------------ // Static Functions //------------------------------------------------------------------ + +std::map<ConstString, std::vector<ConstString> > ItaniumABILanguageRuntime::s_alternate_mangling_prefixes; + LanguageRuntime * ItaniumABILanguageRuntime::CreateInstance (Process *process, lldb::LanguageType language) { @@ -304,6 +338,15 @@ ItaniumABILanguageRuntime::Initialize() PluginManager::RegisterPlugin (GetPluginNameStatic(), "Itanium ABI for the C++ language", CreateInstance); + + // Alternate manglings for std::basic_string<...> + std::vector<ConstString> basic_string_alternates; + basic_string_alternates.push_back(ConstString("_ZNSs")); + basic_string_alternates.push_back(ConstString("_ZNKSs")); + s_alternate_mangling_prefixes[ConstString("_ZNSbIcSt17char_traits<char>St15allocator<char>E")] = + basic_string_alternates; + s_alternate_mangling_prefixes[ConstString("_ZNKSbIcSt17char_traits<char>St15allocator<char>E")] = + basic_string_alternates; } void diff --git a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h index cd0a4b2c15e..d1dbb7ad407 100644 --- a/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/CPlusPlus/ItaniumABI/ItaniumABILanguageRuntime.h @@ -20,6 +20,9 @@ #include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Core/Value.h" +#include <map> +#include <vector> + namespace lldb_private { class ItaniumABILanguageRuntime : @@ -82,6 +85,9 @@ namespace lldb_private { virtual lldb::SearchFilterSP CreateExceptionSearchFilter (); + virtual size_t + GetAlternateManglings(const ConstString &mangled, std::vector<ConstString> &alternates); + protected: lldb::BreakpointResolverSP @@ -97,6 +103,8 @@ namespace lldb_private { ItaniumABILanguageRuntime(Process *process) : lldb_private::CPPLanguageRuntime(process) { } // Call CreateInstance instead. lldb::BreakpointSP m_cxx_exception_bp_sp; + + static std::map<ConstString, std::vector<ConstString> > s_alternate_mangling_prefixes; }; } // namespace lldb_private |