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