4 part of The LLVM Compiler Infrastructure
5 This file is distributed under the University of Illinois Open Source
6 License. See LICENSE.TXT for details.
8 # example summary provider for NSDate
9 # the real summary is now C++ code built into LLDB
12 import lldb.runtime.objc.objc_runtime
13 import lldb.formatters.metrics
18 import lldb.formatters.Logger
20 statistics = lldb.formatters.metrics.Metrics()
21 statistics.add_metric('invalid_isa')
22 statistics.add_metric('invalid_pointer')
23 statistics.add_metric('unknown_class')
24 statistics.add_metric('code_notrun')
26 # Python promises to start counting time at midnight on Jan 1st on the epoch year
27 # hence, all we need to know is the epoch year
28 python_epoch = time.gmtime(0).tm_year
30 osx_epoch = datetime.date(2001,1,1).timetuple()
33 logger = lldb.formatters.Logger.Logger()
34 return time.mktime(t)-time.timezone
36 osx_epoch = mkgmtime(osx_epoch)
38 def osx_to_python_time(osx):
39 logger = lldb.formatters.Logger.Logger()
40 if python_epoch <= 2001:
41 return osx + osx_epoch
43 return osx - osx_epoch
45 # represent a struct_time as a string in the format used by Xcode
46 def xcode_format_time(X):
47 logger = lldb.formatters.Logger.Logger()
48 return time.strftime('%Y-%m-%d %H:%M:%S %Z',X)
50 # represent a count-since-epoch as a string in the format used by Xcode
51 def xcode_format_count(X):
52 logger = lldb.formatters.Logger.Logger()
53 return xcode_format_time(time.localtime(X))
55 # despite the similary to synthetic children providers, these classes are not
56 # trying to provide anything but the summary for NSDate, so they need not
57 # obey the interface specification for synthetic children providers
58 class NSTaggedDate_SummaryProvider:
59 def adjust_for_architecture(self):
62 def __init__(self, valobj, info_bits, data, params):
63 logger = lldb.formatters.Logger.Logger()
65 self.sys_params = params
67 # NSDate is not using its info_bits for info like NSNumber is
68 # so we need to regroup info_bits and data
69 self.data = ((data << 8) | (info_bits << 4))
72 logger = lldb.formatters.Logger.Logger()
73 self.adjust_for_architecture();
76 logger = lldb.formatters.Logger.Logger()
77 # the value of the date-time object is wrapped into the pointer value
78 # unfortunately, it is made as a time-delta after Jan 1 2001 midnight GMT
79 # while all Python knows about is the "epoch", which is a platform-dependent
80 # year (1970 of *nix) whose Jan 1 at midnight is taken as reference
81 value_double = struct.unpack('d', struct.pack('Q', self.data))[0]
82 if value_double == -63114076800.0:
83 return '0001-12-30 00:00:00 +0000'
84 return xcode_format_count(osx_to_python_time(value_double))
87 class NSUntaggedDate_SummaryProvider:
88 def adjust_for_architecture(self):
91 def __init__(self, valobj, params):
92 logger = lldb.formatters.Logger.Logger()
94 self.sys_params = params
95 if not (self.sys_params.types_cache.double):
96 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
100 logger = lldb.formatters.Logger.Logger()
101 self.adjust_for_architecture();
104 logger = lldb.formatters.Logger.Logger()
105 return self.sys_params.pointer_size
108 logger = lldb.formatters.Logger.Logger()
109 value = self.valobj.CreateChildAtOffset("value",
111 self.sys_params.types_cache.double)
112 value_double = struct.unpack('d', struct.pack('Q', value.GetData().uint64[0]))[0]
113 if value_double == -63114076800.0:
114 return '0001-12-30 00:00:00 +0000'
115 return xcode_format_count(osx_to_python_time(value_double))
117 class NSCalendarDate_SummaryProvider:
118 def adjust_for_architecture(self):
121 def __init__(self, valobj, params):
122 logger = lldb.formatters.Logger.Logger()
123 self.valobj = valobj;
124 self.sys_params = params
125 if not (self.sys_params.types_cache.double):
126 self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
130 logger = lldb.formatters.Logger.Logger()
131 self.adjust_for_architecture();
134 logger = lldb.formatters.Logger.Logger()
135 return 2*self.sys_params.pointer_size
138 logger = lldb.formatters.Logger.Logger()
139 value = self.valobj.CreateChildAtOffset("value",
141 self.sys_params.types_cache.double)
142 value_double = struct.unpack('d', struct.pack('Q', value.GetData().uint64[0]))[0]
143 return xcode_format_count(osx_to_python_time(value_double))
145 class NSTimeZoneClass_SummaryProvider:
146 def adjust_for_architecture(self):
149 def __init__(self, valobj, params):
150 logger = lldb.formatters.Logger.Logger()
151 self.valobj = valobj;
152 self.sys_params = params
153 if not (self.sys_params.types_cache.voidptr):
154 self.sys_params.types_cache.voidptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType()
158 logger = lldb.formatters.Logger.Logger()
159 self.adjust_for_architecture();
162 logger = lldb.formatters.Logger.Logger()
163 return self.sys_params.pointer_size
166 logger = lldb.formatters.Logger.Logger()
167 tz_string = self.valobj.CreateChildAtOffset("tz_name",
169 self.sys_params.types_cache.voidptr)
170 return CFString.CFString_SummaryProvider(tz_string,None)
172 class NSUnknownDate_SummaryProvider:
173 def adjust_for_architecture(self):
176 def __init__(self, valobj):
177 logger = lldb.formatters.Logger.Logger()
178 self.valobj = valobj;
182 logger = lldb.formatters.Logger.Logger()
183 self.adjust_for_architecture();
186 logger = lldb.formatters.Logger.Logger()
187 stream = lldb.SBStream()
188 self.valobj.GetExpressionPath(stream)
189 expr = "(NSString*)[" + stream.GetData() + " description]"
190 num_children_vo = self.valobj.CreateValueFromExpression("str",expr);
191 if num_children_vo.IsValid():
192 return num_children_vo.GetSummary()
193 return '<variable is not NSDate>'
195 def GetSummary_Impl(valobj):
196 logger = lldb.formatters.Logger.Logger()
198 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
202 name_string = class_data.class_name()
203 logger >> "class name is: " + str(name_string)
205 if name_string == 'NSDate' or name_string == '__NSDate' or name_string == '__NSTaggedDate':
206 if class_data.is_tagged():
207 wrapper = NSTaggedDate_SummaryProvider(valobj,class_data.info_bits(),class_data.value(), class_data.sys_params)
208 statistics.metric_hit('code_notrun',valobj)
210 wrapper = NSUntaggedDate_SummaryProvider(valobj, class_data.sys_params)
211 statistics.metric_hit('code_notrun',valobj)
212 elif name_string == 'NSCalendarDate':
213 wrapper = NSCalendarDate_SummaryProvider(valobj, class_data.sys_params)
214 statistics.metric_hit('code_notrun',valobj)
215 elif name_string == '__NSTimeZone':
216 wrapper = NSTimeZoneClass_SummaryProvider(valobj, class_data.sys_params)
217 statistics.metric_hit('code_notrun',valobj)
219 wrapper = NSUnknownDate_SummaryProvider(valobj)
220 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
224 def NSDate_SummaryProvider (valobj,dict):
225 logger = lldb.formatters.Logger.Logger()
226 provider = GetSummary_Impl(valobj);
228 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
229 return provider.message()
231 summary = provider.value();
235 summary = '<variable is not NSDate>'
237 return 'Summary Unavailable'
239 def NSTimeZone_SummaryProvider (valobj,dict):
240 logger = lldb.formatters.Logger.Logger()
241 provider = GetSummary_Impl(valobj);
243 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
244 return provider.message()
246 summary = provider.timezone();
249 logger >> "got summary " + str(summary)
251 summary = '<variable is not NSTimeZone>'
253 return 'Summary Unavailable'
256 def CFAbsoluteTime_SummaryProvider (valobj,dict):
257 logger = lldb.formatters.Logger.Logger()
259 value_double = struct.unpack('d', struct.pack('Q', valobj.GetData().uint64[0]))[0]
260 return xcode_format_count(osx_to_python_time(value_double))
262 return 'Summary Unavailable'
265 def __lldb_init_module(debugger,dict):
266 debugger.HandleCommand("type summary add -F NSDate.NSDate_SummaryProvider NSDate")
267 debugger.HandleCommand("type summary add -F NSDate.CFAbsoluteTime_SummaryProvider CFAbsoluteTime")
268 debugger.HandleCommand("type summary add -F NSDate.NSTimeZone_SummaryProvider NSTimeZone CFTimeZoneRef")