xref: /openbsd-src/gnu/llvm/lldb/examples/summaries/cocoa/CFBinaryHeap.py (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1061da546Spatrick"""
2061da546SpatrickLLDB AppKit formatters
3061da546Spatrick
4061da546SpatrickPart of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5061da546SpatrickSee https://llvm.org/LICENSE.txt for license information.
6061da546SpatrickSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7061da546Spatrick"""
8061da546Spatrick# example summary provider for CFBinaryHeap
9061da546Spatrick# the real summary is now C++ code built into LLDB
10061da546Spatrickimport lldb
11061da546Spatrickimport ctypes
12061da546Spatrickimport lldb.runtime.objc.objc_runtime
13061da546Spatrickimport lldb.formatters.metrics
14061da546Spatrickimport lldb.formatters.Logger
15061da546Spatrick
16061da546Spatrickstatistics = lldb.formatters.metrics.Metrics()
17061da546Spatrickstatistics.add_metric('invalid_isa')
18061da546Spatrickstatistics.add_metric('invalid_pointer')
19061da546Spatrickstatistics.add_metric('unknown_class')
20061da546Spatrickstatistics.add_metric('code_notrun')
21061da546Spatrick
22061da546Spatrick# despite the similary to synthetic children providers, these classes are not
23061da546Spatrick# trying to provide anything but the length for an CFBinaryHeap, so they need not
24061da546Spatrick# obey the interface specification for synthetic children providers
25061da546Spatrick
26061da546Spatrick
27061da546Spatrickclass CFBinaryHeapRef_SummaryProvider:
28061da546Spatrick
29061da546Spatrick    def adjust_for_architecture(self):
30061da546Spatrick        pass
31061da546Spatrick
32061da546Spatrick    def __init__(self, valobj, params):
33061da546Spatrick        logger = lldb.formatters.Logger.Logger()
34061da546Spatrick        self.valobj = valobj
35061da546Spatrick        self.sys_params = params
36061da546Spatrick        if not(self.sys_params.types_cache.NSUInteger):
37061da546Spatrick            if self.sys_params.is_64_bit:
38061da546Spatrick                self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
39061da546Spatrick                ).GetBasicType(lldb.eBasicTypeUnsignedLong)
40061da546Spatrick            else:
41061da546Spatrick                self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
42061da546Spatrick                ).GetBasicType(lldb.eBasicTypeUnsignedInt)
43061da546Spatrick        self.update()
44061da546Spatrick
45061da546Spatrick    def update(self):
46061da546Spatrick        logger = lldb.formatters.Logger.Logger()
47061da546Spatrick        self.adjust_for_architecture()
48061da546Spatrick
49061da546Spatrick    # 8 bytes on i386
50061da546Spatrick    # 16 bytes on x64
51061da546Spatrick    # most probably 2 pointers
52061da546Spatrick    def offset(self):
53061da546Spatrick        logger = lldb.formatters.Logger.Logger()
54061da546Spatrick        return 2 * self.sys_params.pointer_size
55061da546Spatrick
56061da546Spatrick    def length(self):
57061da546Spatrick        logger = lldb.formatters.Logger.Logger()
58061da546Spatrick        size = self.valobj.CreateChildAtOffset(
59061da546Spatrick            "count", self.offset(), self.sys_params.types_cache.NSUInteger)
60061da546Spatrick        return size.GetValueAsUnsigned(0)
61061da546Spatrick
62061da546Spatrick
63061da546Spatrickclass CFBinaryHeapUnknown_SummaryProvider:
64061da546Spatrick
65061da546Spatrick    def adjust_for_architecture(self):
66061da546Spatrick        pass
67061da546Spatrick
68061da546Spatrick    def __init__(self, valobj, params):
69061da546Spatrick        logger = lldb.formatters.Logger.Logger()
70061da546Spatrick        self.valobj = valobj
71061da546Spatrick        self.sys_params = params
72061da546Spatrick        self.update()
73061da546Spatrick
74061da546Spatrick    def update(self):
75061da546Spatrick        logger = lldb.formatters.Logger.Logger()
76061da546Spatrick        self.adjust_for_architecture()
77061da546Spatrick
78061da546Spatrick    def length(self):
79061da546Spatrick        logger = lldb.formatters.Logger.Logger()
80061da546Spatrick        stream = lldb.SBStream()
81061da546Spatrick        self.valobj.GetExpressionPath(stream)
82061da546Spatrick        num_children_vo = self.valobj.CreateValueFromExpression(
83061da546Spatrick            "count", "(int)CFBinaryHeapGetCount(" + stream.GetData() + " )")
84061da546Spatrick        if num_children_vo.IsValid():
85061da546Spatrick            return num_children_vo.GetValueAsUnsigned(0)
86061da546Spatrick        return '<variable is not CFBinaryHeap>'
87061da546Spatrick
88061da546Spatrick
89061da546Spatrickdef GetSummary_Impl(valobj):
90061da546Spatrick    logger = lldb.formatters.Logger.Logger()
91061da546Spatrick    global statistics
92061da546Spatrick    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
93061da546Spatrick        valobj, statistics)
94061da546Spatrick    if wrapper:
95061da546Spatrick        return wrapper
96061da546Spatrick
97061da546Spatrick    name_string = class_data.class_name()
98061da546Spatrick    actual_name = class_data.class_name()
99061da546Spatrick
100061da546Spatrick    logger >> "name string got was " + \
101061da546Spatrick        str(name_string) + " but actual name is " + str(actual_name)
102061da546Spatrick
103061da546Spatrick    if class_data.is_cftype():
104061da546Spatrick        # CFBinaryHeap does not expose an actual NSWrapper type, so we have to check that this is
105061da546Spatrick        # an NSCFType and then check we are a pointer-to CFBinaryHeap
106061da546Spatrick        valobj_type = valobj.GetType()
107061da546Spatrick        if valobj_type.IsValid() and valobj_type.IsPointerType():
108061da546Spatrick            valobj_type = valobj_type.GetPointeeType()
109061da546Spatrick            if valobj_type.IsValid():
110061da546Spatrick                actual_name = valobj_type.GetName()
111061da546Spatrick        if actual_name == '__CFBinaryHeap':
112061da546Spatrick            wrapper = CFBinaryHeapRef_SummaryProvider(
113061da546Spatrick                valobj, class_data.sys_params)
114061da546Spatrick            statistics.metric_hit('code_notrun', valobj)
115061da546Spatrick            return wrapper
116061da546Spatrick    wrapper = CFBinaryHeapUnknown_SummaryProvider(
117061da546Spatrick        valobj, class_data.sys_params)
118061da546Spatrick    statistics.metric_hit(
119061da546Spatrick        'unknown_class',
120061da546Spatrick        valobj.GetName() +
121061da546Spatrick        " seen as " +
122061da546Spatrick        name_string)
123061da546Spatrick    return wrapper
124061da546Spatrick
125061da546Spatrick
126061da546Spatrickdef CFBinaryHeap_SummaryProvider(valobj, dict):
127061da546Spatrick    logger = lldb.formatters.Logger.Logger()
128061da546Spatrick    provider = GetSummary_Impl(valobj)
129061da546Spatrick    if provider is not None:
130061da546Spatrick        if isinstance(
131061da546Spatrick                provider,
132061da546Spatrick                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
133061da546Spatrick            return provider.message()
134061da546Spatrick        try:
135061da546Spatrick            summary = provider.length()
136061da546Spatrick        except:
137061da546Spatrick            summary = None
138061da546Spatrick        logger >> "summary got from provider: " + str(summary)
139061da546Spatrick        # for some reason, one needs to clear some bits for the count
140061da546Spatrick        # to be correct when using CF(Mutable)BagRef on x64
141061da546Spatrick        # the bit mask was derived through experimentation
142061da546Spatrick        # (if counts start looking weird, then most probably
143061da546Spatrick        #  the mask needs to be changed)
144061da546Spatrick        if summary is None:
145061da546Spatrick            summary = '<variable is not CFBinaryHeap>'
146*f6aab3d8Srobert        elif isinstance(summary, str):
147061da546Spatrick            pass
148061da546Spatrick        else:
149061da546Spatrick            if provider.sys_params.is_64_bit:
150061da546Spatrick                summary = summary & ~0x1fff000000000000
151061da546Spatrick            if summary == 1:
152061da546Spatrick                return '@"1 item"'
153061da546Spatrick            else:
154061da546Spatrick                summary = '@"' + str(summary) + ' items"'
155061da546Spatrick        return summary
156061da546Spatrick    return 'Summary Unavailable'
157061da546Spatrick
158061da546Spatrick
159061da546Spatrickdef __lldb_init_module(debugger, dict):
160061da546Spatrick    debugger.HandleCommand(
161061da546Spatrick        "type summary add -F CFBinaryHeap.CFBinaryHeap_SummaryProvider CFBinaryHeapRef")
162