xref: /openbsd-src/gnu/llvm/lldb/examples/summaries/cocoa/NSData.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 NSData
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 NSData, so they need not
24061da546Spatrick# obey the interface specification for synthetic children providers
25061da546Spatrick
26061da546Spatrick
27061da546Spatrickclass NSConcreteData_SummaryProvider:
28061da546Spatrick
29061da546Spatrick    def adjust_for_architecture(self):
30061da546Spatrick        pass
31061da546Spatrick
32061da546Spatrick    def __init__(self, valobj, params):
33061da546Spatrick        logger = lldb.formatters.Logger.Logger()
34061da546Spatrick        logger >> "NSConcreteData_SummaryProvider __init__"
35061da546Spatrick        self.valobj = valobj
36061da546Spatrick        self.sys_params = params
37061da546Spatrick        if not(self.sys_params.types_cache.NSUInteger):
38061da546Spatrick            if self.sys_params.is_64_bit:
39061da546Spatrick                self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
40061da546Spatrick                ).GetBasicType(lldb.eBasicTypeUnsignedLong)
41061da546Spatrick            else:
42061da546Spatrick                self.sys_params.types_cache.NSUInteger = self.valobj.GetType(
43061da546Spatrick                ).GetBasicType(lldb.eBasicTypeUnsignedInt)
44061da546Spatrick        self.update()
45061da546Spatrick
46061da546Spatrick    def update(self):
47061da546Spatrick        self.adjust_for_architecture()
48061da546Spatrick
49061da546Spatrick    # one pointer is the ISA
50061da546Spatrick    # then there are 32 bit worth of flags and other data
51061da546Spatrick    # however, on 64bit systems these are padded to be a full
52061da546Spatrick    # machine word long, which means we actually have two pointers
53061da546Spatrick    # worth of data to skip
54061da546Spatrick    def offset(self):
55061da546Spatrick        return 2 * self.sys_params.pointer_size
56061da546Spatrick
57061da546Spatrick    def length(self):
58061da546Spatrick        logger = lldb.formatters.Logger.Logger()
59061da546Spatrick        logger >> "NSConcreteData_SummaryProvider length"
60061da546Spatrick        size = self.valobj.CreateChildAtOffset(
61061da546Spatrick            "count", self.offset(), self.sys_params.types_cache.NSUInteger)
62061da546Spatrick        logger >> str(size)
63061da546Spatrick        logger >> str(size.GetValueAsUnsigned(0))
64061da546Spatrick        return size.GetValueAsUnsigned(0)
65061da546Spatrick
66061da546Spatrick
67061da546Spatrickclass NSDataUnknown_SummaryProvider:
68061da546Spatrick
69061da546Spatrick    def adjust_for_architecture(self):
70061da546Spatrick        pass
71061da546Spatrick
72061da546Spatrick    def __init__(self, valobj, params):
73061da546Spatrick        logger = lldb.formatters.Logger.Logger()
74061da546Spatrick        logger >> "NSDataUnknown_SummaryProvider __init__"
75061da546Spatrick        self.valobj = valobj
76061da546Spatrick        self.sys_params = params
77061da546Spatrick        self.update()
78061da546Spatrick
79061da546Spatrick    def update(self):
80061da546Spatrick        self.adjust_for_architecture()
81061da546Spatrick
82061da546Spatrick    def length(self):
83061da546Spatrick        logger = lldb.formatters.Logger.Logger()
84061da546Spatrick        logger >> "NSDataUnknown_SummaryProvider length"
85061da546Spatrick        stream = lldb.SBStream()
86061da546Spatrick        self.valobj.GetExpressionPath(stream)
87061da546Spatrick        logger >> stream.GetData()
88061da546Spatrick        num_children_vo = self.valobj.CreateValueFromExpression(
89061da546Spatrick            "count", "(int)[" + stream.GetData() + " length]")
90061da546Spatrick        logger >> "still in after expression: " + str(num_children_vo)
91061da546Spatrick        if num_children_vo.IsValid():
92061da546Spatrick            logger >> "wow - expr output is valid: " + \
93061da546Spatrick                str(num_children_vo.GetValueAsUnsigned())
94061da546Spatrick            return num_children_vo.GetValueAsUnsigned(0)
95061da546Spatrick        logger >> "invalid expr output - too bad"
96061da546Spatrick        return '<variable is not NSData>'
97061da546Spatrick
98061da546Spatrick
99061da546Spatrickdef GetSummary_Impl(valobj):
100061da546Spatrick    global statistics
101061da546Spatrick    logger = lldb.formatters.Logger.Logger()
102061da546Spatrick    logger >> "NSData GetSummary_Impl"
103061da546Spatrick    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
104061da546Spatrick        valobj, statistics)
105061da546Spatrick    if wrapper:
106061da546Spatrick        logger >> "got a wrapper summary - using it"
107061da546Spatrick        return wrapper
108061da546Spatrick
109061da546Spatrick    name_string = class_data.class_name()
110061da546Spatrick    logger >> "class name: " + name_string
111061da546Spatrick    if name_string == 'NSConcreteData' or \
112061da546Spatrick       name_string == 'NSConcreteMutableData' or \
113061da546Spatrick       name_string == '__NSCFData':
114061da546Spatrick        wrapper = NSConcreteData_SummaryProvider(valobj, class_data.sys_params)
115061da546Spatrick        statistics.metric_hit('code_notrun', valobj)
116061da546Spatrick    else:
117061da546Spatrick        wrapper = NSDataUnknown_SummaryProvider(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 NSData_SummaryProvider(valobj, dict):
127061da546Spatrick    logger = lldb.formatters.Logger.Logger()
128061da546Spatrick    logger >> "NSData_SummaryProvider"
129061da546Spatrick    provider = GetSummary_Impl(valobj)
130061da546Spatrick    logger >> "found a summary provider, it is: " + str(provider)
131061da546Spatrick    if provider is not None:
132061da546Spatrick        try:
133061da546Spatrick            summary = provider.length()
134061da546Spatrick        except:
135061da546Spatrick            summary = None
136061da546Spatrick        logger >> "got a summary: it is " + str(summary)
137061da546Spatrick        if summary is None:
138061da546Spatrick            summary = '<variable is not NSData>'
139*f6aab3d8Srobert        elif isinstance(summary, str):
140061da546Spatrick            pass
141061da546Spatrick        else:
142061da546Spatrick            if summary == 1:
143061da546Spatrick                summary = '1 byte'
144061da546Spatrick            else:
145061da546Spatrick                summary = str(summary) + ' bytes'
146061da546Spatrick        return summary
147061da546Spatrick    return 'Summary Unavailable'
148061da546Spatrick
149061da546Spatrick
150061da546Spatrickdef NSData_SummaryProvider2(valobj, dict):
151061da546Spatrick    logger = lldb.formatters.Logger.Logger()
152061da546Spatrick    logger >> "NSData_SummaryProvider2"
153061da546Spatrick    provider = GetSummary_Impl(valobj)
154061da546Spatrick    logger >> "found a summary provider, it is: " + str(provider)
155061da546Spatrick    if provider is not None:
156061da546Spatrick        if isinstance(
157061da546Spatrick                provider,
158061da546Spatrick                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
159061da546Spatrick            return provider.message()
160061da546Spatrick        try:
161061da546Spatrick            summary = provider.length()
162061da546Spatrick        except:
163061da546Spatrick            summary = None
164061da546Spatrick        logger >> "got a summary: it is " + str(summary)
165061da546Spatrick        if summary is None:
166061da546Spatrick            summary = '<variable is not CFData>'
167*f6aab3d8Srobert        elif isinstance(summary, str):
168061da546Spatrick            pass
169061da546Spatrick        else:
170061da546Spatrick            if summary == 1:
171061da546Spatrick                summary = '@"1 byte"'
172061da546Spatrick            else:
173061da546Spatrick                summary = '@"' + str(summary) + ' bytes"'
174061da546Spatrick        return summary
175061da546Spatrick    return 'Summary Unavailable'
176061da546Spatrick
177061da546Spatrick
178061da546Spatrickdef __lldb_init_module(debugger, dict):
179061da546Spatrick    debugger.HandleCommand(
180061da546Spatrick        "type summary add -F NSData.NSData_SummaryProvider NSData")
181061da546Spatrick    debugger.HandleCommand(
182061da546Spatrick        "type summary add -F NSData.NSData_SummaryProvider2 CFDataRef CFMutableDataRef")
183