blob: ca9906158a90ea8ad8cbde7f836eeb34eca77e5f [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 Granata6a925112013-03-16 01:18:00 +00008# example summary provider for NS(Mutable)IndexSet
9# the real summary is now C++ code built into LLDB
Enrico Granata896cd1d2012-03-01 19:32:33 +000010import lldb
11import ctypes
Enrico Granata28399ad2012-04-25 01:39:27 +000012import lldb.runtime.objc.objc_runtime
13import lldb.formatters.metrics
14import lldb.formatters.Logger
Enrico Granata896cd1d2012-03-01 19:32:33 +000015
Enrico Granata28399ad2012-04-25 01:39:27 +000016statistics = lldb.formatters.metrics.Metrics()
Enrico Granata896cd1d2012-03-01 19:32:33 +000017statistics.add_metric('invalid_isa')
18statistics.add_metric('invalid_pointer')
19statistics.add_metric('unknown_class')
20statistics.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 of values for an NSIndexSet, so they need not
24# obey the interface specification for synthetic children providers
Kate Stoneb9c1b512016-09-06 20:57:50 +000025
26
Enrico Granata896cd1d2012-03-01 19:32:33 +000027class NSIndexSetClass_SummaryProvider:
Enrico Granata896cd1d2012-03-01 19:32:33 +000028
Kate Stoneb9c1b512016-09-06 20:57:50 +000029 def adjust_for_architecture(self):
30 pass
Enrico Granata896cd1d2012-03-01 19:32:33 +000031
Kate Stoneb9c1b512016-09-06 20:57:50 +000032 def __init__(self, valobj, params):
33 logger = lldb.formatters.Logger.Logger()
34 self.valobj = valobj
35 self.sys_params = params
36 if not(self.sys_params.types_cache.NSUInteger):
37 if self.sys_params.is_64_bit:
38 self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
39 ).GetBasicType(lldb.eBasicTypeUnsignedLong)
40 self.sys_params.types_cache.uint32 = self.valobj.GetType(
41 ).GetBasicType(lldb.eBasicTypeUnsignedInt)
42 else:
43 self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
44 ).GetBasicType(lldb.eBasicTypeUnsignedInt)
45 self.sys_params.types_cache.uint32 = self.valobj.GetType(
46 ).GetBasicType(lldb.eBasicTypeUnsignedInt)
47 if not(self.sys_params.types_cache.uint32):
48 self.sys_params.types_cache.uint32 = self.valobj.GetType(
49 ).GetBasicType(lldb.eBasicTypeUnsignedInt)
50 self.update()
Enrico Granata896cd1d2012-03-01 19:32:33 +000051
Kate Stoneb9c1b512016-09-06 20:57:50 +000052 def update(self):
53 logger = lldb.formatters.Logger.Logger()
54 self.adjust_for_architecture()
55
56 # NS(Mutable)IndexSet works in one of two modes: when having a compact block of data (e.g. a Range)
57 # the count is stored in the set itself, 3 pointers into it
58 # otherwise, it will store a pointer to an additional data structure (2 pointers into itself) and this
59 # additional structure will contain the count two pointers deep
60 # a bunch of flags allow us to detect an empty set, vs. a one-range set,
61 # vs. a multi-range set
62 def count(self):
63 logger = lldb.formatters.Logger.Logger()
64 mode_chooser_vo = self.valobj.CreateChildAtOffset(
65 "mode_chooser",
66 self.sys_params.pointer_size,
67 self.sys_params.types_cache.uint32)
68 mode_chooser = mode_chooser_vo.GetValueAsUnsigned(0)
69 if self.sys_params.is_64_bit:
70 mode_chooser = mode_chooser & 0x00000000FFFFFFFF
71 # empty set
72 if mode_chooser & 0x01 == 1:
73 return 0
74 # single range
75 if mode_chooser & 0x02 == 2:
76 mode = 1
77 # multi range
78 else:
79 mode = 2
80 if mode == 1:
81 count_vo = self.valobj.CreateChildAtOffset(
82 "count",
83 3 * self.sys_params.pointer_size,
84 self.sys_params.types_cache.NSUInteger)
85 else:
86 count_ptr = self.valobj.CreateChildAtOffset(
87 "count_ptr",
88 2 * self.sys_params.pointer_size,
89 self.sys_params.types_cache.NSUInteger)
90 count_vo = self.valobj.CreateValueFromAddress(
91 "count",
92 count_ptr.GetValueAsUnsigned() +
93 2 *
94 self.sys_params.pointer_size,
95 self.sys_params.types_cache.NSUInteger)
96 return count_vo.GetValueAsUnsigned(0)
Enrico Granata896cd1d2012-03-01 19:32:33 +000097
98
99class NSIndexSetUnknown_SummaryProvider:
Enrico Granata896cd1d2012-03-01 19:32:33 +0000100
Kate Stoneb9c1b512016-09-06 20:57:50 +0000101 def adjust_for_architecture(self):
102 pass
Enrico Granata896cd1d2012-03-01 19:32:33 +0000103
Kate Stoneb9c1b512016-09-06 20:57:50 +0000104 def __init__(self, valobj, params):
105 logger = lldb.formatters.Logger.Logger()
106 self.valobj = valobj
107 self.sys_params = params
108 self.update()
Enrico Granata896cd1d2012-03-01 19:32:33 +0000109
Kate Stoneb9c1b512016-09-06 20:57:50 +0000110 def update(self):
111 logger = lldb.formatters.Logger.Logger()
112 self.adjust_for_architecture()
113
114 def count(self):
115 logger = lldb.formatters.Logger.Logger()
116 stream = lldb.SBStream()
117 self.valobj.GetExpressionPath(stream)
118 expr = "(int)[" + stream.GetData() + " count]"
119 num_children_vo = self.valobj.CreateValueFromExpression("count", expr)
120 if num_children_vo.IsValid():
121 return num_children_vo.GetValueAsUnsigned(0)
122 return '<variable is not NSIndexSet>'
Enrico Granata896cd1d2012-03-01 19:32:33 +0000123
124
125def GetSummary_Impl(valobj):
Kate Stoneb9c1b512016-09-06 20:57:50 +0000126 logger = lldb.formatters.Logger.Logger()
127 global statistics
128 class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
129 valobj, statistics)
130 if wrapper:
131 return wrapper
Enrico Granata247bd412012-04-02 16:39:29 +0000132
Kate Stoneb9c1b512016-09-06 20:57:50 +0000133 name_string = class_data.class_name()
134 logger >> "class name is: " + str(name_string)
135
136 if name_string == 'NSIndexSet' or name_string == 'NSMutableIndexSet':
137 wrapper = NSIndexSetClass_SummaryProvider(
138 valobj, class_data.sys_params)
139 statistics.metric_hit('code_notrun', valobj)
140 else:
141 wrapper = NSIndexSetUnknown_SummaryProvider(
142 valobj, class_data.sys_params)
143 statistics.metric_hit(
144 'unknown_class',
145 valobj.GetName() +
146 " seen as " +
147 name_string)
148 return wrapper
Enrico Granata896cd1d2012-03-01 19:32:33 +0000149
150
Kate Stoneb9c1b512016-09-06 20:57:50 +0000151def NSIndexSet_SummaryProvider(valobj, dict):
152 logger = lldb.formatters.Logger.Logger()
153 provider = GetSummary_Impl(valobj)
154 if provider is not None:
155 if isinstance(
156 provider,
157 lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
158 return provider.message()
159 try:
160 summary = provider.count()
161 except:
162 summary = None
163 logger >> "got summary " + str(summary)
164 if summary is None:
165 summary = '<variable is not NSIndexSet>'
166 if isinstance(summary, basestring):
167 return summary
168 else:
169 summary = str(summary) + (' indexes' if summary != 1 else ' index')
170 return summary
171 return 'Summary Unavailable'
Enrico Granata896cd1d2012-03-01 19:32:33 +0000172
173
Kate Stoneb9c1b512016-09-06 20:57:50 +0000174def __lldb_init_module(debugger, dict):
175 debugger.HandleCommand(
176 "type summary add -F NSIndexSet.NSIndexSet_SummaryProvider NSIndexSet NSMutableIndexSet")