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 /lldb/source/Expression/IRForTarget.cpp | |
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
Diffstat (limited to 'lldb/source/Expression/IRForTarget.cpp')
-rw-r--r-- | lldb/source/Expression/IRForTarget.cpp | 51 |
1 files changed, 25 insertions, 26 deletions
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()); |