xref: /llvm-project/lldb/examples/summaries/cocoa/NSException.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# summary provider for class NSException
9import lldb.runtime.objc.objc_runtime
10import lldb.formatters.metrics
11import CFString
12import lldb
13import lldb.formatters.Logger
14
15statistics = lldb.formatters.metrics.Metrics()
16statistics.add_metric("invalid_isa")
17statistics.add_metric("invalid_pointer")
18statistics.add_metric("unknown_class")
19statistics.add_metric("code_notrun")
20
21
22class NSKnownException_SummaryProvider:
23    def adjust_for_architecture(self):
24        pass
25
26    def __init__(self, valobj, params):
27        logger = lldb.formatters.Logger.Logger()
28        self.valobj = valobj
29        self.sys_params = params
30        if not (self.sys_params.types_cache.id):
31            self.sys_params.types_cache.id = self.valobj.GetType().GetBasicType(
32                lldb.eBasicTypeObjCID
33            )
34        self.update()
35
36    def update(self):
37        logger = lldb.formatters.Logger.Logger()
38        self.adjust_for_architecture()
39
40    def offset_name(self):
41        logger = lldb.formatters.Logger.Logger()
42        return self.sys_params.pointer_size
43
44    def offset_reason(self):
45        logger = lldb.formatters.Logger.Logger()
46        return 2 * self.sys_params.pointer_size
47
48    def description(self):
49        logger = lldb.formatters.Logger.Logger()
50        name_ptr = self.valobj.CreateChildAtOffset(
51            "name", self.offset_name(), self.sys_params.types_cache.id
52        )
53        reason_ptr = self.valobj.CreateChildAtOffset(
54            "reason", self.offset_reason(), self.sys_params.types_cache.id
55        )
56        return (
57            "name:"
58            + CFString.CFString_SummaryProvider(name_ptr, None)
59            + " reason:"
60            + CFString.CFString_SummaryProvider(reason_ptr, None)
61        )
62
63
64class NSUnknownException_SummaryProvider:
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 description(self):
79        logger = lldb.formatters.Logger.Logger()
80        stream = lldb.SBStream()
81        self.valobj.GetExpressionPath(stream)
82        name_vo = self.valobj.CreateValueFromExpression(
83            "name", "(NSString*)[" + stream.GetData() + " name]"
84        )
85        reason_vo = self.valobj.CreateValueFromExpression(
86            "reason", "(NSString*)[" + stream.GetData() + " reason]"
87        )
88        if name_vo.IsValid() and reason_vo.IsValid():
89            return (
90                CFString.CFString_SummaryProvider(name_vo, None)
91                + " "
92                + CFString.CFString_SummaryProvider(reason_vo, None)
93            )
94        return "<variable is not NSException>"
95
96
97def GetSummary_Impl(valobj):
98    logger = lldb.formatters.Logger.Logger()
99    global statistics
100    (
101        class_data,
102        wrapper,
103    ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
104        valobj, statistics
105    )
106    if wrapper:
107        return wrapper
108
109    name_string = class_data.class_name()
110    logger >> "class name is: " + str(name_string)
111
112    if name_string == "NSException":
113        wrapper = NSKnownException_SummaryProvider(valobj, class_data.sys_params)
114        statistics.metric_hit("code_notrun", valobj)
115    else:
116        wrapper = NSUnknownException_SummaryProvider(valobj, class_data.sys_params)
117        statistics.metric_hit(
118            "unknown_class", valobj.GetName() + " seen as " + name_string
119        )
120    return wrapper
121
122
123def NSException_SummaryProvider(valobj, dict):
124    logger = lldb.formatters.Logger.Logger()
125    provider = GetSummary_Impl(valobj)
126    if provider is not None:
127        if isinstance(
128            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description
129        ):
130            return provider.message()
131        try:
132            summary = provider.description()
133        except:
134            summary = None
135        logger >> "got summary " + str(summary)
136        if summary is None:
137            summary = "<variable is not NSException>"
138        return str(summary)
139    return "Summary Unavailable"
140
141
142def __lldb_init_module(debugger, dict):
143    debugger.HandleCommand(
144        "type summary add -F NSException.NSException_SummaryProvider NSException"
145    )
146