blob: 73c818b96470e9f6c4a46059e196d621d05b4e06 [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# synthetic children provider for NSArray
9import lldb
10import ctypes
11import objc_runtime
12import metrics
Enrico Granata247bd412012-04-02 16:39:29 +000013import Logger
Enrico Granataeb4a4792012-02-23 23:10:27 +000014
15statistics = metrics.Metrics()
16statistics.add_metric('invalid_isa')
17statistics.add_metric('invalid_pointer')
18statistics.add_metric('unknown_class')
19statistics.add_metric('code_notrun')
20
21# much less functional than the other two cases below
22# just runs code to get to the count and then returns
23# no children
24class NSArrayKVC_SynthProvider:
25
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, dict, params):
Enrico Granata247bd412012-04-02 16:39:29 +000030 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000031 self.valobj = valobj;
32 self.update()
33
34 def update(self):
Enrico Granata247bd412012-04-02 16:39:29 +000035 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000036 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000037
38 def num_children(self):
Enrico Granata247bd412012-04-02 16:39:29 +000039 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000040 stream = lldb.SBStream()
41 self.valobj.GetExpressionPath(stream)
42 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
Enrico Granata3f1052b2012-03-13 21:52:00 +000043 if num_children_vo.IsValid():
44 return num_children_vo.GetValueAsUnsigned(0)
45 return "<variable is not NSArray>"
Enrico Granataeb4a4792012-02-23 23:10:27 +000046
Enrico Granataeb4a4792012-02-23 23:10:27 +000047# much less functional than the other two cases below
48# just runs code to get to the count and then returns
49# no children
50class NSArrayCF_SynthProvider:
51
52 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000053 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000054
Enrico Granatacfdafa32012-03-05 19:56:33 +000055 def __init__(self, valobj, dict, params):
Enrico Granata247bd412012-04-02 16:39:29 +000056 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000057 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000058 self.sys_params = params
59 if not (self.sys_params.types_cache.ulong):
60 self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
Enrico Granataeb4a4792012-02-23 23:10:27 +000061 self.update()
62
63 def update(self):
Enrico Granata247bd412012-04-02 16:39:29 +000064 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000065 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000066
67 def num_children(self):
Enrico Granata247bd412012-04-02 16:39:29 +000068 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000069 num_children_vo = self.valobj.CreateChildAtOffset("count",
Enrico Granatacfdafa32012-03-05 19:56:33 +000070 self.sys_params.cfruntime_size,
71 self.sys_params.types_cache.ulong)
Enrico Granataeb4a4792012-02-23 23:10:27 +000072 return num_children_vo.GetValueAsUnsigned(0)
73
Enrico Granataeb4a4792012-02-23 23:10:27 +000074class NSArrayI_SynthProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +000075 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000076 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000077
Enrico Granatacfdafa32012-03-05 19:56:33 +000078 def __init__(self, valobj, dict, params):
Enrico Granata247bd412012-04-02 16:39:29 +000079 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000080 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000081 self.sys_params = params
82 if not(self.sys_params.types_cache.long):
83 self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
Enrico Granataeb4a4792012-02-23 23:10:27 +000084 self.update()
85
86 def update(self):
Enrico Granata247bd412012-04-02 16:39:29 +000087 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000088 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000089
90 # skip the isa pointer and get at the size
91 def num_children(self):
Enrico Granata247bd412012-04-02 16:39:29 +000092 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000093 count = self.valobj.CreateChildAtOffset("count",
Enrico Granatacfdafa32012-03-05 19:56:33 +000094 self.sys_params.pointer_size,
95 self.sys_params.types_cache.long);
96 return count.GetValueAsUnsigned(0)
Enrico Granataeb4a4792012-02-23 23:10:27 +000097
98class NSArrayM_SynthProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +000099 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000100 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000101
Enrico Granatacfdafa32012-03-05 19:56:33 +0000102 def __init__(self, valobj, dict, params):
Enrico Granata247bd412012-04-02 16:39:29 +0000103 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000104 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000105 self.sys_params = params
106 if not(self.sys_params.types_cache.long):
107 self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
108 self.update()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000109
110 def update(self):
Enrico Granata247bd412012-04-02 16:39:29 +0000111 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000112 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000113
114 # skip the isa pointer and get at the size
115 def num_children(self):
Enrico Granata247bd412012-04-02 16:39:29 +0000116 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000117 count = self.valobj.CreateChildAtOffset("count",
Enrico Granatacfdafa32012-03-05 19:56:33 +0000118 self.sys_params.pointer_size,
119 self.sys_params.types_cache.long);
120 return count.GetValueAsUnsigned(0)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000121
122# this is the actual synth provider, but is just a wrapper that checks
123# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
124# appropriate backend layer to do the computations
125class NSArray_SynthProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000126 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000127 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000128
129 def __init__(self, valobj, dict):
Enrico Granata247bd412012-04-02 16:39:29 +0000130 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000131 self.valobj = valobj;
132 self.adjust_for_architecture()
Enrico Granata3f1052b2012-03-13 21:52:00 +0000133 self.error = False
134 self.wrapper = self.make_wrapper()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000135 self.invalid = (self.wrapper == None)
136
Enrico Granataeb4a4792012-02-23 23:10:27 +0000137 def num_children(self):
Enrico Granata247bd412012-04-02 16:39:29 +0000138 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000139 if self.wrapper == None:
140 return 0;
141 return self.wrapper.num_children()
142
143 def update(self):
Enrico Granata247bd412012-04-02 16:39:29 +0000144 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000145 if self.wrapper == None:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000146 return
147 self.wrapper.update()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000148
149 # this code acts as our defense against NULL and unitialized
150 # NSArray pointers, which makes it much longer than it would be otherwise
Enrico Granata3f1052b2012-03-13 21:52:00 +0000151 def make_wrapper(self):
Enrico Granata247bd412012-04-02 16:39:29 +0000152 logger = Logger.Logger()
Enrico Granata3f1052b2012-03-13 21:52:00 +0000153 if self.valobj.GetValueAsUnsigned() == 0:
154 self.error = True
155 return objc_runtime.InvalidPointer_Description(True)
156 else:
157 global statistics
158 class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics)
159 if wrapper:
160 self.error = True
161 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000162
163 name_string = class_data.class_name()
Enrico Granata247bd412012-04-02 16:39:29 +0000164
165 logger >> "Class name is " + str(name_string)
166
Enrico Granataeb4a4792012-02-23 23:10:27 +0000167 if name_string == '__NSArrayI':
Enrico Granata3f1052b2012-03-13 21:52:00 +0000168 wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)
169 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000170 elif name_string == '__NSArrayM':
Enrico Granata3f1052b2012-03-13 21:52:00 +0000171 wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)
172 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000173 elif name_string == '__NSCFArray':
Enrico Granata3f1052b2012-03-13 21:52:00 +0000174 wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)
175 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000176 else:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000177 wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)
178 statistics.metric_hit('unknown_class',str(self.valobj) + " seen as " + name_string)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000179 return wrapper;
180
181def CFArray_SummaryProvider (valobj,dict):
Enrico Granata247bd412012-04-02 16:39:29 +0000182 logger = Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000183 provider = NSArray_SynthProvider(valobj,dict);
184 if provider.invalid == False:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000185 if provider.error == True:
186 return provider.wrapper.message()
187 try:
188 summary = int(provider.num_children());
189 except:
190 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000191 logger >> "provider gave me " + str(summary)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000192 if summary == None:
193 summary = '<variable is not NSArray>'
194 elif isinstance(summary,basestring):
195 pass
196 else:
197 # we format it like it were a CFString to make it look the same as the summary from Xcode
198 summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'
199 return summary
200 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000201
202def __lldb_init_module(debugger,dict):
203 debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")