blob: 39b7ac85e79fe106e5a5d46f097aad24bb6b6907 [file] [log] [blame]
Enrico Granataeb4a4792012-02-23 23:10:27 +00001# summary provider for NSDictionary
2import lldb
3import ctypes
4import objc_runtime
5import metrics
6
7statistics = metrics.Metrics()
8statistics.add_metric('invalid_isa')
9statistics.add_metric('invalid_pointer')
10statistics.add_metric('unknown_class')
11statistics.add_metric('code_notrun')
12
13# despite the similary to synthetic children providers, these classes are not
14# trying to provide anything but the count for an NSDictionary, so they need not
15# obey the interface specification for synthetic children providers
16class NSCFDictionary_SummaryProvider:
17 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000018 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000019
Enrico Granatacfdafa32012-03-05 19:56:33 +000020 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000021 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000022 self.sys_params = params
23 if not(self.sys_params.types_cache.NSUInteger):
24 if self.sys_params.is_64_bit:
25 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
26 else:
27 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000028 self.update();
29
30 def update(self):
31 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000032
33 # empirically determined on both 32 and 64bit desktop Mac OS X
34 # probably boils down to 2 pointers and 4 bytes of data, but
35 # the description of __CFDictionary is not readily available so most
36 # of this is guesswork, plain and simple
37 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000038 if self.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +000039 return 20
40 else:
41 return 12
42
43 def num_children(self):
44 num_children_vo = self.valobj.CreateChildAtOffset("count",
45 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000046 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000047 return num_children_vo.GetValueAsUnsigned(0)
48
49
50class NSDictionaryI_SummaryProvider:
51 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000052 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000053
Enrico Granatacfdafa32012-03-05 19:56:33 +000054 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000055 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000056 self.sys_params = params
57 if not(self.sys_params.types_cache.NSUInteger):
58 if self.sys_params.is_64_bit:
59 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
60 else:
61 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000062 self.update();
63
64 def update(self):
65 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000066
67 # we just need to skip the ISA and the count immediately follows
68 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000069 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +000070
71 def num_children(self):
72 num_children_vo = self.valobj.CreateChildAtOffset("count",
73 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000074 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000075 value = num_children_vo.GetValueAsUnsigned(0)
76 if value != None:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000077 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
78 # not sure if it is a bug or some weird sort of feature, but masking that out
79 # gets the count right
Enrico Granatacfdafa32012-03-05 19:56:33 +000080 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000081 value = value & ~0xFC00000000000000
Enrico Granataeb4a4792012-02-23 23:10:27 +000082 else:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000083 value = value & ~0xFC000000
Enrico Granataeb4a4792012-02-23 23:10:27 +000084 return value
85
86class NSDictionaryM_SummaryProvider:
87 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000088 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000089
Enrico Granatacfdafa32012-03-05 19:56:33 +000090 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000091 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000092 self.sys_params = params
93 if not(self.sys_params.types_cache.NSUInteger):
94 if self.sys_params.is_64_bit:
95 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
96 else:
97 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000098 self.update();
99
100 def update(self):
101 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000102
103 # we just need to skip the ISA and the count immediately follows
104 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000105 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000106
107 def num_children(self):
108 num_children_vo = self.valobj.CreateChildAtOffset("count",
109 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000110 self.sys_params.types_cache.NSUInteger)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000111 value = num_children_vo.GetValueAsUnsigned(0)
112 if value != None:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000113 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
114 # not sure if it is a bug or some weird sort of feature, but masking that out
115 # gets the count right
116 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000117 value = value & ~0xFC00000000000000
118 else:
119 value = value & ~0xFC000000
120 return value
Enrico Granataeb4a4792012-02-23 23:10:27 +0000121
Enrico Granataeb4a4792012-02-23 23:10:27 +0000122class NSDictionaryUnknown_SummaryProvider:
123 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000124 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000125
Enrico Granatacfdafa32012-03-05 19:56:33 +0000126 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +0000127 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000128 self.sys_params = params
129 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000130
131 def update(self):
132 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000133
134 def num_children(self):
135 stream = lldb.SBStream()
136 self.valobj.GetExpressionPath(stream)
137 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
138 return num_children_vo.GetValueAsUnsigned(0)
139
140
141def GetSummary_Impl(valobj):
142 global statistics
143 class_data = objc_runtime.ObjCRuntime(valobj)
144 if class_data.is_valid() == False:
145 statistics.metric_hit('invalid_pointer',valobj)
146 wrapper = None
147 return
148 class_data = class_data.read_class_data()
149 if class_data.is_valid() == False:
150 statistics.metric_hit('invalid_isa',valobj)
151 wrapper = None
152 return
153 if class_data.is_kvo():
154 class_data = class_data.get_superclass()
155 if class_data.is_valid() == False:
156 statistics.metric_hit('invalid_isa',valobj)
157 wrapper = None
158 return
159
160 name_string = class_data.class_name()
161 if name_string == '__NSCFDictionary':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000162 wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000163 statistics.metric_hit('code_notrun',valobj)
164 elif name_string == '__NSDictionaryI':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000165 wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000166 statistics.metric_hit('code_notrun',valobj)
167 elif name_string == '__NSDictionaryM':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000168 wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000169 statistics.metric_hit('code_notrun',valobj)
170 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000171 wrapper = NSDictionaryUnknown_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000172 statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
173 return wrapper;
174
175def CFDictionary_SummaryProvider (valobj,dict):
176 provider = GetSummary_Impl(valobj);
177 if provider != None:
178 try:
Enrico Granataeb06e252012-03-07 00:56:09 +0000179 summary = provider.num_children();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000180 except:
181 summary = None
182 if summary == None:
183 summary = 'no valid dictionary here'
Enrico Granataeb06e252012-03-07 00:56:09 +0000184 return str(summary) + (" key/value pairs" if summary > 1 else " key/value pair")
Enrico Granataeb4a4792012-02-23 23:10:27 +0000185 return ''
186
187def CFDictionary_SummaryProvider2 (valobj,dict):
188 provider = GetSummary_Impl(valobj);
189 if provider != None:
190 try:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000191 summary = provider.num_children();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000192 except:
193 summary = None
194 if summary == None:
195 summary = 'no valid dictionary here'
Enrico Granataeb06e252012-03-07 00:56:09 +0000196 else:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000197 # needed on OSX Mountain Lion
Enrico Granataeb06e252012-03-07 00:56:09 +0000198 if provider.sys_params.is_64_bit:
199 summary = summary & ~0x0f1f000000000000
Enrico Granata8c69c962012-03-13 00:25:59 +0000200 summary = '@"' + str(summary) + (' entries"' if summary > 1 else ' entry"')
Enrico Granataeb06e252012-03-07 00:56:09 +0000201 return summary
Enrico Granataeb4a4792012-02-23 23:10:27 +0000202 return ''
203
204def __lldb_init_module(debugger,dict):
205 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
206 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")