blob: 9607613058b88d2f159f3a893284f89f9f6c6170 [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
Enrico Granata28399ad2012-04-25 01:39:27 +000011import lldb.runtime.objc.objc_runtime
12import lldb.formatters.metrics
13import lldb.formatters.Logger
Enrico Granataeb4a4792012-02-23 23:10:27 +000014
Enrico Granata28399ad2012-04-25 01:39:27 +000015statistics = lldb.formatters.metrics.Metrics()
Enrico Granataeb4a4792012-02-23 23:10:27 +000016statistics.add_metric('invalid_isa')
17statistics.add_metric('invalid_pointer')
18statistics.add_metric('unknown_class')
19statistics.add_metric('code_notrun')
20
21# despite the similary to synthetic children providers, these classes are not
22# trying to provide anything but the count for an NSDictionary, so they need not
23# obey the interface specification for synthetic children providers
24class NSCFDictionary_SummaryProvider:
25 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000026 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000027
Enrico Granatacfdafa32012-03-05 19:56:33 +000028 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000029 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000030 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000031 self.sys_params = params
32 if not(self.sys_params.types_cache.NSUInteger):
33 if self.sys_params.is_64_bit:
34 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
35 else:
36 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000037 self.update();
38
39 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000040 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000041 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000042
43 # empirically determined on both 32 and 64bit desktop Mac OS X
44 # probably boils down to 2 pointers and 4 bytes of data, but
45 # the description of __CFDictionary is not readily available so most
46 # of this is guesswork, plain and simple
47 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000048 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +000049 if self.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +000050 return 20
51 else:
52 return 12
53
54 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000055 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000056 num_children_vo = self.valobj.CreateChildAtOffset("count",
57 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000058 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000059 return num_children_vo.GetValueAsUnsigned(0)
60
61
62class NSDictionaryI_SummaryProvider:
63 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000064 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000065
Enrico Granatacfdafa32012-03-05 19:56:33 +000066 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000067 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000068 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000069 self.sys_params = params
70 if not(self.sys_params.types_cache.NSUInteger):
71 if self.sys_params.is_64_bit:
72 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
73 else:
74 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000075 self.update();
76
77 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000078 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000079 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000080
81 # we just need to skip the ISA and the count immediately follows
82 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000083 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +000084 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +000085
86 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000087 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000088 num_children_vo = self.valobj.CreateChildAtOffset("count",
89 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000090 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000091 value = num_children_vo.GetValueAsUnsigned(0)
92 if value != None:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000093 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
94 # not sure if it is a bug or some weird sort of feature, but masking that out
95 # gets the count right
Enrico Granatacfdafa32012-03-05 19:56:33 +000096 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000097 value = value & ~0xFC00000000000000
Enrico Granataeb4a4792012-02-23 23:10:27 +000098 else:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000099 value = value & ~0xFC000000
Enrico Granataeb4a4792012-02-23 23:10:27 +0000100 return value
101
102class NSDictionaryM_SummaryProvider:
103 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000104 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000105
Enrico Granatacfdafa32012-03-05 19:56:33 +0000106 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000107 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000108 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000109 self.sys_params = params
110 if not(self.sys_params.types_cache.NSUInteger):
111 if self.sys_params.is_64_bit:
112 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
113 else:
114 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000115 self.update();
116
117 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000118 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000119 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000120
121 # we just need to skip the ISA and the count immediately follows
122 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000123 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000124
125 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000126 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000127 num_children_vo = self.valobj.CreateChildAtOffset("count",
128 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000129 self.sys_params.types_cache.NSUInteger)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000130 value = num_children_vo.GetValueAsUnsigned(0)
131 if value != None:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000132 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
133 # not sure if it is a bug or some weird sort of feature, but masking that out
134 # gets the count right
135 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000136 value = value & ~0xFC00000000000000
137 else:
138 value = value & ~0xFC000000
139 return value
Enrico Granataeb4a4792012-02-23 23:10:27 +0000140
Enrico Granataeb4a4792012-02-23 23:10:27 +0000141class NSDictionaryUnknown_SummaryProvider:
142 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000143 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000144
Enrico Granatacfdafa32012-03-05 19:56:33 +0000145 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000146 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000147 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000148 self.sys_params = params
149 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000150
151 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000152 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000153 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000154
155 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000156 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000157 stream = lldb.SBStream()
158 self.valobj.GetExpressionPath(stream)
159 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
Enrico Granata3f1052b2012-03-13 21:52:00 +0000160 if num_children_vo.IsValid():
161 return num_children_vo.GetValueAsUnsigned(0)
162 return '<variable is not NSDictionary>'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000163
164
165def GetSummary_Impl(valobj):
Enrico Granata28399ad2012-04-25 01:39:27 +0000166 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000167 global statistics
Enrico Granata7d222212012-04-25 17:53:41 +0000168 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000169 if wrapper:
170 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000171
172 name_string = class_data.class_name()
Enrico Granata247bd412012-04-02 16:39:29 +0000173
174 logger >> "class name is: " + str(name_string)
175
Enrico Granataeb4a4792012-02-23 23:10:27 +0000176 if name_string == '__NSCFDictionary':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000177 wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000178 statistics.metric_hit('code_notrun',valobj)
179 elif name_string == '__NSDictionaryI':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000180 wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000181 statistics.metric_hit('code_notrun',valobj)
182 elif name_string == '__NSDictionaryM':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000183 wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000184 statistics.metric_hit('code_notrun',valobj)
185 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000186 wrapper = NSDictionaryUnknown_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataa7daeeb2012-03-30 00:51:12 +0000187 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000188 return wrapper;
189
190def CFDictionary_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000191 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000192 provider = GetSummary_Impl(valobj);
193 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000194 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000195 return provider.message()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000196 try:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000197 summary = provider.num_children();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000198 except:
199 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000200 logger >> "got summary " + str(summary)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000201 if summary == None:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000202 return '<variable is not NSDictionary>'
203 if isinstance(summary,basestring):
204 return summary
205 return str(summary) + (" key/value pairs" if summary != 1 else " key/value pair")
206 return 'Summary Unavailable'
207
208def CFDictionary_SummaryProvider2 (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000209 logger = lldb.formatters.Logger.Logger()
Enrico Granata3f1052b2012-03-13 21:52:00 +0000210 provider = GetSummary_Impl(valobj);
211 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000212 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000213 return provider.message()
214 try:
215 summary = provider.num_children();
216 except:
217 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000218 logger >> "got summary " + str(summary)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000219 if summary == None:
220 summary = '<variable is not CFDictionary>'
221 if isinstance(summary,basestring):
222 return summary
Enrico Granataeb06e252012-03-07 00:56:09 +0000223 else:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000224 # needed on OSX Mountain Lion
Enrico Granataeb06e252012-03-07 00:56:09 +0000225 if provider.sys_params.is_64_bit:
226 summary = summary & ~0x0f1f000000000000
Enrico Granata3f1052b2012-03-13 21:52:00 +0000227 summary = '@"' + str(summary) + (' entries"' if summary != 1 else ' entry"')
Enrico Granataeb06e252012-03-07 00:56:09 +0000228 return summary
Enrico Granata3f1052b2012-03-13 21:52:00 +0000229 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000230
231def __lldb_init_module(debugger,dict):
232 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
233 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")