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 28import re 29 30kSmiTag = 0 31kSmiTagSize = 1 32kSmiTagMask = (1 << kSmiTagSize) - 1 33 34 35kHeapObjectTag = 1 36kHeapObjectTagSize = 2 37kHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1 38 39 40kFailureTag = 3 41kFailureTagSize = 2 42kFailureTagMask = (1 << kFailureTagSize) - 1 43 44 45kSmiShiftSize32 = 0 46kSmiValueSize32 = 31 47kSmiShiftBits32 = kSmiTagSize + kSmiShiftSize32 48 49 50kSmiShiftSize64 = 31 51kSmiValueSize64 = 32 52kSmiShiftBits64 = kSmiTagSize + kSmiShiftSize64 53 54 55kAllBits = 0xFFFFFFFF 56kTopBit32 = 0x80000000 57kTopBit64 = 0x8000000000000000 58 59 60t_u32 = gdb.lookup_type('unsigned int') 61t_u64 = gdb.lookup_type('unsigned long long') 62 63 64def has_smi_tag(v): 65 return v & kSmiTagMask == kSmiTag 66 67 68def has_failure_tag(v): 69 return v & kFailureTagMask == kFailureTag 70 71 72def has_heap_object_tag(v): 73 return v & kHeapObjectTagMask == kHeapObjectTag 74 75 76def raw_heap_object(v): 77 return v - kHeapObjectTag 78 79 80def 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 88def smi_to_int_64(v): 89 return (v >> kSmiShiftBits64) 90 91 92def 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 107class 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 124def 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 131gdb.pretty_printers.append(v8_pretty_printers) 132 133 134def 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 143def v8_get_value(vstring): 144 v = gdb.parse_and_eval(vstring) 145 return v8_to_int(v) 146 147 148class 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) 155V8PrintObject() 156 157 158class 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 186FindAnywhere() 187