Home | History | Annotate | Download | only in tools
      1 # Copyright 2011 the V8 project authors. All rights reserved.
      2 # Redistribution and use in source and binary forms, with or without
      3 # modification, are permitted provided that the following conditions are
      4 # met:
      5 #
      6 #     * Redistributions of source code must retain the above copyright
      7 #       notice, this list of conditions and the following disclaimer.
      8 #     * Redistributions in binary form must reproduce the above
      9 #       copyright notice, this list of conditions and the following
     10 #       disclaimer in the documentation and/or other materials provided
     11 #       with the distribution.
     12 #     * Neither the name of Google Inc. nor the names of its
     13 #       contributors may be used to endorse or promote products derived
     14 #       from this software without specific prior written permission.
     15 #
     16 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     17 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     18 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     19 # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     20 # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     23 # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     24 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     25 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     26 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 
     28 import re
     29 
     30 kSmiTag = 0
     31 kSmiTagSize = 1
     32 kSmiTagMask = (1 << kSmiTagSize) - 1
     33 
     34 
     35 kHeapObjectTag = 1
     36 kHeapObjectTagSize = 2
     37 kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1
     38 
     39 
     40 kFailureTag = 3
     41 kFailureTagSize = 2
     42 kFailureTagMask = (1 << kFailureTagSize) - 1
     43 
     44 
     45 kSmiShiftSize32 = 0
     46 kSmiValueSize32 = 31
     47 kSmiShiftBits32 = kSmiTagSize + kSmiShiftSize32
     48 
     49 
     50 kSmiShiftSize64 = 31
     51 kSmiValueSize64 = 32
     52 kSmiShiftBits64 = kSmiTagSize + kSmiShiftSize64
     53 
     54 
     55 kAllBits = 0xFFFFFFFF
     56 kTopBit32 = 0x80000000
     57 kTopBit64 = 0x8000000000000000
     58 
     59 
     60 t_u32 = gdb.lookup_type('unsigned int')
     61 t_u64 = gdb.lookup_type('unsigned long long')
     62 
     63 
     64 def has_smi_tag(v):
     65   return v & kSmiTagMask == kSmiTag
     66 
     67 
     68 def has_failure_tag(v):
     69   return v & kFailureTagMask == kFailureTag
     70 
     71 
     72 def has_heap_object_tag(v):
     73   return v & kHeapObjectTagMask == kHeapObjectTag
     74 
     75 
     76 def raw_heap_object(v):
     77   return v - kHeapObjectTag
     78 
     79 
     80 def smi_to_int_32(v):
     81   v = v & kAllBits
     82   if (v & kTopBit32) == kTopBit32:
     83     return ((v & kAllBits) >> kSmiShiftBits32) - 2147483648
     84   else:
     85     return (v & kAllBits) >> kSmiShiftBits32
     86 
     87 
     88 def smi_to_int_64(v):
     89   return (v >> kSmiShiftBits64)
     90 
     91 
     92 def decode_v8_value(v, bitness):
     93   base_str = 'v8[%x]' % v
     94   if has_smi_tag(v):
     95     if bitness == 32:
     96       return base_str + (" SMI(%d)" % smi_to_int_32(v))
     97     else:
     98       return base_str + (" SMI(%d)" % smi_to_int_64(v))
     99   elif has_failure_tag(v):
    100     return base_str + " (failure)"
    101   elif has_heap_object_tag(v):
    102     return base_str + (" H(0x%x)" % raw_heap_object(v))
    103   else:
    104     return base_str
    105 
    106 
    107 class V8ValuePrinter(object):
    108   "Print a v8value."
    109   def __init__(self, val):
    110     self.val = val
    111   def to_string(self):
    112     if self.val.type.sizeof == 4:
    113       v_u32 = self.val.cast(t_u32)
    114       return decode_v8_value(int(v_u32), 32)
    115     elif self.val.type.sizeof == 8:
    116       v_u64 = self.val.cast(t_u64)
    117       return decode_v8_value(int(v_u64), 64)
    118     else:
    119       return 'v8value?'
    120   def display_hint(self):
    121     return 'v8value'
    122 
    123 
    124 def v8_pretty_printers(val):
    125   lookup_tag = val.type.tag
    126   if lookup_tag == None:
    127     return None
    128   elif lookup_tag == 'v8value':
    129     return V8ValuePrinter(val)
    130   return None
    131 gdb.pretty_printers.append(v8_pretty_printers)
    132 
    133 
    134 def v8_to_int(v):
    135   if v.type.sizeof == 4:
    136     return int(v.cast(t_u32))
    137   elif v.type.sizeof == 8:
    138     return int(v.cast(t_u64))
    139   else:
    140     return '?'
    141 
    142 
    143 def v8_get_value(vstring):
    144   v = gdb.parse_and_eval(vstring)
    145   return v8_to_int(v)
    146 
    147 
    148 class V8PrintObject (gdb.Command):
    149   """Prints a v8 object."""
    150   def __init__ (self):
    151     super (V8PrintObject, self).__init__ ("v8print", gdb.COMMAND_DATA)
    152   def invoke (self, arg, from_tty):
    153     v = v8_get_value(arg)
    154     gdb.execute('call __gdb_print_v8_object(%d)' % v)
    155 V8PrintObject()
    156 
    157 
    158 class FindAnywhere (gdb.Command):
    159   """Search memory for the given pattern."""
    160   MAPPING_RE = re.compile(r"^\s*\[\d+\]\s+0x([0-9A-Fa-f]+)->0x([0-9A-Fa-f]+)")
    161   LIVE_MAPPING_RE = re.compile(r"^\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)")
    162   def __init__ (self):
    163     super (FindAnywhere, self).__init__ ("find-anywhere", gdb.COMMAND_DATA)
    164   def find (self, startAddr, endAddr, value):
    165     try:
    166       result = gdb.execute(
    167           "find 0x%s, 0x%s, %s" % (startAddr, endAddr, value),
    168           to_string = True)
    169       if result.find("not found") == -1:
    170         print(result)
    171     except:
    172       pass
    173 
    174   def invoke (self, value, from_tty):
    175     for l in gdb.execute("maint info sections", to_string = True).split('\n'):
    176       m = FindAnywhere.MAPPING_RE.match(l)
    177       if m is None:
    178         continue
    179       self.find(m.group(1), m.group(2), value)
    180     for l in gdb.execute("info proc mappings", to_string = True).split('\n'):
    181       m = FindAnywhere.LIVE_MAPPING_RE.match(l)
    182       if m is None:
    183         continue
    184       self.find(m.group(1), m.group(2), value)
    185 
    186 FindAnywhere()
    187