• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright (C) 2012 Apple. All rights reserved.
2#
3# Redistribution and use in source and binary forms, with or without
4# modification, are permitted provided that the following conditions
5# are met:
6# 1.  Redistributions of source code must retain the above copyright
7#     notice, this list of conditions and the following disclaimer.
8# 2.  Redistributions in binary form must reproduce the above copyright
9#     notice, this list of conditions and the following disclaimer in the
10#     documentation and/or other materials provided with the distribution.
11#
12# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
13# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
14# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
15# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
16# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
17# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
18# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
19# ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
20# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
21# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22
23"""
24    LLDB Support for WebKit Types
25
26    Add the following to your .lldbinit file to add WebKit Type summaries in LLDB and Xcode:
27
28    command script import {Path to WebKit Root}/Tools/lldb/lldb_webkit.py
29
30"""
31
32import lldb
33
34
35def __lldb_init_module(debugger, dict):
36    debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFString_SummaryProvider WTF::String')
37    debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFStringImpl_SummaryProvider WTF::StringImpl')
38    debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFAtomicString_SummaryProvider WTF::AtomicString')
39    debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFVector_SummaryProvider -x "WTF::Vector<.+>$"')
40    debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFHashTable_SummaryProvider -x "WTF::HashTable<.+>$"')
41    debugger.HandleCommand('type synthetic add -x "WTF::Vector<.+>$" --python-class lldb_webkit.WTFVectorProvider')
42    debugger.HandleCommand('type synthetic add -x "WTF::HashTable<.+>$" --python-class lldb_webkit.WTFHashTableProvider')
43    debugger.HandleCommand('type summary add -F lldb_webkit.WebCoreLayoutUnit_SummaryProvider WebCore::LayoutUnit')
44    debugger.HandleCommand('type summary add -F lldb_webkit.WebCoreLayoutSize_SummaryProvider WebCore::LayoutSize')
45    debugger.HandleCommand('type summary add -F lldb_webkit.WebCoreLayoutPoint_SummaryProvider WebCore::LayoutPoint')
46
47
48def WTFString_SummaryProvider(valobj, dict):
49    provider = WTFStringProvider(valobj, dict)
50    return "{ length = %d, contents = '%s' }" % (provider.get_length(), provider.to_string())
51
52
53def WTFStringImpl_SummaryProvider(valobj, dict):
54    provider = WTFStringImplProvider(valobj, dict)
55    return "{ length = %d, is8bit = %d, contents = '%s' }" % (provider.get_length(), provider.is_8bit(), provider.to_string())
56
57
58def WTFAtomicString_SummaryProvider(valobj, dict):
59    return WTFString_SummaryProvider(valobj.GetChildMemberWithName('m_string'), dict)
60
61
62def WTFVector_SummaryProvider(valobj, dict):
63    provider = WTFVectorProvider(valobj, dict)
64    return "{ size = %d, capacity = %d }" % (provider.size, provider.capacity)
65
66
67def WTFHashTable_SummaryProvider(valobj, dict):
68    provider = WTFHashTableProvider(valobj, dict)
69    return "{ tableSize = %d, keyCount = %d }" % (provider.tableSize(), provider.keyCount())
70
71
72def WebCoreLayoutUnit_SummaryProvider(valobj, dict):
73    provider = WebCoreLayoutUnitProvider(valobj, dict)
74    return "{ %s }" % provider.to_string()
75
76
77def WebCoreLayoutSize_SummaryProvider(valobj, dict):
78    provider = WebCoreLayoutSizeProvider(valobj, dict)
79    return "{ width = %s, height = %s }" % (provider.get_width(), provider.get_height())
80
81
82def WebCoreLayoutPoint_SummaryProvider(valobj, dict):
83    provider = WebCoreLayoutPointProvider(valobj, dict)
84    return "{ x = %s, y = %s }" % (provider.get_x(), provider.get_y())
85
86# FIXME: Provide support for the following types:
87# def WTFCString_SummaryProvider(valobj, dict):
88# def WebCoreKURLGooglePrivate_SummaryProvider(valobj, dict):
89# def WebCoreQualifiedName_SummaryProvider(valobj, dict):
90# def JSCIdentifier_SummaryProvider(valobj, dict):
91# def JSCJSString_SummaryProvider(valobj, dict):
92
93
94def guess_string_length(valobj, error):
95    if not valobj.GetValue():
96        return 0
97
98    for i in xrange(0, 2048):
99        if valobj.GetPointeeData(i, 1).GetUnsignedInt16(error, 0) == 0:
100            return i
101
102    return 256
103
104
105def ustring_to_string(valobj, error, length=None):
106    if length is None:
107        length = guess_string_length(valobj, error)
108    else:
109        length = int(length)
110
111    out_string = u""
112    for i in xrange(0, length):
113        char_value = valobj.GetPointeeData(i, 1).GetUnsignedInt16(error, 0)
114        out_string = out_string + unichr(char_value)
115
116    return out_string.encode('utf-8')
117
118
119def lstring_to_string(valobj, error, length=None):
120    if length is None:
121        length = guess_string_length(valobj, error)
122    else:
123        length = int(length)
124
125    out_string = u""
126    for i in xrange(0, length):
127        char_value = valobj.GetPointeeData(i, 1).GetUnsignedInt8(error, 0)
128        out_string = out_string + unichr(char_value)
129
130    return out_string.encode('utf-8')
131
132
133class WTFStringImplProvider:
134    def __init__(self, valobj, dict):
135        self.valobj = valobj
136
137    def get_length(self):
138        return self.valobj.GetChildMemberWithName('m_length').GetValueAsUnsigned(0)
139
140    def get_data8(self):
141        return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data8')
142
143    def get_data16(self):
144        return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data16')
145
146    def to_string(self):
147        error = lldb.SBError()
148        if self.is_8bit():
149            return lstring_to_string(self.get_data8(), error, self.get_length())
150        return ustring_to_string(self.get_data16(), error, self.get_length())
151
152    def is_8bit(self):
153        # FIXME: find a way to access WTF::StringImpl::s_hashFlag8BitBuffer
154        return bool(self.valobj.GetChildMemberWithName('m_hashAndFlags').GetValueAsUnsigned(0) \
155            & 1 << 6)
156
157
158class WTFStringProvider:
159    def __init__(self, valobj, dict):
160        self.valobj = valobj
161
162    def stringimpl(self):
163        impl_ptr = self.valobj.GetChildMemberWithName('m_impl').GetChildMemberWithName('m_ptr')
164        return WTFStringImplProvider(impl_ptr, dict)
165
166    def get_length(self):
167        impl = self.stringimpl()
168        if not impl:
169            return 0
170        return impl.get_length()
171
172    def to_string(self):
173        impl = self.stringimpl()
174        if not impl:
175            return u""
176        return impl.to_string()
177
178
179class WebCoreLayoutUnitProvider:
180    "Print a WebCore::LayoutUnit"
181    def __init__(self, valobj, dict):
182        self.valobj = valobj
183
184    def to_string(self):
185        return "%gpx" % (self.valobj.GetChildMemberWithName('m_value').GetValueAsUnsigned(0) / 64.0)
186
187
188class WebCoreLayoutSizeProvider:
189    "Print a WebCore::LayoutSize"
190    def __init__(self, valobj, dict):
191        self.valobj = valobj
192
193    def get_width(self):
194        return WebCoreLayoutUnitProvider(self.valobj.GetChildMemberWithName('m_width'), dict).to_string()
195
196    def get_height(self):
197        return WebCoreLayoutUnitProvider(self.valobj.GetChildMemberWithName('m_height'), dict).to_string()
198
199
200class WebCoreLayoutPointProvider:
201    "Print a WebCore::LayoutPoint"
202    def __init__(self, valobj, dict):
203        self.valobj = valobj
204
205    def get_x(self):
206        return WebCoreLayoutUnitProvider(self.valobj.GetChildMemberWithName('m_x'), dict).to_string()
207
208    def get_y(self):
209        return WebCoreLayoutUnitProvider(self.valobj.GetChildMemberWithName('m_y'), dict).to_string()
210
211
212class WTFVectorProvider:
213    def __init__(self, valobj, internal_dict):
214        self.valobj = valobj
215        self.update()
216
217    def num_children(self):
218        return self.size + 3
219
220    def get_child_index(self, name):
221        if name == "m_size":
222            return self.size
223        elif name == "m_capacity":
224            return self.size + 1
225        elif name == "m_buffer":
226            return self.size + 2
227        else:
228            return int(name.lstrip('[').rstrip(']'))
229
230    def get_child_at_index(self, index):
231        if index == self.size:
232            return self.valobj.GetChildMemberWithName("m_size")
233        elif index == self.size + 1:
234            return self.valobj.GetChildMemberWithName("m_capacity")
235        elif index == self.size + 2:
236            return self.buffer
237        elif index < self.size:
238            offset = index * self.data_size
239            child = self.buffer.CreateChildAtOffset('[' + str(index) + ']', offset, self.data_type)
240            return child
241        else:
242            return None
243
244    def update(self):
245        self.buffer = self.valobj.GetChildMemberWithName('m_buffer')
246        self.size = self.valobj.GetChildMemberWithName('m_size').GetValueAsUnsigned(0)
247        self.capacity = self.buffer.GetChildMemberWithName('m_capacity').GetValueAsUnsigned(0)
248        self.data_type = self.buffer.GetType().GetPointeeType()
249        self.data_size = self.data_type.GetByteSize()
250
251    def has_children(self):
252        return True
253
254
255class WTFHashTableProvider:
256    def __init__(self, valobj, internal_dict):
257        self.valobj = valobj
258        self.update()
259
260    def num_children(self):
261        return self.tableSize() + 5
262
263    def get_child_index(self, name):
264        if name == "m_table":
265            return self.tableSize()
266        elif name == "m_tableSize":
267            return self.tableSize() + 1
268        elif name == "m_tableSizeMask":
269            return self.tableSize() + 2
270        elif name == "m_keyCount":
271            return self.tableSize() + 3
272        elif name == "m_deletedCount":
273            return self.tableSize() + 4
274        else:
275            return int(name.lstrip('[').rstrip(']'))
276
277    def get_child_at_index(self, index):
278        if index == self.tableSize():
279            return self.valobj.GetChildMemberWithName('m_table')
280        elif index == self.tableSize() + 1:
281            return self.valobj.GetChildMemberWithName('m_tableSize')
282        elif index == self.tableSize() + 2:
283            return self.valobj.GetChildMemberWithName('m_tableSizeMask')
284        elif index == self.tableSize() + 3:
285            return self.valobj.GetChildMemberWithName('m_keyCount')
286        elif index == self.tableSize() + 4:
287            return self.valobj.GetChildMemberWithName('m_deletedCount')
288        elif index < self.tableSize():
289            table = self.valobj.GetChildMemberWithName('m_table')
290            return table.CreateChildAtOffset('[' + str(index) + ']', index * self.data_size, self.data_type)
291        else:
292            return None
293
294    def tableSize(self):
295        return self.valobj.GetChildMemberWithName('m_tableSize').GetValueAsUnsigned(0)
296
297    def keyCount(self):
298        return self.valobj.GetChildMemberWithName('m_keyCount').GetValueAsUnsigned(0)
299
300    def update(self):
301        self.data_type = self.valobj.GetType().GetTemplateArgumentType(0)
302        self.data_size = self.data_type.GetByteSize()
303
304    def has_children(self):
305        return True
306