| # 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") |