blob: e0cfd3dece189b42ce81db194fa289af425e7c1f [file] [log] [blame]
Enrico Granataeb4a4792012-02-23 23:10:27 +00001# summary provider for CFBag
2import lldb
3import ctypes
4import objc_runtime
5import metrics
6
7statistics = metrics.Metrics()
8statistics.add_metric('invalid_isa')
9statistics.add_metric('invalid_pointer')
10statistics.add_metric('unknown_class')
11statistics.add_metric('code_notrun')
12
13# despite the similary to synthetic children providers, these classes are not
14# trying to provide anything but the length for an CFBag, so they need not
15# obey the interface specification for synthetic children providers
16class CFBagRef_SummaryProvider:
17 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000018 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000019
Enrico Granatacfdafa32012-03-05 19:56:33 +000020 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000021 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000022 self.sys_params = params
23 if not(self.sys_params.types_cache.NSUInteger):
24 if self.sys_params.is_64_bit:
25 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
26 else:
27 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000028 self.update();
29
30 def update(self):
31 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000032
33 # 12 bytes on i386
34 # 20 bytes on x64
35 # most probably 2 pointers and 4 bytes of data
36 def offset(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000037 if self.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +000038 return 20
39 else:
40 return 12
41
42 def length(self):
43 size = self.valobj.CreateChildAtOffset("count",
44 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000045 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000046 return size.GetValueAsUnsigned(0)
47
48
49class CFBagUnknown_SummaryProvider:
50 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000051 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000052
Enrico Granatacfdafa32012-03-05 19:56:33 +000053 def __init__(self, valobj, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000054 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000055 self.sys_params = params
56 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +000057
58 def update(self):
59 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000060
61 def length(self):
62 stream = lldb.SBStream()
63 self.valobj.GetExpressionPath(stream)
64 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBagGetCount(" + stream.GetData() + " )");
65 return num_children_vo.GetValueAsUnsigned(0)
66
67
68def GetSummary_Impl(valobj):
69 global statistics
70 class_data = objc_runtime.ObjCRuntime(valobj)
71 if class_data.is_valid() == False:
72 statistics.metric_hit('invalid_pointer',valobj)
73 wrapper = None
74 return
75 class_data = class_data.read_class_data()
76 if class_data.is_valid() == False:
77 statistics.metric_hit('invalid_isa',valobj)
78 wrapper = None
79 return
80 if class_data.is_kvo():
81 class_data = class_data.get_superclass()
82 if class_data.is_valid() == False:
83 statistics.metric_hit('invalid_isa',valobj)
84 wrapper = None
85 return
86
87 name_string = class_data.class_name()
88 actual_name = name_string
89 if name_string == '__NSCFType':
90 # CFBag does not expose an actual NSWrapper type, so we have to check that this is
91 # an NSCFType and then check we are a pointer-to __CFBag
92 valobj_type = valobj.GetType()
93 if valobj_type.IsValid() and valobj_type.IsPointerType():
94 pointee_type = valobj_type.GetPointeeType()
95 actual_name = pointee_type.GetName()
96 if actual_name == '__CFBag' or \
97 actual_name == 'const struct __CFBag':
Enrico Granatacfdafa32012-03-05 19:56:33 +000098 wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +000099 statistics.metric_hit('code_notrun',valobj)
100 return wrapper
Enrico Granatacfdafa32012-03-05 19:56:33 +0000101 wrapper = CFBagUnknown_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000102 statistics.metric_hit('unknown_class',str(valobj) + " seen as " + actual_name)
103 return wrapper;
104
105def CFBag_SummaryProvider (valobj,dict):
106 provider = GetSummary_Impl(valobj);
107 if provider != None:
108 try:
109 summary = provider.length();
110 except:
111 summary = None
112 # for some reason, one needs to clear some bits for the count
113 # to be correct when using CF(Mutable)BagRef on x64
114 # the bit mask was derived through experimentation
115 # (if counts start looking weird, then most probably
116 # the mask needs to be changed)
117 if summary == None:
118 summary = 'no valid set here'
119 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000120 if provider.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000121 summary = summary & ~0x1fff000000000000
Enrico Granataeb06e252012-03-07 00:56:09 +0000122 if summary == 1:
Enrico Granata8c69c962012-03-13 00:25:59 +0000123 summary = '@"1 value"'
Enrico Granataeb06e252012-03-07 00:56:09 +0000124 else:
Enrico Granata8c69c962012-03-13 00:25:59 +0000125 summary = '@"' + str(summary) + ' values"'
Enrico Granataeb06e252012-03-07 00:56:09 +0000126 return summary
Enrico Granataeb4a4792012-02-23 23:10:27 +0000127 return ''
128
129def __lldb_init_module(debugger,dict):
130 debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")