skia2/platform_tools/debugging/lldb/skia.py
John Stiles 8eccc2938d Add SkSpan support to the Skia LLDB visualizer.
Change-Id: Ib974e7c1003ca674cbcd67e62b6c2c328c1c2266
Bug: skia:11103
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/346639
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Adlai Holler <adlai@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Adlai Holler <adlai@google.com>
2020-12-22 18:10:12 +00:00

225 lines
6.9 KiB
Python

# 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:
# - SkAutoTArray, SkAutoSTArray
# - 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:
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.fItemArray.CreateChildAtOffset('[' + str(index) + ']',
offset, self.dataType)
except:
return None
def update(self):
try:
self.fItemArray = self.valobj.GetChildMemberWithName('fItemArray')
self.fCount = self.valobj.GetChildMemberWithName('fCount')
self.dataType = self.fItemArray.GetType().GetPointeeType()
self.dataSize = self.dataType.GetByteSize()
except:
pass
def has_children(self):
return True
class SkAutoTArray_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 "^SkS?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 "^SkS?TArray<.+>$" -w skia')
debugger.HandleCommand(
'type synthetic add -l skia.SkAutoTArray_SynthProvider -x "^SkAutoS?TArray<.+>$" -w skia')
debugger.HandleCommand(
'type summary add --summary-string "size=${svar%#}" -e -x "^SkAutoS?TArray<.+>$" -w skia')
debugger.HandleCommand("type category enable skia")