1*061da546Spatrick"""
2*061da546SpatrickLLDB AppKit formatters
3*061da546Spatrick
4*061da546SpatrickPart of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5*061da546SpatrickSee https://llvm.org/LICENSE.txt for license information.
6*061da546SpatrickSPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7*061da546Spatrick"""
8*061da546Spatrick# summary provider for class NSException
9*061da546Spatrickimport lldb.runtime.objc.objc_runtime
10*061da546Spatrickimport lldb.formatters.metrics
11*061da546Spatrickimport CFString
12*061da546Spatrickimport lldb
13*061da546Spatrickimport lldb.formatters.Logger
14*061da546Spatrick
15*061da546Spatrickstatistics = lldb.formatters.metrics.Metrics()
16*061da546Spatrickstatistics.add_metric('invalid_isa')
17*061da546Spatrickstatistics.add_metric('invalid_pointer')
18*061da546Spatrickstatistics.add_metric('unknown_class')
19*061da546Spatrickstatistics.add_metric('code_notrun')
20*061da546Spatrick
21*061da546Spatrick
22*061da546Spatrickclass NSKnownException_SummaryProvider:
23*061da546Spatrick
24*061da546Spatrick    def adjust_for_architecture(self):
25*061da546Spatrick        pass
26*061da546Spatrick
27*061da546Spatrick    def __init__(self, valobj, params):
28*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
29*061da546Spatrick        self.valobj = valobj
30*061da546Spatrick        self.sys_params = params
31*061da546Spatrick        if not (self.sys_params.types_cache.id):
32*061da546Spatrick            self.sys_params.types_cache.id = self.valobj.GetType(
33*061da546Spatrick            ).GetBasicType(lldb.eBasicTypeObjCID)
34*061da546Spatrick        self.update()
35*061da546Spatrick
36*061da546Spatrick    def update(self):
37*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
38*061da546Spatrick        self.adjust_for_architecture()
39*061da546Spatrick
40*061da546Spatrick    def offset_name(self):
41*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
42*061da546Spatrick        return self.sys_params.pointer_size
43*061da546Spatrick
44*061da546Spatrick    def offset_reason(self):
45*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
46*061da546Spatrick        return 2 * self.sys_params.pointer_size
47*061da546Spatrick
48*061da546Spatrick    def description(self):
49*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
50*061da546Spatrick        name_ptr = self.valobj.CreateChildAtOffset(
51*061da546Spatrick            "name", self.offset_name(), self.sys_params.types_cache.id)
52*061da546Spatrick        reason_ptr = self.valobj.CreateChildAtOffset(
53*061da546Spatrick            "reason", self.offset_reason(), self.sys_params.types_cache.id)
54*061da546Spatrick        return 'name:' + CFString.CFString_SummaryProvider(
55*061da546Spatrick            name_ptr, None) + ' reason:' + CFString.CFString_SummaryProvider(reason_ptr, None)
56*061da546Spatrick
57*061da546Spatrick
58*061da546Spatrickclass NSUnknownException_SummaryProvider:
59*061da546Spatrick
60*061da546Spatrick    def adjust_for_architecture(self):
61*061da546Spatrick        pass
62*061da546Spatrick
63*061da546Spatrick    def __init__(self, valobj, params):
64*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
65*061da546Spatrick        self.valobj = valobj
66*061da546Spatrick        self.sys_params = params
67*061da546Spatrick        self.update()
68*061da546Spatrick
69*061da546Spatrick    def update(self):
70*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
71*061da546Spatrick        self.adjust_for_architecture()
72*061da546Spatrick
73*061da546Spatrick    def description(self):
74*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
75*061da546Spatrick        stream = lldb.SBStream()
76*061da546Spatrick        self.valobj.GetExpressionPath(stream)
77*061da546Spatrick        name_vo = self.valobj.CreateValueFromExpression(
78*061da546Spatrick            "name", "(NSString*)[" + stream.GetData() + " name]")
79*061da546Spatrick        reason_vo = self.valobj.CreateValueFromExpression(
80*061da546Spatrick            "reason", "(NSString*)[" + stream.GetData() + " reason]")
81*061da546Spatrick        if name_vo.IsValid() and reason_vo.IsValid():
82*061da546Spatrick            return CFString.CFString_SummaryProvider(
83*061da546Spatrick                name_vo, None) + ' ' + CFString.CFString_SummaryProvider(reason_vo, None)
84*061da546Spatrick        return '<variable is not NSException>'
85*061da546Spatrick
86*061da546Spatrick
87*061da546Spatrickdef GetSummary_Impl(valobj):
88*061da546Spatrick    logger = lldb.formatters.Logger.Logger()
89*061da546Spatrick    global statistics
90*061da546Spatrick    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
91*061da546Spatrick        valobj, statistics)
92*061da546Spatrick    if wrapper:
93*061da546Spatrick        return wrapper
94*061da546Spatrick
95*061da546Spatrick    name_string = class_data.class_name()
96*061da546Spatrick    logger >> "class name is: " + str(name_string)
97*061da546Spatrick
98*061da546Spatrick    if name_string == 'NSException':
99*061da546Spatrick        wrapper = NSKnownException_SummaryProvider(
100*061da546Spatrick            valobj, class_data.sys_params)
101*061da546Spatrick        statistics.metric_hit('code_notrun', valobj)
102*061da546Spatrick    else:
103*061da546Spatrick        wrapper = NSUnknownException_SummaryProvider(
104*061da546Spatrick            valobj, class_data.sys_params)
105*061da546Spatrick        statistics.metric_hit(
106*061da546Spatrick            'unknown_class',
107*061da546Spatrick            valobj.GetName() +
108*061da546Spatrick            " seen as " +
109*061da546Spatrick            name_string)
110*061da546Spatrick    return wrapper
111*061da546Spatrick
112*061da546Spatrick
113*061da546Spatrickdef NSException_SummaryProvider(valobj, dict):
114*061da546Spatrick    logger = lldb.formatters.Logger.Logger()
115*061da546Spatrick    provider = GetSummary_Impl(valobj)
116*061da546Spatrick    if provider is not None:
117*061da546Spatrick        if isinstance(
118*061da546Spatrick                provider,
119*061da546Spatrick                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
120*061da546Spatrick            return provider.message()
121*061da546Spatrick        try:
122*061da546Spatrick            summary = provider.description()
123*061da546Spatrick        except:
124*061da546Spatrick            summary = None
125*061da546Spatrick        logger >> "got summary " + str(summary)
126*061da546Spatrick        if summary is None:
127*061da546Spatrick            summary = '<variable is not NSException>'
128*061da546Spatrick        return str(summary)
129*061da546Spatrick    return 'Summary Unavailable'
130*061da546Spatrick
131*061da546Spatrick
132*061da546Spatrickdef __lldb_init_module(debugger, dict):
133*061da546Spatrick    debugger.HandleCommand(
134*061da546Spatrick        "type summary add -F NSException.NSException_SummaryProvider NSException")
135