Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 1 | """ |
| 2 | LLDB AppKit formatters |
| 3 | |
| 4 | part of The LLVM Compiler Infrastructure |
| 5 | This file is distributed under the University of Illinois Open Source |
| 6 | License. See LICENSE.TXT for details. |
| 7 | """ |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 8 | # summary provider for CF(Mutable)BitVector |
| 9 | import lldb |
| 10 | import ctypes |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 11 | import lldb.runtime.objc.objc_runtime |
| 12 | import lldb.formatters.metrics |
| 13 | import lldb.formatters.Logger |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 14 | |
| 15 | # first define some utility functions |
| 16 | def byte_index(abs_pos): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 17 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 18 | return abs_pos/8 |
| 19 | |
| 20 | def bit_index(abs_pos): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 21 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 22 | return abs_pos & 7 |
| 23 | |
| 24 | def get_bit(byte,index): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 25 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 26 | if index < 0 or index > 7: |
| 27 | return None |
| 28 | return (byte >> (7-index)) & 1 |
| 29 | |
| 30 | def grab_array_item_data(pointer,index): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 31 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 32 | return pointer.GetPointeeData(index,1) |
| 33 | |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 34 | statistics = lldb.formatters.metrics.Metrics() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 35 | statistics.add_metric('invalid_isa') |
| 36 | statistics.add_metric('invalid_pointer') |
| 37 | statistics.add_metric('unknown_class') |
| 38 | statistics.add_metric('code_notrun') |
| 39 | |
| 40 | # despite the similary to synthetic children providers, these classes are not |
| 41 | # trying to provide anything but a summary for a CF*BitVector, so they need not |
| 42 | # obey the interface specification for synthetic children providers |
| 43 | class CFBitVectorKnown_SummaryProvider: |
| 44 | def adjust_for_architecture(self): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 45 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 46 | self.uiint_size = self.sys_params.types_cache.NSUInteger.GetByteSize() |
| 47 | pass |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 48 | |
| 49 | def __init__(self, valobj, params): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 50 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 51 | self.valobj = valobj; |
| 52 | self.sys_params = params |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 53 | if not(self.sys_params.types_cache.NSUInteger): |
| 54 | if self.sys_params.is_64_bit: |
| 55 | self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong) |
| 56 | else: |
| 57 | self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt) |
| 58 | if not(self.sys_params.types_cache.charptr): |
| 59 | self.sys_params.types_cache.charptr = self.valobj.GetType().GetBasicType(lldb.eBasicTypeChar).GetPointerType() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 60 | self.update(); |
| 61 | |
| 62 | def update(self): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 63 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 64 | self.adjust_for_architecture(); |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 65 | |
| 66 | # we skip the CFRuntimeBase |
| 67 | # then the next CFIndex is the count |
| 68 | # then we skip another CFIndex and then we get at a byte array |
| 69 | # that wraps the individual bits |
| 70 | |
| 71 | def contents(self): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 72 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 73 | count_vo = self.valobj.CreateChildAtOffset("count",self.sys_params.cfruntime_size, |
| 74 | self.sys_params.types_cache.NSUInteger) |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 75 | count = count_vo.GetValueAsUnsigned(0) |
| 76 | if count == 0: |
| 77 | return '(empty)' |
| 78 | |
| 79 | array_vo = self.valobj.CreateChildAtOffset("data", |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 80 | self.sys_params.cfruntime_size+2*self.uiint_size, |
| 81 | self.sys_params.types_cache.charptr) |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 82 | |
| 83 | data_list = [] |
| 84 | cur_byte_pos = None |
| 85 | for i in range(0,count): |
| 86 | if cur_byte_pos == None: |
| 87 | cur_byte_pos = byte_index(i) |
| 88 | cur_byte = grab_array_item_data(array_vo,cur_byte_pos) |
| 89 | cur_byte_val = cur_byte.uint8[0] |
| 90 | else: |
| 91 | byte_pos = byte_index(i) |
| 92 | # do not fetch the pointee data every single time through |
| 93 | if byte_pos != cur_byte_pos: |
| 94 | cur_byte_pos = byte_pos |
| 95 | cur_byte = grab_array_item_data(array_vo,cur_byte_pos) |
| 96 | cur_byte_val = cur_byte.uint8[0] |
| 97 | bit = get_bit(cur_byte_val,bit_index(i)) |
| 98 | if (i % 4) == 0: |
| 99 | data_list.append(' ') |
| 100 | if bit == 1: |
| 101 | data_list.append('1') |
| 102 | else: |
| 103 | data_list.append('0') |
| 104 | return ''.join(data_list) |
| 105 | |
| 106 | |
| 107 | class CFBitVectorUnknown_SummaryProvider: |
| 108 | def adjust_for_architecture(self): |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 109 | pass |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 110 | |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 111 | def __init__(self, valobj, params): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 112 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 113 | self.valobj = valobj; |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 114 | self.sys_params = params |
| 115 | self.update(); |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 116 | |
| 117 | def update(self): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 118 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 119 | self.adjust_for_architecture(); |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 120 | |
| 121 | def contents(self): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 122 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 123 | return '<unable to summarize this CFBitVector>' |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 124 | |
| 125 | |
| 126 | def GetSummary_Impl(valobj): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 127 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 128 | global statistics |
Enrico Granata | 7d22221 | 2012-04-25 17:53:41 +0000 | [diff] [blame] | 129 | class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics) |
Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 130 | if wrapper: |
| 131 | return wrapper |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 132 | |
| 133 | name_string = class_data.class_name() |
Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 134 | actual_name = name_string |
Enrico Granata | 247bd41 | 2012-04-02 16:39:29 +0000 | [diff] [blame] | 135 | |
| 136 | logger >> "name string got was " + str(name_string) + " but actual name is " + str(actual_name) |
| 137 | |
Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 138 | if class_data.is_cftype(): |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 139 | # CFBitVectorRef does not expose an actual NSWrapper type, so we have to check that this is |
| 140 | # an NSCFType and then check we are a pointer-to CFBitVectorRef |
| 141 | valobj_type = valobj.GetType() |
| 142 | if valobj_type.IsValid() and valobj_type.IsPointerType(): |
Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 143 | valobj_type = valobj_type.GetPointeeType() |
| 144 | if valobj_type.IsValid(): |
| 145 | actual_name = valobj_type.GetName() |
| 146 | if actual_name == '__CFBitVector' or actual_name == '__CFMutableBitVector': |
| 147 | wrapper = CFBitVectorKnown_SummaryProvider(valobj, class_data.sys_params) |
| 148 | statistics.metric_hit('code_notrun',valobj) |
| 149 | else: |
| 150 | wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params) |
| 151 | print actual_name |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 152 | else: |
Enrico Granata | cfdafa3 | 2012-03-05 19:56:33 +0000 | [diff] [blame] | 153 | wrapper = CFBitVectorUnknown_SummaryProvider(valobj, class_data.sys_params) |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 154 | print name_string |
Enrico Granata | a7daeeb | 2012-03-30 00:51:12 +0000 | [diff] [blame] | 155 | statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string) |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 156 | return wrapper; |
| 157 | |
| 158 | def CFBitVector_SummaryProvider (valobj,dict): |
Enrico Granata | 28399ad | 2012-04-25 01:39:27 +0000 | [diff] [blame] | 159 | logger = lldb.formatters.Logger.Logger() |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 160 | provider = GetSummary_Impl(valobj); |
| 161 | if provider != None: |
Enrico Granata | 7d22221 | 2012-04-25 17:53:41 +0000 | [diff] [blame] | 162 | if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description): |
Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 163 | return provider.message() |
| 164 | try: |
| 165 | summary = provider.contents(); |
| 166 | except: |
| 167 | summary = None |
Enrico Granata | 247bd41 | 2012-04-02 16:39:29 +0000 | [diff] [blame] | 168 | logger >> "summary got from provider: " + str(summary) |
Enrico Granata | 3f1052b | 2012-03-13 21:52:00 +0000 | [diff] [blame] | 169 | if summary == None or summary == '': |
| 170 | summary = '<variable is not CFBitVector>' |
| 171 | return summary |
| 172 | return 'Summary Unavailable' |
Enrico Granata | 385ad4e | 2012-03-03 00:45:57 +0000 | [diff] [blame] | 173 | |
| 174 | def __lldb_init_module(debugger,dict): |
| 175 | debugger.HandleCommand("type summary add -F CFBitVector.CFBitVector_SummaryProvider CFBitVectorRef CFMutableBitVectorRef") |