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"""
8dc1df6b2fd7d359753b2bcfcf2decb114f465a1dEnrico Granata# example summary provider for CFBag
9dc1df6b2fd7d359753b2bcfcf2decb114f465a1dEnrico 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# despite the similary to synthetic children providers, these classes are not
23b370df27c76fd875f3312be487868528121a4838Enrico Granata# trying to provide anything but the length for an CFBag, so they need not
24b370df27c76fd875f3312be487868528121a4838Enrico Granata# obey the interface specification for synthetic children providers
25b370df27c76fd875f3312be487868528121a4838Enrico Granataclass CFBagRef_SummaryProvider:
26b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
27f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
28b370df27c76fd875f3312be487868528121a4838Enrico Granata
29f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, params):
300d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
31b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
32f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
33f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.NSUInteger):
34f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			if self.sys_params.is_64_bit:
35f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
36f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			else:
37f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
38b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update();
39b370df27c76fd875f3312be487868528121a4838Enrico Granata
40b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
410d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
42b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
43b370df27c76fd875f3312be487868528121a4838Enrico Granata
44b370df27c76fd875f3312be487868528121a4838Enrico Granata	# 12 bytes on i386
45b370df27c76fd875f3312be487868528121a4838Enrico Granata	# 20 bytes on x64
46b370df27c76fd875f3312be487868528121a4838Enrico Granata	# most probably 2 pointers and 4 bytes of data
47b370df27c76fd875f3312be487868528121a4838Enrico Granata	def offset(self):
480d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
49f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if self.sys_params.is_64_bit:
50b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 20
51b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
52b370df27c76fd875f3312be487868528121a4838Enrico Granata			return 12
53b370df27c76fd875f3312be487868528121a4838Enrico Granata
54b370df27c76fd875f3312be487868528121a4838Enrico Granata	def length(self):
550d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
56b370df27c76fd875f3312be487868528121a4838Enrico Granata		size = self.valobj.CreateChildAtOffset("count",
57b370df27c76fd875f3312be487868528121a4838Enrico Granata							self.offset(),
58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata							self.sys_params.types_cache.NSUInteger)
59b370df27c76fd875f3312be487868528121a4838Enrico Granata		return size.GetValueAsUnsigned(0)
60b370df27c76fd875f3312be487868528121a4838Enrico Granata
61b370df27c76fd875f3312be487868528121a4838Enrico Granata
62b370df27c76fd875f3312be487868528121a4838Enrico Granataclass CFBagUnknown_SummaryProvider:
63b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
64f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
65b370df27c76fd875f3312be487868528121a4838Enrico Granata
66f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, params):
670d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
68b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
69f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
70f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.update();
71b370df27c76fd875f3312be487868528121a4838Enrico Granata
72b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
730d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
74b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
75b370df27c76fd875f3312be487868528121a4838Enrico Granata
76b370df27c76fd875f3312be487868528121a4838Enrico Granata	def length(self):
770d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
78b370df27c76fd875f3312be487868528121a4838Enrico Granata		stream = lldb.SBStream()
79b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj.GetExpressionPath(stream)
80579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBagGetCount(" + stream.GetData() + " )")
81579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if num_children_vo.IsValid():
82579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return num_children_vo.GetValueAsUnsigned(0)
83579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return "<variable is not CFBag>"
84b370df27c76fd875f3312be487868528121a4838Enrico Granata
85b370df27c76fd875f3312be487868528121a4838Enrico Granata
86b370df27c76fd875f3312be487868528121a4838Enrico Granatadef GetSummary_Impl(valobj):
870d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
88b370df27c76fd875f3312be487868528121a4838Enrico Granata	global statistics
89a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata	class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
90579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	if wrapper:
91579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return wrapper
92b370df27c76fd875f3312be487868528121a4838Enrico Granata
93b370df27c76fd875f3312be487868528121a4838Enrico Granata	name_string = class_data.class_name()
94b370df27c76fd875f3312be487868528121a4838Enrico Granata	actual_name = name_string
958f18240a09893310c43673901d863892ae7b0611Enrico Granata
968f18240a09893310c43673901d863892ae7b0611Enrico Granata	logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
978f18240a09893310c43673901d863892ae7b0611Enrico Granata
98579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	if class_data.is_cftype():
99b370df27c76fd875f3312be487868528121a4838Enrico Granata		# CFBag does not expose an actual NSWrapper type, so we have to check that this is
100b370df27c76fd875f3312be487868528121a4838Enrico Granata		# an NSCFType and then check we are a pointer-to __CFBag
101b370df27c76fd875f3312be487868528121a4838Enrico Granata		valobj_type = valobj.GetType()
102b370df27c76fd875f3312be487868528121a4838Enrico Granata		if valobj_type.IsValid() and valobj_type.IsPointerType():
103579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			valobj_type = valobj_type.GetPointeeType()
104579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			if valobj_type.IsValid():
105579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				actual_name = valobj_type.GetName()
106579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if actual_name == '__CFBag' or \
107579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		   actual_name == 'const struct __CFBag':
108579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
109579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('code_notrun',valobj)
110579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return wrapper
111f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	wrapper = CFBagUnknown_SummaryProvider(valobj, class_data.sys_params)
112805f79b15edd61887c26a3f0ea80457790ba5807Enrico Granata	statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + actual_name)
113b370df27c76fd875f3312be487868528121a4838Enrico Granata	return wrapper;
114b370df27c76fd875f3312be487868528121a4838Enrico Granata
115b370df27c76fd875f3312be487868528121a4838Enrico Granatadef CFBag_SummaryProvider (valobj,dict):
1160d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
117b370df27c76fd875f3312be487868528121a4838Enrico Granata	provider = GetSummary_Impl(valobj);
118b370df27c76fd875f3312be487868528121a4838Enrico Granata	if provider != None:
119a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
120579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return provider.message()
121b370df27c76fd875f3312be487868528121a4838Enrico Granata		try:
122b370df27c76fd875f3312be487868528121a4838Enrico Granata			summary = provider.length();
123b370df27c76fd875f3312be487868528121a4838Enrico Granata		except:
124b370df27c76fd875f3312be487868528121a4838Enrico Granata			summary = None
1258f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "summary got from provider: " + str(summary)
126b370df27c76fd875f3312be487868528121a4838Enrico Granata		# for some reason, one needs to clear some bits for the count
127b370df27c76fd875f3312be487868528121a4838Enrico Granata		# to be correct when using CF(Mutable)BagRef on x64
128b370df27c76fd875f3312be487868528121a4838Enrico Granata		# the bit mask was derived through experimentation
129b370df27c76fd875f3312be487868528121a4838Enrico Granata		# (if counts start looking weird, then most probably
130b370df27c76fd875f3312be487868528121a4838Enrico Granata		#  the mask needs to be changed)
131b370df27c76fd875f3312be487868528121a4838Enrico Granata		if summary == None:
132579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '<variable is not CFBag>'
133579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		elif isinstance(summary,basestring):
134579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			pass
135b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
136f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			if provider.sys_params.is_64_bit:
137b370df27c76fd875f3312be487868528121a4838Enrico Granata				summary = summary & ~0x1fff000000000000
138323cec97d94bd1836e8c158e7065fdb5ad71ad48Enrico Granata			if summary == 1:
1397b9aacf4a454465af905e505f74245173714b23bEnrico Granata				summary = '@"1 value"'
140323cec97d94bd1836e8c158e7065fdb5ad71ad48Enrico Granata			else:
1417b9aacf4a454465af905e505f74245173714b23bEnrico Granata				summary = '@"' + str(summary) + ' values"'
142323cec97d94bd1836e8c158e7065fdb5ad71ad48Enrico Granata		return summary
143579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	return 'Summary Unavailable'
144b370df27c76fd875f3312be487868528121a4838Enrico Granata
145b370df27c76fd875f3312be487868528121a4838Enrico Granatadef __lldb_init_module(debugger,dict):
146b370df27c76fd875f3312be487868528121a4838Enrico Granata	debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")
147