blob: 7edd33803f9cec07fea72cbaa7f21e0d639d7f76 [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 NSNumber
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
Enrico Granataeb4a4792012-02-23 23:10:27 +000014import struct
Enrico Granata28399ad2012-04-25 01:39:27 +000015import lldb.formatters.Logger
Enrico Granataeb4a4792012-02-23 23:10:27 +000016
Enrico Granata28399ad2012-04-25 01:39:27 +000017statistics = lldb.formatters.metrics.Metrics()
Enrico Granataeb4a4792012-02-23 23:10:27 +000018statistics.add_metric('invalid_isa')
19statistics.add_metric('invalid_pointer')
20statistics.add_metric('unknown_class')
21statistics.add_metric('code_notrun')
22
23# despite the similary to synthetic children providers, these classes are not
24# trying to provide anything but the port number of an NSNumber, so they need not
25# obey the interface specification for synthetic children providers
26class NSTaggedNumber_SummaryProvider:
27 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000028 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000029
Enrico Granatacfdafa32012-03-05 19:56:33 +000030 def __init__(self, valobj, info_bits, data, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000031 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000032 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000033 self.sys_params = params
Enrico Granataeb4a4792012-02-23 23:10:27 +000034 self.info_bits = info_bits
35 self.data = data
Enrico Granatacfdafa32012-03-05 19:56:33 +000036 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +000037
38 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000039 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000040 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000041
42 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000043 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000044 # in spite of the plenty of types made available by the public NSNumber API
45 # only a bunch of these are actually used in the internal implementation
46 # unfortunately, the original type information appears to be lost
47 # so we try to at least recover the proper magnitude of the data
48 if self.info_bits == 0:
Enrico Granata811e9052012-07-13 18:53:14 +000049 return '(char)' + str(ord(ctypes.c_char(chr(self.data % 256)).value))
Enrico Granataeb4a4792012-02-23 23:10:27 +000050 if self.info_bits == 4:
Enrico Granata811e9052012-07-13 18:53:14 +000051 return '(short)' + str(ctypes.c_short(self.data % (256*256)).value)
Enrico Granataeb4a4792012-02-23 23:10:27 +000052 if self.info_bits == 8:
Enrico Granata811e9052012-07-13 18:53:14 +000053 return '(int)' + str(ctypes.c_int(self.data % (256*256*256*256)).value)
Enrico Granataeb4a4792012-02-23 23:10:27 +000054 if self.info_bits == 12:
Enrico Granata811e9052012-07-13 18:53:14 +000055 return '(long)' + str(ctypes.c_long(self.data).value)
Enrico Granataeb4a4792012-02-23 23:10:27 +000056 else:
Enrico Granata37c3e912012-12-10 19:23:00 +000057 return 'unexpected value:(info=' + str(self.info_bits) + ", value = " + str(self.data) + ')'
Enrico Granataeb4a4792012-02-23 23:10:27 +000058
59
60class NSUntaggedNumber_SummaryProvider:
61 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000062 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000063
Enrico Granatacfdafa32012-03-05 19:56:33 +000064 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000065 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000066 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000067 self.sys_params = params
68 if not(self.sys_params.types_cache.char):
69 self.sys_params.types_cache.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)
70 if not(self.sys_params.types_cache.short):
71 self.sys_params.types_cache.short = self.valobj.GetType().GetBasicType(lldb.eBasicTypeShort)
72 if not(self.sys_params.types_cache.ushort):
73 self.sys_params.types_cache.ushort = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedShort)
74 if not(self.sys_params.types_cache.int):
75 self.sys_params.types_cache.int = self.valobj.GetType().GetBasicType(lldb.eBasicTypeInt)
76 if not(self.sys_params.types_cache.long):
77 self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
78 if not(self.sys_params.types_cache.ulong):
79 self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
80 if not(self.sys_params.types_cache.longlong):
81 self.sys_params.types_cache.longlong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong)
82 if not(self.sys_params.types_cache.ulonglong):
83 self.sys_params.types_cache.ulonglong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLongLong)
84 if not(self.sys_params.types_cache.float):
85 self.sys_params.types_cache.float = self.valobj.GetType().GetBasicType(lldb.eBasicTypeFloat)
86 if not(self.sys_params.types_cache.double):
87 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
88 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +000089
90 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000091 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000092 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000093
94 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000095 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000096 global statistics
97 # we need to skip the ISA, then the next byte tells us what to read
98 # we then skip one other full pointer worth of data and then fetch the contents
99 # if we are fetching an int64 value, one more pointer must be skipped to get at our data
100 data_type_vo = self.valobj.CreateChildAtOffset("dt",
Enrico Granatacfdafa32012-03-05 19:56:33 +0000101 self.sys_params.pointer_size,
102 self.sys_params.types_cache.char)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000103 data_type = ((data_type_vo.GetValueAsUnsigned(0) % 256) & 0x1F)
Enrico Granatacfdafa32012-03-05 19:56:33 +0000104 data_offset = 2 * self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000105 if data_type == 0B00001:
106 data_vo = self.valobj.CreateChildAtOffset("data",
107 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000108 self.sys_params.types_cache.char)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000109 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granata811e9052012-07-13 18:53:14 +0000110 return '(char)' + str(ord(ctypes.c_char(chr(data_vo.GetValueAsUnsigned(0))).value))
Enrico Granataeb4a4792012-02-23 23:10:27 +0000111 elif data_type == 0B0010:
112 data_vo = self.valobj.CreateChildAtOffset("data",
113 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000114 self.sys_params.types_cache.short)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000115 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granata811e9052012-07-13 18:53:14 +0000116 return '(short)' + str(ctypes.c_short(data_vo.GetValueAsUnsigned(0) % (256*256)).value)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000117 # IF tagged pointers are possible on 32bit+v2 runtime
118 # (of which the only existing instance should be iOS)
119 # then values of this type might be tagged
120 elif data_type == 0B0011:
121 data_vo = self.valobj.CreateChildAtOffset("data",
122 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000123 self.sys_params.types_cache.int)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000124 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granata811e9052012-07-13 18:53:14 +0000125 return '(int)' + str(ctypes.c_int(data_vo.GetValueAsUnsigned(0)% (256*256*256*256)).value)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000126 # apparently, on is_64_bit architectures, these are the only values that will ever
Enrico Granataeb4a4792012-02-23 23:10:27 +0000127 # be represented by a non tagged pointers
Enrico Granata896cd1d2012-03-01 19:32:33 +0000128 elif data_type == 0B10001:
129 data_offset = data_offset + 8 # 8 is needed even if we are on 32bit
130 data_vo = self.valobj.CreateChildAtOffset("data",
131 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000132 self.sys_params.types_cache.longlong)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000133 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granata811e9052012-07-13 18:53:14 +0000134 return '(long)' + str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000135 elif data_type == 0B0100:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000136 if self.sys_params.is_64_bit:
137 data_offset = data_offset + self.sys_params.pointer_size
Enrico Granataeb4a4792012-02-23 23:10:27 +0000138 data_vo = self.valobj.CreateChildAtOffset("data",
139 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000140 self.sys_params.types_cache.longlong)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000141 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granata811e9052012-07-13 18:53:14 +0000142 return '(long)' + str(ctypes.c_long(data_vo.GetValueAsUnsigned(0)).value)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000143 elif data_type == 0B0101:
144 data_vo = self.valobj.CreateChildAtOffset("data",
145 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000146 self.sys_params.types_cache.longlong)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000147 data_plain = int(str(data_vo.GetValueAsUnsigned(0) & 0x00000000FFFFFFFF))
148 packed = struct.pack('I', data_plain)
149 data_float = struct.unpack('f', packed)[0]
150 statistics.metric_hit('code_notrun',self.valobj)
151 return '(float)' + str(data_float)
152 elif data_type == 0B0110:
153 data_vo = self.valobj.CreateChildAtOffset("data",
154 data_offset,
Enrico Granatacfdafa32012-03-05 19:56:33 +0000155 self.sys_params.types_cache.longlong)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000156 data_plain = data_vo.GetValueAsUnsigned(0)
157 data_double = struct.unpack('d', struct.pack('Q', data_plain))[0]
158 statistics.metric_hit('code_notrun',self.valobj)
159 return '(double)' + str(data_double)
Enrico Granataa20e8632012-04-02 23:43:22 +0000160 statistics.metric_hit('unknown_class',str(valobj.GetName()) + " had unknown data_type " + str(data_type))
Enrico Granata37c3e912012-12-10 19:23:00 +0000161 return 'unexpected: dt = ' + str(data_type)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000162
163
164class NSUnknownNumber_SummaryProvider:
165 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000166 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000167
Enrico Granatacfdafa32012-03-05 19:56:33 +0000168 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000169 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000170 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000171 self.sys_params = params
172 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000173
174 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000175 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000176 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000177
178 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000179 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000180 stream = lldb.SBStream()
181 self.valobj.GetExpressionPath(stream)
182 expr = "(NSString*)[" + stream.GetData() + " stringValue]"
Enrico Granata3f1052b2012-03-13 21:52:00 +0000183 num_children_vo = self.valobj.CreateValueFromExpression("str",expr)
184 if num_children_vo.IsValid():
185 return num_children_vo.GetSummary()
186 return '<variable is not NSNumber>'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000187
188def GetSummary_Impl(valobj):
Enrico Granata28399ad2012-04-25 01:39:27 +0000189 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000190 global statistics
Enrico Granata7d222212012-04-25 17:53:41 +0000191 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000192 if wrapper:
193 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000194
195 name_string = class_data.class_name()
Enrico Granata247bd412012-04-02 16:39:29 +0000196 logger >> "class name is: " + str(name_string)
197
Enrico Granataeb4a4792012-02-23 23:10:27 +0000198 if name_string == 'NSNumber' or name_string == '__NSCFNumber':
199 if class_data.is_tagged():
Enrico Granatacfdafa32012-03-05 19:56:33 +0000200 wrapper = NSTaggedNumber_SummaryProvider(valobj,class_data.info_bits(),class_data.value(), class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000201 statistics.metric_hit('code_notrun',valobj)
202 else:
203 # the wrapper might be unable to decipher what is into the NSNumber
204 # and then have to run code on it
Enrico Granatacfdafa32012-03-05 19:56:33 +0000205 wrapper = NSUntaggedNumber_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000206 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000207 wrapper = NSUnknownNumber_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataa7daeeb2012-03-30 00:51:12 +0000208 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000209 return wrapper;
210
211
212def NSNumber_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000213 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000214 provider = GetSummary_Impl(valobj);
215 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000216 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000217 return provider.message()
218 try:
219 summary = provider.value();
Enrico Granata811e9052012-07-13 18:53:14 +0000220 except Exception as foo:
221 print foo
222# except:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000223 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000224 logger >> "got summary " + str(summary)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000225 if summary == None:
226 summary = '<variable is not NSNumber>'
227 return str(summary)
228 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000229
230
231def __lldb_init_module(debugger,dict):
232 debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider NSNumber")
Enrico Granata3f1052b2012-03-13 21:52:00 +0000233 debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFBoolean")
234 debugger.HandleCommand("type summary add -F NSNumber.NSNumber_SummaryProvider __NSCFNumber")
Enrico Granataeb4a4792012-02-23 23:10:27 +0000235