1# Copyright (c) 2020 Google LLC. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5# The following Skia types can be natively visualized in LLDB: 6# - SkAutoTArray, SkAutoSTArray 7# - SkString 8# - SkTArray, SkSTArray 9# - sk_sp 10# 11# To enable LLDB debugging support, run the following command at the (lldb) prompt: 12# 13# command script import (your-skia-local-path)/platform_tools/debugging/lldb/skia.py 14# 15# This can be automatically enabled at the start of every debugging session by creating a 16# ~/.lldbinit file which contains this command. 17 18import lldb 19 20def SkString_SummaryProvider(valobj, dict): 21 fRec = valobj.GetChildMemberWithName('fRec') 22 # The fPtr inside fRec is automatically consumed by sk_sp_SynthProvider. 23 fLength = fRec.GetChildMemberWithName('fLength') 24 if fLength.GetValueAsUnsigned(0) <= 0: 25 return '""' 26 fBeginningOfData = fRec.GetChildMemberWithName('fBeginningOfData') 27 28 # Fetch string contents into an SBData. 29 string = fBeginningOfData.AddressOf().GetPointeeData(0, fLength.GetValueAsUnsigned(0)) 30 # Zero terminate the SBData. (This actually adds four zero bytes, but that's harmless.) 31 string.Append(lldb.SBData.CreateDataFromInt(0)) 32 # Convert our SBData into a string. 33 error = lldb.SBError() 34 string = string.GetString(error, 0) 35 if error.Fail(): 36 return '<error: ' + error.GetCString() + '>' 37 else: 38 return '"' + string + '"' 39 40 41class SkTArray_SynthProvider: 42 43 def __init__(self, valobj, dict): 44 self.valobj = valobj 45 46 def num_children(self): 47 try: 48 count = self.fCount.GetValueAsSigned(0) 49 count = max(count, 0) 50 count = min(count, 10000) 51 return count 52 except: 53 return 0 54 55 def get_child_index(self, name): 56 try: 57 return int(name.lstrip('[').rstrip(']')) 58 except: 59 return -1 60 61 def get_child_at_index(self, index): 62 if index < 0: 63 return None 64 if index >= self.num_children(): 65 return None 66 67 try: 68 offset = index * self.dataSize 69 return self.fItemArray.CreateChildAtOffset('[' + str(index) + ']', 70 offset, self.dataType) 71 except: 72 return None 73 74 def update(self): 75 try: 76 self.fItemArray = self.valobj.GetChildMemberWithName('fItemArray') 77 self.fCount = self.valobj.GetChildMemberWithName('fCount') 78 self.dataType = self.fItemArray.GetType().GetPointeeType() 79 self.dataSize = self.dataType.GetByteSize() 80 except: 81 pass 82 83 def has_children(self): 84 return True 85 86 87class SkAutoTArray_SynthProvider: 88 89 def __init__(self, valobj, dict): 90 self.valobj = valobj 91 92 def num_children(self): 93 try: 94 count = self.fCount.GetValueAsSigned(0) 95 count = max(count, 0) 96 count = min(count, 10000) 97 return count 98 except: 99 return 0 100 101 def get_child_index(self, name): 102 try: 103 return int(name.lstrip('[').rstrip(']')) 104 except: 105 return -1 106 107 def get_child_at_index(self, index): 108 if index < 0: 109 return None 110 if index >= self.num_children(): 111 return None 112 113 try: 114 offset = index * self.dataSize 115 return self.fValue.CreateChildAtOffset('[' + str(index) + ']', 116 offset, self.dataType) 117 except: 118 return None 119 120 def update(self): 121 try: 122 self.fCount = self.valobj.GetChildMemberWithName('fCount') 123 fArray = self.valobj.GetChildMemberWithName('fArray') 124 # These lookups rely on implementation details of unique_ptr and __compressed_pair. 125 ptr = fArray.GetChildMemberWithName('__ptr_') 126 self.fValue = ptr.GetChildMemberWithName('__value_') 127 self.dataType = self.fValue.GetType().GetPointeeType() 128 self.dataSize = self.dataType.GetByteSize() 129 except: 130 pass 131 132 def has_children(self): 133 return True 134 135 136class SkSpan_SynthProvider: 137 138 def __init__(self, valobj, dict): 139 self.valobj = valobj 140 141 def num_children(self): 142 try: 143 count = self.fSize.GetValueAsSigned(0) 144 count = max(count, 0) 145 count = min(count, 10000) 146 return count 147 except: 148 return 0 149 150 def get_child_index(self, name): 151 try: 152 return int(name.lstrip('[').rstrip(']')) 153 except: 154 return -1 155 156 def get_child_at_index(self, index): 157 if index < 0: 158 return None 159 if index >= self.num_children(): 160 return None 161 162 try: 163 offset = index * self.dataSize 164 return self.fPtr.CreateChildAtOffset('[' + str(index) + ']', 165 offset, self.dataType) 166 except: 167 return None 168 169 def update(self): 170 try: 171 self.fPtr = self.valobj.GetChildMemberWithName('fPtr') 172 self.fSize = self.valobj.GetChildMemberWithName('fSize') 173 self.dataType = self.fPtr.GetType().GetPointeeType() 174 self.dataSize = self.dataType.GetByteSize() 175 except: 176 pass 177 178 def has_children(self): 179 return True 180 181 182 183class sk_sp_SynthProvider: 184 185 def __init__(self, valobj, dict): 186 self.valobj = valobj 187 188 def num_children(self): 189 return self.fPtr.GetNumChildren() 190 191 def get_child_at_index(self, index): 192 try: 193 return self.fPtr.GetChildAtIndex(index) 194 except: 195 return None 196 197 def get_child_index(self, name): 198 return self.fPtr.GetIndexOfChildWithName(name) 199 200 def update(self): 201 try: 202 self.fPtr = self.valobj.GetChildMemberWithName('fPtr') 203 except: 204 pass 205 206 207def __lldb_init_module(debugger, dict): 208 debugger.HandleCommand( 209 'type summary add -F skia.SkString_SummaryProvider "SkString" -w skia') 210 debugger.HandleCommand( 211 'type synthetic add -l skia.sk_sp_SynthProvider -x "^sk_sp<.+>$" -w skia') 212 debugger.HandleCommand( 213 'type summary add --summary-string "fPtr = ${var.fPtr}" -x "^sk_sp<.+>$" -w skia') 214 debugger.HandleCommand( 215 'type synthetic add -l skia.SkTArray_SynthProvider -x "^SkS?TArray<.+>$" -w skia') 216 debugger.HandleCommand( 217 'type synthetic add -l skia.SkSpan_SynthProvider -x "^SkSpan<.+>$" -w skia') 218 debugger.HandleCommand( 219 'type summary add --summary-string "size=${svar%#}" -e -x "^SkS?TArray<.+>$" -w skia') 220 debugger.HandleCommand( 221 'type synthetic add -l skia.SkAutoTArray_SynthProvider -x "^SkAutoS?TArray<.+>$" -w skia') 222 debugger.HandleCommand( 223 'type summary add --summary-string "size=${svar%#}" -e -x "^SkAutoS?TArray<.+>$" -w skia') 224 debugger.HandleCommand("type category enable skia") 225