brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · dfb5fb1 Raw
211 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 9# summary provider for CF(Mutable)BitVector10import lldb11import ctypes12import lldb.runtime.objc.objc_runtime13import lldb.formatters.metrics14import lldb.formatters.Logger15 16# first define some utility functions17 18 19def byte_index(abs_pos):20    logger = lldb.formatters.Logger.Logger()21    return abs_pos / 822 23 24def bit_index(abs_pos):25    logger = lldb.formatters.Logger.Logger()26    return abs_pos & 727 28 29def get_bit(byte, index):30    logger = lldb.formatters.Logger.Logger()31    if index < 0 or index > 7:32        return None33    return (byte >> (7 - index)) & 134 35 36def grab_array_item_data(pointer, index):37    logger = lldb.formatters.Logger.Logger()38    return pointer.GetPointeeData(index, 1)39 40 41statistics = lldb.formatters.metrics.Metrics()42statistics.add_metric("invalid_isa")43statistics.add_metric("invalid_pointer")44statistics.add_metric("unknown_class")45statistics.add_metric("code_notrun")46 47# despite the similary to synthetic children providers, these classes are not48# trying to provide anything but a summary for a CF*BitVector, so they need not49# obey the interface specification for synthetic children providers50 51 52class CFBitVectorKnown_SummaryProvider:53    def adjust_for_architecture(self):54        logger = lldb.formatters.Logger.Logger()55        self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize()56        pass57 58    def __init__(self, valobj, params):59        logger = lldb.formatters.Logger.Logger()60        self.valobj = valobj61        self.sys_params = params62        if not (self.sys_params.types_cache.NSUInteger):63            if self.sys_params.is_64_bit:64                self.sys_params.types_cache.NSUInteger = (65                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)66                )67            else:68                self.sys_params.types_cache.NSUInteger = (69                    self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt)70                )71        if not (self.sys_params.types_cache.charptr):72            self.sys_params.types_cache.charptr = (73                self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType()74            )75        self.update()76 77    def update(self):78        logger = lldb.formatters.Logger.Logger()79        self.adjust_for_architecture()80 81    # we skip the CFRuntimeBase82    # then the next CFIndex is the count83    # then we skip another CFIndex and then we get at a byte array84    # that wraps the individual bits85 86    def contents(self):87        logger = lldb.formatters.Logger.Logger()88        count_vo = self.valobj.CreateChildAtOffset(89            "count",90            self.sys_params.cfruntime_size,91            self.sys_params.types_cache.NSUInteger,92        )93        count = count_vo.GetValueAsUnsigned(0)94        if count == 0:95            return "(empty)"96 97        array_vo = self.valobj.CreateChildAtOffset(98            "data",99            self.sys_params.cfruntime_size + 2 * self.uiint_size,100            self.sys_params.types_cache.charptr,101        )102 103        data_list = []104        cur_byte_pos = None105        for i in range(0, count):106            if cur_byte_pos is None:107                cur_byte_pos = byte_index(i)108                cur_byte = grab_array_item_data(array_vo, cur_byte_pos)109                cur_byte_val = cur_byte.uint8[0]110            else:111                byte_pos = byte_index(i)112                # do not fetch the pointee data every single time through113                if byte_pos != cur_byte_pos:114                    cur_byte_pos = byte_pos115                    cur_byte = grab_array_item_data(array_vo, cur_byte_pos)116                    cur_byte_val = cur_byte.uint8[0]117            bit = get_bit(cur_byte_val, bit_index(i))118            if (i % 4) == 0:119                data_list.append(" ")120            if bit == 1:121                data_list.append("1")122            else:123                data_list.append("0")124        return "".join(data_list)125 126 127class CFBitVectorUnknown_SummaryProvider:128    def adjust_for_architecture(self):129        pass130 131    def __init__(self, valobj, params):132        logger = lldb.formatters.Logger.Logger()133        self.valobj = valobj134        self.sys_params = params135        self.update()136 137    def update(self):138        logger = lldb.formatters.Logger.Logger()139        self.adjust_for_architecture()140 141    def contents(self):142        logger = lldb.formatters.Logger.Logger()143        return "<unable to summarize this CFBitVector>"144 145 146def GetSummary_Impl(valobj):147    logger = lldb.formatters.Logger.Logger()148    global statistics149    (150        class_data,151        wrapper,152    ) = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(153        valobj, statistics154    )155    if wrapper:156        return wrapper157 158    name_string = class_data.class_name()159    actual_name = name_string160 161    logger >> "name string got was " + str(name_string) + " but actual name is " + str(162        actual_name163    )164 165    if class_data.is_cftype():166        # CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is167        # an NSCFType and then check we are a pointer-to CFBitVectorRef168        valobj_type = valobj.GetType()169        if valobj_type.IsValid() and valobj_type.IsPointerType():170            valobj_type = valobj_type.GetPointeeType()171            if valobj_type.IsValid():172                actual_name = valobj_type.GetName()173        if actual_name == "__CFBitVector" or actual_name == "__CFMutableBitVector":174            wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params)175            statistics.metric_hit("code_notrun", valobj)176        else:177            wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)178            print(actual_name)179    else:180        wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params)181        print(name_string)182        statistics.metric_hit(183            "unknown_class", valobj.GetName() + " seen as " + name_string184        )185    return wrapper186 187 188def CFBitVector_SummaryProvider(valobj, dict):189    logger = lldb.formatters.Logger.Logger()190    provider = GetSummary_Impl(valobj)191    if provider is not None:192        if isinstance(193            provider, lldb.runtime.objc.objc_runtime.SpecialSituation_Description194        ):195            return provider.message()196        try:197            summary = provider.contents()198        except:199            summary = None200        logger >> "summary got from provider: " + str(summary)201        if summary is None or summary == "":202            summary = "<variable is not CFBitVector>"203        return summary204    return "Summary Unavailable"205 206 207def __lldb_init_module(debugger, dict):208    debugger.HandleCommand(209        "type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef"210    )211