xref: /openbsd-src/gnu/llvm/lldb/examples/summaries/cocoa/CFBag.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 CFBag
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 CFBag, so they need not
24# obey the interface specification for synthetic children providers
25
26
27class CFBagRef_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    # 12 bytes on i386
50    # 20 bytes on x64
51    # most probably 2 pointers and 4 bytes of data
52    def offset(self):
53        logger = lldb.formatters.Logger.Logger()
54        if self.sys_params.is_64_bit:
55            return 20
56        else:
57            return 12
58
59    def length(self):
60        logger = lldb.formatters.Logger.Logger()
61        size = self.valobj.CreateChildAtOffset(
62            "count", self.offset(), self.sys_params.types_cache.NSUInteger)
63        return size.GetValueAsUnsigned(0)
64
65
66class CFBagUnknown_SummaryProvider:
67
68    def adjust_for_architecture(self):
69        pass
70
71    def __init__(self, valobj, params):
72        logger = lldb.formatters.Logger.Logger()
73        self.valobj = valobj
74        self.sys_params = params
75        self.update()
76
77    def update(self):
78        logger = lldb.formatters.Logger.Logger()
79        self.adjust_for_architecture()
80
81    def length(self):
82        logger = lldb.formatters.Logger.Logger()
83        stream = lldb.SBStream()
84        self.valobj.GetExpressionPath(stream)
85        num_children_vo = self.valobj.CreateValueFromExpression(
86            "count", "(int)CFBagGetCount(" + stream.GetData() + " )")
87        if num_children_vo.IsValid():
88            return num_children_vo.GetValueAsUnsigned(0)
89        return "<variable is not CFBag>"
90
91
92def GetSummary_Impl(valobj):
93    logger = lldb.formatters.Logger.Logger()
94    global statistics
95    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
96        valobj, statistics)
97    if wrapper:
98        return wrapper
99
100    name_string = class_data.class_name()
101    actual_name = name_string
102
103    logger >> "name string got was " + \
104        str(name_string) + " but actual name is " + str(actual_name)
105
106    if class_data.is_cftype():
107        # CFBag does not expose an actual NSWrapper type, so we have to check that this is
108        # an NSCFType and then check we are a pointer-to __CFBag
109        valobj_type = valobj.GetType()
110        if valobj_type.IsValid() and valobj_type.IsPointerType():
111            valobj_type = valobj_type.GetPointeeType()
112            if valobj_type.IsValid():
113                actual_name = valobj_type.GetName()
114        if actual_name == '__CFBag' or \
115           actual_name == 'const struct __CFBag':
116            wrapper = CFBagRef_SummaryProvider(valobj, class_data.sys_params)
117            statistics.metric_hit('code_notrun', valobj)
118            return wrapper
119    wrapper = CFBagUnknown_SummaryProvider(valobj, class_data.sys_params)
120    statistics.metric_hit(
121        'unknown_class',
122        valobj.GetName() +
123        " seen as " +
124        actual_name)
125    return wrapper
126
127
128def CFBag_SummaryProvider(valobj, dict):
129    logger = lldb.formatters.Logger.Logger()
130    provider = GetSummary_Impl(valobj)
131    if provider is not None:
132        if isinstance(
133                provider,
134                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
135            return provider.message()
136        try:
137            summary = provider.length()
138        except:
139            summary = None
140        logger >> "summary got from provider: " + str(summary)
141        # for some reason, one needs to clear some bits for the count
142        # to be correct when using CF(Mutable)BagRef on x64
143        # the bit mask was derived through experimentation
144        # (if counts start looking weird, then most probably
145        #  the mask needs to be changed)
146        if summary is None:
147            summary = '<variable is not CFBag>'
148        elif isinstance(summary, str):
149            pass
150        else:
151            if provider.sys_params.is_64_bit:
152                summary = summary & ~0x1fff000000000000
153            if summary == 1:
154                summary = '@"1 value"'
155            else:
156                summary = '@"' + str(summary) + ' values"'
157        return summary
158    return 'Summary Unavailable'
159
160
161def __lldb_init_module(debugger, dict):
162    debugger.HandleCommand(
163        "type summary add -F CFBag.CFBag_SummaryProvider CFBagRef CFMutableBagRef")
164