[Lldb-commits] [lldb] r162680 - in /lldb/trunk: examples/synthetic/gnu_libstdcpp.py examples/synthetic/libcxx.py source/Core/FormatManager.cpp

Enrico Granata egranata at apple.com
Mon Aug 27 10:42:51 PDT 2012


Author: enrico
Date: Mon Aug 27 12:42:50 2012
New Revision: 162680

URL: http://llvm.org/viewvc/llvm-project?rev=162680&view=rev
Log:
Data formatters for libc++ deque and shared/weak ptrs - a contribution by Jared Grubb

Modified:
    lldb/trunk/examples/synthetic/gnu_libstdcpp.py
    lldb/trunk/examples/synthetic/libcxx.py
    lldb/trunk/source/Core/FormatManager.cpp

Modified: lldb/trunk/examples/synthetic/gnu_libstdcpp.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/gnu_libstdcpp.py?rev=162680&r1=162679&r2=162680&view=diff
==============================================================================
--- lldb/trunk/examples/synthetic/gnu_libstdcpp.py (original)
+++ lldb/trunk/examples/synthetic/gnu_libstdcpp.py Mon Aug 27 12:42:50 2012
@@ -3,7 +3,7 @@
 
 # C++ STL formatters for LLDB
 # These formatters are based upon the version of the GNU libstdc++
-# as it ships with Mac OS X 10.6.8 thru 10.7.3
+# as it ships with Mac OS X 10.6.8 thru 10.8.0
 # You are encouraged to look at the STL implementation for your platform
 # before relying on these formatters to do the right thing for your setup
 

Modified: lldb/trunk/examples/synthetic/libcxx.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/synthetic/libcxx.py?rev=162680&r1=162679&r2=162680&view=diff
==============================================================================
--- lldb/trunk/examples/synthetic/libcxx.py (original)
+++ lldb/trunk/examples/synthetic/libcxx.py Mon Aug 27 12:42:50 2012
@@ -44,9 +44,12 @@
 		data_ptr = l.GetChildAtIndex(2)
 		size_vo = l.GetChildAtIndex(1)
 		size = size_vo.GetValueAsUnsigned(0)+1 # the NULL terminator must be accounted for
-		if size <= 1: # should never be the case
+		if size <= 1 or size == None: # should never be the case
+			return '""'
+		try:
+			data = data_ptr.GetPointeeData(0,size)
+		except:
 			return '""'
-		data = data_ptr.GetPointeeData(0,size)
 		error = lldb.SBError()
 		strval = data.GetString(error,0)
 		if error.Fail():
@@ -558,6 +561,183 @@
 	prov = stdmap_SynthProvider(valobj,None)
 	return 'size=' + str(prov.num_children())
 
