[Lldb-commits] [lldb] r232548 - Implement formatter for std::vector<bool, ...> of libstdc++ in Python.
Siva Chandra
sivachandra at google.com
Tue Mar 17 14:23:18 PDT 2015
Author: sivachandra
Date: Tue Mar 17 16:23:17 2015
New Revision: 232548
URL: http://llvm.org/viewvc/llvm-project?rev=232548&view=rev
Log:
Implement formatter for std::vector<bool, ...> of libstdc++ in Python.
Summary:
The existing formatter in C++ has been removed as it was not being used.
The associated test TestDataFormatterStdVBool.py has been enabled for
both Clang and GCC on Linux.
Test Plan: dotest.py -p TestDataFormatterStdVBool
Reviewers: vharron, clayborg
Reviewed By: clayborg
Subscribers: lldb-commits
Differential Revision: http://reviews.llvm.org/D8390
Modified:
lldb/trunk/examples/synthetic/gnu_libstdcpp.py
lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h
lldb/trunk/source/DataFormatters/LibStdcpp.cpp
lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
Modified: lldb/trunk/examples/synthetic/gnu_libstdcpp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/gnu_libstdcpp.py?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- lldb/trunk/examples/synthetic/gnu_libstdcpp.py (original)
+++ lldb/trunk/examples/synthetic/gnu_libstdcpp.py Tue Mar 17 16:23:17 2015
@@ -137,50 +137,134 @@ class StdListSynthProvider:
class StdVectorSynthProvider:
+ class StdVectorImplementation(object):
+ def __init__(self, valobj):
+ self.valobj = valobj
+ self.count = None
+
+ def num_children(self):
+ if self.count == None:
+ self.count = self.num_children_impl()
+ return self.count
+
+ def num_children_impl(self):
+ try:
+ start_val = self.start.GetValueAsUnsigned(0)
+ finish_val = self.finish.GetValueAsUnsigned(0)
+ end_val = self.end.GetValueAsUnsigned(0)
+ # Before a vector has been constructed, it will contain bad values
+ # so we really need to be careful about the length we return since
+ # unitialized data can cause us to return a huge number. We need
+ # to also check for any of the start, finish or end of storage values
+ # being zero (NULL). If any are, then this vector has not been
+ # initialized yet and we should return zero
+
+ # Make sure nothing is NULL
+ if start_val == 0 or finish_val == 0 or end_val == 0:
+ return 0
+ # Make sure start is less than finish
+ if start_val >= finish_val:
+ return 0
+ # Make sure finish is less than or equal to end of storage
+ if finish_val > end_val:
+ return 0
+
+ # if we have a struct (or other data type that the compiler pads to native word size)
+ # this check might fail, unless the sizeof() we get is itself incremented to take the
+ # padding bytes into account - on current clang it looks like this is the case
+ num_children = (finish_val-start_val)
+ if (num_children % self.data_size) != 0:
+ return 0
+ else:
+ num_children = num_children/self.data_size
+ return num_children
+ except:
+ return 0;
+
+ def get_child_at_index(self, index):
+ logger = lldb.formatters.Logger.Logger()
+ logger >> "Retrieving child " + str(index)
+ if index < 0:
+ return None;
+ if index >= self.num_children():
+ return None;
+ try:
+ offset = index * self.data_size
+ return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
+ except:
+ return None
+
+ def update(self):
+ # preemptively setting this to None - we might end up changing our mind later
+ self.count = None
+ try:
+ impl = self.valobj.GetChildMemberWithName('_M_impl')
+ self.start = impl.GetChildMemberWithName('_M_start')
+ self.finish = impl.GetChildMemberWithName('_M_finish')
+ self.end = impl.GetChildMemberWithName('_M_end_of_storage')
+ self.data_type = self.start.GetType().GetPointeeType()
+ self.data_size = self.data_type.GetByteSize()
+ # if any of these objects is invalid, it means there is no point in trying to fetch anything
+ if self.start.IsValid() and self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid():
+ self.count = None
+ else:
+ self.count = 0
+ except:
+ pass
+ return True
+
+ class StdVBoolImplementation(object):
+ def __init__(self, valobj, bool_type):
+ self.valobj = valobj
+ self.bool_type = bool_type
+ self.valid = False
+
+ def num_children(self):
+ if self.valid:
+ start = self.start_p.GetValueAsUnsigned(0)
+ finish = self.finish_p.GetValueAsUnsigned(0)
+ offset = self.offset.GetValueAsUnsigned(0)
+ if finish >= start:
+ return (finish - start) * 8 + offset
+ return 0
+
+ def get_child_at_index(self, index):
+ if index >= self.num_children():
+ return None
+ byte_offset = index / 8
+ bit_offset = index % 8
+ data = self.start_p.GetPointeeData()
+ bit = data.GetUnsignedInt8(lldb.SBError(), byte_offset) & (1 << bit_offset)
+ if bit != 0:
+ value_expr = "(bool)true"
+ else:
+ value_expr = "(bool)false"
+ return self.valobj.CreateValueFromExpression("[%d]" % index, value_expr)
+
+ def update(self):
+ try:
+ m_impl = self.valobj.GetChildMemberWithName('_M_impl')
+ self.m_start = m_impl.GetChildMemberWithName('_M_start')
+ self.m_finish = m_impl.GetChildMemberWithName('_M_finish')
+ self.start_p = self.m_start.GetChildMemberWithName('_M_p')
+ self.finish_p = self.m_finish.GetChildMemberWithName('_M_p')
+ self.offset = self.m_finish.GetChildMemberWithName('_M_offset')
+ self.valid = True
+ except:
+ self.valid = False
+ return True
+
def __init__(self, valobj, dict):
logger = lldb.formatters.Logger.Logger()
- self.count = None
- self.valobj = valobj
+ first_template_arg_type = valobj.GetType().GetTemplateArgumentType(0)
+ if str(first_template_arg_type.GetName()) == "bool":
+ self.impl = self.StdVBoolImplementation(valobj, first_template_arg_type)
+ else:
+ self.impl = self.StdVectorImplementation(valobj)
logger >> "Providing synthetic children for a vector named " + str(valobj.GetName())
def num_children(self):
- if self.count == None:
- self.count = self.num_children_impl()
- return self.count
-
- def num_children_impl(self):
- try:
- start_val = self.start.GetValueAsUnsigned(0)
- finish_val = self.finish.GetValueAsUnsigned(0)
- end_val = self.end.GetValueAsUnsigned(0)
- # Before a vector has been constructed, it will contain bad values
- # so we really need to be careful about the length we return since
- # unitialized data can cause us to return a huge number. We need
- # to also check for any of the start, finish or end of storage values
- # being zero (NULL). If any are, then this vector has not been
- # initialized yet and we should return zero
-
- # Make sure nothing is NULL
- if start_val == 0 or finish_val == 0 or end_val == 0:
- return 0
- # Make sure start is less than finish
- if start_val >= finish_val:
- return 0
- # Make sure finish is less than or equal to end of storage
- if finish_val > end_val:
- return 0
-
- # if we have a struct (or other data type that the compiler pads to native word size)
- # this check might fail, unless the sizeof() we get is itself incremented to take the
- # padding bytes into account - on current clang it looks like this is the case
- num_children = (finish_val-start_val)
- if (num_children % self.data_size) != 0:
- return 0
- else:
- num_children = num_children/self.data_size
- return num_children
- except:
- return 0;
+ return self.impl.num_children()
def get_child_index(self,name):
try:
@@ -188,37 +272,11 @@ class StdVectorSynthProvider:
except:
return -1
- def get_child_at_index(self,index):
- logger = lldb.formatters.Logger.Logger()
- logger >> "Retrieving child " + str(index)
- if index < 0:
- return None;
- if index >= self.num_children():
- return None;
- try:
- offset = index * self.data_size
- return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
- except:
- return None
+ def get_child_at_index(self, index):
+ return self.impl.get_child_at_index(index)
def update(self):
- # preemptively setting this to None - we might end up changing our mind later
- self.count = None
- try:
- impl = self.valobj.GetChildMemberWithName('_M_impl')
- self.start = impl.GetChildMemberWithName('_M_start')
- self.finish = impl.GetChildMemberWithName('_M_finish')
- self.end = impl.GetChildMemberWithName('_M_end_of_storage')
- self.data_type = self.start.GetType().GetPointeeType()
- self.data_size = self.data_type.GetByteSize()
- # if any of these objects is invalid, it means there is no point in trying to fetch anything
- if self.start.IsValid() and self.finish.IsValid() and self.end.IsValid() and self.data_type.IsValid():
- self.count = None
- else:
- self.count = 0
- except:
- pass
-
+ return self.impl.update()
def has_children(self):
return True
Modified: lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h (original)
+++ lldb/trunk/include/lldb/DataFormatters/CXXFormatterFunctions.h Tue Mar 17 16:23:17 2015
@@ -232,37 +232,6 @@ namespace lldb_private {
bool
LibcxxContainerSummaryProvider (ValueObject& valobj, Stream& stream, const TypeSummaryOptions& options);
- class LibstdcppVectorBoolSyntheticFrontEnd : public SyntheticChildrenFrontEnd
- {
- public:
- LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp);
-
- virtual size_t
- CalculateNumChildren ();
-
- virtual lldb::ValueObjectSP
- GetChildAtIndex (size_t idx);
-
- virtual bool
- Update();
-
- virtual bool
- MightHaveChildren ();
-
- virtual size_t
- GetIndexOfChildWithName (const ConstString &name);
-
- virtual
- ~LibstdcppVectorBoolSyntheticFrontEnd ();
- private:
- ExecutionContextRef m_exe_ctx_ref;
- uint64_t m_count;
- lldb::addr_t m_base_data_address;
- EvaluateExpressionOptions m_options;
- };
-
- SyntheticChildrenFrontEnd* LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP);
-
class LibstdcppMapIteratorSyntheticFrontEnd : public SyntheticChildrenFrontEnd
{
public:
Modified: lldb/trunk/source/DataFormatters/LibStdcpp.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/DataFormatters/LibStdcpp.cpp?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- lldb/trunk/source/DataFormatters/LibStdcpp.cpp (original)
+++ lldb/trunk/source/DataFormatters/LibStdcpp.cpp Tue Mar 17 16:23:17 2015
@@ -25,175 +25,6 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::formatters;
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::LibstdcppVectorBoolSyntheticFrontEnd (lldb::ValueObjectSP valobj_sp) :
-SyntheticChildrenFrontEnd(*valobj_sp.get()),
-m_exe_ctx_ref(),
-m_count(0),
-m_base_data_address(0),
-m_options()
-{
- if (valobj_sp)
- Update();
- m_options.SetCoerceToId(false);
- m_options.SetUnwindOnError(true);
- m_options.SetKeepInMemory(true);
- m_options.SetUseDynamic(lldb::eDynamicCanRunTarget);
-}
-
-size_t
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::CalculateNumChildren ()
-{
- return m_count;
-}
-
-lldb::ValueObjectSP
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetChildAtIndex (size_t idx)
-{
- if (idx >= m_count)
- return ValueObjectSP();
- if (m_base_data_address == 0 || m_count == 0)
- return ValueObjectSP();
- size_t byte_idx = (idx >> 3); // divide by 8 to get byte index
- size_t bit_index = (idx & 7); // efficient idx % 8 for bit index
- lldb::addr_t byte_location = m_base_data_address + byte_idx;
- ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
- if (!process_sp)
- return ValueObjectSP();
- uint8_t byte = 0;
- uint8_t mask = 0;
- Error err;
- size_t bytes_read = process_sp->ReadMemory(byte_location, &byte, 1, err);
- if (err.Fail() || bytes_read == 0)
- return ValueObjectSP();
- switch (bit_index)
- {
- case 0:
- mask = 1; break;
- case 1:
- mask = 2; break;
- case 2:
- mask = 4; break;
- case 3:
- mask = 8; break;
- case 4:
- mask = 16; break;
- case 5:
- mask = 32; break;
- case 6:
- mask = 64; break;
- case 7:
- mask = 128; break;
- default:
- return ValueObjectSP();
- }
- bool bit_set = ((byte & mask) != 0);
- Target& target(process_sp->GetTarget());
- ValueObjectSP retval_sp;
- if (bit_set)
- target.EvaluateExpression("(bool)true", NULL, retval_sp);
- else
- target.EvaluateExpression("(bool)false", NULL, retval_sp);
- StreamString name; name.Printf("[%" PRIu64 "]", (uint64_t)idx);
- if (retval_sp)
- retval_sp->SetName(ConstString(name.GetData()));
- return retval_sp;
-}
-
-/*((std::vector<std::allocator<bool> >) vBool = {
- (std::_Bvector_base<std::allocator<bool> >) std::_Bvector_base<std::allocator<bool> > = {
- (std::_Bvector_base<std::allocator<bool> >::_Bvector_impl) _M_impl = {
- (std::_Bit_iterator) _M_start = {
- (std::_Bit_iterator_base) std::_Bit_iterator_base = {
- (_Bit_type *) _M_p = 0x0016b160
- (unsigned int) _M_offset = 0
- }
- }
- (std::_Bit_iterator) _M_finish = {
- (std::_Bit_iterator_base) std::_Bit_iterator_base = {
- (_Bit_type *) _M_p = 0x0016b16c
- (unsigned int) _M_offset = 16
- }
- }
- (_Bit_type *) _M_end_of_storage = 0x0016b170
- }
- }
- }
- */
-
-bool
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::Update()
-{
- ValueObjectSP valobj_sp = m_backend.GetSP();
- if (!valobj_sp)
- return false;
- if (!valobj_sp)
- return false;
- m_exe_ctx_ref = valobj_sp->GetExecutionContextRef();
-
- ValueObjectSP m_impl_sp(valobj_sp->GetChildMemberWithName(ConstString("_M_impl"), true));
- if (!m_impl_sp)
- return false;
-
- ValueObjectSP m_start_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_start"), true));
- ValueObjectSP m_finish_sp(m_impl_sp->GetChildMemberWithName(ConstString("_M_finish"), true));
-
- ValueObjectSP start_p_sp, finish_p_sp, finish_offset_sp;
-
- if (!m_start_sp || !m_finish_sp)
- return false;
-
- start_p_sp = m_start_sp->GetChildMemberWithName(ConstString("_M_p"), true);
- finish_p_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_p"), true);
- finish_offset_sp = m_finish_sp->GetChildMemberWithName(ConstString("_M_offset"), true);
-
- if (!start_p_sp || !finish_offset_sp || !finish_p_sp)
- return false;
-
- m_base_data_address = start_p_sp->GetValueAsUnsigned(0);
- if (!m_base_data_address)
- return false;
-
- lldb::addr_t end_data_address(finish_p_sp->GetValueAsUnsigned(0));
- if (!end_data_address)
- return false;
-
- if (end_data_address < m_base_data_address)
- return false;
- else
- m_count = finish_offset_sp->GetValueAsUnsigned(0) + (end_data_address-m_base_data_address)*8;
-
- return true;
-}
-
-bool
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::MightHaveChildren ()
-{
- return true;
-}
-
-size_t
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::GetIndexOfChildWithName (const ConstString &name)
-{
- if (!m_count || !m_base_data_address)
- return UINT32_MAX;
- const char* item_name = name.GetCString();
- uint32_t idx = ExtractIndexFromString(item_name);
- if (idx < UINT32_MAX && idx >= CalculateNumChildren())
- return UINT32_MAX;
- return idx;
-}
-
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEnd::~LibstdcppVectorBoolSyntheticFrontEnd ()
-{}
-
-SyntheticChildrenFrontEnd*
-lldb_private::formatters::LibstdcppVectorBoolSyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp)
-{
- if (!valobj_sp)
- return NULL;
- return (new LibstdcppVectorBoolSyntheticFrontEnd(valobj_sp));
-}
-
/*
(std::_Rb_tree_iterator<std::pair<const int, std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >) ibeg = {
(_Base_ptr) _M_node = 0x0000000100103910 {
Modified: lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py?rev=232548&r1=232547&r2=232548&view=diff
==============================================================================
--- lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py (original)
+++ lldb/trunk/test/functionalities/data-formatter/data-formatter-stl/libstdcpp/vbool/TestDataFormatterStdVBool.py Tue Mar 17 16:23:17 2015
@@ -21,10 +21,6 @@ class StdVBoolDataFormatterTestCase(Test
self.data_formatter_commands()
@expectedFailureFreeBSD("llvm.org/pr20548") # fails to build on lab.llvm.org buildbot
- @expectedFailureLinux # non-core functionality, need to reenable and fix
- # later (DES 2014.11.07). Most likely failing because
- # of mis-match is version of libstdc++ supported by
- # the data-formatters.
@dwarf_test
@skipIfWindows # http://llvm.org/pr21800
@skipIfDarwin
@@ -39,7 +35,6 @@ class StdVBoolDataFormatterTestCase(Test
# Find the line number to break at.
self.line = line_number('main.cpp', '// Set break point at this line.')
- @expectedFailureGcc # llvm.org/pr15301: lldb does not print the correct sizes of STL containers when building with GCC
@expectedFailureIcc # llvm.org/pr15301: lldb does not print the correct sizes of STL containers when building with ICC
def data_formatter_commands(self):
"""Test that that file and class static variables display correctly."""
More information about the lldb-commits
mailing list