[Lldb-commits] [lldb] r250965 - Fix libstdc++ data formatters on Ubuntu 15.10 x86_64
Todd Fiala via lldb-commits
lldb-commits at lists.llvm.org
Wed Oct 21 17:23:39 PDT 2015
Author: tfiala
Date: Wed Oct 21 19:23:38 2015
New Revision: 250965
URL: http://llvm.org/viewvc/llvm-project?rev=250965&view=rev
Log:
Fix libstdc++ data formatters on Ubuntu 15.10 x86_64
See http://reviews.llvm.org/D13964 for details.
Modified:
lldb/trunk/examples/synthetic/gnu_libstdcpp.py
lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py
lldb/trunk/test/make/Makefile.rules
Modified: lldb/trunk/examples/synthetic/gnu_libstdcpp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/gnu_libstdcpp.py?rev=250965&r1=250964&r2=250965&view=diff
==============================================================================
--- lldb/trunk/examples/synthetic/gnu_libstdcpp.py (original)
+++ lldb/trunk/examples/synthetic/gnu_libstdcpp.py Wed Oct 21 19:23:38 2015
@@ -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:
Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp?rev=250965&r1=250964&r2=250965&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp Wed Oct 21 19:23:38 2015
@@ -545,7 +545,14 @@ LoadLibStdcppFormatters(lldb::TypeCatego
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::TypeCatego
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::TypeCatego
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::TypeCatego
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::TypeCatego
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);
Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp?rev=250965&r1=250964&r2=250965&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.cpp Wed Oct 21 19:23:38 2015
@@ -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::VectorIterator
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;
+}
Modified: lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h?rev=250965&r1=250964&r2=250965&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h (original)
+++ lldb/trunk/source/Plugins/Language/CPlusPlus/LibStdcpp.h Wed Oct 21 19:23:38 2015
@@ -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);
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp?rev=250965&r1=250964&r2=250965&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libcxx/list/loop/main.cpp Wed Oct 21 19:23:38 2015
@@ -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.
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py?rev=250965&r1=250964&r2=250965&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/string/TestDataFormatterStdString.py Wed Oct 21 19:23:38 2015
@@ -47,21 +47,21 @@ class StdStringDataFormatterTestCase(Tes
# 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
Modified: lldb/trunk/test/make/Makefile.rules
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/make/Makefile.rules?rev=250965&r1=250964&r2=250965&view=diff
==============================================================================
--- lldb/trunk/test/make/Makefile.rules (original)
+++ lldb/trunk/test/make/Makefile.rules Wed Oct 21 19:23:38 2015
@@ -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
More information about the lldb-commits
mailing list