1import lldb
2import lldb.formatters.Logger
3
4# libcxx STL formatters for LLDB
5# These formatters are based upon the implementation of libc++ that
6# ships with current releases of OS X - They will not work for other implementations
7# of the standard C++ library - and they are bound to use the libc++-specific namespace
8
9# the std::string summary is just an example for your convenience
10# the actual summary that LLDB uses is C++ code inside the debugger's own core
11
12# this could probably be made more efficient but since it only reads a handful of bytes at a time
13# we probably don't need to worry too much about this for the time being
14def make_string(F,L):
15	strval = ''
16	G = F.GetData().uint8
17	for X in range(L):
18		V = G[X]
19		if V == 0:
20			break
21		strval = strval + chr(V % 256)
22	return '"' + strval + '"'
23
24# if we ever care about big-endian, these two functions might need to change
25def is_short_string(value):
26	return True if (value & 1) == 0 else False
27def extract_short_size(value):
28	return ((value >> 1) % 256)
29
30# some of the members of libc++ std::string are anonymous or have internal names that convey
31# no external significance - we access them by index since this saves a name lookup that would add
32# no information for readers of the code, but when possible try to use meaningful variable names
33def stdstring_SummaryProvider(valobj,dict):
34	logger = lldb.formatters.Logger.Logger()
35	r = valobj.GetChildAtIndex(0)
36	B = r.GetChildAtIndex(0)
37	first = B.GetChildAtIndex(0)
38	D = first.GetChildAtIndex(0)
39	l = D.GetChildAtIndex(0)
40	s = D.GetChildAtIndex(1)
41	D20 = s.GetChildAtIndex(0)
42	size_mode = D20.GetChildAtIndex(0).GetValueAsUnsigned(0)
43	if is_short_string(size_mode):
44		size = extract_short_size(size_mode)
45		return make_string(s.GetChildAtIndex(1),size)
46	else:
47		data_ptr = l.GetChildAtIndex(2)
48		size_vo = l.GetChildAtIndex(1)
49		size = size_vo.GetValueAsUnsigned(0)+1 # the NULL terminator must be accounted for
50		if size <= 1 or size == None: # should never be the case
51			return '""'
52		try:
53			data = data_ptr.GetPointeeData(0,size)
54		except:
55			return '""'
56		error = lldb.SBError()
57		strval = data.GetString(error,0)
58		if error.Fail():
59			return '<error:' + error.GetCString() + '>'
60		else:
61			return '"' + strval + '"'
62
63class stdvector_SynthProvider:
64
65	def __init__(self, valobj, dict):
66		logger = lldb.formatters.Logger.Logger()
67		self.valobj = valobj;
68
69	def num_children(self):
70		logger = lldb.formatters.Logger.Logger()
71		try:
72			start_val = self.start.GetValueAsUnsigned(0)
73			finish_val = self.finish.GetValueAsUnsigned(0)
74			# Before a vector has been constructed, it will contain bad values
75			# so we really need to be careful about the length we return since
76			# unitialized data can cause us to return a huge number. We need
77			# to also check for any of the start, finish or end of storage values
78			# being zero (NULL). If any are, then this vector has not been
79			# initialized yet and we should return zero
80
81			# Make sure nothing is NULL
82			if start_val == 0 or finish_val == 0:
83				return 0
84			# Make sure start is less than finish
85			if start_val >= finish_val:
86				return 0
87
88			num_children = (finish_val-start_val)
89			if (num_children % self.data_size) != 0:
90				return 0
91			else:
92				num_children = num_children/self.data_size
93			return num_children
94		except:
95			return 0;
96
97	def get_child_index(self,name):
98		logger = lldb.formatters.Logger.Logger()
99		try:
100			return int(name.lstrip('[').rstrip(']'))
101		except:
102			return -1
103
104	def get_child_at_index(self,index):
105		logger = lldb.formatters.Logger.Logger()
106		logger >> "Retrieving child " + str(index)
107		if index < 0:
108			return None;
109		if index >= self.num_children():
110			return None;
111		try:
112			offset = index * self.data_size
113			return self.start.CreateChildAtOffset('['+str(index)+']',offset,self.data_type)
114		except:
115			return None
116
117	def update(self):
118		logger = lldb.formatters.Logger.Logger()
119		try:
120			self.start = self.valobj.GetChildMemberWithName('__begin_')
121			self.finish = self.valobj.GetChildMemberWithName('__end_')
122			# the purpose of this field is unclear, but it is the only field whose type is clearly T* for a vector<T>
123			# if this ends up not being correct, we can use the APIs to get at template arguments
124			data_type_finder = self.valobj.GetChildMemberWithName('__end_cap_').GetChildMemberWithName('__first_')
125			self.data_type = data_type_finder.GetType().GetPointeeType()
126			self.data_size = self.data_type.GetByteSize()
127		except:
128			pass
129
130	def has_children(self):
131		return True
132
133# Just an example: the actual summary is produced by a summary string: size=${svar%#}
134def stdvector_SummaryProvider(valobj,dict):
135	prov = stdvector_SynthProvider(valobj,None)
136	return 'size=' + str(prov.num_children())
137
138class stdlist_entry:
139
140	def __init__(self,entry):
141		logger = lldb.formatters.Logger.Logger()
142		self.entry = entry
143
144	def _next_impl(self):
145		logger = lldb.formatters.Logger.Logger()
146		return stdlist_entry(self.entry.GetChildMemberWithName('__next_'))
147
148	def _prev_impl(self):
149		logger = lldb.formatters.Logger.Logger()
150		return stdlist_entry(self.entry.GetChildMemberWithName('__prev_'))
151
152	def _value_impl(self):
153		logger = lldb.formatters.Logger.Logger()
154		return self.entry.GetValueAsUnsigned(0)
155
156	def _isnull_impl(self):
157		logger = lldb.formatters.Logger.Logger()
158		return self._value_impl() == 0
159
160	def _sbvalue_impl(self):
161		logger = lldb.formatters.Logger.Logger()
162		return self.entry
163
164	next = property(_next_impl,None)
165	value = property(_value_impl,None)
166	is_null = property(_isnull_impl,None)
167	sbvalue = property(_sbvalue_impl,None)
168
169class stdlist_iterator:
170
171	def increment_node(self,node):
172		logger = lldb.formatters.Logger.Logger()
173		if node.is_null:
174			return None
175		return node.next
176
177	def __init__(self,node):
178		logger = lldb.formatters.Logger.Logger()
179		self.node = stdlist_entry(node) # we convert the SBValue to an internal node object on entry
180
181	def value(self):
182		logger = lldb.formatters.Logger.Logger()
183		return self.node.sbvalue # and return the SBValue back on exit
184
185	def next(self):
186		logger = lldb.formatters.Logger.Logger()
187		node = self.increment_node(self.node)
188		if node != None and node.sbvalue.IsValid() and not(node.is_null):
189			self.node = node
190			return self.value()
191		else:
192			return None
193
194	def advance(self,N):
195		logger = lldb.formatters.Logger.Logger()
196		if N < 0:
197			return None
198		if N == 0:
199			return self.value()
200		if N == 1:
201			return self.next()
202		while N > 0:
203			self.next()
204			N = N - 1
205		return self.value()
206
207
208class stdlist_SynthProvider:
209	def __init__(self, valobj, dict):
210		logger = lldb.formatters.Logger.Logger()
211		self.valobj = valobj
212		self.count = None
213
214	def next_node(self,node):
215		logger = lldb.formatters.Logger.Logger()
216		return node.GetChildMemberWithName('__next_')
217
218	def value(self,node):
219		logger = lldb.formatters.Logger.Logger()
220		return node.GetValueAsUnsigned()
221
222	# Floyd's cyle-finding algorithm
223	# try to detect if this list has a loop
224	def has_loop(self):
225		global _list_uses_loop_detector
226		logger = lldb.formatters.Logger.Logger()
227		if _list_uses_loop_detector == False:
228			logger >> "Asked not to use loop detection"
229			return False
230		slow = stdlist_entry(self.head)
231		fast1 = stdlist_entry(self.head)
232		fast2 = stdlist_entry(self.head)
233		while slow.next.value != self.node_address:
234			slow_value = slow.value
235			fast1 = fast2.next
236			fast2 = fast1.next
237			if fast1.value == slow_value or fast2.value == slow_value:
238				return True
239			slow = slow.next
240		return False
241
242	def num_children(self):
243		global _list_capping_size
244		logger = lldb.formatters.Logger.Logger()
245		if self.count == None:
246			self.count = self.num_children_impl()
247			if self.count > _list_capping_size:
248				self.count = _list_capping_size
249		return self.count
250
251	def num_children_impl(self):
252		global _list_capping_size
253		logger = lldb.formatters.Logger.Logger()
254		try:
255			next_val = self.head.GetValueAsUnsigned(0)
256			prev_val = self.tail.GetValueAsUnsigned(0)
257			# After a std::list has been initialized, both next and prev will be non-NULL
258			if next_val == 0 or prev_val == 0:
259				return 0
260			if next_val == self.node_address:
261				return 0
262			if next_val == prev_val:
263				return 1
264			if self.has_loop():
265				return 0
266			size = 2
267			current = stdlist_entry(self.head)
268			while current.next.value != self.node_address:
269				size = size + 1
270				current = current.next
271				if size > _list_capping_size:
272					return _list_capping_size
273			return (size - 1)
274		except:
275			return 0;
276
277	def get_child_index(self,name):
278		logger = lldb.formatters.Logger.Logger()
279		try:
280			return int(name.lstrip('[').rstrip(']'))
281		except:
282			return -1
283
284	def get_child_at_index(self,index):
285		logger = lldb.formatters.Logger.Logger()
286		logger >> "Fetching child " + str(index)
287		if index < 0:
288			return None;
289		if index >= self.num_children():
290			return None;
291		try:
292			current = stdlist_iterator(self.head)
293			current = current.advance(index)
294			# we do not return __value_ because then all our children would be named __value_
295			# we need to make a copy of __value__ with the right name - unfortunate
296			obj = current.GetChildMemberWithName('__value_')
297			obj_data = obj.GetData()
298			return self.valobj.CreateValueFromData('[' + str(index) + ']',obj_data,self.data_type)
299		except:
300			return None
301
302	def extract_type(self):
303		logger = lldb.formatters.Logger.Logger()
304		list_type = self.valobj.GetType().GetUnqualifiedType()
305		if list_type.IsReferenceType():
306			list_type = list_type.GetDereferencedType()
307		if list_type.GetNumberOfTemplateArguments() > 0:
308			data_type = list_type.GetTemplateArgumentType(0)
309		else:
310			data_type = None
311		return data_type
312
313	def update(self):
314		logger = lldb.formatters.Logger.Logger()
315		self.count = None
316		try:
317			impl = self.valobj.GetChildMemberWithName('__end_')
318			self.node_address = self.valobj.AddressOf().GetValueAsUnsigned(0)
319			self.head = impl.GetChildMemberWithName('__next_')
320			self.tail = impl.GetChildMemberWithName('__prev_')
321			self.data_type = self.extract_type()
322			self.data_size = self.data_type.GetByteSize()
323		except:
324			pass
325
326	def has_children(self):
327		return True
328
329
330# Just an example: the actual summary is produced by a summary string: size=${svar%#}
331def stdlist_SummaryProvider(valobj,dict):
332	prov = stdlist_SynthProvider(valobj,None)
333	return 'size=' + str(prov.num_children())
334
335# a tree node - this class makes the syntax in the actual iterator nicer to read and maintain
336class stdmap_iterator_node:
337	def _left_impl(self):
338		logger = lldb.formatters.Logger.Logger()
339		return stdmap_iterator_node(self.node.GetChildMemberWithName("__left_"))
340
341	def _right_impl(self):
342		logger = lldb.formatters.Logger.Logger()
343		return stdmap_iterator_node(self.node.GetChildMemberWithName("__right_"))
344
345	def _parent_impl(self):
346		logger = lldb.formatters.Logger.Logger()
347		return stdmap_iterator_node(self.node.GetChildMemberWithName("__parent_"))
348
349	def _value_impl(self):
350		logger = lldb.formatters.Logger.Logger()
351		return self.node.GetValueAsUnsigned(0)
352
353	def _sbvalue_impl(self):
354		logger = lldb.formatters.Logger.Logger()
355		return self.node
356
357	def _null_impl(self):
358		logger = lldb.formatters.Logger.Logger()
359		return self.value == 0
360
361	def __init__(self,node):
362		logger = lldb.formatters.Logger.Logger()
363		self.node = node
364
365	left = property(_left_impl,None)
366	right = property(_right_impl,None)
367	parent = property(_parent_impl,None)
368	value = property(_value_impl,None)
369	is_null = property(_null_impl,None)
370	sbvalue = property(_sbvalue_impl,None)
371
372# a Python implementation of the tree iterator used by libc++
373class stdmap_iterator:
374
375	def tree_min(self,x):
376		logger = lldb.formatters.Logger.Logger()
377		steps = 0
378		if x.is_null:
379			return None
380		while (not x.left.is_null):
381			x = x.left
382			steps += 1
383			if steps > self.max_count:
384				logger >> "Returning None - we overflowed"
385				return None
386		return x
387
388	def tree_max(self,x):
389		logger = lldb.formatters.Logger.Logger()
390		if x.is_null:
391			return None
392		while (not x.right.is_null):
393			x =  x.right
394		return x
395
396	def tree_is_left_child(self,x):
397		logger = lldb.formatters.Logger.Logger()
398		if x.is_null:
399			return None
400		return True if x.value == x.parent.left.value else False
401
402	def increment_node(self,node):
403		logger = lldb.formatters.Logger.Logger()
404		if node.is_null:
405			return None
406		if not node.right.is_null:
407			return self.tree_min(node.right)
408		steps = 0
409		while (not self.tree_is_left_child(node)):
410			steps += 1
411			if steps > self.max_count:
412				logger >> "Returning None - we overflowed"
413				return None
414			node = node.parent
415		return node.parent
416
417	def __init__(self,node,max_count=0):
418		logger = lldb.formatters.Logger.Logger()
419		self.node = stdmap_iterator_node(node) # we convert the SBValue to an internal node object on entry
420		self.max_count = max_count
421
422	def value(self):
423		logger = lldb.formatters.Logger.Logger()
424		return self.node.sbvalue # and return the SBValue back on exit
425
426	def next(self):
427		logger = lldb.formatters.Logger.Logger()
428		node = self.increment_node(self.node)
429		if node != None and node.sbvalue.IsValid() and not(node.is_null):
430			self.node = node
431			return self.value()
432		else:
433			return None
434
435	def advance(self,N):
436		logger = lldb.formatters.Logger.Logger()
437		if N < 0:
438			return None
439		if N == 0:
440			return self.value()
441		if N == 1:
442			return self.next()
443		while N > 0:
444			if self.next() == None:
445				return None
446			N = N - 1
447		return self.value()
448
449class stdmap_SynthProvider:
450
451	def __init__(self, valobj, dict):
452		logger = lldb.formatters.Logger.Logger()
453		self.valobj = valobj;
454		self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
455		self.count = None
456
457	def update(self):
458		logger = lldb.formatters.Logger.Logger()
459		self.count = None
460		try:
461			# we will set this to True if we find out that discovering a node in the map takes more steps than the overall size of the RB tree
462			# if this gets set to True, then we will merrily return None for any child from that moment on
463			self.garbage = False
464			self.tree = self.valobj.GetChildMemberWithName('__tree_')
465			self.root_node = self.tree.GetChildMemberWithName('__begin_node_')
466			# this data is either lazily-calculated, or cannot be inferred at this moment
467			# we still need to mark it as None, meaning "please set me ASAP"
468			self.data_type = None
469			self.data_size = None
470			self.skip_size = None
471		except:
472			pass
473
474	def num_children(self):
475		global _map_capping_size
476		logger = lldb.formatters.Logger.Logger()
477		if self.count == None:
478			self.count = self.num_children_impl()
479			if self.count > _map_capping_size:
480				self.count = _map_capping_size
481		return self.count
482
483	def num_children_impl(self):
484		logger = lldb.formatters.Logger.Logger()
485		try:
486			return self.valobj.GetChildMemberWithName('__tree_').GetChildMemberWithName('__pair3_').GetChildMemberWithName('__first_').GetValueAsUnsigned()
487		except:
488			return 0;
489
490	def has_children(self):
491		return True
492
493	def get_data_type(self):
494		logger = lldb.formatters.Logger.Logger()
495		if self.data_type == None or self.data_size == None:
496			if self.num_children() == 0:
497				return False
498			deref = self.root_node.Dereference()
499			if not(deref.IsValid()):
500				return False
501			value = deref.GetChildMemberWithName('__value_')
502			if not(value.IsValid()):
503				return False
504			self.data_type = value.GetType()
505			self.data_size = self.data_type.GetByteSize()
506			self.skip_size = None
507			return True
508		else:
509			return True
510
511	def get_value_offset(self,node):
512		logger = lldb.formatters.Logger.Logger()
513		if self.skip_size == None:
514			node_type = node.GetType()
515			fields_count = node_type.GetNumberOfFields()
516			for i in range(fields_count):
517				field = node_type.GetFieldAtIndex(i)
518				if field.GetName() == '__value_':
519					self.skip_size = field.GetOffsetInBytes()
520					break
521		return (self.skip_size != None)
522
523	def get_child_index(self,name):
524		logger = lldb.formatters.Logger.Logger()
525		try:
526			return int(name.lstrip('[').rstrip(']'))
527		except:
528			return -1
529
530	def get_child_at_index(self,index):
531		logger = lldb.formatters.Logger.Logger()
532		logger >> "Retrieving child " + str(index)
533		if index < 0:
534			return None
535		if index >= self.num_children():
536			return None;
537		if self.garbage:
538			logger >> "Returning None since this tree is garbage"
539			return None
540		try:
541			iterator = stdmap_iterator(self.root_node,max_count=self.num_children())
542			# the debug info for libc++ std::map is such that __begin_node_ has a very nice and useful type
543			# out of which we can grab the information we need - every other node has a less informative
544			# type which omits all value information and only contains housekeeping information for the RB tree
545			# hence, we need to know if we are at a node != 0, so that we can still get at the data
546			need_to_skip = (index > 0)
547			current = iterator.advance(index)
548			if current == None:
549				logger >> "Tree is garbage - returning None"
550				self.garbage = True
551				return None
552			if self.get_data_type():
553				if not(need_to_skip):
554					current = current.Dereference()
555					obj = current.GetChildMemberWithName('__value_')
556					obj_data = obj.GetData()
557					self.get_value_offset(current) # make sure we have a valid offset for the next items
558					# we do not return __value_ because then we would end up with a child named
559					# __value_ instead of [0]
560					return self.valobj.CreateValueFromData('[' + str(index) + ']',obj_data,self.data_type)
561				else:
562					# FIXME we need to have accessed item 0 before accessing any other item!
563					if self.skip_size == None:
564						logger >> "You asked for item > 0 before asking for item == 0, I will fetch 0 now then retry"
565						if self.get_child_at_index(0):
566							return self.get_child_at_index(index)
567						else:
568							logger >> "item == 0 could not be found. sorry, nothing can be done here."
569							return None
570					return current.CreateChildAtOffset('[' + str(index) + ']',self.skip_size,self.data_type)
571			else:
572				logger >> "Unable to infer data-type - returning None (should mark tree as garbage here?)"
573				return None
574		except Exception as err:
575			logger >> "Hit an exception: " + str(err)
576			return None
577
578# Just an example: the actual summary is produced by a summary string: size=${svar%#}
579def stdmap_SummaryProvider(valobj,dict):
580	prov = stdmap_SynthProvider(valobj,None)
581	return 'size=' + str(prov.num_children())
582
583class stddeque_SynthProvider:
584    def __init__(self, valobj, d):
585        logger = lldb.formatters.Logger.Logger()
586        logger.write("init")
587        self.valobj = valobj
588        self.pointer_size = self.valobj.GetProcess().GetAddressByteSize()
589        self.count = None
590        try:
591            self.find_block_size()
592        except:
593            self.block_size = -1
594            self.element_size = -1
595        logger.write("block_size=%d, element_size=%d" % (self.block_size, self.element_size))
596
597    def find_block_size(self):
598        # in order to use the deque we must have the block size, or else
599        # it's impossible to know what memory addresses are valid
600        self.element_type = self.valobj.GetType().GetTemplateArgumentType(0)
601        self.element_size = self.element_type.GetByteSize()
602        # The code says this, but there must be a better way:
603        # template <class _Tp, class _Allocator>
604        # class __deque_base {
605        #    static const difference_type __block_size = sizeof(value_type) < 256 ? 4096 / sizeof(value_type) : 16;
606        # }
607        if self.element_size < 256:
608            self.block_size =  4096 / self.element_size
609        else:
610            self.block_size = 16
611
612    def num_children(self):
613        global _deque_capping_size
614        logger = lldb.formatters.Logger.Logger()
615        if self.count is None:
616            return 0
617        return min(self.count, _deque_capping_size)
618
619    def has_children(self):
620        return True
621
622    def get_child_index(self,name):
623        logger = lldb.formatters.Logger.Logger()
624        try:
625            return int(name.lstrip('[').rstrip(']'))
626        except:
627            return -1
628
629    def get_child_at_index(self,index):
630        logger = lldb.formatters.Logger.Logger()
631        logger.write("Fetching child " + str(index))
632        if index < 0 or self.count is None:
633                return None;
634        if index >= self.num_children():
635                return None;
636        try:
637            i, j = divmod(self.start+index, self.block_size)
638            return self.first.CreateValueFromExpression('[' + str(index) + ']',
639                                                        '*(*(%s + %d) + %d)' % (self.first.get_expr_path(), i, j))
640        except:
641            return None
642
643    def update(self):
644        logger = lldb.formatters.Logger.Logger()
645        try:
646            # A deque is effectively a two-dim array, with fixed width.
647            # 'map' contains pointers to the rows of this array. The
648            # full memory area allocated by the deque is delimited
649            # by 'first' and 'end_cap'. However, only a subset of this
650            # memory contains valid data since a deque may have some slack
651            # at the front and back in order to have O(1) insertion at
652            # both ends. The rows in active use are delimited by
653            # 'begin' and 'end'.
654            #
655            # To find the elements that are actually constructed, the 'start'
656            # variable tells which element in this NxM array is the 0th
657            # one, and the 'size' element gives the number of elements
658            # in the deque.
659            count = self.valobj.GetChildMemberWithName('__size_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
660            # give up now if we cant access memory reliably
661            if self.block_size < 0:
662                logger.write("block_size < 0")
663                return
664            map_ = self.valobj.GetChildMemberWithName('__map_')
665            start = self.valobj.GetChildMemberWithName('__start_').GetValueAsUnsigned(0)
666            first = map_.GetChildMemberWithName('__first_')
667            map_first = first.GetValueAsUnsigned(0)
668            map_begin = map_.GetChildMemberWithName('__begin_').GetValueAsUnsigned(0)
669            map_end   = map_.GetChildMemberWithName('__end_').GetValueAsUnsigned(0)
670            map_endcap= map_.GetChildMemberWithName('__end_cap_').GetChildMemberWithName('__first_').GetValueAsUnsigned(0)
671            # check consistency
672            if not map_first <= map_begin <= map_end <= map_endcap:
673                logger.write("map pointers are not monotonic")
674                return
675            total_rows, junk = divmod(map_endcap - map_first, self.pointer_size)
676            if junk:
677                logger.write("endcap-first doesnt align correctly")
678                return
679            active_rows, junk = divmod(map_end - map_begin, self.pointer_size)
680            if junk:
681                logger.write("end-begin doesnt align correctly")
682                return
683            start_row, junk = divmod(map_begin - map_first, self.pointer_size)
684            if junk:
685                logger.write("begin-first doesnt align correctly")
686                return
687            if not start_row*self.block_size <= start < (start_row+1)*self.block_size:
688                logger.write("0th element must be in the 'begin' row")
689                return
690            end_row = start_row + active_rows
691            if not count:
692                if active_rows:
693                    logger.write("empty deque but begin!=end")
694                    return
695            elif not (end_row-1)*self.block_size <= start+count < end_row*self.block_size:
696                logger.write("nth element must be before the 'end' row")
697                return
698            logger.write("update success: count=%r, start=%r, first=%r" % (count,start,first))
699            # if consistent, save all we really need:
700            self.count = count
701            self.start = start
702            self.first = first
703        except:
704            self.count = None
705            self.start = None
706            self.map_first = None
707            self.map_begin = None
708
709class stdsharedptr_SynthProvider:
710    def __init__(self, valobj, d):
711        logger = lldb.formatters.Logger.Logger()
712        logger.write("init")
713        self.valobj = valobj
714        #self.element_ptr_type = self.valobj.GetType().GetTemplateArgumentType(0).GetPointerType()
715        self.ptr = None
716        self.cntrl = None
717        process = valobj.GetProcess()
718        self.endianness = process.GetByteOrder()
719        self.pointer_size = process.GetAddressByteSize()
720        self.count_type = valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
721
722    def num_children(self):
723        return 1
724
725    def has_children(self):
726        return True
727
728    def get_child_index(self,name):
729        if name=="__ptr_":
730            return 0
731        if name=="count":
732            return 1
733        if name=="weak_count":
734            return 2
735        return -1
736
737    def get_child_at_index(self,index):
738        if index == 0:
739            return self.ptr
740        if index == 1:
741            if self.cntrl == None:
742                count = 0
743            else:
744                count = 1 + self.cntrl.GetChildMemberWithName('__shared_owners_').GetValueAsSigned()
745            return self.valobj.CreateValueFromData("count",
746                                                   lldb.SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [count]),
747                                                   self.count_type)
748        if index == 2:
749            if self.cntrl == None:
750                count = 0
751            else:
752                count = 1 + self.cntrl.GetChildMemberWithName('__shared_weak_owners_').GetValueAsSigned()
753            return self.valobj.CreateValueFromData("weak_count",
754                                                   lldb.SBData.CreateDataFromUInt64Array(self.endianness, self.pointer_size, [count]),
755                                                   self.count_type)
756        return None
757
758    def update(self):
759        logger = lldb.formatters.Logger.Logger()
760        self.ptr = self.valobj.GetChildMemberWithName('__ptr_')#.Cast(self.element_ptr_type)
761        cntrl = self.valobj.GetChildMemberWithName('__cntrl_')
762        if cntrl.GetValueAsUnsigned(0):
763            self.cntrl = cntrl.Dereference()
764        else:
765            self.cntrl = None
766
767# we can use two different categories for old and new formatters - type names are different enough that we should make no confusion
768# 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"
769def __lldb_init_module(debugger,dict):
770	debugger.HandleCommand('type summary add -F libcxx.stdstring_SummaryProvider "std::__1::string" -w libcxx')
771	debugger.HandleCommand('type summary add -F libcxx.stdstring_SummaryProvider "std::__1::basic_string<char, class std::__1::char_traits<char>, class std::__1::allocator<char> >" -w libcxx')
772	debugger.HandleCommand('type synthetic add -l libcxx.stdvector_SynthProvider -x "^(std::__1::)vector<.+>$" -w libcxx')
773	debugger.HandleCommand('type summary add -F libcxx.stdvector_SummaryProvider -e -x "^(std::__1::)vector<.+>$" -w libcxx')
774	debugger.HandleCommand('type synthetic add -l libcxx.stdlist_SynthProvider -x "^(std::__1::)list<.+>$" -w libcxx')
775	debugger.HandleCommand('type summary add -F libcxx.stdlist_SummaryProvider -e -x "^(std::__1::)list<.+>$" -w libcxx')
776	debugger.HandleCommand('type synthetic add -l libcxx.stdmap_SynthProvider -x "^(std::__1::)map<.+> >$" -w libcxx')
777	debugger.HandleCommand('type summary add -F libcxx.stdmap_SummaryProvider -e -x "^(std::__1::)map<.+> >$" -w libcxx')
778	debugger.HandleCommand("type category enable libcxx")
779	debugger.HandleCommand('type synthetic add -l libcxx.stddeque_SynthProvider -x "^(std::__1::)deque<.+>$" -w libcxx')
780	debugger.HandleCommand('type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)shared_ptr<.+>$" -w libcxx')
781	# turns out the structs look the same, so weak_ptr can be handled the same!
782	debugger.HandleCommand('type synthetic add -l libcxx.stdsharedptr_SynthProvider -x "^(std::__1::)weak_ptr<.+>$" -w libcxx')
783
784_map_capping_size = 255
785_list_capping_size = 255
786_list_uses_loop_detector = True
787_deque_capping_size = 255
788