xref: /openbsd-src/gnu/llvm/lldb/examples/summaries/cocoa/NSBundle.py (revision 061da546b983eb767bad15e67af1174fb0bcf31c)
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# example summary provider for NSBundle
9*061da546Spatrick# the real summary is now C++ code built into LLDB
10*061da546Spatrickimport lldb
11*061da546Spatrickimport ctypes
12*061da546Spatrickimport lldb.runtime.objc.objc_runtime
13*061da546Spatrickimport lldb.formatters.metrics
14*061da546Spatrickimport NSURL
15*061da546Spatrickimport lldb.formatters.Logger
16*061da546Spatrick
17*061da546Spatrickstatistics = lldb.formatters.metrics.Metrics()
18*061da546Spatrickstatistics.add_metric('invalid_isa')
19*061da546Spatrickstatistics.add_metric('invalid_pointer')
20*061da546Spatrickstatistics.add_metric('unknown_class')
21*061da546Spatrickstatistics.add_metric('code_notrun')
22*061da546Spatrick
23*061da546Spatrick# despite the similary to synthetic children providers, these classes are not
24*061da546Spatrick# trying to provide anything but a summary for an NSURL, so they need not
25*061da546Spatrick# obey the interface specification for synthetic children providers
26*061da546Spatrick
27*061da546Spatrick
28*061da546Spatrickclass NSBundleKnown_SummaryProvider:
29*061da546Spatrick
30*061da546Spatrick    def adjust_for_architecture(self):
31*061da546Spatrick        pass
32*061da546Spatrick
33*061da546Spatrick    def __init__(self, valobj, params):
34*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
35*061da546Spatrick        self.valobj = valobj
36*061da546Spatrick        self.sys_params = params
37*061da546Spatrick        if not(self.sys_params.types_cache.NSString):
38*061da546Spatrick            self.sys_params.types_cache.NSString = self.valobj.GetTarget(
39*061da546Spatrick            ).FindFirstType('NSString').GetPointerType()
40*061da546Spatrick        self.update()
41*061da546Spatrick
42*061da546Spatrick    def update(self):
43*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
44*061da546Spatrick        self.adjust_for_architecture()
45*061da546Spatrick
46*061da546Spatrick    # we need to skip the ISA, plus four other values
47*061da546Spatrick    # that are luckily each a pointer in size
48*061da546Spatrick    # which makes our computation trivial :-)
49*061da546Spatrick    def offset(self):
50*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
51*061da546Spatrick        return 5 * self.sys_params.pointer_size
52*061da546Spatrick
53*061da546Spatrick    def url_text(self):
54*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
55*061da546Spatrick        global statistics
56*061da546Spatrick        text = self.valobj.CreateChildAtOffset(
57*061da546Spatrick            "text", self.offset(), self.sys_params.types_cache.NSString)
58*061da546Spatrick        my_string = text.GetSummary()
59*061da546Spatrick        if (my_string is None) or (my_string == ''):
60*061da546Spatrick            statistics.metric_hit(
61*061da546Spatrick                'unknown_class', str(
62*061da546Spatrick                    self.valobj.GetName()) + " triggered unknown pointer location")
63*061da546Spatrick            return NSBundleUnknown_SummaryProvider(
64*061da546Spatrick                self.valobj, self.sys_params).url_text()
65*061da546Spatrick        else:
66*061da546Spatrick            statistics.metric_hit('code_notrun', self.valobj)
67*061da546Spatrick            return my_string
68*061da546Spatrick
69*061da546Spatrick
70*061da546Spatrickclass NSBundleUnknown_SummaryProvider:
71*061da546Spatrick
72*061da546Spatrick    def adjust_for_architecture(self):
73*061da546Spatrick        pass
74*061da546Spatrick
75*061da546Spatrick    def __init__(self, valobj, params):
76*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
77*061da546Spatrick        self.valobj = valobj
78*061da546Spatrick        self.sys_params = params
79*061da546Spatrick        self.update()
80*061da546Spatrick
81*061da546Spatrick    def update(self):
82*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
83*061da546Spatrick        self.adjust_for_architecture()
84*061da546Spatrick
85*061da546Spatrick    def url_text(self):
86*061da546Spatrick        logger = lldb.formatters.Logger.Logger()
87*061da546Spatrick        stream = lldb.SBStream()
88*061da546Spatrick        self.valobj.GetExpressionPath(stream)
89*061da546Spatrick        expr = "(NSString*)[" + stream.GetData() + " bundlePath]"
90*061da546Spatrick        url_text_vo = self.valobj.CreateValueFromExpression("path", expr)
91*061da546Spatrick        if url_text_vo.IsValid():
92*061da546Spatrick            return url_text_vo.GetSummary()
93*061da546Spatrick        return '<variable is not NSBundle>'
94*061da546Spatrick
95*061da546Spatrick
96*061da546Spatrickdef GetSummary_Impl(valobj):
97*061da546Spatrick    logger = lldb.formatters.Logger.Logger()
98*061da546Spatrick    global statistics
99*061da546Spatrick    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
100*061da546Spatrick        valobj, statistics)
101*061da546Spatrick    if wrapper:
102*061da546Spatrick        return wrapper
103*061da546Spatrick
104*061da546Spatrick    name_string = class_data.class_name()
105*061da546Spatrick    logger >> "class name is: " + str(name_string)
106*061da546Spatrick
107*061da546Spatrick    if name_string == 'NSBundle':
108*061da546Spatrick        wrapper = NSBundleKnown_SummaryProvider(valobj, class_data.sys_params)
109*061da546Spatrick        # [NSBundle mainBundle] does return an object that is
110*061da546Spatrick        # not correctly filled out for our purposes, so we still
111*061da546Spatrick        # end up having to run code in that case
112*061da546Spatrick        # statistics.metric_hit('code_notrun',valobj)
113*061da546Spatrick    else:
114*061da546Spatrick        wrapper = NSBundleUnknown_SummaryProvider(
115*061da546Spatrick            valobj, class_data.sys_params)
116*061da546Spatrick        statistics.metric_hit(
117*061da546Spatrick            'unknown_class',
118*061da546Spatrick            valobj.GetName() +
119*061da546Spatrick            " seen as " +
120*061da546Spatrick            name_string)
121*061da546Spatrick    return wrapper
122*061da546Spatrick
123*061da546Spatrick
124*061da546Spatrickdef NSBundle_SummaryProvider(valobj, dict):
125*061da546Spatrick    logger = lldb.formatters.Logger.Logger()
126*061da546Spatrick    provider = GetSummary_Impl(valobj)
127*061da546Spatrick    if provider is not None:
128*061da546Spatrick        if isinstance(
129*061da546Spatrick                provider,
130*061da546Spatrick                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
131*061da546Spatrick            return provider.message()
132*061da546Spatrick        try:
133*061da546Spatrick            summary = provider.url_text()
134*061da546Spatrick        except:
135*061da546Spatrick            summary = None
136*061da546Spatrick        logger >> "got summary " + str(summary)
137*061da546Spatrick        if summary is None or summary == '':
138*061da546Spatrick            summary = '<variable is not NSBundle>'
139*061da546Spatrick        return summary
140*061da546Spatrick    return 'Summary Unavailable'
141*061da546Spatrick
142*061da546Spatrick
143*061da546Spatrickdef __lldb_init_module(debugger, dict):
144*061da546Spatrick    debugger.HandleCommand(
145*061da546Spatrick        "type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle")
146