xref: /openbsd-src/gnu/llvm/lldb/examples/summaries/cocoa/CFBinaryHeap.py (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1"""
2LLDB AppKit formatters
3
4Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5See https://llvm.org/LICENSE.txt for license information.
6SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7"""
8# example summary provider for CFBinaryHeap
9# the real summary is now C++ code built into LLDB
10import lldb
11import ctypes
12import lldb.runtime.objc.objc_runtime
13import lldb.formatters.metrics
14import lldb.formatters.Logger
15
16statistics = lldb.formatters.metrics.Metrics()
17statistics.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 length for an CFBinaryHeap, so they need not
24# obey the interface specification for synthetic children providers
25
26
27class CFBinaryHeapRef_SummaryProvider:
28
29    def adjust_for_architecture(self):
30        pass
31
32    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            else:
41                self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
42                ).GetBasicType(lldb.eBasicTypeUnsignedInt)
43        self.update()
44
45    def update(self):
46        logger = lldb.formatters.Logger.Logger()
47        self.adjust_for_architecture()
48
49    # 8 bytes on i386
50    # 16 bytes on x64
51    # most probably 2 pointers
52    def offset(self):
53        logger = lldb.formatters.Logger.Logger()
54        return 2 * self.sys_params.pointer_size
55
56    def length(self):
57        logger = lldb.formatters.Logger.Logger()
58        size = self.valobj.CreateChildAtOffset(
59            "count", self.offset(), self.sys_params.types_cache.NSUInteger)
60        return size.GetValueAsUnsigned(0)
61
62
63class CFBinaryHeapUnknown_SummaryProvider:
64
65    def adjust_for_architecture(self):
66        pass
67
68    def __init__(self, valobj, params):
69        logger = lldb.formatters.Logger.Logger()
70        self.valobj = valobj
71        self.sys_params = params
72        self.update()
73
74    def update(self):
75        logger = lldb.formatters.Logger.Logger()
76        self.adjust_for_architecture()
77
78    def length(self):
79        logger = lldb.formatters.Logger.Logger()
80        stream = lldb.SBStream()
81        self.valobj.GetExpressionPath(stream)
82        num_children_vo = self.valobj.CreateValueFromExpression(
83            "count", "(int)CFBinaryHeapGetCount(" + stream.GetData() + " )")
84        if num_children_vo.IsValid():
85            return num_children_vo.GetValueAsUnsigned(0)
86        return '<variable is not CFBinaryHeap>'
87
88
89def GetSummary_Impl(valobj):
90    logger = lldb.formatters.Logger.Logger()
91    global statistics
92    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
93        valobj, statistics)
94    if wrapper:
95        return wrapper
96
97    name_string = class_data.class_name()
98    actual_name = class_data.class_name()
99
100    logger >> "name string got was " + \
101        str(name_string) + " but actual name is " + str(actual_name)
102
103    if class_data.is_cftype():
104        # CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
105        # an NSCFType and then check we are a pointer-to CFBinaryHeap
106        valobj_type = valobj.GetType()
107        if valobj_type.IsValid() and valobj_type.IsPointerType():
108            valobj_type = valobj_type.GetPointeeType()
109            if valobj_type.IsValid():
110                actual_name = valobj_type.GetName()
111        if actual_name == '__CFBinaryHeap':
112            wrapper = CFBinaryHeapRef_SummaryProvider(
113                valobj, class_data.sys_params)
114            statistics.metric_hit('code_notrun', valobj)
115            return wrapper
116    wrapper = CFBinaryHeapUnknown_SummaryProvider(
117        valobj, class_data.sys_params)
118    statistics.metric_hit(
119        'unknown_class',
120        valobj.GetName() +
121        " seen as " +
122        name_string)
123    return wrapper
124
125
126def CFBinaryHeap_SummaryProvider(valobj, dict):
127    logger = lldb.formatters.Logger.Logger()
128    provider = GetSummary_Impl(valobj)
129    if provider is not None:
130        if isinstance(
131                provider,
132                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
133            return provider.message()
134        try:
135            summary = provider.length()
136        except:
137            summary = None
138        logger >> "summary got from provider: " + str(summary)
139        # for some reason, one needs to clear some bits for the count
140        # to be correct when using CF(Mutable)BagRef on x64
141        # the bit mask was derived through experimentation
142        # (if counts start looking weird, then most probably
143        #  the mask needs to be changed)
144        if summary is None:
145            summary = '<variable is not CFBinaryHeap>'
146        elif isinstance(summary, str):
147            pass
148        else:
149            if provider.sys_params.is_64_bit:
150                summary = summary & ~0x1fff000000000000
151            if summary == 1:
152                return '@"1 item"'
153            else:
154                summary = '@"' + str(summary) + ' items"'
155        return summary
156    return 'Summary Unavailable'
157
158
159def __lldb_init_module(debugger, dict):
160    debugger.HandleCommand(
161        "type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")
162