diff options
Diffstat (limited to 'examples/summaries/cocoa/CFArray.py')
| -rw-r--r-- | examples/summaries/cocoa/CFArray.py | 204 | 
1 files changed, 204 insertions, 0 deletions
| diff --git a/examples/summaries/cocoa/CFArray.py b/examples/summaries/cocoa/CFArray.py new file mode 100644 index 000000000000..5068875b5b38 --- /dev/null +++ b/examples/summaries/cocoa/CFArray.py @@ -0,0 +1,204 @@ +""" +LLDB AppKit formatters + +part of The LLVM Compiler Infrastructure +This file is distributed under the University of Illinois Open Source +License. See LICENSE.TXT for details. +""" +# example summary provider for NSArray +# the real summary is now C++ code built into LLDB +import lldb +import ctypes +import lldb.runtime.objc.objc_runtime +import lldb.formatters.metrics +import lldb.formatters.Logger + +statistics = lldb.formatters.metrics.Metrics() +statistics.add_metric('invalid_isa') +statistics.add_metric('invalid_pointer') +statistics.add_metric('unknown_class') +statistics.add_metric('code_notrun') + +# much less functional than the other two cases below +# just runs code to get to the count and then returns +# no children +class NSArrayKVC_SynthProvider: + +	def adjust_for_architecture(self): +		pass + +	def __init__(self, valobj, dict, params): +		logger = lldb.formatters.Logger.Logger() +		self.valobj = valobj; +		self.update() + +	def update(self): +		logger = lldb.formatters.Logger.Logger() +		self.adjust_for_architecture(); + +	def num_children(self): +		logger = lldb.formatters.Logger.Logger() +		stream = lldb.SBStream() +		self.valobj.GetExpressionPath(stream) +		num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]"); +		if num_children_vo.IsValid(): +			return num_children_vo.GetValueAsUnsigned(0) +		return "<variable is not NSArray>" + +# much less functional than the other two cases below +# just runs code to get to the count and then returns +# no children +class NSArrayCF_SynthProvider: + +	def adjust_for_architecture(self): +		pass + +	def __init__(self, valobj, dict, params): +		logger = lldb.formatters.Logger.Logger() +		self.valobj = valobj; +		self.sys_params = params +		if not (self.sys_params.types_cache.ulong): +			self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong) +		self.update() + +	def update(self): +		logger = lldb.formatters.Logger.Logger() +		self.adjust_for_architecture(); + +	def num_children(self): +		logger = lldb.formatters.Logger.Logger() +		num_children_vo = self.valobj.CreateChildAtOffset("count", +							self.sys_params.cfruntime_size, +							self.sys_params.types_cache.ulong) +		return num_children_vo.GetValueAsUnsigned(0) + +class NSArrayI_SynthProvider: +	def adjust_for_architecture(self): +		pass + +	def __init__(self, valobj, dict, params): +		logger = lldb.formatters.Logger.Logger() +		self.valobj = valobj; +		self.sys_params = params +		if not(self.sys_params.types_cache.long): +			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong) +		self.update() + +	def update(self): +		logger = lldb.formatters.Logger.Logger() +		self.adjust_for_architecture(); + +	# skip the isa pointer and get at the size +	def num_children(self): +		logger = lldb.formatters.Logger.Logger() +		count = self.valobj.CreateChildAtOffset("count", +				self.sys_params.pointer_size, +				self.sys_params.types_cache.long); +		return count.GetValueAsUnsigned(0) + +class NSArrayM_SynthProvider: +	def adjust_for_architecture(self): +		pass + +	def __init__(self, valobj, dict, params): +		logger = lldb.formatters.Logger.Logger() +		self.valobj = valobj; +		self.sys_params = params +		if not(self.sys_params.types_cache.long): +			self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong) +		self.update() + +	def update(self): +		logger = lldb.formatters.Logger.Logger() +		self.adjust_for_architecture(); + +	# skip the isa pointer and get at the size +	def num_children(self): +		logger = lldb.formatters.Logger.Logger() +		count = self.valobj.CreateChildAtOffset("count", +				self.sys_params.pointer_size, +				self.sys_params.types_cache.long); +		return count.GetValueAsUnsigned(0) + +# this is the actual synth provider, but is just a wrapper that checks +# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an +# appropriate backend layer to do the computations  +class NSArray_SynthProvider: +	def adjust_for_architecture(self): +		pass + +	def __init__(self, valobj, dict): +		logger = lldb.formatters.Logger.Logger() +		self.valobj = valobj; +		self.adjust_for_architecture() +		self.error = False +		self.wrapper = self.make_wrapper() +		self.invalid = (self.wrapper == None) + +	def num_children(self): +		logger = lldb.formatters.Logger.Logger() +		if self.wrapper == None: +			return 0; +		return self.wrapper.num_children() + +	def update(self): +		logger = lldb.formatters.Logger.Logger() +		if self.wrapper == None: +			return +		self.wrapper.update() + +	# this code acts as our defense against NULL and uninitialized +	# NSArray pointers, which makes it much longer than it would be otherwise +	def make_wrapper(self): +		logger = lldb.formatters.Logger.Logger() +		if self.valobj.GetValueAsUnsigned() == 0: +			self.error = True +			return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(True) +		else: +			global statistics +			class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics) +			if wrapper: +				self.error = True +				return wrapper +		 +		name_string = class_data.class_name() +		 +		logger >> "Class name is " + str(name_string) +		 +		if name_string == '__NSArrayI': +			wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params) +			statistics.metric_hit('code_notrun',self.valobj.GetName()) +		elif name_string == '__NSArrayM': +			wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params) +			statistics.metric_hit('code_notrun',self.valobj.GetName()) +		elif name_string == '__NSCFArray': +			wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params) +			statistics.metric_hit('code_notrun',self.valobj.GetName()) +		else: +			wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params) +			statistics.metric_hit('unknown_class',str(self.valobj.GetName()) + " seen as " + name_string) +		return wrapper; + +def CFArray_SummaryProvider (valobj,dict): +	logger = lldb.formatters.Logger.Logger() +	provider = NSArray_SynthProvider(valobj,dict); +	if provider.invalid == False: +		if provider.error == True: +			return provider.wrapper.message() +		try: +			summary = int(provider.num_children()); +		except: +			summary = None +		logger >> "provider gave me " + str(summary) +		if summary == None: +			summary = '<variable is not NSArray>' +		elif isinstance(summary,basestring): +			pass +		else: +			# we format it like it were a CFString to make it look the same as the summary from Xcode +			summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"' +		return summary +	return 'Summary Unavailable' + +def __lldb_init_module(debugger,dict): +	debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef") | 
