brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · e0eeba0 Raw
150 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 NSBundle9# the real summary is now C++ code built into LLDB10import lldb11import ctypes12import lldb.runtime.objc.objc_runtime13import lldb.formatters.metrics14import NSURL15import lldb.formatters.Logger16 17statistics = lldb.formatters.metrics.Metrics()18statistics.add_metric("invalid_isa")19statistics.add_metric("invalid_pointer")20statistics.add_metric("unknown_class")21statistics.add_metric("code_notrun")22 23# despite the similary to synthetic children providers, these classes are not24# trying to provide anything but a summary for an NSURL, so they need not25# obey the interface specification for synthetic children providers26 27 28class NSBundleKnown_SummaryProvider:29    def adjust_for_architecture(self):30        pass31 32    def __init__(self, valobj, params):33        logger = lldb.formatters.Logger.Logger()34        self.valobj = valobj35        self.sys_params = params36        if not (self.sys_params.types_cache.NSString):37            self.sys_params.types_cache.NSString = (38                self.valobj.GetTarget().FindFirstType("NSString").GetPointerType()39            )40        self.update()41 42    def update(self):43        logger = lldb.formatters.Logger.Logger()44        self.adjust_for_architecture()45 46    # we need to skip the ISA, plus four other values47    # that are luckily each a pointer in size48    # which makes our computation trivial :-)49    def offset(self):50        logger = lldb.formatters.Logger.Logger()51        return 5 * self.sys_params.pointer_size52 53    def url_text(self):54        logger = lldb.formatters.Logger.Logger()55        global statistics56        text = self.valobj.CreateChildAtOffset(57            "text", self.offset(), self.sys_params.types_cache.NSString58        )59        my_string = text.GetSummary()60        if (my_string is None) or (my_string == ""):61            statistics.metric_hit(62                "unknown_class",63                str(self.valobj.GetName()) + " triggered unknown pointer location",64            )65            return NSBundleUnknown_SummaryProvider(66                self.valobj, self.sys_params67            ).url_text()68        else:69            statistics.metric_hit("code_notrun", self.valobj)70            return my_string71 72 73class NSBundleUnknown_SummaryProvider:74    def adjust_for_architecture(self):75        pass76 77    def __init__(self, valobj, params):78        logger = lldb.formatters.Logger.Logger()79        self.valobj = valobj80        self.sys_params = params81        self.update()82 83    def update(self):84        logger = lldb.formatters.Logger.Logger()85        self.adjust_for_architecture()86 87    def url_text(self):88        logger = lldb.formatters.Logger.Logger()89        stream = lldb.SBStream()90        self.valobj.GetExpressionPath(stream)91        expr = "(NSString*)[" + stream.GetData() + " bundlePath]"92        url_text_vo = self.valobj.CreateValueFromExpression("path", expr)93        if url_text_vo.IsValid():94            return url_text_vo.GetSummary()95        return "<variable is not NSBundle>"96 97 98def GetSummary_Impl(valobj):99    logger = lldb.formatters.Logger.Logger()100    global statistics101    (102        class_data,103        wrapper,104    ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(105        valobj, statistics106    )107    if wrapper:108        return wrapper109 110    name_string = class_data.class_name()111    logger >> "class name is: " + str(name_string)112 113    if name_string == "NSBundle":114        wrapper = NSBundleKnown_SummaryProvider(valobj, class_data.sys_params)115        # [NSBundle mainBundle] does return an object that is116        # not correctly filled out for our purposes, so we still117        # end up having to run code in that case118        # statistics.metric_hit('code_notrun',valobj)119    else:120        wrapper = NSBundleUnknown_SummaryProvider(valobj, class_data.sys_params)121        statistics.metric_hit(122            "unknown_class", valobj.GetName() + " seen as " + name_string123        )124    return wrapper125 126 127def NSBundle_SummaryProvider(valobj, dict):128    logger = lldb.formatters.Logger.Logger()129    provider = GetSummary_Impl(valobj)130    if provider is not None:131        if isinstance(132            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description133        ):134            return provider.message()135        try:136            summary = provider.url_text()137        except:138            summary = None139        logger >> "got summary " + str(summary)140        if summary is None or summary == "":141            summary = "<variable is not NSBundle>"142        return summary143    return "Summary Unavailable"144 145 146def __lldb_init_module(debugger, dict):147    debugger.HandleCommand(148        "type summary add -F NSBundle.NSBundle_SummaryProvider NSBundle"149    )150