Home | History | Annotate | Download | only in lldb
      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