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