brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.4 KiB · 559b8eb Raw
183 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 NS(Mutable)IndexSet9# 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# despite the similary to synthetic children providers, these classes are not23# trying to provide anything but the count of values for an NSIndexSet, so they need not24# obey the interface specification for synthetic children providers25 26 27class NSIndexSetClass_SummaryProvider:28    def adjust_for_architecture(self):29        pass30 31    def __init__(self, valobj, params):32        logger = lldb.formatters.Logger.Logger()33        self.valobj = valobj34        self.sys_params = params35        if not (self.sys_params.types_cache.NSUInteger):36            if self.sys_params.is_64_bit:37                self.sys_params.types_cache.NSUInteger = (38                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)39                )40                self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(41                    lldb.eBasicTypeUnsignedInt42                )43            else:44                self.sys_params.types_cache.NSUInteger = (45                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)46                )47                self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(48                    lldb.eBasicTypeUnsignedInt49                )50        if not (self.sys_params.types_cache.uint32):51            self.sys_params.types_cache.uint32 = self.valobj.GetType().GetBasicType(52                lldb.eBasicTypeUnsignedInt53            )54        self.update()55 56    def update(self):57        logger = lldb.formatters.Logger.Logger()58        self.adjust_for_architecture()59 60    # NS(Mutable)IndexSet works in one of two modes: when having a compact block of data (e.g. a Range)61    # the count is stored in the set itself, 3 pointers into it62    # otherwise, it will store a pointer to an additional data structure (2 pointers into itself) and this63    # additional structure will contain the count two pointers deep64    # a bunch of flags allow us to detect an empty set, vs. a one-range set,65    # vs. a multi-range set66    def count(self):67        logger = lldb.formatters.Logger.Logger()68        mode_chooser_vo = self.valobj.CreateChildAtOffset(69            "mode_chooser",70            self.sys_params.pointer_size,71            self.sys_params.types_cache.uint32,72        )73        mode_chooser = mode_chooser_vo.GetValueAsUnsigned(0)74        if self.sys_params.is_64_bit:75            mode_chooser = mode_chooser & 0x00000000FFFFFFFF76        # empty set77        if mode_chooser & 0x01 == 1:78            return 079        # single range80        if mode_chooser & 0x02 == 2:81            mode = 182        # multi range83        else:84            mode = 285        if mode == 1:86            count_vo = self.valobj.CreateChildAtOffset(87                "count",88                3 * self.sys_params.pointer_size,89                self.sys_params.types_cache.NSUInteger,90            )91        else:92            count_ptr = self.valobj.CreateChildAtOffset(93                "count_ptr",94                2 * self.sys_params.pointer_size,95                self.sys_params.types_cache.NSUInteger,96            )97            count_vo = self.valobj.CreateValueFromAddress(98                "count",99                count_ptr.GetValueAsUnsigned() + 2 * self.sys_params.pointer_size,100                self.sys_params.types_cache.NSUInteger,101            )102        return count_vo.GetValueAsUnsigned(0)103 104 105class NSIndexSetUnknown_SummaryProvider:106    def adjust_for_architecture(self):107        pass108 109    def __init__(self, valobj, params):110        logger = lldb.formatters.Logger.Logger()111        self.valobj = valobj112        self.sys_params = params113        self.update()114 115    def update(self):116        logger = lldb.formatters.Logger.Logger()117        self.adjust_for_architecture()118 119    def count(self):120        logger = lldb.formatters.Logger.Logger()121        stream = lldb.SBStream()122        self.valobj.GetExpressionPath(stream)123        expr = "(int)[" + stream.GetData() + " count]"124        num_children_vo = self.valobj.CreateValueFromExpression("count", expr)125        if num_children_vo.IsValid():126            return num_children_vo.GetValueAsUnsigned(0)127        return "<variable is not NSIndexSet>"128 129 130def GetSummary_Impl(valobj):131    logger = lldb.formatters.Logger.Logger()132    global statistics133    (134        class_data,135        wrapper,136    ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(137        valobj, statistics138    )139    if wrapper:140        return wrapper141 142    name_string = class_data.class_name()143    logger >> "class name is: " + str(name_string)144 145    if name_string == "NSIndexSet" or name_string == "NSMutableIndexSet":146        wrapper = NSIndexSetClass_SummaryProvider(valobj, class_data.sys_params)147        statistics.metric_hit("code_notrun", valobj)148    else:149        wrapper = NSIndexSetUnknown_SummaryProvider(valobj, class_data.sys_params)150        statistics.metric_hit(151            "unknown_class", valobj.GetName() + " seen as " + name_string152        )153    return wrapper154 155 156def NSIndexSet_SummaryProvider(valobj, dict):157    logger = lldb.formatters.Logger.Logger()158    provider = GetSummary_Impl(valobj)159    if provider is not None:160        if isinstance(161            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description162        ):163            return provider.message()164        try:165            summary = provider.count()166        except:167            summary = None168        logger >> "got summary " + str(summary)169        if summary is None:170            summary = "<variable is not NSIndexSet>"171        if isinstance(summary, str):172            return summary173        else:174            summary = str(summary) + (" indexes" if summary != 1 else " index")175        return summary176    return "Summary Unavailable"177 178 179def __lldb_init_module(debugger, dict):180    debugger.HandleCommand(181        "type summary add -F NSIndexSet.NSIndexSet_SummaryProvider NSIndexSet NSMutableIndexSet"182    )183