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 CFBinaryHeap
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 CFBinaryHeap, so they need not
24b370df27c76fd875f3312be487868528121a4838Enrico Granata# obey the interface specification for synthetic children providers
25b370df27c76fd875f3312be487868528121a4838Enrico Granataclass CFBinaryHeapRef_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	# 8 bytes on i386
45b370df27c76fd875f3312be487868528121a4838Enrico Granata	# 16 bytes on x64
46b370df27c76fd875f3312be487868528121a4838Enrico Granata	# most probably 2 pointers
47b370df27c76fd875f3312be487868528121a4838Enrico Granata	def offset(self):
480d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
49f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return 2 * self.sys_params.pointer_size
50b370df27c76fd875f3312be487868528121a4838Enrico Granata
51b370df27c76fd875f3312be487868528121a4838Enrico Granata	def length(self):
520d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
53b370df27c76fd875f3312be487868528121a4838Enrico Granata		size = self.valobj.CreateChildAtOffset("count",
54b370df27c76fd875f3312be487868528121a4838Enrico Granata							self.offset(),
55f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata							self.sys_params.types_cache.NSUInteger)
56b370df27c76fd875f3312be487868528121a4838Enrico Granata		return size.GetValueAsUnsigned(0)
57b370df27c76fd875f3312be487868528121a4838Enrico Granata
58b370df27c76fd875f3312be487868528121a4838Enrico Granata
59b370df27c76fd875f3312be487868528121a4838Enrico Granataclass CFBinaryHeapUnknown_SummaryProvider:
60b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
61f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
62b370df27c76fd875f3312be487868528121a4838Enrico Granata
63f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, params):
640d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
65b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
66f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
67f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.update();
68b370df27c76fd875f3312be487868528121a4838Enrico Granata
69b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
700d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
71b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
72b370df27c76fd875f3312be487868528121a4838Enrico Granata
73b370df27c76fd875f3312be487868528121a4838Enrico Granata	def length(self):
740d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
75b370df27c76fd875f3312be487868528121a4838Enrico Granata		stream = lldb.SBStream()
76b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj.GetExpressionPath(stream)
77b370df27c76fd875f3312be487868528121a4838Enrico Granata		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBinaryHeapGetCount(" + stream.GetData() + " )");
78579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if num_children_vo.IsValid():
79579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return num_children_vo.GetValueAsUnsigned(0)
80579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return '<variable is not CFBinaryHeap>'
81b370df27c76fd875f3312be487868528121a4838Enrico Granata
82b370df27c76fd875f3312be487868528121a4838Enrico Granata
83b370df27c76fd875f3312be487868528121a4838Enrico Granatadef GetSummary_Impl(valobj):
840d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
85b370df27c76fd875f3312be487868528121a4838Enrico Granata	global statistics
86a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata	class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
87579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	if wrapper:
88579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return wrapper
89b370df27c76fd875f3312be487868528121a4838Enrico Granata
90b370df27c76fd875f3312be487868528121a4838Enrico Granata	name_string = class_data.class_name()
91579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	actual_name = class_data.class_name()
928f18240a09893310c43673901d863892ae7b0611Enrico Granata
938f18240a09893310c43673901d863892ae7b0611Enrico Granata	logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
948f18240a09893310c43673901d863892ae7b0611Enrico Granata
95579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	if class_data.is_cftype():
96b370df27c76fd875f3312be487868528121a4838Enrico Granata		# CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
97b370df27c76fd875f3312be487868528121a4838Enrico Granata		# an NSCFType and then check we are a pointer-to CFBinaryHeap
98b370df27c76fd875f3312be487868528121a4838Enrico Granata		valobj_type = valobj.GetType()
99b370df27c76fd875f3312be487868528121a4838Enrico Granata		if valobj_type.IsValid() and valobj_type.IsPointerType():
100579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			valobj_type = valobj_type.GetPointeeType()
101579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			if valobj_type.IsValid():
102579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata				actual_name = valobj_type.GetName()
103579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if actual_name == '__CFBinaryHeap':
104579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			wrapper = CFBinaryHeapRef_SummaryProvider(valobj, class_data.sys_params)
105579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			statistics.metric_hit('code_notrun',valobj)
106579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return wrapper
107f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	wrapper = CFBinaryHeapUnknown_SummaryProvider(valobj, class_data.sys_params)
108805f79b15edd61887c26a3f0ea80457790ba5807Enrico Granata	statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
109b370df27c76fd875f3312be487868528121a4838Enrico Granata	return wrapper;
110b370df27c76fd875f3312be487868528121a4838Enrico Granata
111b370df27c76fd875f3312be487868528121a4838Enrico Granatadef CFBinaryHeap_SummaryProvider (valobj,dict):
1120d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
113b370df27c76fd875f3312be487868528121a4838Enrico Granata	provider = GetSummary_Impl(valobj);
114b370df27c76fd875f3312be487868528121a4838Enrico Granata	if provider != None:
115a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
116579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return provider.message()
117b370df27c76fd875f3312be487868528121a4838Enrico Granata		try:
118b370df27c76fd875f3312be487868528121a4838Enrico Granata			summary = provider.length();
119b370df27c76fd875f3312be487868528121a4838Enrico Granata		except:
120b370df27c76fd875f3312be487868528121a4838Enrico Granata			summary = None
1218f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "summary got from provider: " + str(summary)
122b370df27c76fd875f3312be487868528121a4838Enrico Granata		# for some reason, one needs to clear some bits for the count
123b370df27c76fd875f3312be487868528121a4838Enrico Granata		# to be correct when using CF(Mutable)BagRef on x64
124b370df27c76fd875f3312be487868528121a4838Enrico Granata		# the bit mask was derived through experimentation
125b370df27c76fd875f3312be487868528121a4838Enrico Granata		# (if counts start looking weird, then most probably
126b370df27c76fd875f3312be487868528121a4838Enrico Granata		#  the mask needs to be changed)
127b370df27c76fd875f3312be487868528121a4838Enrico Granata		if summary == None:
128579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '<variable is not CFBinaryHeap>'
129579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		elif isinstance(summary,basestring):
130579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			pass
131b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
132f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			if provider.sys_params.is_64_bit:
133b370df27c76fd875f3312be487868528121a4838Enrico Granata				summary = summary & ~0x1fff000000000000
134323cec97d94bd1836e8c158e7065fdb5ad71ad48Enrico Granata			if summary == 1:
1357b9aacf4a454465af905e505f74245173714b23bEnrico Granata				return '@"1 item"'
136323cec97d94bd1836e8c158e7065fdb5ad71ad48Enrico Granata			else:
1377b9aacf4a454465af905e505f74245173714b23bEnrico Granata				summary = '@"' + str(summary) + ' items"'
138323cec97d94bd1836e8c158e7065fdb5ad71ad48Enrico Granata		return summary
139579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	return 'Summary Unavailable'
140b370df27c76fd875f3312be487868528121a4838Enrico Granata
141b370df27c76fd875f3312be487868528121a4838Enrico Granatadef __lldb_init_module(debugger,dict):
142b370df27c76fd875f3312be487868528121a4838Enrico Granata	debugger.HandleCommand("type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")
143