• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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# - AutoTArray, AutoSTArray
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            size = self.fSize.GetValueAsSigned(0)
49            size = max(size, 0)
50            size = min(size, 10000)
51            return size
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.fData.CreateChildAtOffset('[' + str(index) + ']', offset, self.dataType)
70        except:
71            return None
72
73    def update(self):
74        try:
75            self.fData = self.valobj.GetChildMemberWithName('fData')
76            self.fSize = self.valobj.GetChildMemberWithName('fSize')
77            self.dataType = self.fData.GetType().GetPointeeType()
78            self.dataSize = self.dataType.GetByteSize()
79        except:
80            pass
81
82    def has_children(self):
83        return True
84
85
86class AutoTArray_SynthProvider:
87
88    def __init__(self, valobj, dict):
89        self.valobj = valobj
90
91    def num_children(self):
92        try:
93            count = self.fCount.GetValueAsSigned(0)
94            count = max(count, 0)
95            count = min(count, 10000)
96            return count
97        except:
98            return 0
99
100    def get_child_index(self, name):
101        try:
102            return int(name.lstrip('[').rstrip(']'))
103        except:
104            return -1
105
106    def get_child_at_index(self, index):
107        if index < 0:
108            return None
109        if index >= self.num_children():
110            return None
111
112        try:
113            offset = index * self.dataSize
114            return self.fValue.CreateChildAtOffset('[' + str(index) + ']',
115                                                   offset, self.dataType)
116        except:
117            return None
118
119    def update(self):
120        try:
121            self.fCount = self.valobj.GetChildMemberWithName('fCount')
122            fArray = self.valobj.GetChildMemberWithName('fArray')
123            # These lookups rely on implementation details of unique_ptr and __compressed_pair.
124            ptr = fArray.GetChildMemberWithName('__ptr_')
125            self.fValue = ptr.GetChildMemberWithName('__value_')
126            self.dataType = self.fValue.GetType().GetPointeeType()
127            self.dataSize = self.dataType.GetByteSize()
128        except:
129            pass
130
131    def has_children(self):
132        return True
133
134
135class SkSpan_SynthProvider:
136
137    def __init__(self, valobj, dict):
138        self.valobj = valobj
139
140    def num_children(self):
141        try:
142            count = self.fSize.GetValueAsSigned(0)
143            count = max(count, 0)
144            count = min(count, 10000)
145            return count
146        except:
147            return 0
148
149    def get_child_index(self, name):
150        try:
151            return int(name.lstrip('[').rstrip(']'))
152        except:
153            return -1
154
155    def get_child_at_index(self, index):
156        if index < 0:
157            return None
158        if index >= self.num_children():
159            return None
160
161        try:
162            offset = index * self.dataSize
163            return self.fPtr.CreateChildAtOffset('[' + str(index) + ']',
164                                                 offset, self.dataType)
165        except:
166            return None
167
168    def update(self):
169        try:
170            self.fPtr = self.valobj.GetChildMemberWithName('fPtr')
171            self.fSize = self.valobj.GetChildMemberWithName('fSize')
172            self.dataType = self.fPtr.GetType().GetPointeeType()
173            self.dataSize = self.dataType.GetByteSize()
174        except:
175            pass
176
177    def has_children(self):
178        return True
179
180
181
182class sk_sp_SynthProvider:
183
184    def __init__(self, valobj, dict):
185        self.valobj = valobj
186
187    def num_children(self):
188        return self.fPtr.GetNumChildren()
189
190    def get_child_at_index(self, index):
191        try:
192            return self.fPtr.GetChildAtIndex(index)
193        except:
194            return None
195
196    def get_child_index(self, name):
197        return self.fPtr.GetIndexOfChildWithName(name)
198
199    def update(self):
200        try:
201            self.fPtr = self.valobj.GetChildMemberWithName('fPtr')
202        except:
203            pass
204
205
206def __lldb_init_module(debugger, dict):
207    debugger.HandleCommand(
208        'type summary add -F skia.SkString_SummaryProvider "SkString" -w skia')
209    debugger.HandleCommand(
210        'type synthetic add -l skia.sk_sp_SynthProvider -x "^sk_sp<.+>$" -w skia')
211    debugger.HandleCommand(
212        'type summary add --summary-string "fPtr = ${var.fPtr}" -x "^sk_sp<.+>$" -w skia')
213    debugger.HandleCommand(
214        'type synthetic add -l skia.SkTArray_SynthProvider -x "^SkS?TArray<.+>$" -w skia')
215    debugger.HandleCommand(
216        'type synthetic add -l skia.SkSpan_SynthProvider -x "^SkSpan<.+>$" -w skia')
217    debugger.HandleCommand(
218        'type summary add --summary-string "size=${svar%#}" -e -x "^SkS?TArray<.+>$" -w skia')
219    debugger.HandleCommand(
220        'type synthetic add -l skia.AutoTArray_SynthProvider -x "^AutoS?TArray<.+>$" -w skia')
221    debugger.HandleCommand(
222        'type summary add --summary-string "size=${svar%#}" -e -x "^AutoS?TArray<.+>$" -w skia')
223    debugger.HandleCommand("type category enable skia")
224