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"""
8ae2ae94bd72daf435204e99a0e03ccc64470a843Enrico Granata# example summary provider for NSArray
9ae2ae94bd72daf435204e99a0e03ccc64470a843Enrico Granata# the real summary is now C++ code built into LLDB
10b370df27c76fd875f3312be487868528121a4838Enrico Granataimport lldb
11b370df27c76fd875f3312be487868528121a4838Enrico Granataimport ctypes
120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.runtime.objc.objc_runtime
130d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.metrics
140d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.Logger
15b370df27c76fd875f3312be487868528121a4838Enrico Granata
160d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granatastatistics = lldb.formatters.metrics.Metrics()
17b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('invalid_isa')
18b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('invalid_pointer')
19b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('unknown_class')
20b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('code_notrun')
21b370df27c76fd875f3312be487868528121a4838Enrico Granata
22b370df27c76fd875f3312be487868528121a4838Enrico Granata# much less functional than the other two cases below
23b370df27c76fd875f3312be487868528121a4838Enrico Granata# just runs code to get to the count and then returns
24b370df27c76fd875f3312be487868528121a4838Enrico Granata# no children
25b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayKVC_SynthProvider:
26b370df27c76fd875f3312be487868528121a4838Enrico Granata
27b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
28f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
29b370df27c76fd875f3312be487868528121a4838Enrico Granata
30f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
310d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
32b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
33b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
34b370df27c76fd875f3312be487868528121a4838Enrico Granata
35b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
360d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
37b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
38b370df27c76fd875f3312be487868528121a4838Enrico Granata
39b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
400d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
41b370df27c76fd875f3312be487868528121a4838Enrico Granata		stream = lldb.SBStream()
42b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj.GetExpressionPath(stream)
43b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
44579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if num_children_vo.IsValid():
45579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return num_children_vo.GetValueAsUnsigned(0)
46579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return "<variable is not NSArray>"
47b370df27c76fd875f3312be487868528121a4838Enrico Granata
48b370df27c76fd875f3312be487868528121a4838Enrico Granata# much less functional than the other two cases below
49b370df27c76fd875f3312be487868528121a4838Enrico Granata# just runs code to get to the count and then returns
50b370df27c76fd875f3312be487868528121a4838Enrico Granata# no children
51b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayCF_SynthProvider:
52b370df27c76fd875f3312be487868528121a4838Enrico Granata
53b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
54f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
55b370df27c76fd875f3312be487868528121a4838Enrico Granata
56f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
570d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
58b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
59f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
60f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not (self.sys_params.types_cache.ulong):
61f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
62b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
63b370df27c76fd875f3312be487868528121a4838Enrico Granata
64b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
650d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
66b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
67b370df27c76fd875f3312be487868528121a4838Enrico Granata
68b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
690d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
70b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_children_vo = self.valobj.CreateChildAtOffset("count",
71f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata							self.sys_params.cfruntime_size,
72f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata							self.sys_params.types_cache.ulong)
73b370df27c76fd875f3312be487868528121a4838Enrico Granata		return num_children_vo.GetValueAsUnsigned(0)
74b370df27c76fd875f3312be487868528121a4838Enrico Granata
75b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayI_SynthProvider:
76b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
77f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
78b370df27c76fd875f3312be487868528121a4838Enrico Granata
79f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
800d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
81b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
82f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
83f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.long):
84f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
85b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
86b370df27c76fd875f3312be487868528121a4838Enrico Granata
87b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
880d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
89b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
90b370df27c76fd875f3312be487868528121a4838Enrico Granata
91b370df27c76fd875f3312be487868528121a4838Enrico Granata	# skip the isa pointer and get at the size
92b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
930d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
94b370df27c76fd875f3312be487868528121a4838Enrico Granata		count = self.valobj.CreateChildAtOffset("count",
95f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.pointer_size,
96f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.long);
97f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return count.GetValueAsUnsigned(0)
98b370df27c76fd875f3312be487868528121a4838Enrico Granata
99b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArrayM_SynthProvider:
100b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
101f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
102b370df27c76fd875f3312be487868528121a4838Enrico Granata
103f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, dict, params):
1040d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
105b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
106f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
107f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.long):
108f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
109f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.update()
110b370df27c76fd875f3312be487868528121a4838Enrico Granata
111b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
1120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
113b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
114b370df27c76fd875f3312be487868528121a4838Enrico Granata
115b370df27c76fd875f3312be487868528121a4838Enrico Granata	# skip the isa pointer and get at the size
116b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
1170d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
118b370df27c76fd875f3312be487868528121a4838Enrico Granata		count = self.valobj.CreateChildAtOffset("count",
119f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.pointer_size,
120f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.long);
121f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return count.GetValueAsUnsigned(0)
122b370df27c76fd875f3312be487868528121a4838Enrico Granata
123b370df27c76fd875f3312be487868528121a4838Enrico Granata# this is the actual synth provider, but is just a wrapper that checks
124b370df27c76fd875f3312be487868528121a4838Enrico Granata# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
125b370df27c76fd875f3312be487868528121a4838Enrico Granata# appropriate backend layer to do the computations
126b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSArray_SynthProvider:
127b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
128f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
129b370df27c76fd875f3312be487868528121a4838Enrico Granata
130b370df27c76fd875f3312be487868528121a4838Enrico Granata	def __init__(self, valobj, dict):
1310d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
132b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
133b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture()
134579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		self.error = False
135579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		self.wrapper = self.make_wrapper()
136b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.invalid = (self.wrapper == None)
137b370df27c76fd875f3312be487868528121a4838Enrico Granata
138b370df27c76fd875f3312be487868528121a4838Enrico Granata	def num_children(self):
1390d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
140b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.wrapper == None:
141b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 0;
142b370df27c76fd875f3312be487868528121a4838Enrico Granata		return self.wrapper.num_children()
143b370df27c76fd875f3312be487868528121a4838Enrico Granata
144b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
1450d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
146b370df27c76fd875f3312be487868528121a4838Enrico Granata		if self.wrapper == None:
147f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			return
148f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.wrapper.update()
149b370df27c76fd875f3312be487868528121a4838Enrico Granata
150b370df27c76fd875f3312be487868528121a4838Enrico Granata	# this code acts as our defense against NULL and unitialized
151b370df27c76fd875f3312be487868528121a4838Enrico Granata	# NSArray pointers, which makes it much longer than it would be otherwise
152579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	def make_wrapper(self):
1530d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
154579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if self.valobj.GetValueAsUnsigned() == 0:
155579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			self.error = True
1560ff10b595416cc33bd66ecbdbcb93935327be0d0Enrico Granata			return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(True)
157579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		else:
158579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			global statistics
159a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata			class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics)
160579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			if wrapper:
161579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				self.error = True
162579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				return wrapper
163b370df27c76fd875f3312be487868528121a4838Enrico Granata
164b370df27c76fd875f3312be487868528121a4838Enrico Granata		name_string = class_data.class_name()
1658f18240a09893310c43673901d863892ae7b0611Enrico Granata
1668f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "Class name is " + str(name_string)
1678f18240a09893310c43673901d863892ae7b0611Enrico Granata
168b370df27c76fd875f3312be487868528121a4838Enrico Granata		if name_string == '__NSArrayI':
169579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)
1706805e3f988769b01a1c9bcdba1497afb026a8058Enrico Granata			statistics.metric_hit('code_notrun',self.valobj.GetName())
171b370df27c76fd875f3312be487868528121a4838Enrico Granata		elif name_string == '__NSArrayM':
172579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)
1736805e3f988769b01a1c9bcdba1497afb026a8058Enrico Granata			statistics.metric_hit('code_notrun',self.valobj.GetName())
174b370df27c76fd875f3312be487868528121a4838Enrico Granata		elif name_string == '__NSCFArray':
175579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)
1766805e3f988769b01a1c9bcdba1497afb026a8058Enrico Granata			statistics.metric_hit('code_notrun',self.valobj.GetName())
177b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
178579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)
1796805e3f988769b01a1c9bcdba1497afb026a8058Enrico Granata			statistics.metric_hit('unknown_class',str(self.valobj.GetName()) + " seen as " + name_string)
180b370df27c76fd875f3312be487868528121a4838Enrico Granata		return wrapper;
181b370df27c76fd875f3312be487868528121a4838Enrico Granata
182b370df27c76fd875f3312be487868528121a4838Enrico Granatadef CFArray_SummaryProvider (valobj,dict):
1830d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
184b370df27c76fd875f3312be487868528121a4838Enrico Granata	provider = NSArray_SynthProvider(valobj,dict);
185b370df27c76fd875f3312be487868528121a4838Enrico Granata	if provider.invalid == False:
186579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if provider.error == True:
187579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return provider.wrapper.message()
188579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		try:
189579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = int(provider.num_children());
190579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		except:
191579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = None
1928f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "provider gave me " + str(summary)
193579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if summary == None:
194579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '<variable is not NSArray>'
195579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		elif isinstance(summary,basestring):
196579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			pass
197579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		else:
198579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			# we format it like it were a CFString to make it look the same as the summary from Xcode
199579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'
200579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return summary
201579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	return 'Summary Unavailable'
202b370df27c76fd875f3312be487868528121a4838Enrico Granata
203b370df27c76fd875f3312be487868528121a4838Enrico Granatadef __lldb_init_module(debugger,dict):
204b370df27c76fd875f3312be487868528121a4838Enrico Granata	debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")
205