CFBitVector.py revision f2a84671ff78bee1f82b60698f3ee9791585f8ac
1de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# summary provider for CF(Mutable)BitVector
2de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport lldb
3de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport ctypes
4de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport objc_runtime
5de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport metrics
6de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
7de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# first define some utility functions
8de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef byte_index(abs_pos):
9de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return abs_pos/8
10de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
11de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef bit_index(abs_pos):
12de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return abs_pos & 7
13de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
14de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef get_bit(byte,index):
15de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if index < 0 or index > 7:
16de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return None
17de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return (byte >> (7-index)) & 1
18de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
19de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef grab_array_item_data(pointer,index):
20de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return pointer.GetPointeeData(index,1)
21de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
22de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics = metrics.Metrics()
23de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('invalid_isa')
24de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('invalid_pointer')
25de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('unknown_class')
26de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('code_notrun')
27de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
28de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# despite the similary to synthetic children providers, these classes are not
29de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# trying to provide anything but a summary for a CF*BitVector, so they need not
30de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# obey the interface specification for synthetic children providers
31de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataclass CFBitVectorKnown_SummaryProvider:
32de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def adjust_for_architecture(self):
33f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()
34f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
35de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
36de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def __init__(self, valobj, params):
37de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.valobj = valobj;
38de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.sys_params = params
39f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.NSUInteger):
40f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			if self.sys_params.is_64_bit:
41f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
42f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			else:
43f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
44f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.charptr):
45f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.charptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
46de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.update();
47de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
48de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def update(self):
49de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.adjust_for_architecture();
50de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
51de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# we skip the CFRuntimeBase
52de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# then the next CFIndex is the count
53de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# then we skip another CFIndex and then we get at a byte array
54de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# that wraps the individual bits
55de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
56de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def contents(self):
57f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		count_vo = self.valobj.CreateChildAtOffset("count",self.sys_params.cfruntime_size,
58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata													self.sys_params.types_cache.NSUInteger)
59de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		count = count_vo.GetValueAsUnsigned(0)
60de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		if count == 0:
61de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			return '(empty)'
62de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
63de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		array_vo = self.valobj.CreateChildAtOffset("data",
64f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata													self.sys_params.cfruntime_size+2*self.uiint_size,
65f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata													self.sys_params.types_cache.charptr)
66de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
67de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		data_list = []
68de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		cur_byte_pos = None
69de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		for i in range(0,count):
70de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			if cur_byte_pos == None:
71de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				cur_byte_pos = byte_index(i)
72de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
73de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				cur_byte_val = cur_byte.uint8[0]
74de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			else:
75de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				byte_pos = byte_index(i)
76de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				# do not fetch the pointee data every single time through
77de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				if byte_pos != cur_byte_pos:
78de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata					cur_byte_pos = byte_pos
79de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata					cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
80de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata					cur_byte_val = cur_byte.uint8[0]
81de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			bit = get_bit(cur_byte_val,bit_index(i))
82de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			if (i % 4) == 0:
83de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				data_list.append(' ')
84de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			if bit == 1:
85de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				data_list.append('1')
86de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			else:
87de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				data_list.append('0')
88de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return ''.join(data_list)
89de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
90de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
91de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataclass CFBitVectorUnknown_SummaryProvider:
92de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def adjust_for_architecture(self):
93f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
94de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
95f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, params):
96de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.valobj = valobj;
97f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
98f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.update();
99de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
100de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def update(self):
101de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.adjust_for_architecture();
102de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
103de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def contents(self):
104de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return '*** unknown class *** very bad thing *** find out my name ***'
105de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
106de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
107de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef GetSummary_Impl(valobj):
108de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	global statistics
109de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	class_data = objc_runtime.ObjCRuntime(valobj)
110de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if class_data.is_valid() == False:
111de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		statistics.metric_hit('invalid_pointer',valobj)
112de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		wrapper = None
113de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return
114de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	class_data = class_data.read_class_data()
115de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if class_data.is_valid() == False:
116de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		statistics.metric_hit('invalid_isa',valobj)
117de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		wrapper = None
118de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return
119de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if class_data.is_kvo():
120de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		class_data = class_data.get_superclass()
121de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if class_data.is_valid() == False:
122de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		statistics.metric_hit('invalid_isa',valobj)
123de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		wrapper = None
124de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return
125de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
126de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	name_string = class_data.class_name()
127de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if name_string == '__NSCFType':
128de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		# CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is
129de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		# an NSCFType and then check we are a pointer-to CFBitVectorRef
130de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		valobj_type = valobj.GetType()
131de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		if valobj_type.IsValid() and valobj_type.IsPointerType():
132de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			pointee_type = valobj_type.GetPointeeType()
133de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			if pointee_type.GetName() == '__CFBitVector' or pointee_type.GetName() == '__CFMutableBitVector':
134de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params)
135de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				statistics.metric_hit('code_notrun',valobj)
136de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			else:
137de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				wrapper = CFBitVectorUnknown_SummaryProvider(valobj)
138de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				print pointee_type.GetName()
139de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	else:
140f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
141de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		print name_string
142de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
143de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return wrapper;
144de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
145de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef CFBitVector_SummaryProvider (valobj,dict):
146de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	provider = GetSummary_Impl(valobj);
147de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if provider != None:
148de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	    #try:
149de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	    summary = provider.contents();
150de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	    #except:
151de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	    #    summary = None
152de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	    if summary == None or summary == '':
153de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	        summary = 'no valid bitvector here'
154de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	    return summary
155de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return ''
156de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
157de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef __lldb_init_module(debugger,dict):
158de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	debugger.HandleCommand("type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef")
159