blob: 400540385c4f35a22861f2bb6577350c4d94708d [file] [log] [blame]
Enrico Granata3f1052b2012-03-13 21:52:00 +00001"""
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"""
Enrico Granataeb4a4792012-02-23 23:10:27 +00008# summary provider for NSDictionary
9import lldb
10import ctypes
11import objc_runtime
12import metrics
13
14statistics = metrics.Metrics()
15statistics.add_metric('invalid_isa')
16statistics.add_metric('invalid_pointer')
17statistics.add_metric('unknown_class')
18statistics.add_metric('code_notrun')
19
20# despite the similary to synthetic children providers, these classes are not
21# trying to provide anything but the count for an NSDictionary, so they need not
22# obey the interface specification for synthetic children providers
23class NSCFDictionary_SummaryProvider:
24 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000025 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000026
Enrico Granatacfdafa32012-03-05 19:56:33 +000027 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000028 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000029 self.sys_params = params
30 if not(self.sys_params.types_cache.NSUInteger):
31 if self.sys_params.is_64_bit:
32 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
33 else:
34 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000035 self.update();
36
37 def update(self):
38 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000039
40 # empirically determined on both 32 and 64bit desktop Mac OS X
41 # probably boils down to 2 pointers and 4 bytes of data, but
42 # the description of __CFDictionary is not readily available so most
43 # of this is guesswork, plain and simple
44 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000045 if self.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +000046 return 20
47 else:
48 return 12
49
50 def num_children(self):
51 num_children_vo = self.valobj.CreateChildAtOffset("count",
52 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000053 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000054 return num_children_vo.GetValueAsUnsigned(0)
55
56
57class NSDictionaryI_SummaryProvider:
58 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000059 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000060
Enrico Granatacfdafa32012-03-05 19:56:33 +000061 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000062 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000063 self.sys_params = params
64 if not(self.sys_params.types_cache.NSUInteger):
65 if self.sys_params.is_64_bit:
66 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
67 else:
68 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000069 self.update();
70
71 def update(self):
72 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000073
74 # we just need to skip the ISA and the count immediately follows
75 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000076 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +000077
78 def num_children(self):
79 num_children_vo = self.valobj.CreateChildAtOffset("count",
80 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000081 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000082 value = num_children_vo.GetValueAsUnsigned(0)
83 if value != None:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000084 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
85 # not sure if it is a bug or some weird sort of feature, but masking that out
86 # gets the count right
Enrico Granatacfdafa32012-03-05 19:56:33 +000087 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000088 value = value & ~0xFC00000000000000
Enrico Granataeb4a4792012-02-23 23:10:27 +000089 else:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000090 value = value & ~0xFC000000
Enrico Granataeb4a4792012-02-23 23:10:27 +000091 return value
92
93class NSDictionaryM_SummaryProvider:
94 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000095 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000096
Enrico Granatacfdafa32012-03-05 19:56:33 +000097 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000098 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000099 self.sys_params = params
100 if not(self.sys_params.types_cache.NSUInteger):
101 if self.sys_params.is_64_bit:
102 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
103 else:
104 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000105 self.update();
106
107 def update(self):
108 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000109
110 # we just need to skip the ISA and the count immediately follows
111 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000112 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000113
114 def num_children(self):
115 num_children_vo = self.valobj.CreateChildAtOffset("count",
116 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000117 self.sys_params.types_cache.NSUInteger)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000118 value = num_children_vo.GetValueAsUnsigned(0)
119 if value != None:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000120 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
121 # not sure if it is a bug or some weird sort of feature, but masking that out
122 # gets the count right
123 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000124 value = value & ~0xFC00000000000000
125 else:
126 value = value & ~0xFC000000
127 return value
Enrico Granataeb4a4792012-02-23 23:10:27 +0000128
Enrico Granataeb4a4792012-02-23 23:10:27 +0000129class NSDictionaryUnknown_SummaryProvider:
130 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000131 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000132
Enrico Granatacfdafa32012-03-05 19:56:33 +0000133 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +0000134 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000135 self.sys_params = params
136 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000137
138 def update(self):
139 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000140
141 def num_children(self):
142 stream = lldb.SBStream()
143 self.valobj.GetExpressionPath(stream)
144 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
Enrico Granata3f1052b2012-03-13 21:52:00 +0000145 if num_children_vo.IsValid():
146 return num_children_vo.GetValueAsUnsigned(0)
147 return '<variable is not NSDictionary>'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000148
149
150def GetSummary_Impl(valobj):
151 global statistics
Enrico Granata3f1052b2012-03-13 21:52:00 +0000152 class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
153 if wrapper:
154 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000155
156 name_string = class_data.class_name()
157 if name_string == '__NSCFDictionary':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000158 wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000159 statistics.metric_hit('code_notrun',valobj)
160 elif name_string == '__NSDictionaryI':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000161 wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000162 statistics.metric_hit('code_notrun',valobj)
163 elif name_string == '__NSDictionaryM':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000164 wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000165 statistics.metric_hit('code_notrun',valobj)
166 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000167 wrapper = NSDictionaryUnknown_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000168 statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
169 return wrapper;
170
171def CFDictionary_SummaryProvider (valobj,dict):
172 provider = GetSummary_Impl(valobj);
173 if provider != None:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000174 if isinstance(provider,objc_runtime.SpecialSituation_Description):
175 return provider.message()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000176 try:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000177 summary = provider.num_children();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000178 except:
179 summary = None
180 if summary == None:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000181 return '<variable is not NSDictionary>'
182 if isinstance(summary,basestring):
183 return summary
184 return str(summary) + (" key/value pairs" if summary != 1 else " key/value pair")
185 return 'Summary Unavailable'
186
187def CFDictionary_SummaryProvider2 (valobj,dict):
188 provider = GetSummary_Impl(valobj);
189 if provider != None:
190 if isinstance(provider,objc_runtime.SpecialSituation_Description):
191 return provider.message()
192 try:
193 summary = provider.num_children();
194 except:
195 summary = None
196 if summary == None:
197 summary = '<variable is not CFDictionary>'
198 if isinstance(summary,basestring):
199 return summary
Enrico Granataeb06e252012-03-07 00:56:09 +0000200 else:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000201 # needed on OSX Mountain Lion
Enrico Granataeb06e252012-03-07 00:56:09 +0000202 if provider.sys_params.is_64_bit:
203 summary = summary & ~0x0f1f000000000000
Enrico Granata3f1052b2012-03-13 21:52:00 +0000204 summary = '@"' + str(summary) + (' entries"' if summary != 1 else ' entry"')
Enrico Granataeb06e252012-03-07 00:56:09 +0000205 return summary
Enrico Granata3f1052b2012-03-13 21:52:00 +0000206 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000207
208def __lldb_init_module(debugger,dict):
209 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
210 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")