CFBitVector.py revision f2a84671ff78bee1f82b60698f3ee9791585f8ac
1de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# summary provider for CF(Mutable)BitVector 2de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport lldb 3de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport ctypes 4de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport objc_runtime 5de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataimport metrics 6de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 7de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# first define some utility functions 8de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef byte_index(abs_pos): 9de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return abs_pos/8 10de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 11de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef bit_index(abs_pos): 12de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return abs_pos & 7 13de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 14de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef get_bit(byte,index): 15de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if index < 0 or index > 7: 16de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return None 17de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return (byte >> (7-index)) & 1 18de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 19de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef grab_array_item_data(pointer,index): 20de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return pointer.GetPointeeData(index,1) 21de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 22de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics = metrics.Metrics() 23de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('invalid_isa') 24de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('invalid_pointer') 25de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('unknown_class') 26de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatastatistics.add_metric('code_notrun') 27de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 28de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# despite the similary to synthetic children providers, these classes are not 29de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# trying to provide anything but a summary for a CF*BitVector, so they need not 30de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata# obey the interface specification for synthetic children providers 31de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataclass CFBitVectorKnown_SummaryProvider: 32de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata def adjust_for_architecture(self): 33f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize() 34f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata pass 35de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 36de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata def __init__(self, valobj, params): 37de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata self.valobj = valobj; 38de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata self.sys_params = params 39f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata if not(self.sys_params.types_cache.NSUInteger): 40f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata if self.sys_params.is_64_bit: 41f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong) 42f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata else: 43f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt) 44f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata if not(self.sys_params.types_cache.charptr): 45f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.sys_params.types_cache.charptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType() 46de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata self.update(); 47de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 48de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata def update(self): 49de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata self.adjust_for_architecture(); 50de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 51de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # we skip the CFRuntimeBase 52de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # then the next CFIndex is the count 53de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # then we skip another CFIndex and then we get at a byte array 54de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # that wraps the individual bits 55de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 56de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata def contents(self): 57f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata count_vo = self.valobj.CreateChildAtOffset("count",self.sys_params.cfruntime_size, 58f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.sys_params.types_cache.NSUInteger) 59de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata count = count_vo.GetValueAsUnsigned(0) 60de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if count == 0: 61de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return '(empty)' 62de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 63de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata array_vo = self.valobj.CreateChildAtOffset("data", 64f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.sys_params.cfruntime_size+2*self.uiint_size, 65f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.sys_params.types_cache.charptr) 66de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 67de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata data_list = [] 68de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata cur_byte_pos = None 69de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata for i in range(0,count): 70de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if cur_byte_pos == None: 71de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata cur_byte_pos = byte_index(i) 72de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata cur_byte = grab_array_item_data(array_vo,cur_byte_pos) 73de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata cur_byte_val = cur_byte.uint8[0] 74de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata else: 75de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata byte_pos = byte_index(i) 76de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # do not fetch the pointee data every single time through 77de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if byte_pos != cur_byte_pos: 78de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata cur_byte_pos = byte_pos 79de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata cur_byte = grab_array_item_data(array_vo,cur_byte_pos) 80de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata cur_byte_val = cur_byte.uint8[0] 81de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata bit = get_bit(cur_byte_val,bit_index(i)) 82de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if (i % 4) == 0: 83de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata data_list.append(' ') 84de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if bit == 1: 85de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata data_list.append('1') 86de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata else: 87de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata data_list.append('0') 88de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return ''.join(data_list) 89de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 90de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 91de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granataclass CFBitVectorUnknown_SummaryProvider: 92de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata def adjust_for_architecture(self): 93f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata pass 94de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 95f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata def __init__(self, valobj, params): 96de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata self.valobj = valobj; 97f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.sys_params = params 98f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata self.update(); 99de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 100de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata def update(self): 101de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata self.adjust_for_architecture(); 102de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 103de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata def contents(self): 104de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return '*** unknown class *** very bad thing *** find out my name ***' 105de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 106de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 107de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef GetSummary_Impl(valobj): 108de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata global statistics 109de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata class_data = objc_runtime.ObjCRuntime(valobj) 110de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if class_data.is_valid() == False: 111de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata statistics.metric_hit('invalid_pointer',valobj) 112de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata wrapper = None 113de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return 114de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata class_data = class_data.read_class_data() 115de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if class_data.is_valid() == False: 116de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata statistics.metric_hit('invalid_isa',valobj) 117de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata wrapper = None 118de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return 119de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if class_data.is_kvo(): 120de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata class_data = class_data.get_superclass() 121de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if class_data.is_valid() == False: 122de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata statistics.metric_hit('invalid_isa',valobj) 123de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata wrapper = None 124de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return 125de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 126de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata name_string = class_data.class_name() 127de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if name_string == '__NSCFType': 128de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is 129de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # an NSCFType and then check we are a pointer-to CFBitVectorRef 130de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata valobj_type = valobj.GetType() 131de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if valobj_type.IsValid() and valobj_type.IsPointerType(): 132de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata pointee_type = valobj_type.GetPointeeType() 133de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if pointee_type.GetName() == '__CFBitVector' or pointee_type.GetName() == '__CFMutableBitVector': 134de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params) 135de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata statistics.metric_hit('code_notrun',valobj) 136de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata else: 137de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata wrapper = CFBitVectorUnknown_SummaryProvider(valobj) 138de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata print pointee_type.GetName() 139de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata else: 140f2a84671ff78bee1f82b60698f3ee9791585f8acEnrico Granata wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params) 141de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata print name_string 142de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string) 143de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return wrapper; 144de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 145de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef CFBitVector_SummaryProvider (valobj,dict): 146de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata provider = GetSummary_Impl(valobj); 147de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if provider != None: 148de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata #try: 149de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata summary = provider.contents(); 150de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata #except: 151de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata # summary = None 152de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata if summary == None or summary == '': 153de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata summary = 'no valid bitvector here' 154de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return summary 155de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata return '' 156de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata 157de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granatadef __lldb_init_module(debugger,dict): 158de3b25b645e4b4d97a87ebf059056a6c696d4e9cEnrico Granata debugger.HandleCommand("type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef") 159