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