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