brintos

brintos / llvm-project-archived public Read only

0
0
Text · 10.1 KiB · 6441c69 Raw
322 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 NSDate9# the real summary is now C++ code built into LLDB10import lldb11import ctypes12import lldb.runtime.objc.objc_runtime13import lldb.formatters.metrics14import struct15import time16import datetime17import CFString18import lldb.formatters.Logger19 20statistics = lldb.formatters.metrics.Metrics()21statistics.add_metric("invalid_isa")22statistics.add_metric("invalid_pointer")23statistics.add_metric("unknown_class")24statistics.add_metric("code_notrun")25 26# Python promises to start counting time at midnight on Jan 1st on the epoch year27# hence, all we need to know is the epoch year28python_epoch = time.gmtime(0).tm_year29 30osx_epoch = datetime.date(2001, 1, 1).timetuple()31 32 33def mkgmtime(t):34    logger = lldb.formatters.Logger.Logger()35    return time.mktime(t) - time.timezone36 37 38osx_epoch = mkgmtime(osx_epoch)39 40 41def osx_to_python_time(osx):42    logger = lldb.formatters.Logger.Logger()43    if python_epoch <= 2001:44        return osx + osx_epoch45    else:46        return osx - osx_epoch47 48 49# represent a struct_time as a string in the format used by Xcode50 51 52def xcode_format_time(X):53    logger = lldb.formatters.Logger.Logger()54    return time.strftime("%Y-%m-%d %H:%M:%S %Z", X)55 56 57# represent a count-since-epoch as a string in the format used by Xcode58 59 60def xcode_format_count(X):61    logger = lldb.formatters.Logger.Logger()62    return xcode_format_time(time.localtime(X))63 64 65# despite the similary to synthetic children providers, these classes are not66# trying to provide anything but the summary for NSDate, so they need not67# obey the interface specification for synthetic children providers68 69 70class NSTaggedDate_SummaryProvider:71    def adjust_for_architecture(self):72        pass73 74    def __init__(self, valobj, info_bits, data, params):75        logger = lldb.formatters.Logger.Logger()76        self.valobj = valobj77        self.sys_params = params78        self.update()79        # NSDate is not using its info_bits for info like NSNumber is80        # so we need to regroup info_bits and data81        self.data = (data << 8) | (info_bits << 4)82 83    def update(self):84        logger = lldb.formatters.Logger.Logger()85        self.adjust_for_architecture()86 87    def value(self):88        logger = lldb.formatters.Logger.Logger()89        # the value of the date-time object is wrapped into the pointer value90        # unfortunately, it is made as a time-delta after Jan 1 2001 midnight GMT91        # while all Python knows about is the "epoch", which is a platform-dependent92        # year (1970 of *nix) whose Jan 1 at midnight is taken as reference93        value_double = struct.unpack("d", struct.pack("Q", self.data))[0]94        if value_double == -63114076800.0:95            return "0001-12-30 00:00:00 +0000"96        return xcode_format_count(osx_to_python_time(value_double))97 98 99class NSUntaggedDate_SummaryProvider:100    def adjust_for_architecture(self):101        pass102 103    def __init__(self, valobj, params):104        logger = lldb.formatters.Logger.Logger()105        self.valobj = valobj106        self.sys_params = params107        if not (self.sys_params.types_cache.double):108            self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(109                lldb.eBasicTypeDouble110            )111        self.update()112 113    def update(self):114        logger = lldb.formatters.Logger.Logger()115        self.adjust_for_architecture()116 117    def offset(self):118        logger = lldb.formatters.Logger.Logger()119        return self.sys_params.pointer_size120 121    def value(self):122        logger = lldb.formatters.Logger.Logger()123        value = self.valobj.CreateChildAtOffset(124            "value", self.offset(), self.sys_params.types_cache.double125        )126        value_double = struct.unpack("d", struct.pack("Q", value.GetData().uint64[0]))[127            0128        ]129        if value_double == -63114076800.0:130            return "0001-12-30 00:00:00 +0000"131        return xcode_format_count(osx_to_python_time(value_double))132 133 134class NSCalendarDate_SummaryProvider:135    def adjust_for_architecture(self):136        pass137 138    def __init__(self, valobj, params):139        logger = lldb.formatters.Logger.Logger()140        self.valobj = valobj141        self.sys_params = params142        if not (self.sys_params.types_cache.double):143            self.sys_params.types_cache.double = self.valobj.GetType().GetBasicType(144                lldb.eBasicTypeDouble145            )146        self.update()147 148    def update(self):149        logger = lldb.formatters.Logger.Logger()150        self.adjust_for_architecture()151 152    def offset(self):153        logger = lldb.formatters.Logger.Logger()154        return 2 * self.sys_params.pointer_size155 156    def value(self):157        logger = lldb.formatters.Logger.Logger()158        value = self.valobj.CreateChildAtOffset(159            "value", self.offset(), self.sys_params.types_cache.double160        )161        value_double = struct.unpack("d", struct.pack("Q", value.GetData().uint64[0]))[162            0163        ]164        return xcode_format_count(osx_to_python_time(value_double))165 166 167class NSTimeZoneClass_SummaryProvider:168    def adjust_for_architecture(self):169        pass170 171    def __init__(self, valobj, params):172        logger = lldb.formatters.Logger.Logger()173        self.valobj = valobj174        self.sys_params = params175        if not (self.sys_params.types_cache.voidptr):176            self.sys_params.types_cache.voidptr = (177                self.valobj.GetType().GetBasicType(lldb.eBasicTypeVoid).GetPointerType()178            )179        self.update()180 181    def update(self):182        logger = lldb.formatters.Logger.Logger()183        self.adjust_for_architecture()184 185    def offset(self):186        logger = lldb.formatters.Logger.Logger()187        return self.sys_params.pointer_size188 189    def timezone(self):190        logger = lldb.formatters.Logger.Logger()191        tz_string = self.valobj.CreateChildAtOffset(192            "tz_name", self.offset(), self.sys_params.types_cache.voidptr193        )194        return CFString.CFString_SummaryProvider(tz_string, None)195 196 197class NSUnknownDate_SummaryProvider:198    def adjust_for_architecture(self):199        pass200 201    def __init__(self, valobj):202        logger = lldb.formatters.Logger.Logger()203        self.valobj = valobj204        self.update()205 206    def update(self):207        logger = lldb.formatters.Logger.Logger()208        self.adjust_for_architecture()209 210    def value(self):211        logger = lldb.formatters.Logger.Logger()212        stream = lldb.SBStream()213        self.valobj.GetExpressionPath(stream)214        expr = "(NSString*)[" + stream.GetData() + " description]"215        num_children_vo = self.valobj.CreateValueFromExpression("str", expr)216        if num_children_vo.IsValid():217            return num_children_vo.GetSummary()218        return "<variable is not NSDate>"219 220 221def GetSummary_Impl(valobj):222    logger = lldb.formatters.Logger.Logger()223    global statistics224    (225        class_data,226        wrapper,227    ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(228        valobj, statistics229    )230    if wrapper:231        return wrapper232 233    name_string = class_data.class_name()234    logger >> "class name is: " + str(name_string)235 236    if (237        name_string == "NSDate"238        or name_string == "__NSDate"239        or name_string == "__NSTaggedDate"240    ):241        if class_data.is_tagged():242            wrapper = NSTaggedDate_SummaryProvider(243                valobj,244                class_data.info_bits(),245                class_data.value(),246                class_data.sys_params,247            )248            statistics.metric_hit("code_notrun", valobj)249        else:250            wrapper = NSUntaggedDate_SummaryProvider(valobj, class_data.sys_params)251            statistics.metric_hit("code_notrun", valobj)252    elif name_string == "NSCalendarDate":253        wrapper = NSCalendarDate_SummaryProvider(valobj, class_data.sys_params)254        statistics.metric_hit("code_notrun", valobj)255    elif name_string == "__NSTimeZone":256        wrapper = NSTimeZoneClass_SummaryProvider(valobj, class_data.sys_params)257        statistics.metric_hit("code_notrun", valobj)258    else:259        wrapper = NSUnknownDate_SummaryProvider(valobj)260        statistics.metric_hit(261            "unknown_class", valobj.GetName() + " seen as " + name_string262        )263    return wrapper264 265 266def NSDate_SummaryProvider(valobj, dict):267    logger = lldb.formatters.Logger.Logger()268    provider = GetSummary_Impl(valobj)269    if provider is not None:270        if isinstance(271            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description272        ):273            return provider.message()274        try:275            summary = provider.value()276        except:277            summary = None278        if summary is None:279            summary = "<variable is not NSDate>"280        return str(summary)281    return "Summary Unavailable"282 283 284def NSTimeZone_SummaryProvider(valobj, dict):285    logger = lldb.formatters.Logger.Logger()286    provider = GetSummary_Impl(valobj)287    if provider is not None:288        if isinstance(289            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description290        ):291            return provider.message()292        try:293            summary = provider.timezone()294        except:295            summary = None296        logger >> "got summary " + str(summary)297        if summary is None:298            summary = "<variable is not NSTimeZone>"299        return str(summary)300    return "Summary Unavailable"301 302 303def CFAbsoluteTime_SummaryProvider(valobj, dict):304    logger = lldb.formatters.Logger.Logger()305    try:306        value_double = struct.unpack("d", struct.pack("Q", valobj.GetData().uint64[0]))[307            0308        ]309        return xcode_format_count(osx_to_python_time(value_double))310    except:311        return "Summary Unavailable"312 313 314def __lldb_init_module(debugger, dict):315    debugger.HandleCommand("type summary add -F NSDate.NSDate_SummaryProvider NSDate")316    debugger.HandleCommand(317        "type summary add -F NSDate.CFAbsoluteTime_SummaryProvider CFAbsoluteTime"318    )319    debugger.HandleCommand(320        "type summary add -F NSDate.NSTimeZone_SummaryProvider NSTimeZone CFTimeZoneRef"321    )322