Home | History | Annotate | Download | only in cocoa
      1 """
      2 LLDB AppKit formatters
      3 
      4 part of The LLVM Compiler Infrastructure
      5 This file is distributed under the University of Illinois Open Source
      6 License. See LICENSE.TXT for details.
      7 """
      8 # summary provider for CF(Mutable)BitVector
      9 import lldb
     10 import ctypes
     11 import lldb.runtime.objc.objc_runtime
     12 import lldb.formatters.metrics
     13 import lldb.formatters.Logger
     14 
     15 # first define some utility functions
     16 def byte_index(abs_pos):
     17 	logger = lldb.formatters.Logger.Logger()
     18 	return abs_pos/8
     19 
     20 def bit_index(abs_pos):
     21 	logger = lldb.formatters.Logger.Logger()
     22 	return abs_pos & 7
     23 
     24 def get_bit(byte,index):
     25 	logger = lldb.formatters.Logger.Logger()
     26 	if index < 0 or index > 7:
     27 		return None
     28 	return (byte >> (7-index)) & 1
     29 
     30 def grab_array_item_data(pointer,index):
     31 	logger = lldb.formatters.Logger.Logger()
     32 	return pointer.GetPointeeData(index,1)
     33 
     34 statistics = lldb.formatters.metrics.Metrics()
     35 statistics.add_metric('invalid_isa')
     36 statistics.add_metric('invalid_pointer')
     37 statistics.add_metric('unknown_class')
     38 statistics.add_metric('code_notrun')
     39 
     40 # despite the similary to synthetic children providers, these classes are not
     41 # trying to provide anything but a summary for a CF*BitVector, so they need not
     42 # obey the interface specification for synthetic children providers
     43 class CFBitVectorKnown_SummaryProvider:
     44 	def adjust_for_architecture(self):
     45 		logger = lldb.formatters.Logger.Logger()
     46 		self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()
     47 		pass
     48 
     49 	def __init__(self, valobj, params):
     50 		logger = lldb.formatters.Logger.Logger()
     51 		self.valobj = valobj;
     52 		self.sys_params = params
     53 		if not(self.sys_params.types_cache.NSUInteger):
     54 			if self.sys_params.is_64_bit:
     55 				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
     56 			else:
     57 				self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
     58 		if not(self.sys_params.types_cache.charptr):
     59 			self.sys_params.types_cache.charptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()
     60 		self.update();
     61 
     62 	def update(self):
     63 		logger = lldb.formatters.Logger.Logger()
     64 		self.adjust_for_architecture();
     65 
     66 	# we skip the CFRuntimeBase
     67 	# then the next CFIndex is the count
     68 	# then we skip another CFIndex and then we get at a byte array
     69 	# that wraps the individual bits
     70 
     71 	def contents(self):
     72 		logger = lldb.formatters.Logger.Logger()
     73 		count_vo = self.valobj.CreateChildAtOffset("count",self.sys_params.cfruntime_size,
     74 													self.sys_params.types_cache.NSUInteger)
     75 		count = count_vo.GetValueAsUnsigned(0)
     76 		if count == 0:
     77 			return '(empty)'
     78 		
     79 		array_vo = self.valobj.CreateChildAtOffset("data",
     80 													self.sys_params.cfruntime_size+2*self.uiint_size,
     81 													self.sys_params.types_cache.charptr)
     82 		
     83 		data_list = []
     84 		cur_byte_pos = None
     85 		for i in range(0,count):
     86 			if cur_byte_pos == None:
     87 				cur_byte_pos = byte_index(i)
     88 				cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
     89 				cur_byte_val = cur_byte.uint8[0]
     90 			else:
     91 				byte_pos = byte_index(i)
     92 				# do not fetch the pointee data every single time through
     93 				if byte_pos != cur_byte_pos:
     94 					cur_byte_pos = byte_pos
     95 					cur_byte = grab_array_item_data(array_vo,cur_byte_pos)
     96 					cur_byte_val = cur_byte.uint8[0]
     97 			bit = get_bit(cur_byte_val,bit_index(i))
     98 			if (i % 4) == 0:
     99 				data_list.append(' ')
    100 			if bit == 1:
    101 				data_list.append('1')
    102 			else:
    103 				data_list.append('0')
    104 		return ''.join(data_list)
    105 
    106 
    107 class CFBitVectorUnknown_SummaryProvider:
    108 	def adjust_for_architecture(self):
    109 		pass
    110 
    111 	def __init__(self, valobj, params):
    112 		logger = lldb.formatters.Logger.Logger()
    113 		self.valobj = valobj;
    114 		self.sys_params = params
    115 		self.update();
    116 
    117 	def update(self):
    118 		logger = lldb.formatters.Logger.Logger()
    119 		self.adjust_for_architecture();
    120 
    121 	def contents(self):
    122 		logger = lldb.formatters.Logger.Logger()
    123 		return '<unable to summarize this CFBitVector>'
    124 
    125 
    126 def GetSummary_Impl(valobj):
    127 	logger = lldb.formatters.Logger.Logger()
    128 	global statistics
    129 	class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
    130 	if wrapper:
    131 		return wrapper
    132 
    133 	name_string = class_data.class_name()
    134 	actual_name = name_string
    135 	
    136 	logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
    137 	
    138 	if class_data.is_cftype():
    139 		# CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is
    140 		# an NSCFType and then check we are a pointer-to CFBitVectorRef
    141 		valobj_type = valobj.GetType()
    142 		if valobj_type.IsValid() and valobj_type.IsPointerType():
    143 			valobj_type = valobj_type.GetPointeeType()
    144 			if valobj_type.IsValid():
    145 				actual_name = valobj_type.GetName()
    146 		if actual_name == '__CFBitVector' or actual_name == '__CFMutableBitVector':
    147 			wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params)
    148 			statistics.metric_hit('code_notrun',valobj)
    149 		else:
    150 			wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
    151 			print actual_name
    152 	else:
    153 		wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)
    154 		print name_string
    155 		statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
    156 	return wrapper;
    157 
    158 def CFBitVector_SummaryProvider (valobj,dict):
    159 	logger = lldb.formatters.Logger.Logger()
    160 	provider = GetSummary_Impl(valobj);
    161 	if provider != None:
    162 		if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
    163 			return provider.message()
    164 		try:
    165 			summary = provider.contents();
    166 		except:
    167 			summary = None
    168 		logger >> "summary got from provider: " + str(summary)
    169 		if summary == None or summary == '':
    170 			summary = '<variable is not CFBitVector>'
    171 		return summary
    172 	return 'Summary Unavailable'
    173 
    174 def __lldb_init_module(debugger,dict):
    175 	debugger.HandleCommand("type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef")
    176