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