blob: aa059e2e79ca6c61f42e0b797f4bdb57ff9c7448 [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
9
10statistics = metrics.Metrics()
11statistics.add_metric('invalid_isa')
12statistics.add_metric('invalid_pointer')
13statistics.add_metric('unknown_class')
14statistics.add_metric('code_notrun')
15
16# Python promises to start counting time at midnight on Jan 1st on the epoch year
17# hence, all we need to know is the epoch year
18python_epoch = time.gmtime(0).tm_year
19
20osx_epoch = datetime.date(2001,1,1).timetuple()
21
22def mkgmtime(t):
23 return time.mktime(t)-time.timezone
24
25osx_epoch = mkgmtime(osx_epoch)
26
27def osx_to_python_time(osx):
28 if python_epoch <= 2011:
29 return osx + osx_epoch
30 else:
31 return osx - osx_epoch
32
33
34# despite the similary to synthetic children providers, these classes are not
35# trying to provide anything but the port number of an NSDate, so they need not
36# obey the interface specification for synthetic children providers
37class NSTaggedDate_SummaryProvider:
38 def adjust_for_architecture(self):
39 self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
40 self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
41 self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
42
43 def __init__(self, valobj, info_bits, data):
44 self.valobj = valobj;
45 self.update();
46 self.info_bits = info_bits
47 self.data = data
48
49 def update(self):
50 self.adjust_for_architecture();
51 self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
52
53 self.char = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar)
54 self.short = self.valobj.GetType().GetBasicType(lldb.eBasicTypeShort)
55 self.ushort = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedShort)
56 self.int = self.valobj.GetType().GetBasicType(lldb.eBasicTypeInt)
57 self.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
58 self.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
59 self.longlong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLongLong)
60 self.ulonglong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLongLong)
61 self.float = self.valobj.GetType().GetBasicType(lldb.eBasicTypeFloat)
62 self.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
63
64 def value(self):
65 # the value of the date-time object is wrapped into the pointer value
66 # unfortunately, it is made as a time-delta after Jan 1 2011 midnight GMT
67 # while all Python knows about is the "epoch", which is a platform-dependent
68 # year (1970 of *nix) whose Jan 1 at midnight is taken as reference
69 return time.ctime(osx_to_python_time(self.data))
70
71
72class NSUntaggedDate_SummaryProvider:
73 def adjust_for_architecture(self):
74 self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
75 self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
76 self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
77
78 def __init__(self, valobj):
79 self.valobj = valobj;
80 self.update()
81
82 def update(self):
83 self.adjust_for_architecture();
84 self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
85 self.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
86 self.double = self.valobj.GetType().GetBasicType(lldb.eBasicTypeDouble)
87
88 def offset(self):
89 if self.is_64_bit:
90 return 8
91 else:
92 return 4
93
94
95 def value(self):
96 value = self.valobj.CreateChildAtOffset("value",
97 self.offset(),
98 self.double)
99 value_double = struct.unpack('d', struct.pack('Q', value.GetValueAsUnsigned(0)))[0]
100 return time.ctime(osx_to_python_time(value_double))
101
102class NSUnknownDate_SummaryProvider:
103 def adjust_for_architecture(self):
104 self.is_64_bit = (self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8)
105 self.is_little = (self.valobj.GetTarget().GetProcess().GetByteOrder() == lldb.eByteOrderLittle)
106 self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize()
107
108 def __init__(self, valobj):
109 self.valobj = valobj;
110 self.update()
111
112 def update(self):
113 self.adjust_for_architecture();
114 self.id_type = self.valobj.GetType().GetBasicType(lldb.eBasicTypeObjCID)
115
116 def value(self):
117 stream = lldb.SBStream()
118 self.valobj.GetExpressionPath(stream)
119 expr = "(NSString*)[" + stream.GetData() + " description]"
120 num_children_vo = self.valobj.CreateValueFromExpression("str",expr);
121 return num_children_vo.GetSummary()
122
123def GetSummary_Impl(valobj):
124 global statistics
125 class_data = objc_runtime.ObjCRuntime(valobj)
126 if class_data.is_valid() == False:
127 statistics.metric_hit('invalid_pointer',valobj)
128 wrapper = None
129 return
130 class_data = class_data.read_class_data()
131 if class_data.is_valid() == False:
132 statistics.metric_hit('invalid_isa',valobj)
133 wrapper = None
134 return
135 if class_data.is_kvo():
136 class_data = class_data.get_superclass()
137 if class_data.is_valid() == False:
138 statistics.metric_hit('invalid_isa',valobj)
139 wrapper = None
140 return
141
142 name_string = class_data.class_name()
143 if name_string == 'NSDate' or name_string == '__NSDate' or name_string == '__NSTaggedDate':
144 if class_data.is_tagged():
145 wrapper = NSTaggedDate_SummaryProvider(valobj,class_data.info_bits(),class_data.value())
146 statistics.metric_hit('code_notrun',valobj)
147 else:
148 wrapper = NSUntaggedDate_SummaryProvider(valobj)
149 statistics.metric_hit('code_notrun',valobj)
150 else:
151 wrapper = NSUnknownDate_SummaryProvider(valobj)
152 statistics.metric_hit('unknown_class',str(valobj) + " seen as " + name_string)
153 return wrapper;
154
155
156def NSDate_SummaryProvider (valobj,dict):
157 provider = GetSummary_Impl(valobj);
158 if provider != None:
159 #try:
160 summary = provider.value();
161 #except:
162 # summary = None
163 if summary == None:
164 summary = 'no valid number here'
165 return str(summary)
166 return ''
167
168
169def __lldb_init_module(debugger,dict):
170 debugger.HandleCommand("type summary add -F NSDate.NSDate_SummaryProvider NSDate")
171