Fix libstdc++ data formatters on Ubuntu 15.10 x86_64
See http://reviews.llvm.org/D13964 for details. llvm-svn: 250965
This commit is contained in:
parent
a8f17871e4
commit
82ffb8e904
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue