1579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata"""
2579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico GranataLLDB AppKit formatters
3579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata
4579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granatapart of The LLVM Compiler Infrastructure
5579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico GranataThis file is distributed under the University of Illinois Open Source
6579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico GranataLicense. See LICENSE.TXT for details.
7579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata"""
8de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# summary provider for CF(Mutable)BitVector
9de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport lldb
10de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport ctypes
110d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.runtime.objc.objc_runtime
120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.metrics
130d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.Logger
14de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
15de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# first define some utility functions
16de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef byte_index(abs_pos):
170d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
18de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return abs_pos/8
19de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
20de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef bit_index(abs_pos):
210d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
22de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return abs_pos & 7
23de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
24de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef get_bit(byte,index):
250d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
26de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if index < 0 or index > 7:
27de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return None
28de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return (byte >> (7-index)) & 1
29de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
30de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef grab_array_item_data(pointer,index):
310d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
32de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return pointer.GetPointeeData(index,1)
33de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
340d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granatastatistics = lldb.formatters.metrics.Metrics()
35de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('invalid_isa')
36de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('invalid_pointer')
37de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('unknown_class')
38de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('code_notrun')
39de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
40de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# despite the similary to synthetic children providers, these classes are not
41de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# trying to provide anything but a summary for a CF*BitVector, so they need not
42de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# obey the interface specification for synthetic children providers
43de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataclass CFBitVectorKnown_SummaryProvider:
44de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def adjust_for_architecture(self):
450d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
46f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()
47f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
48de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
49de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def __init__(self, valobj, params):
500d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
51de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.valobj = valobj;
52de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.sys_params = params
53f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.NSUInteger):
54f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			if self.sys_params.is_64_bit:
55f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
56f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			else:
57f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.charptr):
59f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.charptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
60de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.update();
61de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
62de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def update(self):
630d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
64de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.adjust_for_architecture();
65de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
66de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# we skip the CFRuntimeBase
67de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# then the next CFIndex is the count
68de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# then we skip another CFIndex and then we get at a byte array
69de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	# that wraps the individual bits
70de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
71de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def contents(self):
720d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
73f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		count_vo = self.valobj.CreateChildAtOffset("count",self.sys_params.cfruntime_size,
74f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata													self.sys_params.types_cache.NSUInteger)
75de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		count = count_vo.GetValueAsUnsigned(0)
76de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		if count == 0:
77de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			return '(empty)'
78de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
79de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		array_vo = self.valobj.CreateChildAtOffset("data",
80f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata													self.sys_params.cfruntime_size+2*self.uiint_size,
81f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata													self.sys_params.types_cache.charptr)
82de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
83de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		data_list = []
84de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		cur_byte_pos = None
85de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		for i in range(0,count):
86de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			if cur_byte_pos == None:
87de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				cur_byte_pos = byte_index(i)
88de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
89de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				cur_byte_val = cur_byte.uint8[0]
90de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			else:
91de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				byte_pos = byte_index(i)
92de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				# do not fetch the pointee data every single time through
93de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				if byte_pos != cur_byte_pos:
94de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata					cur_byte_pos = byte_pos
95de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata					cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
96de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata					cur_byte_val = cur_byte.uint8[0]
97de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			bit = get_bit(cur_byte_val,bit_index(i))
98de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			if (i % 4) == 0:
99de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				data_list.append(' ')
100de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			if bit == 1:
101de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				data_list.append('1')
102de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata			else:
103de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata				data_list.append('0')
104de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		return ''.join(data_list)
105de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
106de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
107de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataclass CFBitVectorUnknown_SummaryProvider:
108de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def adjust_for_architecture(self):
109f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
110de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
111f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, params):
1120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
113de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.valobj = valobj;
114f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
115f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.update();
116de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
117de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def update(self):
1180d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
119de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		self.adjust_for_architecture();
120de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
121de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	def contents(self):
1220d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
123579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return '<unable to summarize this CFBitVector>'
124de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
125de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
126de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef GetSummary_Impl(valobj):
1270d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
128de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	global statistics
129a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata	class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
130579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	if wrapper:
131579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return wrapper
132de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
133de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	name_string = class_data.class_name()
134579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	actual_name = name_string
1358f18240a09893310c43673901d863892ae7b0611Enrico Granata
1368f18240a09893310c43673901d863892ae7b0611Enrico Granata	logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
1378f18240a09893310c43673901d863892ae7b0611Enrico Granata
138579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	if class_data.is_cftype():
139de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		# CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is
140de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		# an NSCFType and then check we are a pointer-to CFBitVectorRef
141de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		valobj_type = valobj.GetType()
142de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		if valobj_type.IsValid() and valobj_type.IsPointerType():
143579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			valobj_type = valobj_type.GetPointeeType()
144579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			if valobj_type.IsValid():
145579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				actual_name = valobj_type.GetName()
146579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if actual_name == '__CFBitVector' or actual_name == '__CFMutableBitVector':
147579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params)
148579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('code_notrun',valobj)
149579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		else:
150579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
151579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			print actual_name
152de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	else:
153f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
154de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata		print name_string
155805f79b15edd61887c26a3f0ea80457790ba5807Enrico Granata		statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
156de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	return wrapper;
157de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
158de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef CFBitVector_SummaryProvider (valobj,dict):
1590d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
160de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	provider = GetSummary_Impl(valobj);
161de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	if provider != None:
162a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
163579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return provider.message()
164579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		try:
165579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = provider.contents();
166579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		except:
167579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = None
1688f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "summary got from provider: " + str(summary)
169579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if summary == None or summary == '':
170579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '<variable is not CFBitVector>'
171579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return summary
172579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	return 'Summary Unavailable'
173de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata
174de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef __lldb_init_module(debugger,dict):
175de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata	debugger.HandleCommand("type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef")
176