+class stddeque_SynthProvider:
+    def __init__(self, valobj, d):
+        logger = lldb.formatters.Logger.Logger()
+        logger.write("init")
+        self.valobj = valobj
+        self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
+        self.count = None
+        try:
+            self.find_block_size()
+        except:
+            self.block_size = -1
+            self.element_size = -1
+        logger.write("block_size=%d, element_size=%d" % (self.block_size, self.element_size))
+
+    def find_block_size(self):
+        # in order to use the deque we must have the block size, or else
+        # it's impossible to know what memory addresses are valid
+        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
+        self.element_size = self.element_type.GetByteSize()
+        # The code says this, but there must be a better way:
+        # template <class _Tp, class _Allocator>
+        # class __deque_base {
+        #    static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16;
+        # }
+        if self.element_size < 256:
+            self.block_size =  4096 / self.element_size
+        else:
+            self.block_size = 16
+
+    def num_children(self):
+        global _deque_capping_size
+        logger = lldb.formatters.Logger.Logger()
+        if self.count is None:
+            return 0
+        return min(self.count, _deque_capping_size)
+
+    def get_child_index(self,name):
+        logger = lldb.formatters.Logger.Logger()
+        try:
+            return int(name.lstrip('[').rstrip(']'))
+        except:
+            return -1
+
+    def get_child_at_index(self,index):
+        logger = lldb.formatters.Logger.Logger()
+        logger.write("Fetching child " + str(index))
+        if index < 0 or self.count is None:
+                return None;
+        if index >= self.num_children():
+                return None;
+        try:
+            i, j = divmod(self.start+index, self.block_size)
+            return self.first.CreateValueFromExpression('[' + str(index) + ']',
+                                                        '*(*(%s + %d) + %d)' % (self.first.get_expr_path(), i, j))
+        except:
+            return None
+
+    def update(self):
+        logger = lldb.formatters.Logger.Logger()
+        try:
+            # A deque is effectively a two-dim array, with fixed width.
+            # 'map' contains pointers to the rows of this array. The
+            # full memory area allocated by the deque is delimited
+            # by 'first' and 'end_cap'. However, only a subset of this
+            # memory contains valid data since a deque may have some slack
+            # at the front and back in order to have O(1) insertion at
+            # both ends. The rows in active use are delimited by
+            # 'begin' and 'end'.
+            #
+            # To find the elements that are actually constructed, the 'start'
+            # variable tells which element in this NxM array is the 0th
+            # one, and the 'size' element gives the number of elements
+            # in the deque.
+            count = self.valobj.GetChildMemberWithName('__size_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
+            # give up now if we cant access memory reliably
+            if self.block_size < 0:
+                logger.write("block_size < 0")
+                return
+            map_ = self.valobj.GetChildMemberWithName('__map_')
+            start = self.valobj.GetChildMemberWithName('__start_').GetValueAsUnsigned(0)
+            first = map_.GetChildMemberWithName('__first_')
+            map_first = first.GetValueAsUnsigned(0)
+            map_begin = map_.GetChildMemberWithName('__begin_').GetValueAsUnsigned(0)
+            map_end   = map_.GetChildMemberWithName('__end_').GetValueAsUnsigned(0)
+            map_endcap= map_.GetChildMemberWithName('__end_cap_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
+            # check consistency
+            if not map_first <= map_begin <= map_end <= map_endcap:
+                logger.write("map pointers are not monotonic")
+                return
+            total_rows, junk = divmod(map_endcap - map_first, self.pointer_size)
+            if junk:
+                logger.write("endcap-first doesnt align correctly")
+                return
+            active_rows, junk = divmod(map_end - map_begin, self.pointer_size)
+            if junk:
+                logger.write("end-begin doesnt align correctly")
+                return
+            start_row, junk = divmod(map_begin - map_first, self.pointer_size)
+            if junk:
+                logger.write("begin-first doesnt align correctly")
+                return
+            if not start_row*self.block_size <= start < (start_row+1)*self.block_size:
+                logger.write("0th element must be in the 'begin' row")
+                return
+            end_row = start_row + active_rows
+            if not count:
+                if active_rows:
+                    logger.write("empty deque but begin!=end")
+                    return                            
+            elif not (end_row-1)*self.block_size <= start+count < end_row*self.block_size:
+                logger.write("nth element must be before the 'end' row")
+                return
+            logger.write("update success: count=%r, start=%r, first=%r" % (count,start,first))
+            # if consistent, save all we really need:
+            self.count = count
+            self.start = start
+            self.first = first
+        except:
+            self.count = None
+            self.start = None
+            self.map_first = None
+            self.map_begin = None
+
+class stdsharedptr_SynthProvider:
+    def __init__(self, valobj, d):
+        logger = lldb.formatters.Logger.Logger()
+        logger.write("init")
+        self.valobj = valobj
+        #self.element_ptr_type = self.valobj.GetType().GetTemplateArgumentType(0).GetPointerType()
+        self.ptr = None
+        self.cntrl = None
+        process = valobj.GetProcess()
+        self.endianness = process.GetByteOrder()
+        self.pointer_size = process.GetAddressByteSize()
+        self.count_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
+
+    def num_children(self):
+        return 1
+
+    def get_child_index(self,name):
+        if name=="__ptr_":
+            return 0
+        if name=="count":
+            return 1
+        if name=="weak_count":
+            return 2
+        return -1
+
+    def get_child_at_index(self,index):
+        if index == 0:
+            return self.ptr
+        if index == 1:
+            if self.cntrl == None:
+                count = 0
+            else:
+                count = 1 + self.cntrl.GetChildMemberWithName('__shared_owners_').GetValueAsSigned()
+            return self.valobj.CreateValueFromData("count",
+                                                   lldb.SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [count]),
+                                                   self.count_type)
+        if index == 2:
+            if self.cntrl == None:
+                count = 0
+            else:
+                count = 1 + self.cntrl.GetChildMemberWithName('__shared_weak_owners_').GetValueAsSigned()
+            return self.valobj.CreateValueFromData("weak_count",
+                                                   lldb.SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [count]),
+                                                   self.count_type)
+        return None
+
+    def update(self):
+        logger = lldb.formatters.Logger.Logger()
+        self.ptr = self.valobj.GetChildMemberWithName('__ptr_')#.Cast(self.element_ptr_type)
+        cntrl = self.valobj.GetChildMemberWithName('__cntrl_')
+        if cntrl.GetValueAsUnsigned(0):
+            self.cntrl = cntrl.Dereference()
+        else:
+            self.cntrl = None
 
 # we can use two different categories for old and new formatters - type names are different enough that we should make no confusion
 # talking with libc++ developer: "std::__1::class_name is set in stone until we decide to change the ABI. That shouldn't happen within a 5 year time frame"
