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 NSBundle
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
14b370df27c76fd875f3312be487868528121a4838Enrico Granataimport NSURL
150d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granataimport lldb.formatters.Logger
16b370df27c76fd875f3312be487868528121a4838Enrico Granata
170d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granatastatistics = lldb.formatters.metrics.Metrics()
18b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('invalid_isa')
19b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('invalid_pointer')
20b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('unknown_class')
21b370df27c76fd875f3312be487868528121a4838Enrico Granatastatistics.add_metric('code_notrun')
22b370df27c76fd875f3312be487868528121a4838Enrico Granata
23b370df27c76fd875f3312be487868528121a4838Enrico Granata# despite the similary to synthetic children providers, these classes are not
24b370df27c76fd875f3312be487868528121a4838Enrico Granata# trying to provide anything but a summary for an NSURL, so they need not
25b370df27c76fd875f3312be487868528121a4838Enrico Granata# obey the interface specification for synthetic children providers
26b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSBundleKnown_SummaryProvider:
27b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
28f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
29b370df27c76fd875f3312be487868528121a4838Enrico Granata
30f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, params):
310d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
32b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
33f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
34f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		if not(self.sys_params.types_cache.NSString):
35f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			self.sys_params.types_cache.NSString = self.valobj.GetTarget().FindFirstType('NSString').GetPointerType()
36b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update();
37b370df27c76fd875f3312be487868528121a4838Enrico Granata
38b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
390d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
40b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
41b370df27c76fd875f3312be487868528121a4838Enrico Granata
42b370df27c76fd875f3312be487868528121a4838Enrico Granata	# we need to skip the ISA, plus four other values
43b370df27c76fd875f3312be487868528121a4838Enrico Granata	# that are luckily each a pointer in size
44b370df27c76fd875f3312be487868528121a4838Enrico Granata	# which makes our computation trivial :-)
45b370df27c76fd875f3312be487868528121a4838Enrico Granata	def offset(self):
460d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
47f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		return 5 * self.sys_params.pointer_size
48b370df27c76fd875f3312be487868528121a4838Enrico Granata
49b370df27c76fd875f3312be487868528121a4838Enrico Granata	def url_text(self):
500d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
51b370df27c76fd875f3312be487868528121a4838Enrico Granata		global statistics
52b370df27c76fd875f3312be487868528121a4838Enrico Granata		text = self.valobj.CreateChildAtOffset("text",
53b370df27c76fd875f3312be487868528121a4838Enrico Granata							self.offset(),
54f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata							self.sys_params.types_cache.NSString)
55b370df27c76fd875f3312be487868528121a4838Enrico Granata		my_string = text.GetSummary()
56b370df27c76fd875f3312be487868528121a4838Enrico Granata		if (my_string == None) or (my_string == ''):
5735eac9d979574950afa087fed398179a92a45c36Enrico Granata			statistics.metric_hit('unknown_class',str(self.valobj.GetName()) + " triggered unkown pointer location")
58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata			return NSBundleUnknown_SummaryProvider(self.valobj, self.sys_params).url_text()
59b370df27c76fd875f3312be487868528121a4838Enrico Granata		else:
60b370df27c76fd875f3312be487868528121a4838Enrico Granata			statistics.metric_hit('code_notrun',self.valobj)
61b370df27c76fd875f3312be487868528121a4838Enrico Granata			return my_string
62b370df27c76fd875f3312be487868528121a4838Enrico Granata
63b370df27c76fd875f3312be487868528121a4838Enrico Granata
64b370df27c76fd875f3312be487868528121a4838Enrico Granataclass NSBundleUnknown_SummaryProvider:
65b370df27c76fd875f3312be487868528121a4838Enrico Granata	def adjust_for_architecture(self):
66f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		pass
67b370df27c76fd875f3312be487868528121a4838Enrico Granata
68f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata	def __init__(self, valobj, params):
690d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
70b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj = valobj;
71f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		self.sys_params = params
72b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.update()
73b370df27c76fd875f3312be487868528121a4838Enrico Granata
74b370df27c76fd875f3312be487868528121a4838Enrico Granata	def update(self):
750d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
76b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.adjust_for_architecture();
77b370df27c76fd875f3312be487868528121a4838Enrico Granata
78b370df27c76fd875f3312be487868528121a4838Enrico Granata	def url_text(self):
790d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata		logger = lldb.formatters.Logger.Logger()
80b370df27c76fd875f3312be487868528121a4838Enrico Granata		stream = lldb.SBStream()
81b370df27c76fd875f3312be487868528121a4838Enrico Granata		self.valobj.GetExpressionPath(stream)
82b370df27c76fd875f3312be487868528121a4838Enrico Granata		expr = "(NSString*)[" + stream.GetData() + " bundlePath]"
83b370df27c76fd875f3312be487868528121a4838Enrico Granata		url_text_vo = self.valobj.CreateValueFromExpression("path",expr);
84579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if url_text_vo.IsValid():
85579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return url_text_vo.GetSummary()
86579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return '<variable is not NSBundle>'
87b370df27c76fd875f3312be487868528121a4838Enrico Granata
88b370df27c76fd875f3312be487868528121a4838Enrico Granata
89b370df27c76fd875f3312be487868528121a4838Enrico Granatadef GetSummary_Impl(valobj):
900d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
91b370df27c76fd875f3312be487868528121a4838Enrico Granata	global statistics
92a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata	class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
93579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	if wrapper:
94579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return wrapper
95b370df27c76fd875f3312be487868528121a4838Enrico Granata
96b370df27c76fd875f3312be487868528121a4838Enrico Granata	name_string = class_data.class_name()
978f18240a09893310c43673901d863892ae7b0611Enrico Granata	logger >> "class name is: " + str(name_string)
988f18240a09893310c43673901d863892ae7b0611Enrico Granata
99b370df27c76fd875f3312be487868528121a4838Enrico Granata	if name_string == 'NSBundle':
100f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		wrapper = NSBundleKnown_SummaryProvider(valobj, class_data.sys_params)
101b370df27c76fd875f3312be487868528121a4838Enrico Granata		# [NSBundle mainBundle] does return an object that is
102b370df27c76fd875f3312be487868528121a4838Enrico Granata		# not correctly filled out for our purposes, so we still
103b370df27c76fd875f3312be487868528121a4838Enrico Granata		# end up having to run code in that case
104b370df27c76fd875f3312be487868528121a4838Enrico Granata		#statistics.metric_hit('code_notrun',valobj)
105b370df27c76fd875f3312be487868528121a4838Enrico Granata	else:
106f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata		wrapper = NSBundleUnknown_SummaryProvider(valobj, class_data.sys_params)
107805f79b15edd61887c26a3f0ea80457790ba5807Enrico Granata		statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
108b370df27c76fd875f3312be487868528121a4838Enrico Granata	return wrapper;
109b370df27c76fd875f3312be487868528121a4838Enrico Granata
110b370df27c76fd875f3312be487868528121a4838Enrico Granatadef NSBundle_SummaryProvider (valobj,dict):
1110d235d5864e996d95f485df1a0df406126e1ccdeEnrico Granata	logger = lldb.formatters.Logger.Logger()
112b370df27c76fd875f3312be487868528121a4838Enrico Granata	provider = GetSummary_Impl(valobj);
113b370df27c76fd875f3312be487868528121a4838Enrico Granata	if provider != None:
114a5c2ce05705f784fd4ada97823af6ff7006fea58Enrico Granata		if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
115579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			return provider.message()
116579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		try:
117579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = provider.url_text();
118579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		except:
119579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = None
1208f18240a09893310c43673901d863892ae7b0611Enrico Granata		logger >> "got summary " + str(summary)
121579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		if summary == None or summary == '':
122579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata			summary = '<variable is not NSBundle>'
123579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata		return summary
124579a296e7566b7b6d24b51e383bca1fe1e62086fEnrico Granata	return 'Summary Unavailable'
125b370df27c76fd875f3312be487868528121a4838Enrico Granata
126b370df27c76fd875f3312be487868528121a4838Enrico Granatadef __lldb_init_module(debugger,dict):
127b370df27c76fd875f3312be487868528121a4838Enrico Granata	debugger.HandleCommand("type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle")
128