blob: 061f5c56f9d65b141df8cbb7cfe721f96ece92de [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 Granata3467d802012-09-04 18:47:54 +00008# example summary provider for NSDictionary
9# the real summary is now C++ code built into LLDB
Enrico Granataeb4a4792012-02-23 23:10:27 +000010import lldb
11import ctypes
Enrico Granata28399ad2012-04-25 01:39:27 +000012import lldb.runtime.objc.objc_runtime
13import lldb.formatters.metrics
14import lldb.formatters.Logger
Enrico Granataeb4a4792012-02-23 23:10:27 +000015
Enrico Granata28399ad2012-04-25 01:39:27 +000016statistics = lldb.formatters.metrics.Metrics()
Enrico Granataeb4a4792012-02-23 23:10:27 +000017statistics.add_metric('invalid_isa')
18statistics.add_metric('invalid_pointer')
19statistics.add_metric('unknown_class')
20statistics.add_metric('code_notrun')
21
22# despite the similary to synthetic children providers, these classes are not
23# trying to provide anything but the count for an NSDictionary, so they need not
24# obey the interface specification for synthetic children providers
25class NSCFDictionary_SummaryProvider:
26 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000027 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000028
Enrico Granatacfdafa32012-03-05 19:56:33 +000029 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000030 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000031 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000032 self.sys_params = params
33 if not(self.sys_params.types_cache.NSUInteger):
34 if self.sys_params.is_64_bit:
35 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
36 else:
37 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000038 self.update();
39
40 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000041 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000042 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000043
44 # empirically determined on both 32 and 64bit desktop Mac OS X
45 # probably boils down to 2 pointers and 4 bytes of data, but
46 # the description of __CFDictionary is not readily available so most
47 # of this is guesswork, plain and simple
48 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000049 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +000050 if self.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +000051 return 20
52 else:
53 return 12
54
55 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000056 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000057 num_children_vo = self.valobj.CreateChildAtOffset("count",
58 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000059 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000060 return num_children_vo.GetValueAsUnsigned(0)
61
62
63class NSDictionaryI_SummaryProvider:
64 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000065 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000066
Enrico Granatacfdafa32012-03-05 19:56:33 +000067 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000068 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000069 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000070 self.sys_params = params
71 if not(self.sys_params.types_cache.NSUInteger):
72 if self.sys_params.is_64_bit:
73 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
74 else:
75 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000076 self.update();
77
78 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000079 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000080 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000081
82 # we just need to skip the ISA and the count immediately follows
83 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000084 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +000085 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +000086
87 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000088 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000089 num_children_vo = self.valobj.CreateChildAtOffset("count",
90 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000091 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000092 value = num_children_vo.GetValueAsUnsigned(0)
93 if value != None:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000094 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
95 # not sure if it is a bug or some weird sort of feature, but masking that out
96 # gets the count right
Enrico Granatacfdafa32012-03-05 19:56:33 +000097 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000098 value = value & ~0xFC00000000000000
Enrico Granataeb4a4792012-02-23 23:10:27 +000099 else:
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000100 value = value & ~0xFC000000
Enrico Granataeb4a4792012-02-23 23:10:27 +0000101 return value
102
103class NSDictionaryM_SummaryProvider:
104 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000105 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000106
Enrico Granatacfdafa32012-03-05 19:56:33 +0000107 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000108 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000109 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000110 self.sys_params = params
111 if not(self.sys_params.types_cache.NSUInteger):
112 if self.sys_params.is_64_bit:
113 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
114 else:
115 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000116 self.update();
117
118 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000119 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000120 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000121
122 # we just need to skip the ISA and the count immediately follows
123 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000124 return self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000125
126 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000127 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000128 num_children_vo = self.valobj.CreateChildAtOffset("count",
129 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000130 self.sys_params.types_cache.NSUInteger)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000131 value = num_children_vo.GetValueAsUnsigned(0)
132 if value != None:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000133 # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
134 # not sure if it is a bug or some weird sort of feature, but masking that out
135 # gets the count right
136 if self.sys_params.is_64_bit:
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000137 value = value & ~0xFC00000000000000
138 else:
139 value = value & ~0xFC000000
140 return value
Enrico Granataeb4a4792012-02-23 23:10:27 +0000141
Enrico Granataeb4a4792012-02-23 23:10:27 +0000142class NSDictionaryUnknown_SummaryProvider:
143 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000144 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000145
Enrico Granatacfdafa32012-03-05 19:56:33 +0000146 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000147 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000148 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000149 self.sys_params = params
150 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000151
152 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000153 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000154 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000155
156 def num_children(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000157 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000158 stream = lldb.SBStream()
159 self.valobj.GetExpressionPath(stream)
160 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
Enrico Granata3f1052b2012-03-13 21:52:00 +0000161 if num_children_vo.IsValid():
162 return num_children_vo.GetValueAsUnsigned(0)
163 return '<variable is not NSDictionary>'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000164
165
166def GetSummary_Impl(valobj):
Enrico Granata28399ad2012-04-25 01:39:27 +0000167 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000168 global statistics
Enrico Granata7d222212012-04-25 17:53:41 +0000169 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000170 if wrapper:
171 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000172
173 name_string = class_data.class_name()
Enrico Granata247bd412012-04-02 16:39:29 +0000174
175 logger >> "class name is: " + str(name_string)
176
Enrico Granataeb4a4792012-02-23 23:10:27 +0000177 if name_string == '__NSCFDictionary':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000178 wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000179 statistics.metric_hit('code_notrun',valobj)
180 elif name_string == '__NSDictionaryI':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000181 wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000182 statistics.metric_hit('code_notrun',valobj)
183 elif name_string == '__NSDictionaryM':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000184 wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000185 statistics.metric_hit('code_notrun',valobj)
186 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000187 wrapper = NSDictionaryUnknown_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataa7daeeb2012-03-30 00:51:12 +0000188 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000189 return wrapper;
190
191def CFDictionary_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000192 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000193 provider = GetSummary_Impl(valobj);
194 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000195 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000196 return provider.message()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000197 try:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000198 summary = provider.num_children();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000199 except:
200 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000201 logger >> "got summary " + str(summary)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000202 if summary == None:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000203 return '<variable is not NSDictionary>'
204 if isinstance(summary,basestring):
205 return summary
206 return str(summary) + (" key/value pairs" if summary != 1 else " key/value pair")
207 return 'Summary Unavailable'
208
209def CFDictionary_SummaryProvider2 (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000210 logger = lldb.formatters.Logger.Logger()
Enrico Granata3f1052b2012-03-13 21:52:00 +0000211 provider = GetSummary_Impl(valobj);
212 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000213 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000214 return provider.message()
215 try:
216 summary = provider.num_children();
217 except:
218 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000219 logger >> "got summary " + str(summary)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000220 if summary == None:
221 summary = '<variable is not CFDictionary>'
222 if isinstance(summary,basestring):
223 return summary
Enrico Granataeb06e252012-03-07 00:56:09 +0000224 else:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000225 # needed on OSX Mountain Lion
Enrico Granataeb06e252012-03-07 00:56:09 +0000226 if provider.sys_params.is_64_bit:
227 summary = summary & ~0x0f1f000000000000
Enrico Granata3f1052b2012-03-13 21:52:00 +0000228 summary = '@"' + str(summary) + (' entries"' if summary != 1 else ' entry"')
Enrico Granataeb06e252012-03-07 00:56:09 +0000229 return summary
Enrico Granata3f1052b2012-03-13 21:52:00 +0000230 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000231
232def __lldb_init_module(debugger,dict):
233 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
234 debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")