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