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<.+>$"') 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 48 def WTFString_SummaryProvider(valobj, dict): 49 provider = WTFStringProvider(valobj, dict) 50 return "{ length = %d, contents = '%s' }" % (provider.get_length(), provider.to_string()) 51 52 53 def 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 58 def WTFAtomicString_SummaryProvider(valobj, dict): 59 return WTFString_SummaryProvider(valobj.GetChildMemberWithName('m_string'), dict) 60 61 62 def WTFVector_SummaryProvider(valobj, dict): 63 provider = WTFVectorProvider(valobj, dict) 64 return "{ size = %d, capacity = %d }" % (provider.size, provider.capacity) 65 66 67 def WTFHashTable_SummaryProvider(valobj, dict): 68 provider = WTFHashTableProvider(valobj, dict) 69 return "{ tableSize = %d, keyCount = %d }" % (provider.tableSize(), provider.keyCount()) 70 71 72 def WebCoreLayoutUnit_SummaryProvider(valobj, dict): 73 provider = WebCoreLayoutUnitProvider(valobj, dict) 74 return "{ %s }" % provider.to_string() 75 76 77 def WebCoreLayoutSize_SummaryProvider(valobj, dict): 78 provider = WebCoreLayoutSizeProvider(valobj, dict) 79 return "{ width = %s, height = %s }" % (provider.get_width(), provider.get_height()) 80 81 82 def 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 94 def 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 105 def 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 119 def 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 133 class 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 158 class 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 179 class 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 188 class 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 200 class 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 212 class 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 255 class 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