brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.7 KiB · c911573 Raw
235 lines · python
1"""2LLDB AppKit formatters3 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-exception7"""8# example summary provider for NSArray9# the real summary is now C++ code built into LLDB10import lldb11import ctypes12import lldb.runtime.objc.objc_runtime13import lldb.formatters.metrics14import lldb.formatters.Logger15 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# much less functional than the other two cases below23# just runs code to get to the count and then returns24# no children25 26 27class NSArrayKVC_SynthProvider:28    def adjust_for_architecture(self):29        pass30 31    def __init__(self, valobj, dict, params):32        logger = lldb.formatters.Logger.Logger()33        self.valobj = valobj34        self.update()35 36    def update(self):37        logger = lldb.formatters.Logger.Logger()38        self.adjust_for_architecture()39 40    def num_children(self):41        logger = lldb.formatters.Logger.Logger()42        stream = lldb.SBStream()43        self.valobj.GetExpressionPath(stream)44        num_children_vo = self.valobj.CreateValueFromExpression(45            "count", "(int)[" + stream.GetData() + " count]"46        )47        if num_children_vo.IsValid():48            return num_children_vo.GetValueAsUnsigned(0)49        return "<variable is not NSArray>"50 51 52# much less functional than the other two cases below53# just runs code to get to the count and then returns54# no children55 56 57class NSArrayCF_SynthProvider:58    def adjust_for_architecture(self):59        pass60 61    def __init__(self, valobj, dict, params):62        logger = lldb.formatters.Logger.Logger()63        self.valobj = valobj64        self.sys_params = params65        if not (self.sys_params.types_cache.ulong):66            self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(67                lldb.eBasicTypeUnsignedLong68            )69        self.update()70 71    def update(self):72        logger = lldb.formatters.Logger.Logger()73        self.adjust_for_architecture()74 75    def num_children(self):76        logger = lldb.formatters.Logger.Logger()77        num_children_vo = self.valobj.CreateChildAtOffset(78            "count", self.sys_params.cfruntime_size, self.sys_params.types_cache.ulong79        )80        return num_children_vo.GetValueAsUnsigned(0)81 82 83class NSArrayI_SynthProvider:84    def adjust_for_architecture(self):85        pass86 87    def __init__(self, valobj, dict, params):88        logger = lldb.formatters.Logger.Logger()89        self.valobj = valobj90        self.sys_params = params91        if not (self.sys_params.types_cache.long):92            self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(93                lldb.eBasicTypeLong94            )95        self.update()96 97    def update(self):98        logger = lldb.formatters.Logger.Logger()99        self.adjust_for_architecture()100 101    # skip the isa pointer and get at the size102    def num_children(self):103        logger = lldb.formatters.Logger.Logger()104        count = self.valobj.CreateChildAtOffset(105            "count", self.sys_params.pointer_size, self.sys_params.types_cache.long106        )107        return count.GetValueAsUnsigned(0)108 109 110class NSArrayM_SynthProvider:111    def adjust_for_architecture(self):112        pass113 114    def __init__(self, valobj, dict, params):115        logger = lldb.formatters.Logger.Logger()116        self.valobj = valobj117        self.sys_params = params118        if not (self.sys_params.types_cache.long):119            self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(120                lldb.eBasicTypeLong121            )122        self.update()123 124    def update(self):125        logger = lldb.formatters.Logger.Logger()126        self.adjust_for_architecture()127 128    # skip the isa pointer and get at the size129    def num_children(self):130        logger = lldb.formatters.Logger.Logger()131        count = self.valobj.CreateChildAtOffset(132            "count", self.sys_params.pointer_size, self.sys_params.types_cache.long133        )134        return count.GetValueAsUnsigned(0)135 136 137# this is the actual synth provider, but is just a wrapper that checks138# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an139# appropriate backend layer to do the computations140 141 142class NSArray_SynthProvider:143    def adjust_for_architecture(self):144        pass145 146    def __init__(self, valobj, dict):147        logger = lldb.formatters.Logger.Logger()148        self.valobj = valobj149        self.adjust_for_architecture()150        self.error = False151        self.wrapper = self.make_wrapper()152        self.invalid = self.wrapper is None153 154    def num_children(self):155        logger = lldb.formatters.Logger.Logger()156        if self.wrapper is None:157            return 0158        return self.wrapper.num_children()159 160    def update(self):161        logger = lldb.formatters.Logger.Logger()162        if self.wrapper is None:163            return164        self.wrapper.update()165 166    # this code acts as our defense against NULL and uninitialized167    # NSArray pointers, which makes it much longer than it would be otherwise168    def make_wrapper(self):169        logger = lldb.formatters.Logger.Logger()170        if self.valobj.GetValueAsUnsigned() == 0:171            self.error = True172            return lldb.runtime.objc.objc_runtime.InvalidPointer_Description(True)173        else:174            global statistics175            (176                class_data,177                wrapper,178            ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(179                self.valobj, statistics180            )181            if wrapper:182                self.error = True183                return wrapper184 185        name_string = class_data.class_name()186 187        logger >> "Class name is " + str(name_string)188 189        if name_string == "__NSArrayI":190            wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)191            statistics.metric_hit("code_notrun", self.valobj.GetName())192        elif name_string == "__NSArrayM":193            wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)194            statistics.metric_hit("code_notrun", self.valobj.GetName())195        elif name_string == "__NSCFArray":196            wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)197            statistics.metric_hit("code_notrun", self.valobj.GetName())198        else:199            wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)200            statistics.metric_hit(201                "unknown_class", str(self.valobj.GetName()) + " seen as " + name_string202            )203        return wrapper204 205 206def CFArray_SummaryProvider(valobj, dict):207    logger = lldb.formatters.Logger.Logger()208    provider = NSArray_SynthProvider(valobj, dict)209    if not provider.invalid:210        if provider.error:211            return provider.wrapper.message()212        try:213            summary = int(provider.num_children())214        except:215            summary = None216        logger >> "provider gave me " + str(summary)217        if summary is None:218            summary = "<variable is not NSArray>"219        elif isinstance(summary, str):220            pass221        else:222            # we format it like it were a CFString to make it look the same as223            # the summary from Xcode224            summary = (225                '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'226            )227        return summary228    return "Summary Unavailable"229 230 231def __lldb_init_module(debugger, dict):232    debugger.HandleCommand(233        "type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef"234    )235