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 return GetOptionalValue(valobj).summary 124 125class OptionalSynthProvider: 126 """Provides deref support to llvm::Optional<T>""" 127 def __init__(self, valobj, internal_dict): 128 self.valobj = valobj 129 130 def num_children(self): 131 return self.valobj.num_children 132 133 def get_child_index(self, name): 134 if name == '$$dereference$$': 135 return self.valobj.num_children 136 return self.valobj.GetIndexOfChildWithName(name) 137 138 def get_child_at_index(self, index): 139 if index < self.valobj.num_children: 140 return self.valobj.GetChildAtIndex(index) 141 return GetOptionalValue(self.valobj) or lldb.SBValue() 142 143def SmallStringSummaryProvider(valobj, internal_dict): 144 num_elements = valobj.GetNumChildren() 145 res = "\"" 146 for i in range(0, num_elements): 147 c = valobj.GetChildAtIndex(i).GetValue() 148 if c: 149 res += c.strip("'") 150 res += "\"" 151 return res 152 153def StringRefSummaryProvider(valobj, internal_dict): 154 if valobj.GetNumChildren() == 2: 155 # StringRef's are also used to point at binary blobs in memory, 156 # so filter out suspiciously long strings. 157 max_length = 256 158 length = valobj.GetChildAtIndex(1).GetValueAsUnsigned(max_length) 159 if length == 0: 160 return "NULL" 161 if length < max_length: 162 return valobj.GetChildAtIndex(0).GetSummary() 163 return "" 164 165def ConstStringSummaryProvider(valobj, internal_dict): 166 if valobj.GetNumChildren() == 1: 167 return valobj.GetChildAtIndex(0).GetSummary() 168 return "" 169