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