@@ -571,7 +751,12 @@
 	debugger.HandleCommand('type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
 	debugger.HandleCommand('type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
 	debugger.HandleCommand("type category enable libcxx")
+	debugger.HandleCommand('type synthetic add -l libcxx.stddeque_SynthProvider -x "^(std::__1::)deque<.+>$" -w libcxx')
+	debugger.HandleCommand('type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)shared_ptr<.+>$" -w libcxx')
+	# turns out the structs look the same, so weak_ptr can be handled the same!
+	debugger.HandleCommand('type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)weak_ptr<.+>$" -w libcxx')
 
 _map_capping_size = 255
 _list_capping_size = 255
 _list_uses_loop_detector = True
+_deque_capping_size = 255

Modified: lldb/trunk/source/Core/FormatManager.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/FormatManager.cpp?rev=162680&r1=162679&r2=162680&view=diff
==============================================================================
--- lldb/trunk/source/Core/FormatManager.cpp (original)
+++ lldb/trunk/source/Core/FormatManager.cpp Mon Aug 27 12:42:50 2012
@@ -796,14 +796,30 @@
     libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::map<.+> >(( )?&)?$")),
                                                        SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
                                                                                                  "lldb.formatters.cpp.libcxx.stdmap_SynthProvider")));
+    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)deque<.+>(( )?&)?$")),
+                                                          SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
+                                                                                                    "lldb.formatters.cpp.libcxx.stddeque_SynthProvider")));
+    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)shared_ptr<.+>(( )?&)?$")),
+                                                          SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
+                                                                                                    "lldb.formatters.cpp.libcxx.stdsharedptr_SynthProvider")));
+    libcxx_category_sp->GetRegexSyntheticNavigator()->Add(RegularExpressionSP(new RegularExpression("^(std::__1::)weak_ptr<.+>(( )?&)?$")),
+                                                          SyntheticChildrenSP(new TypeSyntheticImpl(stl_synth_flags,
+                                                                                                    "lldb.formatters.cpp.libcxx.stdsharedptr_SynthProvider")));
     
-    stl_summary_flags.SetDontShowChildren(false);
-    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::vector<.+>(( )?&)?")),
+    stl_summary_flags.SetDontShowChildren(false);stl_summary_flags.SetSkipPointers(true);
+    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::vector<.+>(( )?&)?$")),
                                                         TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
     libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::list<.+>(( )?&)?$")),
                                                         TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
     libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::map<.+> >(( )?&)?$")),
                                                         TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
+    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::deque<.+>(( )?&)?$")),
+                                                        TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "size=${svar%#}")));
+    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::shared_ptr<.+>(( )?&)?$")),
+                                                        TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})")));
+    libcxx_category_sp->GetRegexSummaryNavigator()->Add(RegularExpressionSP(new RegularExpression("^std::__1::weak_ptr<.+>(( )?&)?$")),
+                                                        TypeSummaryImplSP(new StringSummaryFormat(stl_summary_flags, "{${var.__ptr_%S}} (strong=${var.count} weak=${var.weak_count})")));
+
 #endif
 }
 





More information about the lldb-commits mailing list