[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