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 """ 8 # example summary provider for NSData 9 # the real summary is now C++ code built into LLDB 10 import lldb 11 import ctypes 12 import lldb.runtime.objc.objc_runtime 13 import lldb.formatters.metrics 14 import lldb.formatters.Logger 15 16 statistics = lldb.formatters.metrics.Metrics() 17 statistics.add_metric('invalid_isa') 18 statistics.add_metric('invalid_pointer') 19 statistics.add_metric('unknown_class') 20 statistics.add_metric('code_notrun') 21 22 # despite the similary to synthetic children providers, these classes are not 23 # trying to provide anything but the length for an NSData, so they need not 24 # obey the interface specification for synthetic children providers 25 class NSConcreteData_SummaryProvider: 26 def adjust_for_architecture(self): 27 pass 28 29 def __init__(self, valobj, params): 30 logger = lldb.formatters.Logger.Logger() 31 logger >> "NSConcreteData_SummaryProvider __init__" 32 self.valobj = valobj; 33 self.sys_params = params 34 if not(self.sys_params.types_cache.NSUInteger): 35 if self.sys_params.is_64_bit: 36 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong) 37 else: 38 self.sys_params.types_cache.NSUInteger = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedInt) 39 self.update(); 40 41 def update(self): 42 self.adjust_for_architecture(); 43 44 # one pointer is the ISA 45 # then there are 32 bit worth of flags and other data 46 # however, on 64bit systems these are padded to be a full 47 # machine word long, which means we actually have two pointers 48 # worth of data to skip 49 def offset(self): 50 return 2 * self.sys_params.pointer_size 51 52 def length(self): 53 logger = lldb.formatters.Logger.Logger() 54 logger >> "NSConcreteData_SummaryProvider length" 55 size = self.valobj.CreateChildAtOffset("count", 56 self.offset(), 57 self.sys_params.types_cache.NSUInteger) 58 logger >> str(size) 59 logger >> str(size.GetValueAsUnsigned(0)) 60 return size.GetValueAsUnsigned(0) 61 62 63 class NSDataUnknown_SummaryProvider: 64 def adjust_for_architecture(self): 65 pass 66 67 def __init__(self, valobj, params): 68 logger = lldb.formatters.Logger.Logger() 69 logger >> "NSDataUnknown_SummaryProvider __init__" 70 self.valobj = valobj; 71 self.sys_params = params 72 self.update(); 73 74 def update(self): 75 self.adjust_for_architecture(); 76 77 def length(self): 78 logger = lldb.formatters.Logger.Logger() 79 logger >> "NSDataUnknown_SummaryProvider length" 80 stream = lldb.SBStream() 81 self.valobj.GetExpressionPath(stream) 82 logger >> stream.GetData() 83 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " length]"); 84 logger >> "still in after expression: " + str(num_children_vo) 85 if num_children_vo.IsValid(): 86 logger >> "wow - expr output is valid: " + str(num_children_vo.GetValueAsUnsigned()) 87 return num_children_vo.GetValueAsUnsigned(0) 88 logger >> "invalid expr output - too bad" 89 return '<variable is not NSData>' 90 91 92 def GetSummary_Impl(valobj): 93 global statistics 94 logger = lldb.formatters.Logger.Logger() 95 logger >> "NSData GetSummary_Impl" 96 class_data,wrapper =lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(valobj,statistics) 97 if wrapper: 98 logger >> "got a wrapper summary - using it" 99 return wrapper 100 101 name_string = class_data.class_name() 102 logger >> "class name: " + name_string 103 if name_string == 'NSConcreteData' or \ 104 name_string == 'NSConcreteMutableData' or \ 105 name_string == '__NSCFData': 106 wrapper = NSConcreteData_SummaryProvider(valobj, class_data.sys_params) 107 statistics.metric_hit('code_notrun',valobj) 108 else: 109 wrapper = NSDataUnknown_SummaryProvider(valobj, class_data.sys_params) 110 statistics.metric_hit('unknown_class',valobj.GetName() + " seen as " + name_string) 111 return wrapper; 112 113 def NSData_SummaryProvider (valobj,dict): 114 logger = lldb.formatters.Logger.Logger() 115 logger >> "NSData_SummaryProvider" 116 provider = GetSummary_Impl(valobj); 117 logger >> "found a summary provider, it is: " + str(provider) 118 if provider != None: 119 try: 120 summary = provider.length(); 121 except: 122 summary = None 123 logger >> "got a summary: it is " + str(summary) 124 if summary == None: 125 summary = '<variable is not NSData>' 126 elif isinstance(summary,basestring): 127 pass 128 else: 129 if summary == 1: 130 summary = '1 byte' 131 else: 132 summary = str(summary) + ' bytes' 133 return summary 134 return 'Summary Unavailable' 135 136 def NSData_SummaryProvider2 (valobj,dict): 137 logger = lldb.formatters.Logger.Logger() 138 logger >> "NSData_SummaryProvider2" 139 provider = GetSummary_Impl(valobj); 140 logger >> "found a summary provider, it is: " + str(provider) 141 if provider != None: 142 if isinstance(provider,lldb.runtime.objc.objc_runtime.SpecialSituation_Description): 143 return provider.message() 144 try: 145 summary = provider.length(); 146 except: 147 summary = None 148 logger >> "got a summary: it is " + str(summary) 149 if summary == None: 150 summary = '<variable is not CFData>' 151 elif isinstance(summary,basestring): 152 pass 153 else: 154 if summary == 1: 155 summary = '@"1 byte"' 156 else: 157 summary = '@"' + str(summary) + ' bytes"' 158 return summary 159 return 'Summary Unavailable' 160 161 def __lldb_init_module(debugger,dict): 162 debugger.HandleCommand("type summary add -F NSData.NSData_SummaryProvider NSData") 163 debugger.HandleCommand("type summary add -F NSData.NSData_SummaryProvider2 CFDataRef CFMutableDataRef") 164