summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTodd Fiala <todd.fiala@gmail.com>2015-10-22 00:23:38 +0000
committerTodd Fiala <todd.fiala@gmail.com>2015-10-22 00:23:38 +0000
commit82ffb8e90495a580b8f2a9248001851a52301e56 (patch)
tree679fb46b0c476be4ac007f60052a26ef4c6f8e9c
parenta8f17871e4ad8c6d49d258e4de9d4cc47900a976 (diff)
downloadbcm5719-llvm-82ffb8e90495a580b8f2a9248001851a52301e56.tar.gz
bcm5719-llvm-82ffb8e90495a580b8f2a9248001851a52301e56.zip
Fix libstdc++ data formatters on Ubuntu 15.10 x86_64
See http://reviews.llvm.org/D13964 for details. llvm-svn: 250965
-rw-r--r--lldb/examples/synthetic/gnu_libstdcpp.py28
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp43
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp115
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h6
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp2
-rw-r--r--lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py26
-rw-r--r--lldb/test/make/Makefile.rules4
7 files changed, 195 insertions, 29 deletions
diff --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py
index 8c11770899f..0daa95f36d0 100644
--- a/lldb/examples/synthetic/gnu_libstdcpp.py
+++ b/lldb/examples/synthetic/gnu_libstdcpp.py
@@ -13,7 +13,7 @@ class StdListSynthProvider:
logger = lldb.formatters.Logger.Logger()
self.valobj = valobj
self.count = None
- logger >> "Providing synthetic children for a map named " + str(valobj.GetName())
+ logger >> "Providing synthetic children for a list named " + str(valobj.GetName())
def next_node(self,node):
logger = lldb.formatters.Logger.Logger()
@@ -21,11 +21,20 @@ class StdListSynthProvider:
def is_valid(self,node):
logger = lldb.formatters.Logger.Logger()
- return self.value(self.next_node(node)) != self.node_address
+ valid = self.value(self.next_node(node)) != self.node_address
+ if valid:
+ logger >> "%s is valid" % str(self.valobj.GetName())
+ else:
+ logger >> "synthetic value is not valid"
+ return valid
def value(self,node):
logger = lldb.formatters.Logger.Logger()
- return node.GetValueAsUnsigned()
+ value = node.GetValueAsUnsigned()
+ logger >> "synthetic value for {}: {}".format(
+ str(self.valobj.GetName()),
+ value)
+ return value
# Floyd's cycle-finding algorithm
# try to detect if this list has a loop
@@ -49,7 +58,12 @@ class StdListSynthProvider:
def num_children(self):
logger = lldb.formatters.Logger.Logger()
- if self.count == None:
+ if self.count is None:
+ # libstdc++ 6.0.21 added dedicated count field.
+ count_child = self.node.GetChildMemberWithName('_M_data')
+ if count_child and count_child.IsValid():
+ self.count = count_child.GetValueAsUnsigned(0)
+ if self.count is None:
self.count = self.num_children_impl()
return self.count
@@ -117,10 +131,10 @@ class StdListSynthProvider:
self.count = None
try:
impl = self.valobj.GetChildMemberWithName('_M_impl')
- node = impl.GetChildMemberWithName('_M_node')
+ self.node = impl.GetChildMemberWithName('_M_node')
self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
- self.next = node.GetChildMemberWithName('_M_next')
- self.prev = node.GetChildMemberWithName('_M_prev')
+ self.next = self.node.GetChildMemberWithName('_M_next')
+ self.prev = self.node.GetChildMemberWithName('_M_prev')
self.data_type = self.extract_type()
self.data_size = self.data_type.GetByteSize()
except:
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index f09e4037890..b5634ec4d24 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -545,7 +545,14 @@ LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
lldb::TypeSummaryImplSP std_string_summary_sp(new StringSummaryFormat(stl_summary_flags,
"${var._M_dataplus._M_p}"));
-
+
+ lldb::TypeSummaryImplSP cxx11_string_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
+ LibStdcppStringSummaryProvider,
+ "libstdc++ c++11 std::string summary provider"));
+ lldb::TypeSummaryImplSP cxx11_wstring_summary_sp(new CXXFunctionSummaryFormat(stl_summary_flags,
+ LibStdcppWStringSummaryProvider,
+ "libstdc++ c++11 std::wstring summary provider"));
+
cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::string"),
std_string_summary_sp);
cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char>"),
@@ -554,7 +561,12 @@ LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
std_string_summary_sp);
cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
std_string_summary_sp);
-
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::string"),
+ cxx11_string_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >"),
+ cxx11_string_summary_sp);
+
// making sure we force-pick the summary for printing wstring (_M_p is a wchar_t*)
lldb::TypeSummaryImplSP std_wstring_summary_sp(new StringSummaryFormat(stl_summary_flags,
"${var._M_dataplus._M_p%S}"));
@@ -567,8 +579,12 @@ LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
std_wstring_summary_sp);
cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
std_wstring_summary_sp);
-
-
+
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::wstring"),
+ cxx11_wstring_summary_sp);
+ cpp_category_sp->GetTypeSummariesContainer()->Add(ConstString("std::__cxx11::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >"),
+ cxx11_wstring_summary_sp);
+
#ifndef LLDB_DISABLE_PYTHON
SyntheticChildren::Flags stl_synth_flags;
@@ -580,9 +596,16 @@ LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdMapSynthProvider")));
- cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
+ SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
+ "lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
+#if 0
+ // With only this, I get std::list showing the content, all children on the same line.
+ // With this and the section below, I see one child element per line.
+ cpp_category_sp->GetRegexTypeSyntheticsContainer()->Add(RegularExpressionSP(new RegularExpression("^std::__cxx11::_List_base<.+>(( )?&)?$")),
SyntheticChildrenSP(new ScriptedSyntheticChildren(stl_synth_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdListSynthProvider")));
+#endif
stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::vector<.+>(( )?&)?$")),
@@ -591,10 +614,16 @@ LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp)
cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::map<.+> >(( )?&)?$")),
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
"size=${svar%#}")));
- cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::list<.+>(( )?&)?$")),
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::(__cxx11::)?list<.+>(( )?&)?$")),
TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
"size=${svar%#}")));
-
+#if 0
+ // With this, I get std::list showing one child per line. Requires the change above to get anything, though.
+ cpp_category_sp->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression("^std::__cxx11::_List_base<.+>(( )?&)?$")),
+ TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags,
+ "size=${svar%#}")));
+#endif
+
AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibStdcppVectorIteratorSyntheticFrontEndCreator, "std::vector iterator synthetic children", ConstString("^__gnu_cxx::__normal_iterator<.+>$"), stl_synth_flags, true);
AddCXXSynthetic(cpp_category_sp, lldb_private::formatters::LibstdcppMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", ConstString("^std::_Rb_tree_iterator<.+>$"), stl_synth_flags, true);
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
index 14f7527d73a..ed89c5c84ea 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
@@ -14,6 +14,7 @@
#include "lldb/Core/Stream.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
+#include "lldb/DataFormatters/StringPrinter.h"
#include "lldb/DataFormatters/VectorIterator.h"
#include "lldb/Host/Endian.h"
#include "lldb/Symbol/ClangASTContext.h"
@@ -256,3 +257,117 @@ lldb_private::formatters::VectorIteratorSyntheticFrontEnd::GetIndexOfChildWithNa
lldb_private::formatters::VectorIteratorSyntheticFrontEnd::~VectorIteratorSyntheticFrontEnd ()
{
}
+
+bool
+lldb_private::formatters::LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const bool scalar_is_load_addr = true;
+ AddressType addr_type;
+ lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+ if (addr_of_string != LLDB_INVALID_ADDRESS)
+ {
+ switch (addr_type)
+ {
+ case eAddressTypeLoad:
+ {
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ Error error;
+ lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
+ if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
+ return false;
+ options.SetLocation(addr_of_data);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetNeedsZeroTermination(false);
+ options.SetBinaryZeroIsTerminator(true);
+ lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
+ if (error.Fail())
+ return false;
+ options.SetSourceSize(size_of_data);
+
+ if (!StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options))
+ {
+ stream.Printf("Summary Unavailable");
+ return true;
+ }
+ else
+ return true;
+ }
+ break;
+ case eAddressTypeHost:
+ break;
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ break;
+ }
+ }
+ return false;
+}
+
+bool
+lldb_private::formatters::LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options)
+{
+ const bool scalar_is_load_addr = true;
+ AddressType addr_type;
+ lldb::addr_t addr_of_string = valobj.GetAddressOf(scalar_is_load_addr, &addr_type);
+ if (addr_of_string != LLDB_INVALID_ADDRESS)
+ {
+ switch (addr_type)
+ {
+ case eAddressTypeLoad:
+ {
+ ProcessSP process_sp(valobj.GetProcessSP());
+ if (!process_sp)
+ return false;
+
+ CompilerType wchar_compiler_type = valobj.GetCompilerType().GetBasicTypeFromAST(lldb::eBasicTypeWChar);
+
+ if (!wchar_compiler_type)
+ return false;
+
+ const uint32_t wchar_size = wchar_compiler_type.GetBitSize(nullptr); // Safe to pass NULL for exe_scope here
+
+ StringPrinter::ReadStringAndDumpToStreamOptions options(valobj);
+ Error error;
+ lldb::addr_t addr_of_data = process_sp->ReadPointerFromMemory(addr_of_string, error);
+ if (error.Fail() || addr_of_data == 0 || addr_of_data == LLDB_INVALID_ADDRESS)
+ return false;
+ options.SetLocation(addr_of_data);
+ options.SetProcessSP(process_sp);
+ options.SetStream(&stream);
+ options.SetNeedsZeroTermination(false);
+ options.SetBinaryZeroIsTerminator(false);
+ lldb::addr_t size_of_data = process_sp->ReadPointerFromMemory(addr_of_string + process_sp->GetAddressByteSize(), error);
+ if (error.Fail())
+ return false;
+ options.SetSourceSize(size_of_data);
+ options.SetPrefixToken("L");
+
+ switch (wchar_size)
+ {
+ case 8:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF8>(options);
+ case 16:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF16>(options);
+ case 32:
+ return StringPrinter::ReadStringAndDumpToStream<StringPrinter::StringElementType::UTF32>(options);
+ default:
+ stream.Printf("size for wchar_t is not valid");
+ return true;
+ }
+ return true;
+ }
+ break;
+ case eAddressTypeHost:
+ break;
+ case eAddressTypeInvalid:
+ case eAddressTypeFile:
+ break;
+ }
+ }
+ return false;
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
index 21b2ea44fc8..347856a1695 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/LibStdcpp.h
@@ -18,6 +18,12 @@
namespace lldb_private {
namespace formatters
{
+ bool
+ LibStdcppStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::string
+
+ bool
+ LibStdcppWStringSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options); // libcstdc++ c++11 std::wstring
+
SyntheticChildrenFrontEnd* LibstdcppMapIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
SyntheticChildrenFrontEnd* LibStdcppVectorIteratorSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp
index 8b872398d4e..6a1266528d5 100644
--- a/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp
+++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp
@@ -15,6 +15,7 @@ typedef std::list<int> int_list;
int main()
{
+#ifdef LLDB_USING_LIBCPP
int_list *numbers_list = new int_list{1,2,3,4,5,6,7,8,9,10};
auto *third_elem = numbers_list->__end_.__next_->__next_->__next_; // Set break point at this line.
@@ -22,6 +23,7 @@ int main()
auto *fifth_elem = third_elem->__next_->__next_;
assert(fifth_elem->__value_ == 5);
fifth_elem->__next_ = third_elem;
+#endif
// Any attempt to free the list will probably crash the program. Let's just leak it.
return 0; // Set second break point at this line.
diff --git a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py
index b34e0e430bf..1a13571c4d6 100644
--- a/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py
+++ b/lldb/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py
@@ -47,21 +47,21 @@ class StdStringDataFormatterTestCase(TestBase):
# Execute the cleanup function during test case tear down.
self.addTearDownHook(cleanup)
- self.expect("frame variable",
- substrs = ['(std::wstring) s = L"hello world! מזל טוב!"',
- '(std::wstring) S = L"!!!!"',
- '(const wchar_t *) mazeltov = 0x','L"מזל טוב"',
- '(std::string) q = "hello world"',
- '(std::string) Q = "quite a long std::strin with lots of info inside it"'])
+ var_s = self.frame().FindVariable('s')
+ var_S = self.frame().FindVariable('S')
+ var_mazeltov = self.frame().FindVariable('mazeltov')
+ var_q = self.frame().FindVariable('q')
+ var_Q = self.frame().FindVariable('Q')
- self.runCmd("n")
+ self.assertTrue(var_s.GetSummary() == 'L"hello world! מזל טוב!"', "s summary wrong")
+ self.assertTrue(var_S.GetSummary() == 'L"!!!!"', "S summary wrong")
+ self.assertTrue(var_mazeltov.GetSummary() == 'L"מזל טוב"', "mazeltov summary wrong")
+ self.assertTrue(var_q.GetSummary() == '"hello world"', "q summary wrong")
+ self.assertTrue(var_Q.GetSummary() == '"quite a long std::strin with lots of info inside it"', "Q summary wrong")
- self.expect("frame variable",
- substrs = ['(std::wstring) s = L"hello world! מזל טוב!"',
- '(std::wstring) S = L"!!!!!"',
- '(const wchar_t *) mazeltov = 0x','L"מזל טוב"',
- '(std::string) q = "hello world"',
- '(std::string) Q = "quite a long std::strin with lots of info inside it"'])
+ self.runCmd("next")
+
+ self.assertTrue(var_S.GetSummary() == 'L"!!!!!"', "new S summary wrong")
if __name__ == '__main__':
import atexit
diff --git a/lldb/test/make/Makefile.rules b/lldb/test/make/Makefile.rules
index 796a7a0453e..e72b2d0931e 100644
--- a/lldb/test/make/Makefile.rules
+++ b/lldb/test/make/Makefile.rules
@@ -296,12 +296,12 @@ ifeq (1,$(USE_LIBCPP))
ifeq "$(OS)" "Linux"
# This is the default install location on Ubuntu 14.04
ifneq ($(wildcard /usr/include/c++/v1/.),)
- CXXFLAGS += -stdlib=libc++
+ CXXFLAGS += -stdlib=libc++ -DLLDB_USING_LIBCPP
LDFLAGS += -stdlib=libc++
CXXFLAGS += -I/usr/include/c++/v1
endif
else
- CXXFLAGS += -stdlib=libc++
+ CXXFLAGS += -stdlib=libc++ -DLLDB_USING_LIBCPP
LDFLAGS += -stdlib=libc++
endif
endif
OpenPOWER on IntegriCloud