blob: 082cd1900371901e40ad1853bd666ab2e2b04a46 [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 Granata7bc0ec32012-02-29 03:28:49 +00008# summary provider for NSDate
9import lldb
10import ctypes
Enrico Granata28399ad2012-04-25 01:39:27 +000011import lldb.runtime.objc.objc_runtime
12import lldb.formatters.metrics
Enrico Granata7bc0ec32012-02-29 03:28:49 +000013import struct
14import time
15import datetime
Enrico Granata8d5c83f2012-03-02 00:55:53 +000016import CFString
Enrico Granata28399ad2012-04-25 01:39:27 +000017import lldb.formatters.Logger
Enrico Granata7bc0ec32012-02-29 03:28:49 +000018
Enrico Granata28399ad2012-04-25 01:39:27 +000019statistics = lldb.formatters.metrics.Metrics()
Enrico Granata7bc0ec32012-02-29 03:28:49 +000020statistics.add_metric('invalid_isa')
21statistics.add_metric('invalid_pointer')
22statistics.add_metric('unknown_class')
23statistics.add_metric('code_notrun')
24
25# Python promises to start counting time at midnight on Jan 1st on the epoch year
26# hence, all we need to know is the epoch year
27python_epoch = time.gmtime(0).tm_year
28
29osx_epoch = datetime.date(2001,1,1).timetuple()
30
31def mkgmtime(t):
Enrico Granata28399ad2012-04-25 01:39:27 +000032 logger = lldb.formatters.Logger.Logger()
Enrico Granata247bd412012-04-02 16:39:29 +000033 return time.mktime(t)-time.timezone
Enrico Granata7bc0ec32012-02-29 03:28:49 +000034
35osx_epoch = mkgmtime(osx_epoch)
36
37def osx_to_python_time(osx):
Enrico Granata28399ad2012-04-25 01:39:27 +000038 logger = lldb.formatters.Logger.Logger()
Enrico Granata896cd1d2012-03-01 19:32:33 +000039 if python_epoch <= 2001:
Enrico Granata7bc0ec32012-02-29 03:28:49 +000040 return osx + osx_epoch
41 else:
42 return osx - osx_epoch
43
Enrico Granata8c69c962012-03-13 00:25:59 +000044# represent a struct_time as a string in the format used by Xcode
45def xcode_format_time(X):
Enrico Granata28399ad2012-04-25 01:39:27 +000046 logger = lldb.formatters.Logger.Logger()
Enrico Granata8c69c962012-03-13 00:25:59 +000047 return time.strftime('%Y-%m-%d %H:%M:%S %Z',X)
48
49# represent a count-since-epoch as a string in the format used by Xcode
50def xcode_format_count(X):
Enrico Granata28399ad2012-04-25 01:39:27 +000051 logger = lldb.formatters.Logger.Logger()
Enrico Granata8c69c962012-03-13 00:25:59 +000052 return xcode_format_time(time.localtime(X))
Enrico Granata7bc0ec32012-02-29 03:28:49 +000053
54# despite the similary to synthetic children providers, these classes are not
Enrico Granata896cd1d2012-03-01 19:32:33 +000055# trying to provide anything but the summary for NSDate, so they need not
Enrico Granata7bc0ec32012-02-29 03:28:49 +000056# obey the interface specification for synthetic children providers
57class NSTaggedDate_SummaryProvider:
58 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000059 pass
Enrico Granata7bc0ec32012-02-29 03:28:49 +000060
Enrico Granatacfdafa32012-03-05 19:56:33 +000061 def __init__(self, valobj, info_bits, data, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000062 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +000063 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000064 self.sys_params = params
Enrico Granata7bc0ec32012-02-29 03:28:49 +000065 self.update();
Enrico Granata896cd1d2012-03-01 19:32:33 +000066 # NSDate is not using its info_bits for info like NSNumber is
67 # so we need to regroup info_bits and data
68 self.data = ((data << 8) | (info_bits << 4))
Enrico Granata7bc0ec32012-02-29 03:28:49 +000069
70 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000071 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +000072 self.adjust_for_architecture();
Enrico Granata7bc0ec32012-02-29 03:28:49 +000073
74 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000075 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +000076 # the value of the date-time object is wrapped into the pointer value
Enrico Granata896cd1d2012-03-01 19:32:33 +000077 # unfortunately, it is made as a time-delta after Jan 1 2001 midnight GMT
Enrico Granata7bc0ec32012-02-29 03:28:49 +000078 # while all Python knows about is the "epoch", which is a platform-dependent
79 # year (1970 of *nix) whose Jan 1 at midnight is taken as reference
Enrico Granata896cd1d2012-03-01 19:32:33 +000080 value_double = struct.unpack('d', struct.pack('Q', self.data))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +000081 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata7bc0ec32012-02-29 03:28:49 +000082
83
84class NSUntaggedDate_SummaryProvider:
85 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000086 pass
Enrico Granata7bc0ec32012-02-29 03:28:49 +000087
Enrico Granatacfdafa32012-03-05 19:56:33 +000088 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000089 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +000090 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000091 self.sys_params = params
92 if not (self.sys_params.types_cache.double):
93 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
Enrico Granata7bc0ec32012-02-29 03:28:49 +000094 self.update()
95
96 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000097 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +000098 self.adjust_for_architecture();
Enrico Granata7bc0ec32012-02-29 03:28:49 +000099
100 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000101 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +0000102 return self.sys_params.pointer_size
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000103
104 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000105 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000106 value = self.valobj.CreateChildAtOffset("value",
107 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000108 self.sys_params.types_cache.double)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000109 value_double = struct.unpack('d', struct.pack('Q', value.GetValueAsUnsigned(0)))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +0000110 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000111
Enrico Granata896cd1d2012-03-01 19:32:33 +0000112class NSCalendarDate_SummaryProvider:
113 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000114 pass
Enrico Granata896cd1d2012-03-01 19:32:33 +0000115
Enrico Granatacfdafa32012-03-05 19:56:33 +0000116 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000117 logger = lldb.formatters.Logger.Logger()
Enrico Granata896cd1d2012-03-01 19:32:33 +0000118 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000119 self.sys_params = params
120 if not (self.sys_params.types_cache.double):
121 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000122 self.update()
123
124 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000125 logger = lldb.formatters.Logger.Logger()
Enrico Granata896cd1d2012-03-01 19:32:33 +0000126 self.adjust_for_architecture();
Enrico Granata896cd1d2012-03-01 19:32:33 +0000127
128 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000129 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +0000130 return 2*self.sys_params.pointer_size
Enrico Granata896cd1d2012-03-01 19:32:33 +0000131
132 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000133 logger = lldb.formatters.Logger.Logger()
Enrico Granata896cd1d2012-03-01 19:32:33 +0000134 value = self.valobj.CreateChildAtOffset("value",
135 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000136 self.sys_params.types_cache.double)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000137 value_double = struct.unpack('d', struct.pack('Q', value.GetValueAsUnsigned(0)))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +0000138 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata896cd1d2012-03-01 19:32:33 +0000139
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000140class NSTimeZoneClass_SummaryProvider:
141 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000142 pass
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000143
Enrico Granatacfdafa32012-03-05 19:56:33 +0000144 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +0000145 logger = lldb.formatters.Logger.Logger()
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000146 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +0000147 self.sys_params = params
148 if not (self.sys_params.types_cache.voidptr):
149 self.sys_params.types_cache.voidptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000150 self.update()
151
152 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000153 logger = lldb.formatters.Logger.Logger()
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000154 self.adjust_for_architecture();
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000155
156 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000157 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +0000158 return self.sys_params.pointer_size
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000159
160 def timezone(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000161 logger = lldb.formatters.Logger.Logger()
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000162 tz_string = self.valobj.CreateChildAtOffset("tz_name",
163 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +0000164 self.sys_params.types_cache.voidptr)
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000165 return CFString.CFString_SummaryProvider(tz_string,None)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000166
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000167class NSUnknownDate_SummaryProvider:
168 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000169 pass
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000170
171 def __init__(self, valobj):
Enrico Granata28399ad2012-04-25 01:39:27 +0000172 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000173 self.valobj = valobj;
174 self.update()
175
176 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000177 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000178 self.adjust_for_architecture();
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000179
180 def value(self):
Enrico Granata28399ad2012-04-25 01:39:27 +0000181 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000182 stream = lldb.SBStream()
183 self.valobj.GetExpressionPath(stream)
184 expr = "(NSString*)[" + stream.GetData() + " description]"
185 num_children_vo = self.valobj.CreateValueFromExpression("str",expr);
Enrico Granata3f1052b2012-03-13 21:52:00 +0000186 if num_children_vo.IsValid():
187 return num_children_vo.GetSummary()
188 return '<variable is not NSDate>'
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000189
190def GetSummary_Impl(valobj):
Enrico Granata28399ad2012-04-25 01:39:27 +0000191 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000192 global statistics
Enrico Granata7d222212012-04-25 17:53:41 +0000193 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000194 if wrapper:
195 return wrapper
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000196
197 name_string = class_data.class_name()
Enrico Granata247bd412012-04-02 16:39:29 +0000198 logger >> "class name is: " + str(name_string)
199
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000200 if name_string == 'NSDate' or name_string == '__NSDate' or name_string == '__NSTaggedDate':
201 if class_data.is_tagged():
Enrico Granatacfdafa32012-03-05 19:56:33 +0000202 wrapper = NSTaggedDate_SummaryProvider(valobj,class_data.info_bits(),class_data.value(), class_data.sys_params)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000203 statistics.metric_hit('code_notrun',valobj)
204 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000205 wrapper = NSUntaggedDate_SummaryProvider(valobj, class_data.sys_params)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000206 statistics.metric_hit('code_notrun',valobj)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000207 elif name_string == 'NSCalendarDate':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000208 wrapper = NSCalendarDate_SummaryProvider(valobj, class_data.sys_params)
Enrico Granata896cd1d2012-03-01 19:32:33 +0000209 statistics.metric_hit('code_notrun',valobj)
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000210 elif name_string == '__NSTimeZone':
Enrico Granatacfdafa32012-03-05 19:56:33 +0000211 wrapper = NSTimeZoneClass_SummaryProvider(valobj, class_data.sys_params)
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000212 statistics.metric_hit('code_notrun',valobj)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000213 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000214 wrapper = NSUnknownDate_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataa7daeeb2012-03-30 00:51:12 +0000215 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000216 return wrapper;
217
218
219def NSDate_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000220 logger = lldb.formatters.Logger.Logger()
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000221 provider = GetSummary_Impl(valobj);
222 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000223 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000224 return provider.message()
225 try:
226 summary = provider.value();
227 except:
228 summary = None
229 if summary == None:
230 summary = '<variable is not NSDate>'
231 return str(summary)
232 return 'Summary Unavailable'
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000233
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000234def NSTimeZone_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000235 logger = lldb.formatters.Logger.Logger()
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000236 provider = GetSummary_Impl(valobj);
237 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000238 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000239 return provider.message()
240 try:
241 summary = provider.timezone();
242 except:
243 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000244 logger >> "got summary " + str(summary)
Enrico Granata3f1052b2012-03-13 21:52:00 +0000245 if summary == None:
246 summary = '<variable is not NSTimeZone>'
247 return str(summary)
248 return 'Summary Unavailable'
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000249
250
Enrico Granata896cd1d2012-03-01 19:32:33 +0000251def CFAbsoluteTime_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000252 logger = lldb.formatters.Logger.Logger()
Enrico Granata896cd1d2012-03-01 19:32:33 +0000253 try:
254 value_double = struct.unpack('d', struct.pack('Q', valobj.GetValueAsUnsigned(0)))[0]
Enrico Granata8c69c962012-03-13 00:25:59 +0000255 return xcode_format_count(osx_to_python_time(value_double))
Enrico Granata896cd1d2012-03-01 19:32:33 +0000256 except:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000257 return 'Summary Unavailable'
Enrico Granata896cd1d2012-03-01 19:32:33 +0000258
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000259
260def __lldb_init_module(debugger,dict):
261 debugger.HandleCommand("type summary add -F NSDate.NSDate_SummaryProvider NSDate")
Enrico Granata896cd1d2012-03-01 19:32:33 +0000262 debugger.HandleCommand("type summary add -F NSDate.CFAbsoluteTime_SummaryProvider CFAbsoluteTime")
Enrico Granata8d5c83f2012-03-02 00:55:53 +0000263 debugger.HandleCommand("type summary add -F NSDate.NSTimeZone_SummaryProvider NSTimeZone CFTimeZoneRef")
Enrico Granata7bc0ec32012-02-29 03:28:49 +0000264