brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.4 KiB · 6b8bf39 Raw
273 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 NSDictionary9# 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 for an NSDictionary, so they need not24# obey the interface specification for synthetic children providers25 26 27class NSCFDictionary_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            else:41                self.sys_params.types_cache.NSUInteger = (42                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)43                )44        self.update()45 46    def update(self):47        logger = lldb.formatters.Logger.Logger()48        self.adjust_for_architecture()49 50    # empirically determined on both 32 and 64bit desktop Mac OS X51    # probably boils down to 2 pointers and 4 bytes of data, but52    # the description of __CFDictionary is not readily available so most53    # of this is guesswork, plain and simple54    def offset(self):55        logger = lldb.formatters.Logger.Logger()56        if self.sys_params.is_64_bit:57            return 2058        else:59            return 1260 61    def num_children(self):62        logger = lldb.formatters.Logger.Logger()63        num_children_vo = self.valobj.CreateChildAtOffset(64            "count", self.offset(), self.sys_params.types_cache.NSUInteger65        )66        return num_children_vo.GetValueAsUnsigned(0)67 68 69class NSDictionaryI_SummaryProvider:70    def adjust_for_architecture(self):71        pass72 73    def __init__(self, valobj, params):74        logger = lldb.formatters.Logger.Logger()75        self.valobj = valobj76        self.sys_params = params77        if not (self.sys_params.types_cache.NSUInteger):78            if self.sys_params.is_64_bit:79                self.sys_params.types_cache.NSUInteger = (80                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)81                )82            else:83                self.sys_params.types_cache.NSUInteger = (84                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)85                )86        self.update()87 88    def update(self):89        logger = lldb.formatters.Logger.Logger()90        self.adjust_for_architecture()91 92    # we just need to skip the ISA and the count immediately follows93    def offset(self):94        logger = lldb.formatters.Logger.Logger()95        return self.sys_params.pointer_size96 97    def num_children(self):98        logger = lldb.formatters.Logger.Logger()99        num_children_vo = self.valobj.CreateChildAtOffset(100            "count", self.offset(), self.sys_params.types_cache.NSUInteger101        )102        value = num_children_vo.GetValueAsUnsigned(0)103        if value is not None:104            # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity105            # not sure if it is a bug or some weird sort of feature, but masking that out106            # gets the count right107            if self.sys_params.is_64_bit:108                value = value & ~0xFC00000000000000109            else:110                value = value & ~0xFC000000111        return value112 113 114class NSDictionaryM_SummaryProvider:115    def adjust_for_architecture(self):116        pass117 118    def __init__(self, valobj, params):119        logger = lldb.formatters.Logger.Logger()120        self.valobj = valobj121        self.sys_params = params122        if not (self.sys_params.types_cache.NSUInteger):123            if self.sys_params.is_64_bit:124                self.sys_params.types_cache.NSUInteger = (125                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)126                )127            else:128                self.sys_params.types_cache.NSUInteger = (129                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)130                )131        self.update()132 133    def update(self):134        logger = lldb.formatters.Logger.Logger()135        self.adjust_for_architecture()136 137    # we just need to skip the ISA and the count immediately follows138    def offset(self):139        return self.sys_params.pointer_size140 141    def num_children(self):142        logger = lldb.formatters.Logger.Logger()143        num_children_vo = self.valobj.CreateChildAtOffset(144            "count", self.offset(), self.sys_params.types_cache.NSUInteger145        )146        value = num_children_vo.GetValueAsUnsigned(0)147        if value is not None:148            # the MS6bits on immutable dictionaries seem to be taken by the LSB of capacity149            # not sure if it is a bug or some weird sort of feature, but masking that out150            # gets the count right151            if self.sys_params.is_64_bit:152                value = value & ~0xFC00000000000000153            else:154                value = value & ~0xFC000000155        return value156 157 158class NSDictionaryUnknown_SummaryProvider:159    def adjust_for_architecture(self):160        pass161 162    def __init__(self, valobj, params):163        logger = lldb.formatters.Logger.Logger()164        self.valobj = valobj165        self.sys_params = params166        self.update()167 168    def update(self):169        logger = lldb.formatters.Logger.Logger()170        self.adjust_for_architecture()171 172    def num_children(self):173        logger = lldb.formatters.Logger.Logger()174        stream = lldb.SBStream()175        self.valobj.GetExpressionPath(stream)176        num_children_vo = self.valobj.CreateValueFromExpression(177            "count", "(int)[" + stream.GetData() + " count]"178        )179        if num_children_vo.IsValid():180            return num_children_vo.GetValueAsUnsigned(0)181        return "<variable is not NSDictionary>"182 183 184def GetSummary_Impl(valobj):185    logger = lldb.formatters.Logger.Logger()186    global statistics187    (188        class_data,189        wrapper,190    ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(191        valobj, statistics192    )193    if wrapper:194        return wrapper195 196    name_string = class_data.class_name()197 198    logger >> "class name is: " + str(name_string)199 200    if name_string == "__NSCFDictionary":201        wrapper = NSCFDictionary_SummaryProvider(valobj, class_data.sys_params)202        statistics.metric_hit("code_notrun", valobj)203    elif name_string == "__NSDictionaryI":204        wrapper = NSDictionaryI_SummaryProvider(valobj, class_data.sys_params)205        statistics.metric_hit("code_notrun", valobj)206    elif name_string == "__NSDictionaryM":207        wrapper = NSDictionaryM_SummaryProvider(valobj, class_data.sys_params)208        statistics.metric_hit("code_notrun", valobj)209    else:210        wrapper = NSDictionaryUnknown_SummaryProvider(valobj, class_data.sys_params)211        statistics.metric_hit(212            "unknown_class", valobj.GetName() + " seen as " + name_string213        )214    return wrapper215 216 217def CFDictionary_SummaryProvider(valobj, dict):218    logger = lldb.formatters.Logger.Logger()219    provider = GetSummary_Impl(valobj)220    if provider is not None:221        if isinstance(222            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description223        ):224            return provider.message()225        try:226            summary = provider.num_children()227        except:228            summary = None229        logger >> "got summary " + str(summary)230        if summary is None:231            return "<variable is not NSDictionary>"232        if isinstance(summary, str):233            return summary234        return str(summary) + (235            " key/value pairs" if summary != 1 else " key/value pair"236        )237    return "Summary Unavailable"238 239 240def CFDictionary_SummaryProvider2(valobj, dict):241    logger = lldb.formatters.Logger.Logger()242    provider = GetSummary_Impl(valobj)243    if provider is not None:244        if isinstance(245            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description246        ):247            return provider.message()248        try:249            summary = provider.num_children()250        except:251            summary = None252        logger >> "got summary " + str(summary)253        if summary is None:254            summary = "<variable is not CFDictionary>"255        if isinstance(summary, str):256            return summary257        else:258            # needed on OSX Mountain Lion259            if provider.sys_params.is_64_bit:260                summary = summary & ~0x0F1F000000000000261            summary = '@"' + str(summary) + (' entries"' if summary != 1 else ' entry"')262        return summary263    return "Summary Unavailable"264 265 266def __lldb_init_module(debugger, dict):267    debugger.HandleCommand(268        "type summary add -F CFDictionary.CFDictionary_SummaryProvider NSDictionary"269    )270    debugger.HandleCommand(271        "type summary add -F CFDictionary.CFDictionary_SummaryProvider2 CFDictionaryRef CFMutableDictionaryRef"272    )273