blob: 7c7493e2a778ae6e5b5e7c256ead1f7d56cce1ea [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 Granataeb4a4792012-02-23 23:10:27 +00008# summary provider for CFBag
9import lldb
10import ctypes
Enrico Granata28399ad2012-04-25 01:39:27 +000011import lldb.runtime.objc.objc_runtime
12import lldb.formatters.metrics
13import lldb.formatters.Logger
Enrico Granataeb4a4792012-02-23 23:10:27 +000014
Enrico Granata28399ad2012-04-25 01:39:27 +000015statistics = lldb.formatters.metrics.Metrics()
Enrico Granataeb4a4792012-02-23 23:10:27 +000016statistics.add_metric('invalid_isa')
17statistics.add_metric('invalid_pointer')
18statistics.add_metric('unknown_class')
19statistics.add_metric('code_notrun')
20
21# despite the similary to synthetic children providers, these classes are not
22# trying to provide anything but the length for an CFBag, so they need not
23# obey the interface specification for synthetic children providers
24class CFBagRef_SummaryProvider:
25 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000026 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000027
Enrico Granatacfdafa32012-03-05 19:56:33 +000028 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000029 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000030 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000031 self.sys_params = params
32 if not(self.sys_params.types_cache.NSUInteger):
33 if self.sys_params.is_64_bit:
34 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
35 else:
36 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
Enrico Granataeb4a4792012-02-23 23:10:27 +000037 self.update();
38
39 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000040 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000041 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000042
43 # 12 bytes on i386
44 # 20 bytes on x64
45 # most probably 2 pointers and 4 bytes of data
46 def offset(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000047 logger = lldb.formatters.Logger.Logger()
Enrico Granatacfdafa32012-03-05 19:56:33 +000048 if self.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +000049 return 20
50 else:
51 return 12
52
53 def length(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000054 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000055 size = self.valobj.CreateChildAtOffset("count",
56 self.offset(),
Enrico Granatacfdafa32012-03-05 19:56:33 +000057 self.sys_params.types_cache.NSUInteger)
Enrico Granataeb4a4792012-02-23 23:10:27 +000058 return size.GetValueAsUnsigned(0)
59
60
61class CFBagUnknown_SummaryProvider:
62 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000063 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000064
Enrico Granatacfdafa32012-03-05 19:56:33 +000065 def __init__(self, valobj, params):
Enrico Granata28399ad2012-04-25 01:39:27 +000066 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000067 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000068 self.sys_params = params
69 self.update();
Enrico Granataeb4a4792012-02-23 23:10:27 +000070
71 def update(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000072 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000073 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000074
75 def length(self):
Enrico Granata28399ad2012-04-25 01:39:27 +000076 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000077 stream = lldb.SBStream()
78 self.valobj.GetExpressionPath(stream)
Enrico Granata3f1052b2012-03-13 21:52:00 +000079 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)CFBagGetCount(" + stream.GetData() + " )")
80 if num_children_vo.IsValid():
81 return num_children_vo.GetValueAsUnsigned(0)
82 return "<variable is not CFBag>"
Enrico Granataeb4a4792012-02-23 23:10:27 +000083
84
85def GetSummary_Impl(valobj):
Enrico Granata28399ad2012-04-25 01:39:27 +000086 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +000087 global statistics
Enrico Granata7d222212012-04-25 17:53:41 +000088 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics)
Enrico Granata3f1052b2012-03-13 21:52:00 +000089 if wrapper:
90 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +000091
92 name_string = class_data.class_name()
93 actual_name = name_string
Enrico Granata247bd412012-04-02 16:39:29 +000094
95 logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name)
96
Enrico Granata3f1052b2012-03-13 21:52:00 +000097 if class_data.is_cftype():
Enrico Granataeb4a4792012-02-23 23:10:27 +000098 # CFBag does not expose an actual NSWrapper type, so we have to check that this is
99 # an NSCFType and then check we are a pointer-to __CFBag
100 valobj_type = valobj.GetType()
101 if valobj_type.IsValid() and valobj_type.IsPointerType():
Enrico Granata3f1052b2012-03-13 21:52:00 +0000102 valobj_type = valobj_type.GetPointeeType()
103 if valobj_type.IsValid():
104 actual_name = valobj_type.GetName()
105 if actual_name == '__CFBag' or \
106 actual_name == 'const struct __CFBag':
107 wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
108 statistics.metric_hit('code_notrun',valobj)
109 return wrapper
Enrico Granatacfdafa32012-03-05 19:56:33 +0000110 wrapper = CFBagUnknown_SummaryProvider(valobj, class_data.sys_params)
Enrico Granataa7daeeb2012-03-30 00:51:12 +0000111 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + actual_name)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000112 return wrapper;
113
114def CFBag_SummaryProvider (valobj,dict):
Enrico Granata28399ad2012-04-25 01:39:27 +0000115 logger = lldb.formatters.Logger.Logger()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000116 provider = GetSummary_Impl(valobj);
117 if provider != None:
Enrico Granata7d222212012-04-25 17:53:41 +0000118 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
Enrico Granata3f1052b2012-03-13 21:52:00 +0000119 return provider.message()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000120 try:
121 summary = provider.length();
122 except:
123 summary = None
Enrico Granata247bd412012-04-02 16:39:29 +0000124 logger >> "summary got from provider: " + str(summary)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000125 # for some reason, one needs to clear some bits for the count
126 # to be correct when using CF(Mutable)BagRef on x64
127 # the bit mask was derived through experimentation
128 # (if counts start looking weird, then most probably
129 # the mask needs to be changed)
130 if summary == None:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000131 summary = '<variable is not CFBag>'
132 elif isinstance(summary,basestring):
133 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000134 else:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000135 if provider.sys_params.is_64_bit:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000136 summary = summary & ~0x1fff000000000000
Enrico Granataeb06e252012-03-07 00:56:09 +0000137 if summary == 1:
Enrico Granata8c69c962012-03-13 00:25:59 +0000138 summary = '@"1 value"'
Enrico Granataeb06e252012-03-07 00:56:09 +0000139 else:
Enrico Granata8c69c962012-03-13 00:25:59 +0000140 summary = '@"' + str(summary) + ' values"'
Enrico Granataeb06e252012-03-07 00:56:09 +0000141 return summary
Enrico Granata3f1052b2012-03-13 21:52:00 +0000142 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000143
144def __lldb_init_module(debugger,dict):
145 debugger.HandleCommand("type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")