blob: fb35c76591995f8357c526d5f2606199842bd872 [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 NSNumber
9import lldb
10import ctypes
Enrico Granata28399ad2012-04-25 01:39:27 +000011import lldb.runtime.objc.objc_runtime
12import lldb.formatters.metrics
Enrico Granataeb4a4792012-02-23 23:10:27 +000013import struct
Enrico Granata28399ad2012-04-25 01:39:27 +000014import 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 port number of an NSNumber, so they need not
24# obey the interface specification for synthetic children providers
25class NSTaggedNumber_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, info_bits, data, 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
Enrico Granataeb4a4792012-02-23 23:10:27 +000033 self.info_bits = info_bits
34 self.data = data
Enrico Granatacfdafa32012-03-05 19:56:33 +000035 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +000036
37 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000038 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000039 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000040
41 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000042 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000043 # in spite of the plenty of types made available by the public NSNumber API
44 # only a bunch of these are actually used in the internal implementation
45 # unfortunately, the original type information appears to be lost
46 # so we try to at least recover the proper magnitude of the data
47 if self.info_bits == 0:
48 return '(char)' + str(self.data % 256)
49 if self.info_bits == 4:
50 return '(short)' + str(self.data % (256*256))
51 if self.info_bits == 8:
52 return '(int)' + str(self.data % (256*256*256*256))
53 if self.info_bits == 12:
54 return '(long)' + str(self.data)
55 else:
56 return 'absurd value:(info=' + str(self.info_bits) + ", value = " + str(self.data) + ')'
57
58
59class NSUntaggedNumber_SummaryProvider:
60 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000061 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000062
Enrico Granatacfdafa32012-03-05 19:56:33 +000063 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000064 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000065 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000066 self.sys_params = params
67 if not(self.sys_params.types_cache.char):
68 self.sys_params.types_cache.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)
69 if not(self.sys_params.types_cache.short):
70 self.sys_params.types_cache.short = self.valobj.GetType().GetBasicType(lldb.eBasicTypeShort)
71 if not(self.sys_params.types_cache.ushort):
72 self.sys_params.types_cache.ushort = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedShort)
73 if not(self.sys_params.types_cache.int):
74 self.sys_params.types_cache.int = self.valobj.GetType().GetBasicType(lldb.eBasicTypeInt)
75 if not(self.sys_params.types_cache.long):
76 self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
77 if not(self.sys_params.types_cache.ulong):
78 self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
79 if not(self.sys_params.types_cache.longlong):
80 self.sys_params.types_cache.longlong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong)
81 if not(self.sys_params.types_cache.ulonglong):
82 self.sys_params.types_cache.ulonglong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLongLong)
83 if not(self.sys_params.types_cache.float):
84 self.sys_params.types_cache.float = self.valobj.GetType().GetBasicType(lldb.eBasicTypeFloat)
85 if not(self.sys_params.types_cache.double):
86 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
87 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +000088
89 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000090 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000091 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000092
93 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000094 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000095 global statistics
96 # we need to skip the ISA, then the next byte tells us what to read
97 # we then skip one other full pointer worth of data and then fetch the contents
98 # if we are fetching an int64 value, one more pointer must be skipped to get at our data
99 data_type_vo = self.valobj.CreateChildAtOffset("dt",
Enrico Granatacfdafa32012-03-05 19:56:33 +0000100 self.sys_params.pointer_size,
101 self.sys_params.types_cache.char)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000102 data_type = ((data_type_vo.GetValueAsUnsigned(0) % 256) & 0x1F)
Enrico Granatacfdafa32012-03-05 19:56:33 +0000103 data_offset = 2 * self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000104 if data_type == 0B00001:
105 data_vo = self.valobj.CreateChildAtOffset("data",
106 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000107 self.sys_params.types_cache.char)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000108 statistics.metric_hit('code_notrun',self.valobj)
109 return '(char)' + str(data_vo.GetValueAsUnsigned(0))
110 elif data_type == 0B0010:
111 data_vo = self.valobj.CreateChildAtOffset("data",
112 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000113 self.sys_params.types_cache.short)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000114 statistics.metric_hit('code_notrun',self.valobj)
115 return '(short)' + str(data_vo.GetValueAsUnsigned(0) % (256*256))
116 # IF tagged pointers are possible on 32bit+v2 runtime
117 # (of which the only existing instance should be iOS)
118 # then values of this type might be tagged
119 elif data_type == 0B0011:
120 data_vo = self.valobj.CreateChildAtOffset("data",
121 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000122 self.sys_params.types_cache.int)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000123 statistics.metric_hit('code_notrun',self.valobj)
124 return '(int)' + str(data_vo.GetValueAsUnsigned(0) % (256*256*256*256))
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000125 # apparently, on is_64_bit architectures, these are the only values that will ever
Enrico Granataeb4a4792012-02-23 23:10:27 +0000126 # be represented by a non tagged pointers
Enrico Granata896cd1d2012-03-01 19:32:33 +0000127 elif data_type == 0B10001:
128 data_offset = data_offset + 8 # 8 is needed even if we are on 32bit
129 data_vo = self.valobj.CreateChildAtOffset("data",
130 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000131 self.sys_params.types_cache.longlong)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000132 statistics.metric_hit('code_notrun',self.valobj)
133 return '(long)' + str(data_vo.GetValueAsUnsigned(0))
134 elif data_type == 0B0100:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000135 if self.sys_params.is_64_bit:
136 data_offset = data_offset + self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000137 data_vo = self.valobj.CreateChildAtOffset("data",
138 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000139 self.sys_params.types_cache.longlong)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000140 statistics.metric_hit('code_notrun',self.valobj)
141 return '(long)' + str(data_vo.GetValueAsUnsigned(0))
142 elif data_type == 0B0101:
143 data_vo = self.valobj.CreateChildAtOffset("data",
144 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000145 self.sys_params.types_cache.longlong)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000146 data_plain = int(str(data_vo.GetValueAsUnsigned(0) & 0x00000000FFFFFFFF))
147 packed = struct.pack('I', data_plain)
148 data_float = struct.unpack('f', packed)[0]
149 statistics.metric_hit('code_notrun',self.valobj)
150 return '(float)' + str(data_float)
151 elif data_type == 0B0110:
152 data_vo = self.valobj.CreateChildAtOffset("data",
153 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000154 self.sys_params.types_cache.longlong)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000155 data_plain = data_vo.GetValueAsUnsigned(0)
156 data_double = struct.unpack('d', struct.pack('Q', data_plain))[0]
157 statistics.metric_hit('code_notrun',self.valobj)
158 return '(double)' + str(data_double)
Enrico Granataa20e8632012-04-02 23:43:22 +0000159 statistics.metric_hit('unknown_class',str(valobj.GetName()) + " had unknown data_type " + str(data_type))
Enrico Granataeb4a4792012-02-23 23:10:27 +0000160 return 'absurd: dt = ' + str(data_type)
161
162
163class NSUnknownNumber_SummaryProvider:
164 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000165 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000166
Enrico Granatacfdafa32012-03-05 19:56:33 +0000167 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000168 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000169 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000170 self.sys_params = params
171 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000172
173 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000174 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000175 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000176
177 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000178 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000179 stream = lldb.SBStream()
180 self.valobj.GetExpressionPath(stream)
181 expr = "(NSString*)[" + stream.GetData() + " stringValue]"
Enrico Granata3f1052b2012-03-13 21:52:00 +0000182 num_children_vo = self.valobj.CreateValueFromExpression("str",expr)
183 if num_children_vo.IsValid():
184 return num_children_vo.GetSummary()
185 return '<variable is not NSNumber>'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000186
187def GetSummary_Impl(valobj):
Enrico Granata28399ad2012-04-25 01:39:27 +0000188 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000189 global statistics
Enrico Granata7d222212012-04-25 17:53:41 +0000190 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000191 if wrapper:
192 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000193
194 name_string = class_data.class_name()
Enrico Granata247bd412012-04-02 16:39:29 +0000195 logger >> "class name is: " + str(name_string)
196
Enrico Granataeb4a4792012-02-23 23:10:27 +0000197 if name_string == 'NSNumber' or name_string == '__NSCFNumber':
198 if class_data.is_tagged():
Enrico Granatacfdafa32012-03-05 19:56:33 +0000199 wrapper = NSTaggedNumber_SummaryProvider(valobj,class_data.info_bits(),class_data.value(), class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000200 statistics.metric_hit('code_notrun',valobj)
201 else:
202 # the wrapper might be unable to decipher what is into the NSNumber
203 # and then have to run code on it
Enrico Granatacfdafa32012-03-05 19:56:33 +0000204 wrapper = NSUntaggedNumber_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000205 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000206 wrapper = NSUnknownNumber_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataa7daeeb2012-03-30 00:51:12 +0000207 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000208 return wrapper;
209
210
211def NSNumber_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000212 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000213 provider = GetSummary_Impl(valobj);
214 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000215 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000216 return provider.message()
217 try:
218 summary = provider.value();
219 except:
220 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000221 logger >> "got summary " + str(summary)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000222 if summary == None:
223 summary = '<variable is not NSNumber>'
224 return str(summary)
225 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000226
227
228def __lldb_init_module(debugger,dict):
229 debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider NSNumber")
Enrico Granata3f1052b2012-03-13 21:52:00 +0000230 debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFBoolean")
231 debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFNumber")
Enrico Granataeb4a4792012-02-23 23:10:27 +0000232