Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 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 | |
| 32 | import lldb |
| 33 | |
| 34 | |
| 35 | def __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<.+>$"') |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 40 | debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFHashTable_SummaryProvider -x "WTF::HashTable<.+>$"') |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 41 | debugger.HandleCommand('type synthetic add -x "WTF::Vector<.+>$" --python-class lldb_webkit.WTFVectorProvider') |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 42 | debugger.HandleCommand('type synthetic add -x "WTF::HashTable<.+>$" --python-class lldb_webkit.WTFHashTableProvider') |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 43 | |
| 44 | |
| 45 | def WTFString_SummaryProvider(valobj, dict): |
| 46 | provider = WTFStringProvider(valobj, dict) |
| 47 | return "{ length = %d, contents = '%s' }" % (provider.get_length(), provider.to_string()) |
| 48 | |
| 49 | |
| 50 | def WTFStringImpl_SummaryProvider(valobj, dict): |
| 51 | provider = WTFStringImplProvider(valobj, dict) |
| 52 | return "{ length = %d, is8bit = %d, contents = '%s' }" % (provider.get_length(), provider.is_8bit(), provider.to_string()) |
| 53 | |
| 54 | |
| 55 | def WTFAtomicString_SummaryProvider(valobj, dict): |
| 56 | return WTFString_SummaryProvider(valobj.GetChildMemberWithName('m_string'), dict) |
| 57 | |
| 58 | |
| 59 | def WTFVector_SummaryProvider(valobj, dict): |
| 60 | provider = WTFVectorProvider(valobj, dict) |
| 61 | return "{ size = %d, capacity = %d }" % (provider.size, provider.capacity) |
| 62 | |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 63 | |
| 64 | def WTFHashTable_SummaryProvider(valobj, dict): |
| 65 | provider = WTFHashTableProvider(valobj, dict) |
| 66 | return "{ tableSize = %d, keyCount = %d }" % (provider.tableSize(), provider.keyCount()) |
| 67 | |
Torne (Richard Coles) | 5c87bf8 | 2012-11-14 11:46:17 +0000 | [diff] [blame] | 68 | # FIXME: Provide support for the following types: |
| 69 | # def WTFVector_SummaryProvider(valobj, dict): |
| 70 | # def WTFCString_SummaryProvider(valobj, dict): |
| 71 | # def WebCoreKURLGooglePrivate_SummaryProvider(valobj, dict): |
| 72 | # def WebCoreQualifiedName_SummaryProvider(valobj, dict): |
| 73 | # def JSCIdentifier_SummaryProvider(valobj, dict): |
| 74 | # def JSCJSString_SummaryProvider(valobj, dict): |
| 75 | |
| 76 | |
| 77 | def guess_string_length(valobj, error): |
| 78 | if not valobj.GetValue(): |
| 79 | return 0 |
| 80 | |
| 81 | for i in xrange(0, 2048): |
| 82 | if valobj.GetPointeeData(i, 1).GetUnsignedInt16(error, 0) == 0: |
| 83 | return i |
| 84 | |
| 85 | return 256 |
| 86 | |
| 87 | |
| 88 | def ustring_to_string(valobj, error, length=None): |
| 89 | if length is None: |
| 90 | length = guess_string_length(valobj, error) |
| 91 | else: |
| 92 | length = int(length) |
| 93 | |
| 94 | out_string = u"" |
| 95 | for i in xrange(0, length): |
| 96 | char_value = valobj.GetPointeeData(i, 1).GetUnsignedInt16(error, 0) |
| 97 | out_string = out_string + unichr(char_value) |
| 98 | |
| 99 | return out_string.encode('utf-8') |
| 100 | |
| 101 | |
| 102 | def lstring_to_string(valobj, error, length=None): |
| 103 | if length is None: |
| 104 | length = guess_string_length(valobj, error) |
| 105 | else: |
| 106 | length = int(length) |
| 107 | |
| 108 | out_string = u"" |
| 109 | for i in xrange(0, length): |
| 110 | char_value = valobj.GetPointeeData(i, 1).GetUnsignedInt8(error, 0) |
| 111 | out_string = out_string + unichr(char_value) |
| 112 | |
| 113 | return out_string.encode('utf-8') |
| 114 | |
| 115 | |
| 116 | class WTFStringImplProvider: |
| 117 | def __init__(self, valobj, dict): |
| 118 | self.valobj = valobj |
| 119 | |
| 120 | def get_length(self): |
| 121 | return self.valobj.GetChildMemberWithName('m_length').GetValueAsUnsigned(0) |
| 122 | |
| 123 | def get_data8(self): |
| 124 | return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data8') |
| 125 | |
| 126 | def get_data16(self): |
| 127 | return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data16') |
| 128 | |
| 129 | def to_string(self): |
| 130 | error = lldb.SBError() |
| 131 | if self.is_8bit(): |
| 132 | return lstring_to_string(self.get_data8(), error, self.get_length()) |
| 133 | return ustring_to_string(self.get_data16(), error, self.get_length()) |
| 134 | |
| 135 | def is_8bit(self): |
| 136 | # FIXME: find a way to access WTF::StringImpl::s_hashFlag8BitBuffer |
| 137 | return bool(self.valobj.GetChildMemberWithName('m_hashAndFlags').GetValueAsUnsigned(0) \ |
| 138 | & 1 << 6) |
| 139 | |
| 140 | |
| 141 | class WTFStringProvider: |
| 142 | def __init__(self, valobj, dict): |
| 143 | self.valobj = valobj |
| 144 | |
| 145 | def stringimpl(self): |
| 146 | impl_ptr = self.valobj.GetChildMemberWithName('m_impl').GetChildMemberWithName('m_ptr') |
| 147 | return WTFStringImplProvider(impl_ptr, dict) |
| 148 | |
| 149 | def get_length(self): |
| 150 | impl = self.stringimpl() |
| 151 | if not impl: |
| 152 | return 0 |
| 153 | return impl.get_length() |
| 154 | |
| 155 | def to_string(self): |
| 156 | impl = self.stringimpl() |
| 157 | if not impl: |
| 158 | return u"" |
| 159 | return impl.to_string() |
| 160 | |
| 161 | |
| 162 | class WTFVectorProvider: |
| 163 | def __init__(self, valobj, internal_dict): |
| 164 | self.valobj = valobj |
| 165 | self.update() |
| 166 | |
| 167 | def num_children(self): |
| 168 | return self.size + 2 |
| 169 | |
| 170 | def get_child_index(self, name): |
| 171 | if name == "m_size": |
| 172 | return self.size |
| 173 | elif name == "m_buffer": |
| 174 | return self.size + 1 |
| 175 | else: |
| 176 | return int(name.lstrip('[').rstrip(']')) |
| 177 | |
| 178 | def get_child_at_index(self, index): |
| 179 | if index == self.size: |
| 180 | return self.valobj.GetChildMemberWithName("m_size") |
| 181 | elif index == self.size + 1: |
| 182 | return self.vector_buffer |
| 183 | elif index < self.size: |
| 184 | offset = index * self.data_size |
| 185 | child = self.buffer.CreateChildAtOffset('[' + str(index) + ']', offset, self.data_type) |
| 186 | return child |
| 187 | else: |
| 188 | return None |
| 189 | |
| 190 | def update(self): |
| 191 | self.vector_buffer = self.valobj.GetChildMemberWithName('m_buffer') |
| 192 | self.buffer = self.vector_buffer.GetChildMemberWithName('m_buffer') |
| 193 | self.size = self.valobj.GetChildMemberWithName('m_size').GetValueAsUnsigned(0) |
| 194 | self.capacity = self.vector_buffer.GetChildMemberWithName('m_capacity').GetValueAsUnsigned(0) |
| 195 | self.data_type = self.buffer.GetType().GetPointeeType() |
| 196 | self.data_size = self.data_type.GetByteSize() |
| 197 | |
| 198 | def has_children(self): |
| 199 | return True |
Torne (Richard Coles) | 926b001 | 2013-03-28 15:32:48 +0000 | [diff] [blame] | 200 | |
| 201 | |
| 202 | class WTFHashTableProvider: |
| 203 | def __init__(self, valobj, internal_dict): |
| 204 | self.valobj = valobj |
| 205 | self.update() |
| 206 | |
| 207 | def num_children(self): |
| 208 | return self.tableSize() + 5 |
| 209 | |
| 210 | def get_child_index(self, name): |
| 211 | if name == "m_table": |
| 212 | return self.tableSize() |
| 213 | elif name == "m_tableSize": |
| 214 | return self.tableSize() + 1 |
| 215 | elif name == "m_tableSizeMask": |
| 216 | return self.tableSize() + 2 |
| 217 | elif name == "m_keyCount": |
| 218 | return self.tableSize() + 3 |
| 219 | elif name == "m_deletedCount": |
| 220 | return self.tableSize() + 4 |
| 221 | else: |
| 222 | return int(name.lstrip('[').rstrip(']')) |
| 223 | |
| 224 | def get_child_at_index(self, index): |
| 225 | if index == self.tableSize(): |
| 226 | return self.valobj.GetChildMemberWithName('m_table') |
| 227 | elif index == self.tableSize() + 1: |
| 228 | return self.valobj.GetChildMemberWithName('m_tableSize') |
| 229 | elif index == self.tableSize() + 2: |
| 230 | return self.valobj.GetChildMemberWithName('m_tableSizeMask') |
| 231 | elif index == self.tableSize() + 3: |
| 232 | return self.valobj.GetChildMemberWithName('m_keyCount') |
| 233 | elif index == self.tableSize() + 4: |
| 234 | return self.valobj.GetChildMemberWithName('m_deletedCount') |
| 235 | elif index < self.tableSize(): |
| 236 | table = self.valobj.GetChildMemberWithName('m_table') |
| 237 | return table.CreateChildAtOffset('[' + str(index) + ']', index * self.data_size, self.data_type) |
| 238 | else: |
| 239 | return None |
| 240 | |
| 241 | def tableSize(self): |
| 242 | return self.valobj.GetChildMemberWithName('m_tableSize').GetValueAsUnsigned(0) |
| 243 | |
| 244 | def keyCount(self): |
| 245 | return self.valobj.GetChildMemberWithName('m_keyCount').GetValueAsUnsigned(0) |
| 246 | |
| 247 | def update(self): |
| 248 | self.data_type = self.valobj.GetType().GetTemplateArgumentType(0) |
| 249 | self.data_size = self.data_type.GetByteSize() |
| 250 | |
| 251 | def has_children(self): |
| 252 | return True |