1""" 2LLDB Formatters for LLVM data types. 3 4Load into LLDB with 'command script import /path/to/lldbDataFormatters.py' 5""" 6 7import lldb 8 9def __lldb_init_module(debugger, internal_dict): 10 debugger.HandleCommand('type category define -e llvm -l c++') 11 debugger.HandleCommand('type synthetic add -w llvm ' 12 '-l lldbDataFormatters.SmallVectorSynthProvider ' 13 '-x "^llvm::SmallVectorImpl<.+>$"') 14 debugger.HandleCommand('type synthetic add -w llvm ' 15 '-l lldbDataFormatters.SmallVectorSynthProvider ' 16 '-x "^llvm::SmallVector<.+,.+>$"') 17 debugger.HandleCommand('type synthetic add -w llvm ' 18 '-l lldbDataFormatters.ArrayRefSynthProvider ' 19 '-x "^llvm::ArrayRef<.+>$"') 20 debugger.HandleCommand('type synthetic add -w llvm ' 21 '-l lldbDataFormatters.OptionalSynthProvider ' 22 '-x "^llvm::Optional<.+>$"') 23 debugger.HandleCommand('type summary add -w llvm ' 24 '-F lldbDataFormatters.OptionalSummaryProvider ' 25 '-x "^llvm::Optional<.+>$"') 26 debugger.HandleCommand('type summary add -w llvm ' 27 '-F lldbDataFormatters.SmallStringSummaryProvider ' 28 '-x "^llvm::SmallString<.+>$"') 29 debugger.HandleCommand('type summary add -w llvm ' 30 '-F lldbDataFormatters.StringRefSummaryProvider ' 31 '-x "^llvm::StringRef$"') 32 debugger.HandleCommand('type summary add -w llvm ' 33 '-F lldbDataFormatters.ConstStringSummaryProvider ' 34 '-x "^lldb_private::ConstString$"') 35 36# Pretty printer for llvm::SmallVector/llvm::SmallVectorImpl 37class SmallVectorSynthProvider: 38 def __init__(self, valobj, internal_dict): 39 self.valobj = valobj; 40 self.update() # initialize this provider 41 42 def num_children(self): 43 return self.size.GetValueAsUnsigned(0) 44 45 def get_child_index(self, name): 46 try: 47 return int(name.lstrip('[').rstrip(']')) 48 except: 49 return -1; 50 51 def get_child_at_index(self, index): 52 # Do bounds checking. 53 if index < 0: 54 return None 55 if index >= self.num_children(): 56 return None; 57 58 offset = index * self.type_size 59 return self.begin.CreateChildAtOffset('['+str(index)+']', 60 offset, self.data_type) 61 62 def update(self): 63 self.begin = self.valobj.GetChildMemberWithName('BeginX') 64 self.size = self.valobj.GetChildMemberWithName('Size') 65 the_type = self.valobj.GetType() 66 # If this is a reference type we have to dereference it to get to the 67 # template parameter. 68 if the_type.IsReferenceType(): 69 the_type = the_type.GetDereferencedType() 70 71 self.data_type = the_type.GetTemplateArgumentType(0) 72 self.type_size = self.data_type.GetByteSize() 73 assert self.type_size != 0 74 75class ArrayRefSynthProvider: 76 """ Provider for llvm::ArrayRef """ 77 def __init__(self, valobj, internal_dict): 78 self.valobj = valobj; 79 self.update() # initialize this provider 80 81 def num_children(self): 82 return self.length 83 84 def get_child_index(self, name): 85 try: 86 return int(name.lstrip('[').rstrip(']')) 87 except: 88 return -1; 89 90 def get_child_at_index(self, index): 91 if index < 0 or index >= self.num_children(): 92 return None; 93 offset = index * self.type_size 94 return self.data.CreateChildAtOffset('[' + str(index) + ']', 95 offset, self.data_type) 96 97 def update(self): 98 self.data = self.valobj.GetChildMemberWithName('Data') 99 length_obj = self.valobj.GetChildMemberWithName('Length') 100 self.length = length_obj.GetValueAsUnsigned(0) 101 self.data_type = self.data.GetType().GetPointeeType() 102 self.type_size = self.data_type.GetByteSize() 103 assert self.type_size != 0 104 105def GetOptionalValue(valobj): 106 storage = valobj.GetChildMemberWithName('Storage') 107 if not storage: 108 storage = valobj 109 110 failure = 2 111 hasVal = storage.GetChildMemberWithName('hasVal').GetValueAsUnsigned(failure) 112 if hasVal == failure: 113 return '<could not read llvm::Optional>' 114 115 if hasVal == 0: 116 return None 117 118 underlying_type = storage.GetType().GetTemplateArgumentType(0) 119 storage = storage.GetChildMemberWithName('value') 120 return storage.Cast(underlying_type) 121 122def OptionalSummaryProvider(valobj, internal_dict): 123 val = GetOptionalValue(valobj) 124 return val.summary if val else 'None' 125 126class OptionalSynthProvider: 127 """Provides deref support to llvm::Optional<T>""" 128 def __init__(self, valobj, internal_dict): 129 self.valobj = valobj 130 131 def num_children(self): 132 return self.valobj.num_children 133 134 def get_child_index(self, name): 135 if name == '$$dereference$$': 136 return self.valobj.num_children 137 return self.valobj.GetIndexOfChildWithName(name) 138 139 def get_child_at_index(self, index): 140 if index < self.valobj.num_children: 141 return self.valobj.GetChildAtIndex(index) 142 return GetOptionalValue(self.valobj) or lldb.SBValue() 143 144def SmallStringSummaryProvider(valobj, internal_dict): 145 num_elements = valobj.GetNumChildren() 146 res = "\"" 147 for i in range(0, num_elements): 148 c = valobj.GetChildAtIndex(i).GetValue() 149 if c: 150 res += c.strip("'") 151 res += "\"" 152 return res 153 154def StringRefSummaryProvider(valobj, internal_dict): 155 if valobj.GetNumChildren() == 2: 156 # StringRef's are also used to point at binary blobs in memory, 157 # so filter out suspiciously long strings. 158 max_length = 256 159 length = valobj.GetChildAtIndex(1).GetValueAsUnsigned(max_length) 160 if length == 0: 161 return "NULL" 162 if length < max_length: 163 return valobj.GetChildAtIndex(0).GetSummary() 164 return "" 165 166def ConstStringSummaryProvider(valobj, internal_dict): 167 if valobj.GetNumChildren() == 1: 168 return valobj.GetChildAtIndex(0).GetSummary() 169 return "" 170