| # Copyright (c) 2020 Google LLC All rights reserved. | |
| # Use of this source code is governed by a BSD-style license that can be | |
| # found in the LICENSE file. | |
| # The following Skia types can be natively visualized in LLDB: | |
| # - AutoTArray, AutoSTArray | |
| # - SkString | |
| # - SkTArray, SkSTArray | |
| # - sk_sp | |
| # | |
| # To enable LLDB debugging support, run the following command at the (lldb) prompt: | |
| # | |
| # command script import (your-skia-local-path)/platform_tools/debugging/lldb/skia.py | |
| # | |
| # This can be automatically enabled at the start of every debugging session by creating a | |
| # ~/.lldbinit file which contains this command. | |
| import lldb | |
| def SkString_SummaryProvider(valobj, dict): | |
| fRec = valobj.GetChildMemberWithName('fRec') | |
| # The fPtr inside fRec is automatically consumed by sk_sp_SynthProvider. | |
| fLength = fRec.GetChildMemberWithName('fLength') | |
| if fLength.GetValueAsUnsigned(0) <= 0: | |
| return '""' | |
| fBeginningOfData = fRec.GetChildMemberWithName('fBeginningOfData') | |
| # Fetch string contents into an SBData. | |
| string = fBeginningOfData.AddressOf().GetPointeeData(0, fLength.GetValueAsUnsigned(0)) | |
| # Zero terminate the SBData. (This actually adds four zero bytes, but that's harmless.) | |
| string.Append(lldb.SBData.CreateDataFromInt(0)) | |
| # Convert our SBData into a string. | |
| error = lldb.SBError() | |
| string = string.GetString(error, 0) | |
| if error.Fail(): | |
| return '<error: ' + error.GetCString() + '>' | |
| else: | |
| return '"' + string + '"' | |
| class SkTArray_SynthProvider: | |
| def __init__(self, valobj, dict): | |
| self.valobj = valobj | |
| def num_children(self): | |
| try: | |
| size = self.fSize.GetValueAsSigned(0) | |
| size = max(size, 0) | |
| size = min(size, 10000) | |
| return size | |
| except: | |
| return 0 | |
| 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: | |
| return None | |
| if index >= self.num_children(): | |
| return None | |
| try: | |
| offset = index * self.dataSize | |
| return self.fData.CreateChildAtOffset('[' + str(index) + ']', offset, self.dataType) | |
| except: | |
| return None | |
| def update(self): | |
| try: | |
| self.fData = self.valobj.GetChildMemberWithName('fData') | |
| self.fSize = self.valobj.GetChildMemberWithName('fSize') | |
| self.dataType = self.fData.GetType().GetPointeeType() | |
| self.dataSize = self.dataType.GetByteSize() | |
| except: | |
| pass | |
| def has_children(self): | |
| return True | |
| class AutoTArray_SynthProvider: | |
| def __init__(self, valobj, dict): | |
| self.valobj = valobj | |
| def num_children(self): | |
| try: | |
| count = self.fCount.GetValueAsSigned(0) | |
| count = max(count, 0) | |
| count = min(count, 10000) | |
| return count | |
| except: | |
| return 0 | |
| 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: | |
| return None | |
| if index >= self.num_children(): | |
| return None | |
| try: | |
| offset = index * self.dataSize | |
| return self.fValue.CreateChildAtOffset('[' + str(index) + ']', | |
| offset, self.dataType) | |
| except: | |
| return None | |
| def update(self): | |
| try: | |
| self.fCount = self.valobj.GetChildMemberWithName('fCount') | |
| fArray = self.valobj.GetChildMemberWithName('fArray') | |
| # These lookups rely on implementation details of unique_ptr and __compressed_pair. | |
| ptr = fArray.GetChildMemberWithName('__ptr_') | |
| self.fValue = ptr.GetChildMemberWithName('__value_') | |
| self.dataType = self.fValue.GetType().GetPointeeType() | |
| self.dataSize = self.dataType.GetByteSize() | |
| except: | |
| pass | |
| def has_children(self): | |
| return True | |
| class SkSpan_SynthProvider: | |
| def __init__(self, valobj, dict): | |
| self.valobj = valobj | |
| def num_children(self): | |
| try: | |
| count = self.fSize.GetValueAsSigned(0) | |
| count = max(count, 0) | |
| count = min(count, 10000) | |
| return count | |
| except: | |
| return 0 | |
| 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: | |
| return None | |
| if index >= self.num_children(): | |
| return None | |
| try: | |
| offset = index * self.dataSize | |
| return self.fPtr.CreateChildAtOffset('[' + str(index) + ']', | |
| offset, self.dataType) | |
| except: | |
| return None | |
| def update(self): | |
| try: | |
| self.fPtr = self.valobj.GetChildMemberWithName('fPtr') | |
| self.fSize = self.valobj.GetChildMemberWithName('fSize') | |
| self.dataType = self.fPtr.GetType().GetPointeeType() | |
| self.dataSize = self.dataType.GetByteSize() | |
| except: | |
| pass | |
| def has_children(self): | |
| return True | |
| class sk_sp_SynthProvider: | |
| def __init__(self, valobj, dict): | |
| self.valobj = valobj | |
| def num_children(self): | |
| return self.fPtr.GetNumChildren() | |
| def get_child_at_index(self, index): | |
| try: | |
| return self.fPtr.GetChildAtIndex(index) | |
| except: | |
| return None | |
| def get_child_index(self, name): | |
| return self.fPtr.GetIndexOfChildWithName(name) | |
| def update(self): | |
| try: | |
| self.fPtr = self.valobj.GetChildMemberWithName('fPtr') | |
| except: | |
| pass | |
| def __lldb_init_module(debugger, dict): | |
| debugger.HandleCommand( | |
| 'type summary add -F skia.SkString_SummaryProvider "SkString" -w skia') | |
| debugger.HandleCommand( | |
| 'type synthetic add -l skia.sk_sp_SynthProvider -x "^sk_sp<.+>$" -w skia') | |
| debugger.HandleCommand( | |
| 'type summary add --summary-string "fPtr = ${var.fPtr}" -x "^sk_sp<.+>$" -w skia') | |
| debugger.HandleCommand( | |
| 'type synthetic add -l skia.SkTArray_SynthProvider -x "^skia_private::S?TArray<.+>$" -w skia') | |
| debugger.HandleCommand( | |
| 'type synthetic add -l skia.SkSpan_SynthProvider -x "^SkSpan<.+>$" -w skia') | |
| debugger.HandleCommand( | |
| 'type summary add --summary-string "size=${svar%#}" -e -x "^skia_private::S?TArray<.+>$" -w skia') | |
| debugger.HandleCommand( | |
| 'type synthetic add -l skia.AutoTArray_SynthProvider -x "^skia_private::AutoS?TArray<.+>$" -w skia') | |
| debugger.HandleCommand( | |
| 'type summary add --summary-string "size=${svar%#}" -e -x "^skia_private::AutoS?TArray<.+>$" -w skia') | |
| debugger.HandleCommand( | |
| 'type summary add --python-script "v = valobj.GetValueAsSigned(0);return str(v) + \' (\' + str(v/65536.0) + \')\';" SkFixed') | |
| debugger.HandleCommand("type category enable skia") |