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