4 Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5 See https://llvm.org/LICENSE.txt for license information.
6 SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8 # example summary provider for CFBinaryHeap
9 # the real summary is now C++ code built into LLDB
12 import lldb
.runtime
.objc
.objc_runtime
13 import lldb
.formatters
.metrics
14 import lldb
.formatters
.Logger
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")
22 # despite the similary to synthetic children providers, these classes are not
23 # trying to provide anything but the length for an CFBinaryHeap, so they need not
24 # obey the interface specification for synthetic children providers
27 class CFBinaryHeapRef_SummaryProvider
:
28 def adjust_for_architecture(self
):
31 def __init__(self
, valobj
, params
):
32 logger
= lldb
.formatters
.Logger
.Logger()
34 self
.sys_params
= params
35 if not (self
.sys_params
.types_cache
.NSUInteger
):
36 if self
.sys_params
.is_64_bit
:
37 self
.sys_params
.types_cache
.NSUInteger
= (
38 self
.valobj
.GetType().GetBasicType(lldb
.eBasicTypeUnsignedLong
)
41 self
.sys_params
.types_cache
.NSUInteger
= (
42 self
.valobj
.GetType().GetBasicType(lldb
.eBasicTypeUnsignedInt
)
47 logger
= lldb
.formatters
.Logger
.Logger()
48 self
.adjust_for_architecture()
52 # most probably 2 pointers
54 logger
= lldb
.formatters
.Logger
.Logger()
55 return 2 * self
.sys_params
.pointer_size
58 logger
= lldb
.formatters
.Logger
.Logger()
59 size
= self
.valobj
.CreateChildAtOffset(
60 "count", self
.offset(), self
.sys_params
.types_cache
.NSUInteger
62 return size
.GetValueAsUnsigned(0)
65 class CFBinaryHeapUnknown_SummaryProvider
:
66 def adjust_for_architecture(self
):
69 def __init__(self
, valobj
, params
):
70 logger
= lldb
.formatters
.Logger
.Logger()
72 self
.sys_params
= params
76 logger
= lldb
.formatters
.Logger
.Logger()
77 self
.adjust_for_architecture()
80 logger
= lldb
.formatters
.Logger
.Logger()
81 stream
= lldb
.SBStream()
82 self
.valobj
.GetExpressionPath(stream
)
83 num_children_vo
= self
.valobj
.CreateValueFromExpression(
84 "count", "(int)CFBinaryHeapGetCount(" + stream
.GetData() + " )"
86 if num_children_vo
.IsValid():
87 return num_children_vo
.GetValueAsUnsigned(0)
88 return "<variable is not CFBinaryHeap>"
91 def GetSummary_Impl(valobj
):
92 logger
= lldb
.formatters
.Logger
.Logger()
97 ) = lldb
.runtime
.objc
.objc_runtime
.Utilities
.prepare_class_detection(
103 name_string
= class_data
.class_name()
104 actual_name
= class_data
.class_name()
106 logger
>> "name string got was " + str(name_string
) + " but actual name is " + str(
110 if class_data
.is_cftype():
111 # CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
112 # an NSCFType and then check we are a pointer-to CFBinaryHeap
113 valobj_type
= valobj
.GetType()
114 if valobj_type
.IsValid() and valobj_type
.IsPointerType():
115 valobj_type
= valobj_type
.GetPointeeType()
116 if valobj_type
.IsValid():
117 actual_name
= valobj_type
.GetName()
118 if actual_name
== "__CFBinaryHeap":
119 wrapper
= CFBinaryHeapRef_SummaryProvider(valobj
, class_data
.sys_params
)
120 statistics
.metric_hit("code_notrun", valobj
)
122 wrapper
= CFBinaryHeapUnknown_SummaryProvider(valobj
, class_data
.sys_params
)
123 statistics
.metric_hit("unknown_class", valobj
.GetName() + " seen as " + name_string
)
127 def CFBinaryHeap_SummaryProvider(valobj
, dict):
128 logger
= lldb
.formatters
.Logger
.Logger()
129 provider
= GetSummary_Impl(valobj
)
130 if provider
is not None:
132 provider
, lldb
.runtime
.objc
.objc_runtime
.SpecialSituation_Description
134 return provider
.message()
136 summary
= provider
.length()
139 logger
>> "summary got from provider: " + str(summary
)
140 # for some reason, one needs to clear some bits for the count
141 # to be correct when using CF(Mutable)BagRef on x64
142 # the bit mask was derived through experimentation
143 # (if counts start looking weird, then most probably
144 # the mask needs to be changed)
146 summary
= "<variable is not CFBinaryHeap>"
147 elif isinstance(summary
, str):
150 if provider
.sys_params
.is_64_bit
:
151 summary
= summary
& ~
0x1FFF000000000000
155 summary
= '@"' + str(summary
) + ' items"'
157 return "Summary Unavailable"
160 def __lldb_init_module(debugger
, dict):
161 debugger
.HandleCommand(
162 "type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef"