123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- # Copyright (C) 2012 Apple. All rights reserved.
- #
- # Redistribution and use in source and binary forms, with or without
- # modification, are permitted provided that the following conditions
- # are met:
- # 1. Redistributions of source code must retain the above copyright
- # notice, this list of conditions and the following disclaimer.
- # 2. Redistributions in binary form must reproduce the above copyright
- # notice, this list of conditions and the following disclaimer in the
- # documentation and/or other materials provided with the distribution.
- #
- # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
- # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- # DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- # DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- """
- LLDB Support for WebKit Types
- Add the following to your .lldbinit file to add WebKit Type summaries in LLDB and Xcode:
- command script import {Path to WebKit Root}/Tools/lldb/lldb_webkit.py
- """
- import lldb
- import struct
- def __lldb_init_module(debugger, dict):
- debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFString_SummaryProvider WTF::String')
- debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFStringImpl_SummaryProvider WTF::StringImpl')
- debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFAtomicString_SummaryProvider WTF::AtomicString')
- debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFVector_SummaryProvider -x "WTF::Vector<.+>$"')
- debugger.HandleCommand('type summary add --expand -F lldb_webkit.WTFHashTable_SummaryProvider -x "WTF::HashTable<.+>$"')
- debugger.HandleCommand('type synthetic add -x "WTF::Vector<.+>$" --python-class lldb_webkit.WTFVectorProvider')
- debugger.HandleCommand('type synthetic add -x "WTF::HashTable<.+>$" --python-class lldb_webkit.WTFHashTableProvider')
- def WTFString_SummaryProvider(valobj, dict):
- provider = WTFStringProvider(valobj, dict)
- return "{ length = %d, contents = '%s' }" % (provider.get_length(), provider.to_string())
- def WTFStringImpl_SummaryProvider(valobj, dict):
- provider = WTFStringImplProvider(valobj, dict)
- return "{ length = %d, is8bit = %d, contents = '%s' }" % (provider.get_length(), provider.is_8bit(), provider.to_string())
- def WTFAtomicString_SummaryProvider(valobj, dict):
- return WTFString_SummaryProvider(valobj.GetChildMemberWithName('m_string'), dict)
- def WTFVector_SummaryProvider(valobj, dict):
- provider = WTFVectorProvider(valobj, dict)
- return "{ size = %d, capacity = %d }" % (provider.size, provider.capacity)
- def WTFHashTable_SummaryProvider(valobj, dict):
- provider = WTFHashTableProvider(valobj, dict)
- return "{ tableSize = %d, keyCount = %d }" % (provider.tableSize(), provider.keyCount())
- # FIXME: Provide support for the following types:
- # def WTFVector_SummaryProvider(valobj, dict):
- # def WTFCString_SummaryProvider(valobj, dict):
- # def WebCoreKURLGooglePrivate_SummaryProvider(valobj, dict):
- # def WebCoreQualifiedName_SummaryProvider(valobj, dict):
- # def JSCIdentifier_SummaryProvider(valobj, dict):
- # def JSCJSString_SummaryProvider(valobj, dict):
- def guess_string_length(valobj, charSize, error):
- if not valobj.GetValue():
- return 0
- maxLength = 256
- pointer = valobj.GetValueAsUnsigned()
- contents = valobj.GetProcess().ReadMemory(pointer, maxLength * charSize, lldb.SBError())
- format = 'B' if charSize == 1 else 'H'
- for i in xrange(0, maxLength):
- if not struct.unpack_from(format, contents, i * charSize)[0]:
- return i
- return maxLength
- def ustring_to_string(valobj, error, length=None):
- if length is None:
- length = guess_string_length(valobj, 2, error)
- else:
- length = int(length)
- pointer = valobj.GetValueAsUnsigned()
- contents = valobj.GetProcess().ReadMemory(pointer, length * 2, lldb.SBError())
- # lldb does not (currently) support returning unicode from python summary providers,
- # so potentially convert this to ascii by escaping
- string = contents.decode('utf16')
- try:
- return str(string)
- except:
- return string.encode('unicode_escape')
- def lstring_to_string(valobj, error, length=None):
- if length is None:
- length = guess_string_length(valobj, 1, error)
- else:
- length = int(length)
- pointer = valobj.GetValueAsUnsigned()
- contents = valobj.GetProcess().ReadMemory(pointer, length, lldb.SBError())
- # lldb does not (currently) support returning unicode from python summary providers,
- # so potentially convert this to ascii by escaping
- string = contents.decode('utf8')
- try:
- return str(string)
- except:
- return string.encode('unicode_escape')
- class WTFStringImplProvider:
- def __init__(self, valobj, dict):
- self.valobj = valobj
- def get_length(self):
- return self.valobj.GetChildMemberWithName('m_length').GetValueAsUnsigned(0)
- def get_data8(self):
- return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data8')
- def get_data16(self):
- return self.valobj.GetChildAtIndex(2).GetChildMemberWithName('m_data16')
- def to_string(self):
- error = lldb.SBError()
- if self.is_8bit():
- return lstring_to_string(self.get_data8(), error, self.get_length())
- return ustring_to_string(self.get_data16(), error, self.get_length())
- def is_8bit(self):
- # FIXME: find a way to access WTF::StringImpl::s_hashFlag8BitBuffer
- return bool(self.valobj.GetChildMemberWithName('m_hashAndFlags').GetValueAsUnsigned(0) \
- & 1 << 6)
- class WTFStringProvider:
- def __init__(self, valobj, dict):
- self.valobj = valobj
- def stringimpl(self):
- impl_ptr = self.valobj.GetChildMemberWithName('m_impl').GetChildMemberWithName('m_ptr')
- return WTFStringImplProvider(impl_ptr, dict)
- def get_length(self):
- impl = self.stringimpl()
- if not impl:
- return 0
- return impl.get_length()
- def to_string(self):
- impl = self.stringimpl()
- if not impl:
- return u""
- return impl.to_string()
- class WTFVectorProvider:
- def __init__(self, valobj, internal_dict):
- self.valobj = valobj
- self.update()
- def num_children(self):
- return self.size + 3
- def get_child_index(self, name):
- if name == "m_size":
- return self.size
- elif name == "m_capacity":
- return self.size + 1
- elif name == "m_buffer":
- return self.size + 2
- else:
- return int(name.lstrip('[').rstrip(']'))
- def get_child_at_index(self, index):
- if index == self.size:
- return self.valobj.GetChildMemberWithName("m_size")
- elif index == self.size + 1:
- return self.valobj.GetChildMemberWithName("m_capacity")
- elif index == self.size + 2:
- return self.buffer
- elif index < self.size:
- offset = index * self.data_size
- child = self.buffer.CreateChildAtOffset('[' + str(index) + ']', offset, self.data_type)
- return child
- else:
- return None
- def update(self):
- self.buffer = self.valobj.GetChildMemberWithName('m_buffer')
- self.size = self.valobj.GetChildMemberWithName('m_size').GetValueAsUnsigned(0)
- self.capacity = self.buffer.GetChildMemberWithName('m_capacity').GetValueAsUnsigned(0)
- self.data_type = self.buffer.GetType().GetPointeeType()
- self.data_size = self.data_type.GetByteSize()
- def has_children(self):
- return True
- class WTFHashTableProvider:
- def __init__(self, valobj, internal_dict):
- self.valobj = valobj
- self.update()
- def num_children(self):
- return self.tableSize() + 5
- def get_child_index(self, name):
- if name == "m_table":
- return self.tableSize()
- elif name == "m_tableSize":
- return self.tableSize() + 1
- elif name == "m_tableSizeMask":
- return self.tableSize() + 2
- elif name == "m_keyCount":
- return self.tableSize() + 3
- elif name == "m_deletedCount":
- return self.tableSize() + 4
- else:
- return int(name.lstrip('[').rstrip(']'))
- def get_child_at_index(self, index):
- if index == self.tableSize():
- return self.valobj.GetChildMemberWithName('m_table')
- elif index == self.tableSize() + 1:
- return self.valobj.GetChildMemberWithName('m_tableSize')
- elif index == self.tableSize() + 2:
- return self.valobj.GetChildMemberWithName('m_tableSizeMask')
- elif index == self.tableSize() + 3:
- return self.valobj.GetChildMemberWithName('m_keyCount')
- elif index == self.tableSize() + 4:
- return self.valobj.GetChildMemberWithName('m_deletedCount')
- elif index < self.tableSize():
- table = self.valobj.GetChildMemberWithName('m_table')
- return table.CreateChildAtOffset('[' + str(index) + ']', index * self.data_size, self.data_type)
- else:
- return None
- def tableSize(self):
- return self.valobj.GetChildMemberWithName('m_tableSize').GetValueAsUnsigned(0)
- def keyCount(self):
- return self.valobj.GetChildMemberWithName('m_keyCount').GetValueAsUnsigned(0)
- def update(self):
- self.data_type = self.valobj.GetType().GetTemplateArgumentType(0)
- self.data_size = self.data_type.GetByteSize()
- def has_children(self):
- return True
|