diff options
Diffstat (limited to 'lldb')
| -rw-r--r-- | lldb/examples/synthetic/gnu_libstdcpp.py | 2 | ||||
| -rw-r--r-- | lldb/examples/synthetic/libcxx.py | 189 | ||||
| -rw-r--r-- | lldb/source/Core/FormatManager.cpp | 20 | 
3 files changed, 206 insertions, 5 deletions
diff --git a/lldb/examples/synthetic/gnu_libstdcpp.py b/lldb/examples/synthetic/gnu_libstdcpp.py index 2d2801a5833..c08a42c6063 100644 --- a/lldb/examples/synthetic/gnu_libstdcpp.py +++ b/lldb/examples/synthetic/gnu_libstdcpp.py @@ -3,7 +3,7 @@ import lldb.formatters.Logger  # 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 diff --git a/lldb/examples/synthetic/libcxx.py b/lldb/examples/synthetic/libcxx.py index 99f4c0e650c..cffb3fc2f11 100644 --- a/lldb/examples/synthetic/libcxx.py +++ b/lldb/examples/synthetic/libcxx.py @@ -44,9 +44,12 @@ def stdstring_SummaryProvider(valobj,dict):  		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 @@ def stdmap_SummaryProvider(valobj,dict):  	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 @@ def __lldb_init_module(debugger,dict):  	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 diff --git a/lldb/source/Core/FormatManager.cpp b/lldb/source/Core/FormatManager.cpp index c35c0b3cd26..fb2441d7ae9 100644 --- a/lldb/source/Core/FormatManager.cpp +++ b/lldb/source/Core/FormatManager.cpp @@ -796,14 +796,30 @@ FormatManager::LoadLibcxxFormatters()      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  }  | 

