blob: b3c3039466afd2fe12f11934f442f5bac26746b2 [file] [log] [blame]
Enrico Granata7bc0ec32012-02-29 03:28:49 +00001# summary provider for NSDate
2import lldb
3import ctypes
4import objc_runtime
5import metrics
6import struct
7import time
8import datetime
Enrico Granata8d5c83f2012-03-02 00:55:53 +00009import CFString
Enrico Granata7bc0ec32012-02-29 03:28:49 +000010
11statistics = metrics.Metrics()
12statistics.add_metric('invalid_isa')
13statistics.add_metric('invalid_pointer')
14statistics.add_metric('unknown_class')
15statistics.add_metric('code_notrun')
16
17# Python promises to start counting time at midnight on Jan 1st on the epoch year
18# hence, all we need to know is the epoch year
19python_epoch = time.gmtime(0).tm_year
20
21osx_epoch = datetime.date(2001,1,1).timetuple()
22
23def mkgmtime(t):
24 return time.mktime(t)-time.timezone
25
26osx_epoch = mkgmtime(osx_epoch)
27
28def osx_to_python_time(osx):
Enrico Granata896cd1d2012-03-01 19:32:33 +000029 if python_epoch <= 2001:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000030 return osx + osx_epoch
31 else:
32 return osx - osx_epoch
33
Enrico Granata8c69c962012-03-13 00:25:59 +000034# represent a struct_time as a string in the format used by Xcode
35def xcode_format_time(X):
36 return time.strftime('%Y-%m-%d %H:%M:%S %Z',X)
37
38# represent a count-since-epoch as a string in the format used by Xcode
39def xcode_format_count(X):
40 return xcode_format_time(time.localtime(X))
Enrico Granata7bc0ec32012-02-29 03:28:49 +000041
42# despite the similary to synthetic children providers, these classes are not
Enrico Granata896cd1d2012-03-01 19:32:33 +000043# trying to provide anything but the summary for NSDate, so they need not
Enrico Granata7bc0ec32012-02-29 03:28:49 +000044# obey the interface specification for synthetic children providers
45class NSTaggedDate_SummaryProvider:
46 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000047 pass
Enrico Granata7bc0ec32012-02-29 03:28:49 +000048
Enrico Granatacfdafa32012-03-05 19:56:33 +000049 def __init__(self, valobj, info_bits, data, params):
Enrico Granata7bc0ec32012-02-29 03:28:49 +000050 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000051 self.sys_params = params
Enrico Granata7bc0ec32012-02-29 03:28:49 +000052 self.update();
Enrico Granata896cd1d2012-03-01 19:32:33 +000053 # NSDate is not using its info_bits for info like NSNumber is
54 # so we need to regroup info_bits and data
55 self.data = ((data << 8) | (info_bits << 4))
Enrico Granata7bc0ec32012-02-29 03:28:49 +000056
57 def update(self):
58 self.adjust_for_architecture();
Enrico Granata7bc0ec32012-02-29 03:28:49 +000059
60 def value(self):
61 # the value of the date-time object is wrapped into the pointer value
Enrico Granata896cd1d2012-03-01 19:32:33 +000062 # unfortunately, it is made as a time-delta after Jan 1 2001 midnight GMT
Enrico Granata7bc0ec32012-02-29 03:28:49 +000063 # while all Python knows about is the "epoch", which is a platform-dependent
64 # year (1970 of *nix) whose Jan 1 at midnight is taken as reference
Enrico Granata896cd1d2012-03-01 19:32:33 +000065 value_double = struct.unpack('d', struct.pack('Q', self.data))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +000066 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata7bc0ec32012-02-29 03:28:49 +000067
68
69class NSUntaggedDate_SummaryProvider:
70 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000071 pass
Enrico Granata7bc0ec32012-02-29 03:28:49 +000072
Enrico Granatacfdafa32012-03-05 19:56:33 +000073 def __init__(self, valobj, params):
Enrico Granata7bc0ec32012-02-29 03:28:49 +000074 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000075 self.sys_params = params
76 if not (self.sys_params.types_cache.double):
77 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
Enrico Granata7bc0ec32012-02-29 03:28:49 +000078 self.update()
79
80 def update(self):
81 self.adjust_for_architecture();
Enrico Granata7bc0ec32012-02-29 03:28:49 +000082
83 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000084 return self.sys_params.pointer_size
Enrico Granata7bc0ec32012-02-29 03:28:49 +000085
86 def value(self):
87 value = self.valobj.CreateChildAtOffset("value",
88 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000089 self.sys_params.types_cache.double)
Enrico Granata7bc0ec32012-02-29 03:28:49 +000090 value_double = struct.unpack('d', struct.pack('Q', value.GetValueAsUnsigned(0)))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +000091 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata7bc0ec32012-02-29 03:28:49 +000092
Enrico Granata896cd1d2012-03-01 19:32:33 +000093class NSCalendarDate_SummaryProvider:
94 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000095 pass
Enrico Granata896cd1d2012-03-01 19:32:33 +000096
Enrico Granatacfdafa32012-03-05 19:56:33 +000097 def __init__(self, valobj, params):
Enrico Granata896cd1d2012-03-01 19:32:33 +000098 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000099 self.sys_params = params
100 if not (self.sys_params.types_cache.double):
101 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000102 self.update()
103
104 def update(self):
105 self.adjust_for_architecture();
Enrico Granata896cd1d2012-03-01 19:32:33 +0000106
107 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000108 return 2*self.sys_params.pointer_size
Enrico Granata896cd1d2012-03-01 19:32:33 +0000109
110 def value(self):
111 value = self.valobj.CreateChildAtOffset("value",
112 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000113 self.sys_params.types_cache.double)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000114 value_double = struct.unpack('d', struct.pack('Q', value.GetValueAsUnsigned(0)))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +0000115 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata896cd1d2012-03-01 19:32:33 +0000116
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000117class NSTimeZoneClass_SummaryProvider:
118 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000119 pass
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000120
Enrico Granatacfdafa32012-03-05 19:56:33 +0000121 def __init__(self, valobj, params):
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000122 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000123 self.sys_params = params
124 if not (self.sys_params.types_cache.voidptr):
125 self.sys_params.types_cache.voidptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000126 self.update()
127
128 def update(self):
129 self.adjust_for_architecture();
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000130
131 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000132 return self.sys_params.pointer_size
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000133
134 def timezone(self):
135 tz_string = self.valobj.CreateChildAtOffset("tz_name",
136 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000137 self.sys_params.types_cache.voidptr)
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000138 return CFString.CFString_SummaryProvider(tz_string,None)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000139
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000140class NSUnknownDate_SummaryProvider:
141 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000142 pass
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000143
144 def __init__(self, valobj):
145 self.valobj = valobj;
146 self.update()
147
148 def update(self):
149 self.adjust_for_architecture();
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000150
151 def value(self):
152 stream = lldb.SBStream()
153 self.valobj.GetExpressionPath(stream)
154 expr = "(NSString*)[" + stream.GetData() + " description]"
155 num_children_vo = self.valobj.CreateValueFromExpression("str",expr);
156 return num_children_vo.GetSummary()
157
158def GetSummary_Impl(valobj):
159 global statistics
160 class_data = objc_runtime.ObjCRuntime(valobj)
161 if class_data.is_valid() == False:
162 statistics.metric_hit('invalid_pointer',valobj)
163 wrapper = None
164 return
165 class_data = class_data.read_class_data()
166 if class_data.is_valid() == False:
167 statistics.metric_hit('invalid_isa',valobj)
168 wrapper = None
169 return
170 if class_data.is_kvo():
171 class_data = class_data.get_superclass()
172 if class_data.is_valid() == False:
173 statistics.metric_hit('invalid_isa',valobj)
174 wrapper = None
175 return
176
177 name_string = class_data.class_name()
178 if name_string == 'NSDate' or name_string == '__NSDate' or name_string == '__NSTaggedDate':
179 if class_data.is_tagged():
Enrico Granatacfdafa32012-03-05 19:56:33 +0000180 wrapper = NSTaggedDate_SummaryProvider(valobj,class_data.info_bits(),class_data.value(), class_data.sys_params)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000181 statistics.metric_hit('code_notrun',valobj)
182 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000183 wrapper = NSUntaggedDate_SummaryProvider(valobj, class_data.sys_params)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000184 statistics.metric_hit('code_notrun',valobj)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000185 elif name_string == 'NSCalendarDate':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000186 wrapper = NSCalendarDate_SummaryProvider(valobj, class_data.sys_params)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000187 statistics.metric_hit('code_notrun',valobj)
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000188 elif name_string == '__NSTimeZone':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000189 wrapper = NSTimeZoneClass_SummaryProvider(valobj, class_data.sys_params)
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000190 statistics.metric_hit('code_notrun',valobj)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000191 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000192 wrapper = NSUnknownDate_SummaryProvider(valobj, class_data.sys_params)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000193 statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
194 return wrapper;
195
196
197def NSDate_SummaryProvider (valobj,dict):
198 provider = GetSummary_Impl(valobj);
199 if provider != None:
200 #try:
201 summary = provider.value();
202 #except:
203 # summary = None
204 if summary == None:
Enrico Granata896cd1d2012-03-01 19:32:33 +0000205 summary = 'no valid date here'
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000206 return str(summary)
207 return ''
208
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000209def NSTimeZone_SummaryProvider (valobj,dict):
210 provider = GetSummary_Impl(valobj);
211 if provider != None:
212 try:
213 summary = provider.timezone();
214 except:
215 summary = None
216 if summary == None:
217 summary = 'no valid timezone here'
218 return str(summary)
219 return ''
220
221
Enrico Granata896cd1d2012-03-01 19:32:33 +0000222def CFAbsoluteTime_SummaryProvider (valobj,dict):
223 try:
224 value_double = struct.unpack('d', struct.pack('Q', valobj.GetValueAsUnsigned(0)))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +0000225 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata896cd1d2012-03-01 19:32:33 +0000226 except:
227 return 'unable to provide a summary'
228
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000229
230def __lldb_init_module(debugger,dict):
231 debugger.HandleCommand("type summary add -F NSDate.NSDate_SummaryProvider NSDate")
Enrico Granata896cd1d2012-03-01 19:32:33 +0000232 debugger.HandleCommand("type summary add -F NSDate.CFAbsoluteTime_SummaryProvider CFAbsoluteTime")
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000233 debugger.HandleCommand("type summary add -F NSDate.NSTimeZone_SummaryProvider NSTimeZone CFTimeZoneRef")
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000234