xref: /llvm-project/lldb/examples/summaries/cocoa/NSMachPort.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
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 NSMachPort
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 port number of an NSMachPort, so they need not
24# obey the interface specification for synthetic children providers
25
26
27class NSMachPortKnown_SummaryProvider:
28    def adjust_for_architecture(self):
29        pass
30
31    def __init__(self, valobj, params):
32        logger = lldb.formatters.Logger.Logger()
33        self.valobj = valobj
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)
39                )
40            else:
41                self.sys_params.types_cache.NSUInteger = (
42                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)
43                )
44        self.update()
45
46    def update(self):
47        logger = lldb.formatters.Logger.Logger()
48        self.adjust_for_architecture()
49
50    # one pointer is the ISA
51    # then we have one other internal pointer, plus
52    # 4 bytes worth of flags. hence, these values
53    def offset(self):
54        logger = lldb.formatters.Logger.Logger()
55        if self.sys_params.is_64_bit:
56            return 20
57        else:
58            return 12
59
60    def port(self):
61        logger = lldb.formatters.Logger.Logger()
62        vport = self.valobj.CreateChildAtOffset(
63            "port", self.offset(), self.sys_params.types_cache.NSUInteger
64        )
65        return vport.GetValueAsUnsigned(0)
66
67
68class NSMachPortUnknown_SummaryProvider:
69    def adjust_for_architecture(self):
70        pass
71
72    def __init__(self, valobj, params):
73        logger = lldb.formatters.Logger.Logger()
74        self.valobj = valobj
75        self.sys_params = params
76        self.update()
77
78    def update(self):
79        logger = lldb.formatters.Logger.Logger()
80        self.adjust_for_architecture()
81
82    def port(self):
83        logger = lldb.formatters.Logger.Logger()
84        stream = lldb.SBStream()
85        self.valobj.GetExpressionPath(stream)
86        num_children_vo = self.valobj.CreateValueFromExpression(
87            "port", "(int)[" + stream.GetData() + " machPort]"
88        )
89        if num_children_vo.IsValid():
90            return num_children_vo.GetValueAsUnsigned(0)
91        return "<variable is not NSMachPort>"
92
93
94def GetSummary_Impl(valobj):
95    logger = lldb.formatters.Logger.Logger()
96    global statistics
97    (
98        class_data,
99        wrapper,
100    ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
101        valobj, statistics
102    )
103    if wrapper:
104        return wrapper
105
106    name_string = class_data.class_name()
107    logger >> "class name is: " + str(name_string)
108
109    if name_string == "NSMachPort":
110        wrapper = NSMachPortKnown_SummaryProvider(valobj, class_data.sys_params)
111        statistics.metric_hit("code_notrun", valobj)
112    else:
113        wrapper = NSMachPortUnknown_SummaryProvider(valobj, class_data.sys_params)
114        statistics.metric_hit(
115            "unknown_class", valobj.GetName() + " seen as " + name_string
116        )
117    return wrapper
118
119
120def NSMachPort_SummaryProvider(valobj, dict):
121    logger = lldb.formatters.Logger.Logger()
122    provider = GetSummary_Impl(valobj)
123    if provider is not None:
124        if isinstance(
125            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description
126        ):
127            return provider.message()
128        try:
129            summary = provider.port()
130        except:
131            summary = None
132        logger >> "got summary " + str(summary)
133        if summary is None:
134            summary = "<variable is not NSMachPort>"
135        if isinstance(summary, str):
136            return summay
137        return "mach port: " + str(summary)
138    return "Summary Unavailable"
139
140
141def __lldb_init_module(debugger, dict):
142    debugger.HandleCommand(
143        "type summary add -F NSMachPort.NSMachPort_SummaryProvider NSMachPort"
144    )
145