]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - examples/summaries/cocoa/CFDictionary.py
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / examples / summaries / cocoa / CFDictionary.py
1 """
2 LLDB AppKit formatters
3
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.
7 """
8 # example summary provider for NSDictionary
9 # the real summary is now C++ code built into LLDB
10 import lldb
11 import ctypes
12 import lldb.runtime.objc.objc_runtime
13 import lldb.formatters.metrics
14 import lldb.formatters.Logger
15
16 statistics = lldb.formatters.metrics.Metrics()
17 statistics.add_metric('invalid_isa')
18 statistics.add_metric('invalid_pointer')
19 statistics.add_metric('unknown_class')
20 statistics.add_metric('code_notrun')
21
22 # despite the similary to synthetic children providers, these classes are not
23 # trying to provide anything but the count for an NSDictionary, so they need not
24 # obey the interface specification for synthetic children providers
25 class NSCFDictionary_SummaryProvider:
26         def adjust_for_architecture(self):
27                 pass
28
29         def __init__(self, valobj, params):
30                 logger = lldb.formatters.Logger.Logger()
31                 self.valobj = valobj;
32                 self.sys_params = params
33                 if not(self.sys_params.types_cache.NSUInteger):
34                         if self.sys_params.is_64_bit:
35                                 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
36                         else:
37                                 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
38                 self.update();
39
40         def update(self):
41                 logger = lldb.formatters.Logger.Logger()
42                 self.adjust_for_architecture();
43
44         # empirically determined on both 32 and 64bit desktop Mac OS X
45         # probably boils down to 2 pointers and 4 bytes of data, but
46         # the description of __CFDictionary is not readily available so most
47         # of this is guesswork, plain and simple
48         def offset(self):
49                 logger = lldb.formatters.Logger.Logger()
50                 if self.sys_params.is_64_bit:
51                         return 20
52                 else:
53                         return 12
54
55         def num_children(self):
56                 logger = lldb.formatters.Logger.Logger()
57                 num_children_vo = self.valobj.CreateChildAtOffset("count",
58                                                         self.offset(),
59                                                         self.sys_params.types_cache.NSUInteger)
60                 return num_children_vo.GetValueAsUnsigned(0)
61
62
63 class NSDictionaryI_SummaryProvider:
64         def adjust_for_architecture(self):
65                 pass
66
67         def __init__(self, valobj, params):
68                 logger = lldb.formatters.Logger.Logger()
69                 self.valobj = valobj;
70                 self.sys_params = params
71                 if not(self.sys_params.types_cache.NSUInteger):
72                         if self.sys_params.is_64_bit:
73                                 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
74                         else:
75                                 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
76                 self.update();
77
78         def update(self):
79                 logger = lldb.formatters.Logger.Logger()
80                 self.adjust_for_architecture();
81
82         # we just need to skip the ISA and the count immediately follows
83         def offset(self):
84                 logger = lldb.formatters.Logger.Logger()
85                 return self.sys_params.pointer_size
86
87         def num_children(self):
88                 logger = lldb.formatters.Logger.Logger()
89                 num_children_vo = self.valobj.CreateChildAtOffset("count",
90                                                         self.offset(),
91                                                         self.sys_params.types_cache.NSUInteger)
92                 value = num_children_vo.GetValueAsUnsigned(0)
93                 if value != None:
94                         # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
95                         # not sure if it is a bug or some weird sort of feature, but masking that out
96                         # gets the count right
97                         if self.sys_params.is_64_bit:
98                                 value = value & ~0xFC00000000000000
99                         else:
100                                 value = value & ~0xFC000000
101                 return value
102
103 class NSDictionaryM_SummaryProvider:
104         def adjust_for_architecture(self):
105                 pass
106
107         def __init__(self, valobj, params):
108                 logger = lldb.formatters.Logger.Logger()
109                 self.valobj = valobj;
110                 self.sys_params = params
111                 if not(self.sys_params.types_cache.NSUInteger):
112                         if self.sys_params.is_64_bit:
113                                 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
114                         else:
115                                 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
116                 self.update();
117
118         def update(self):
119                 logger = lldb.formatters.Logger.Logger()
120                 self.adjust_for_architecture();
121
122         # we just need to skip the ISA and the count immediately follows
123         def offset(self):
124                 return self.sys_params.pointer_size
125
126         def num_children(self):
127                 logger = lldb.formatters.Logger.Logger()
128                 num_children_vo = self.valobj.CreateChildAtOffset("count",
129                                                         self.offset(),
130                                                         self.sys_params.types_cache.NSUInteger)
131                 value = num_children_vo.GetValueAsUnsigned(0)
132                 if value != None:
133                         # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity
134                         # not sure if it is a bug or some weird sort of feature, but masking that out
135                         # gets the count right
136                         if self.sys_params.is_64_bit:
137                                 value = value & ~0xFC00000000000000
138                         else:
139                                 value = value & ~0xFC000000
140                 return value
141
142 class NSDictionaryUnknown_SummaryProvider:
143         def adjust_for_architecture(self):
144                 pass
145
146         def __init__(self, valobj, params):
147                 logger = lldb.formatters.Logger.Logger()
148                 self.valobj = valobj;
149                 self.sys_params = params
150                 self.update();
151
152         def update(self):
153                 logger = lldb.formatters.Logger.Logger()
154                 self.adjust_for_architecture();
155
156         def num_children(self):
157                 logger = lldb.formatters.Logger.Logger()
158                 stream = lldb.SBStream()
159                 self.valobj.GetExpressionPath(stream)
160                 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
161                 if num_children_vo.IsValid():
162                         return num_children_vo.GetValueAsUnsigned(0)
163                 return '<variable is not NSDictionary>'
164
165
166 def GetSummary_Impl(valobj):
167         logger = lldb.formatters.Logger.Logger()
168         global statistics
169         class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
170         if wrapper:
171                 return wrapper
172         
173         name_string = class_data.class_name()
174         
175         logger >> "class name is: " + str(name_string)
176         
177         if name_string == '__NSCFDictionary':
178                 wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)
179                 statistics.metric_hit('code_notrun',valobj)
180         elif name_string == '__NSDictionaryI':
181                 wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)
182                 statistics.metric_hit('code_notrun',valobj)
183         elif name_string == '__NSDictionaryM':
184                 wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)
185                 statistics.metric_hit('code_notrun',valobj)
186         else:
187                 wrapper = NSDictionaryUnknown_SummaryProvider(valobj, class_data.sys_params)
188                 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string)
189         return wrapper;
190
191 def CFDictionary_SummaryProvider (valobj,dict):
192         logger = lldb.formatters.Logger.Logger()
193         provider = GetSummary_Impl(valobj);
194         if provider != None:
195                 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
196                         return provider.message()
197                 try:
198                         summary = provider.num_children();
199                 except:
200                         summary = None
201                 logger >> "got summary " + str(summary)
202                 if summary == None:
203                         return '<variable is not NSDictionary>'
204                 if isinstance(summary,basestring):
205                         return summary
206                 return str(summary) + (" key/value pairs" if summary != 1 else " key/value pair")
207         return 'Summary Unavailable'
208
209 def CFDictionary_SummaryProvider2 (valobj,dict):
210         logger = lldb.formatters.Logger.Logger()
211         provider = GetSummary_Impl(valobj);
212         if provider != None:
213                 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
214                         return provider.message()
215                 try:
216                         summary = provider.num_children();
217                 except:
218                         summary = None
219                 logger >> "got summary " + str(summary)
220                 if summary == None:
221                         summary = '<variable is not CFDictionary>'
222                 if isinstance(summary,basestring):
223                         return summary
224                 else:
225                 # needed on OSX Mountain Lion
226                         if provider.sys_params.is_64_bit:
227                                 summary = summary & ~0x0f1f000000000000
228                         summary = '@"' + str(summary) + (' entries"' if summary != 1 else ' entry"')
229                 return summary
230         return 'Summary Unavailable'
231
232 def __lldb_init_module(debugger,dict):
233         debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary")
234         debugger.HandleCommand("type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef")