CFArray.py revision 8f18240a09893310c43673901d863892ae7b0611
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"""
8b370df27c76fd875f3312be487868528121a4838Enrico Granata# synthetic children provider for NSArray
9b370df27c76fd875f3312be487868528121a4838Enrico Granataimport lldb
10b370df27c76fd875f3312be487868528121a4838Enrico Granataimport ctypes
11b370df27c76fd875f3312be487868528121a4838Enrico Granataimport objc_runtime
12b370df27c76fd875f3312be487868528121a4838Enrico Granataimport metrics
138f18240a09893310c43673901d863892ae7b0611Enrico Granataimport Logger
14b370df27c76fd875f3312be487868528121a4838Enrico Granata
15b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics = metrics.Metrics()
16b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('invalid_isa')
17b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('invalid_pointer')
18b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('unknown_class')
19b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('code_notrun')
20b370df27c76fd875f3312be487868528121a4838Enrico Granata
21b370df27c76fd875f3312be487868528121a4838Enrico Granata# much less functional than the other two cases below
22b370df27c76fd875f3312be487868528121a4838Enrico Granata# just runs code to get to the count and then returns
23b370df27c76fd875f3312be487868528121a4838Enrico Granata# no children
24b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayKVC_SynthProvider:
25b370df27c76fd875f3312be487868528121a4838Enrico Granata
26b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
27f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
28b370df27c76fd875f3312be487868528121a4838Enrico Granata
29f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
308f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
31b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
32b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
33b370df27c76fd875f3312be487868528121a4838Enrico Granata
34b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
358f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
36b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
37b370df27c76fd875f3312be487868528121a4838Enrico Granata
38b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
398f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
40b370df27c76fd875f3312be487868528121a4838Enrico Granata		stream = lldb.SBStream()
41b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj.GetExpressionPath(stream)
42b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
43579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if num_children_vo.IsValid():
44579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return num_children_vo.GetValueAsUnsigned(0)
45579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return "<variable is not NSArray>"
46b370df27c76fd875f3312be487868528121a4838Enrico Granata
47b370df27c76fd875f3312be487868528121a4838Enrico Granata# much less functional than the other two cases below
48b370df27c76fd875f3312be487868528121a4838Enrico Granata# just runs code to get to the count and then returns
49b370df27c76fd875f3312be487868528121a4838Enrico Granata# no children
50b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayCF_SynthProvider:
51b370df27c76fd875f3312be487868528121a4838Enrico Granata
52b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
53f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
54b370df27c76fd875f3312be487868528121a4838Enrico Granata
55f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
568f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
57b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
59f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not (self.sys_params.types_cache.ulong):
60f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
61b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
62b370df27c76fd875f3312be487868528121a4838Enrico Granata
63b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
648f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
65b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
66b370df27c76fd875f3312be487868528121a4838Enrico Granata
67b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
688f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
69b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_children_vo = self.valobj.CreateChildAtOffset("count",
70f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata							self.sys_params.cfruntime_size,
71f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata							self.sys_params.types_cache.ulong)
72b370df27c76fd875f3312be487868528121a4838Enrico Granata		return num_children_vo.GetValueAsUnsigned(0)
73b370df27c76fd875f3312be487868528121a4838Enrico Granata
74b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayI_SynthProvider:
75b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
76f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
77b370df27c76fd875f3312be487868528121a4838Enrico Granata
78f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
798f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
80b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
81f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
82f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.long):
83f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
84b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
85b370df27c76fd875f3312be487868528121a4838Enrico Granata
86b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
878f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
88b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
89b370df27c76fd875f3312be487868528121a4838Enrico Granata
90b370df27c76fd875f3312be487868528121a4838Enrico Granata	# skip the isa pointer and get at the size
91b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
928f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
93b370df27c76fd875f3312be487868528121a4838Enrico Granata		count = self.valobj.CreateChildAtOffset("count",
94f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.pointer_size,
95f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.long);
96f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return count.GetValueAsUnsigned(0)
97b370df27c76fd875f3312be487868528121a4838Enrico Granata
98b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayM_SynthProvider:
99b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
100f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
101b370df27c76fd875f3312be487868528121a4838Enrico Granata
102f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
1038f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
104b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
105f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
106f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.long):
107f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
108f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.update()
109b370df27c76fd875f3312be487868528121a4838Enrico Granata
110b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
1118f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
112b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
113b370df27c76fd875f3312be487868528121a4838Enrico Granata
114b370df27c76fd875f3312be487868528121a4838Enrico Granata	# skip the isa pointer and get at the size
115b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
1168f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
117b370df27c76fd875f3312be487868528121a4838Enrico Granata		count = self.valobj.CreateChildAtOffset("count",
118f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.pointer_size,
119f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.long);
120f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return count.GetValueAsUnsigned(0)
121b370df27c76fd875f3312be487868528121a4838Enrico Granata
122b370df27c76fd875f3312be487868528121a4838Enrico Granata# this is the actual synth provider, but is just a wrapper that checks
123b370df27c76fd875f3312be487868528121a4838Enrico Granata# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
124b370df27c76fd875f3312be487868528121a4838Enrico Granata# appropriate backend layer to do the computations
125b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArray_SynthProvider:
126b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
127f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
128b370df27c76fd875f3312be487868528121a4838Enrico Granata
129b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self, valobj, dict):
1308f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
131b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
132b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture()
133579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		self.error = False
134579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		self.wrapper = self.make_wrapper()
135b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.invalid = (self.wrapper == None)
136b370df27c76fd875f3312be487868528121a4838Enrico Granata
137b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
1388f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
139b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.wrapper == None:
140b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 0;
141b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.wrapper.num_children()
142b370df27c76fd875f3312be487868528121a4838Enrico Granata
143b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
1448f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
145b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.wrapper == None:
146f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			return
147f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.wrapper.update()
148b370df27c76fd875f3312be487868528121a4838Enrico Granata
149b370df27c76fd875f3312be487868528121a4838Enrico Granata	# this code acts as our defense against NULL and unitialized
150b370df27c76fd875f3312be487868528121a4838Enrico Granata	# NSArray pointers, which makes it much longer than it would be otherwise
151579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def make_wrapper(self):
1528f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger = Logger.Logger()
153579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if self.valobj.GetValueAsUnsigned() == 0:
154579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			self.error = True
155579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return objc_runtime.InvalidPointer_Description(True)
156579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		else:
157579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			global statistics
158579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics)
159579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			if wrapper:
160579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				self.error = True
161579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				return wrapper
162b370df27c76fd875f3312be487868528121a4838Enrico Granata
163b370df27c76fd875f3312be487868528121a4838Enrico Granata		name_string = class_data.class_name()
1648f18240a09893310c43673901d863892ae7b0611Enrico Granata
1658f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "Class name is " + str(name_string)
1668f18240a09893310c43673901d863892ae7b0611Enrico Granata
167b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name_string == '__NSArrayI':
168579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)
169579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('code_notrun',self.valobj)
170b370df27c76fd875f3312be487868528121a4838Enrico Granata		elif name_string == '__NSArrayM':
171579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)
172579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('code_notrun',self.valobj)
173b370df27c76fd875f3312be487868528121a4838Enrico Granata		elif name_string == '__NSCFArray':
174579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)
175579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('code_notrun',self.valobj)
176b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
177579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)
178579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('unknown_class',str(self.valobj) + " seen as " + name_string)
179b370df27c76fd875f3312be487868528121a4838Enrico Granata		return wrapper;
180b370df27c76fd875f3312be487868528121a4838Enrico Granata
181b370df27c76fd875f3312be487868528121a4838Enrico Granatadef CFArray_SummaryProvider (valobj,dict):
1828f18240a09893310c43673901d863892ae7b0611Enrico Granata	logger = Logger.Logger()
183b370df27c76fd875f3312be487868528121a4838Enrico Granata	provider = NSArray_SynthProvider(valobj,dict);
184b370df27c76fd875f3312be487868528121a4838Enrico Granata	if provider.invalid == False:
185579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if provider.error == True:
186579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return provider.wrapper.message()
187579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		try:
188579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = int(provider.num_children());
189579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		except:
190579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = None
1918f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "provider gave me " + str(summary)
192579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if summary == None:
193579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '<variable is not NSArray>'
194579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		elif isinstance(summary,basestring):
195579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			pass
196579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		else:
197579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			# we format it like it were a CFString to make it look the same as the summary from Xcode
198579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'
199579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return summary
200579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	return 'Summary Unavailable'
201b370df27c76fd875f3312be487868528121a4838Enrico Granata
202b370df27c76fd875f3312be487868528121a4838Enrico Granatadef __lldb_init_module(debugger,dict):
203b370df27c76fd875f3312be487868528121a4838Enrico Granata	debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
204