11cb0ef41Sopenharmony_ci# Copyright 2011 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci# Redistribution and use in source and binary forms, with or without 31cb0ef41Sopenharmony_ci# modification, are permitted provided that the following conditions are 41cb0ef41Sopenharmony_ci# met: 51cb0ef41Sopenharmony_ci# 61cb0ef41Sopenharmony_ci# * Redistributions of source code must retain the above copyright 71cb0ef41Sopenharmony_ci# notice, this list of conditions and the following disclaimer. 81cb0ef41Sopenharmony_ci# * Redistributions in binary form must reproduce the above 91cb0ef41Sopenharmony_ci# copyright notice, this list of conditions and the following 101cb0ef41Sopenharmony_ci# disclaimer in the documentation and/or other materials provided 111cb0ef41Sopenharmony_ci# with the distribution. 121cb0ef41Sopenharmony_ci# * Neither the name of Google Inc. nor the names of its 131cb0ef41Sopenharmony_ci# contributors may be used to endorse or promote products derived 141cb0ef41Sopenharmony_ci# from this software without specific prior written permission. 151cb0ef41Sopenharmony_ci# 161cb0ef41Sopenharmony_ci# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 171cb0ef41Sopenharmony_ci# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 181cb0ef41Sopenharmony_ci# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 191cb0ef41Sopenharmony_ci# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 201cb0ef41Sopenharmony_ci# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 211cb0ef41Sopenharmony_ci# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 221cb0ef41Sopenharmony_ci# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 231cb0ef41Sopenharmony_ci# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 241cb0ef41Sopenharmony_ci# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 251cb0ef41Sopenharmony_ci# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 261cb0ef41Sopenharmony_ci# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 271cb0ef41Sopenharmony_ci 281cb0ef41Sopenharmony_ci# for py2/py3 compatibility 291cb0ef41Sopenharmony_cifrom __future__ import print_function 301cb0ef41Sopenharmony_ci 311cb0ef41Sopenharmony_ciimport re 321cb0ef41Sopenharmony_ciimport tempfile 331cb0ef41Sopenharmony_ciimport os 341cb0ef41Sopenharmony_ciimport subprocess 351cb0ef41Sopenharmony_ciimport time 361cb0ef41Sopenharmony_ciimport gdb 371cb0ef41Sopenharmony_ci 381cb0ef41Sopenharmony_cikSmiTag = 0 391cb0ef41Sopenharmony_cikSmiTagSize = 1 401cb0ef41Sopenharmony_cikSmiTagMask = (1 << kSmiTagSize) - 1 411cb0ef41Sopenharmony_ci 421cb0ef41Sopenharmony_cikHeapObjectTag = 1 431cb0ef41Sopenharmony_cikHeapObjectTagSize = 2 441cb0ef41Sopenharmony_cikHeapObjectTagMask = (1 << kHeapObjectTagSize) - 1 451cb0ef41Sopenharmony_ci 461cb0ef41Sopenharmony_cikFailureTag = 3 471cb0ef41Sopenharmony_cikFailureTagSize = 2 481cb0ef41Sopenharmony_cikFailureTagMask = (1 << kFailureTagSize) - 1 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_cikSmiShiftSize32 = 0 511cb0ef41Sopenharmony_cikSmiValueSize32 = 31 521cb0ef41Sopenharmony_cikSmiShiftBits32 = kSmiTagSize + kSmiShiftSize32 531cb0ef41Sopenharmony_ci 541cb0ef41Sopenharmony_cikSmiShiftSize64 = 31 551cb0ef41Sopenharmony_cikSmiValueSize64 = 32 561cb0ef41Sopenharmony_cikSmiShiftBits64 = kSmiTagSize + kSmiShiftSize64 571cb0ef41Sopenharmony_ci 581cb0ef41Sopenharmony_cikAllBits = 0xFFFFFFFF 591cb0ef41Sopenharmony_cikTopBit32 = 0x80000000 601cb0ef41Sopenharmony_cikTopBit64 = 0x8000000000000000 611cb0ef41Sopenharmony_ci 621cb0ef41Sopenharmony_cit_u32 = gdb.lookup_type('unsigned int') 631cb0ef41Sopenharmony_cit_u64 = gdb.lookup_type('unsigned long long') 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_cidef has_smi_tag(v): 671cb0ef41Sopenharmony_ci return v & kSmiTagMask == kSmiTag 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_ci 701cb0ef41Sopenharmony_cidef has_failure_tag(v): 711cb0ef41Sopenharmony_ci return v & kFailureTagMask == kFailureTag 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_ci 741cb0ef41Sopenharmony_cidef has_heap_object_tag(v): 751cb0ef41Sopenharmony_ci return v & kHeapObjectTagMask == kHeapObjectTag 761cb0ef41Sopenharmony_ci 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_cidef raw_heap_object(v): 791cb0ef41Sopenharmony_ci return v - kHeapObjectTag 801cb0ef41Sopenharmony_ci 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_cidef smi_to_int_32(v): 831cb0ef41Sopenharmony_ci v = v & kAllBits 841cb0ef41Sopenharmony_ci if (v & kTopBit32) == kTopBit32: 851cb0ef41Sopenharmony_ci return ((v & kAllBits) >> kSmiShiftBits32) - 2147483648 861cb0ef41Sopenharmony_ci else: 871cb0ef41Sopenharmony_ci return (v & kAllBits) >> kSmiShiftBits32 881cb0ef41Sopenharmony_ci 891cb0ef41Sopenharmony_ci 901cb0ef41Sopenharmony_cidef smi_to_int_64(v): 911cb0ef41Sopenharmony_ci return (v >> kSmiShiftBits64) 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_cidef decode_v8_value(v, bitness): 951cb0ef41Sopenharmony_ci base_str = 'v8[%x]' % v 961cb0ef41Sopenharmony_ci if has_smi_tag(v): 971cb0ef41Sopenharmony_ci if bitness == 32: 981cb0ef41Sopenharmony_ci return base_str + (" SMI(%d)" % smi_to_int_32(v)) 991cb0ef41Sopenharmony_ci else: 1001cb0ef41Sopenharmony_ci return base_str + (" SMI(%d)" % smi_to_int_64(v)) 1011cb0ef41Sopenharmony_ci elif has_failure_tag(v): 1021cb0ef41Sopenharmony_ci return base_str + " (failure)" 1031cb0ef41Sopenharmony_ci elif has_heap_object_tag(v): 1041cb0ef41Sopenharmony_ci return base_str + (" H(0x%x)" % raw_heap_object(v)) 1051cb0ef41Sopenharmony_ci else: 1061cb0ef41Sopenharmony_ci return base_str 1071cb0ef41Sopenharmony_ci 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_ciclass V8ValuePrinter(object): 1101cb0ef41Sopenharmony_ci "Print a v8value." 1111cb0ef41Sopenharmony_ci 1121cb0ef41Sopenharmony_ci def __init__(self, val): 1131cb0ef41Sopenharmony_ci self.val = val 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_ci def to_string(self): 1161cb0ef41Sopenharmony_ci if self.val.type.sizeof == 4: 1171cb0ef41Sopenharmony_ci v_u32 = self.val.cast(t_u32) 1181cb0ef41Sopenharmony_ci return decode_v8_value(int(v_u32), 32) 1191cb0ef41Sopenharmony_ci elif self.val.type.sizeof == 8: 1201cb0ef41Sopenharmony_ci v_u64 = self.val.cast(t_u64) 1211cb0ef41Sopenharmony_ci return decode_v8_value(int(v_u64), 64) 1221cb0ef41Sopenharmony_ci else: 1231cb0ef41Sopenharmony_ci return 'v8value?' 1241cb0ef41Sopenharmony_ci 1251cb0ef41Sopenharmony_ci def display_hint(self): 1261cb0ef41Sopenharmony_ci return 'v8value' 1271cb0ef41Sopenharmony_ci 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_cidef v8_pretty_printers(val): 1301cb0ef41Sopenharmony_ci lookup_tag = val.type.tag 1311cb0ef41Sopenharmony_ci if lookup_tag == None: 1321cb0ef41Sopenharmony_ci return None 1331cb0ef41Sopenharmony_ci elif lookup_tag == 'v8value': 1341cb0ef41Sopenharmony_ci return V8ValuePrinter(val) 1351cb0ef41Sopenharmony_ci return None 1361cb0ef41Sopenharmony_ci 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_cigdb.pretty_printers.append(v8_pretty_printers) 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_ci 1411cb0ef41Sopenharmony_cidef v8_to_int(v): 1421cb0ef41Sopenharmony_ci if v.type.sizeof == 4: 1431cb0ef41Sopenharmony_ci return int(v.cast(t_u32)) 1441cb0ef41Sopenharmony_ci elif v.type.sizeof == 8: 1451cb0ef41Sopenharmony_ci return int(v.cast(t_u64)) 1461cb0ef41Sopenharmony_ci else: 1471cb0ef41Sopenharmony_ci return '?' 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_cidef v8_get_value(vstring): 1511cb0ef41Sopenharmony_ci v = gdb.parse_and_eval(vstring) 1521cb0ef41Sopenharmony_ci return v8_to_int(v) 1531cb0ef41Sopenharmony_ci 1541cb0ef41Sopenharmony_ci 1551cb0ef41Sopenharmony_ciclass V8PrintObject(gdb.Command): 1561cb0ef41Sopenharmony_ci """Prints a v8 object.""" 1571cb0ef41Sopenharmony_ci def __init__(self): 1581cb0ef41Sopenharmony_ci super(V8PrintObject, self).__init__("v8print", gdb.COMMAND_DATA) 1591cb0ef41Sopenharmony_ci 1601cb0ef41Sopenharmony_ci def invoke(self, arg, from_tty): 1611cb0ef41Sopenharmony_ci v = v8_get_value(arg) 1621cb0ef41Sopenharmony_ci gdb.execute('call __gdb_print_v8_object(%d)' % v) 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ci 1651cb0ef41Sopenharmony_ciV8PrintObject() 1661cb0ef41Sopenharmony_ci 1671cb0ef41Sopenharmony_ci 1681cb0ef41Sopenharmony_ciclass FindAnywhere(gdb.Command): 1691cb0ef41Sopenharmony_ci """Search memory for the given pattern.""" 1701cb0ef41Sopenharmony_ci MAPPING_RE = re.compile(r"^\s*\[\d+\]\s+0x([0-9A-Fa-f]+)->0x([0-9A-Fa-f]+)") 1711cb0ef41Sopenharmony_ci LIVE_MAPPING_RE = re.compile(r"^\s+0x([0-9A-Fa-f]+)\s+0x([0-9A-Fa-f]+)") 1721cb0ef41Sopenharmony_ci 1731cb0ef41Sopenharmony_ci def __init__(self): 1741cb0ef41Sopenharmony_ci super(FindAnywhere, self).__init__("find-anywhere", gdb.COMMAND_DATA) 1751cb0ef41Sopenharmony_ci 1761cb0ef41Sopenharmony_ci def find(self, startAddr, endAddr, value): 1771cb0ef41Sopenharmony_ci try: 1781cb0ef41Sopenharmony_ci result = gdb.execute("find 0x%s, 0x%s, %s" % (startAddr, endAddr, value), 1791cb0ef41Sopenharmony_ci to_string=True) 1801cb0ef41Sopenharmony_ci if result.find("not found") == -1: 1811cb0ef41Sopenharmony_ci print(result) 1821cb0ef41Sopenharmony_ci except: 1831cb0ef41Sopenharmony_ci pass 1841cb0ef41Sopenharmony_ci 1851cb0ef41Sopenharmony_ci def invoke(self, value, from_tty): 1861cb0ef41Sopenharmony_ci for l in gdb.execute("maint info sections", to_string=True).split('\n'): 1871cb0ef41Sopenharmony_ci m = FindAnywhere.MAPPING_RE.match(l) 1881cb0ef41Sopenharmony_ci if m is None: 1891cb0ef41Sopenharmony_ci continue 1901cb0ef41Sopenharmony_ci self.find(m.group(1), m.group(2), value) 1911cb0ef41Sopenharmony_ci for l in gdb.execute("info proc mappings", to_string=True).split('\n'): 1921cb0ef41Sopenharmony_ci m = FindAnywhere.LIVE_MAPPING_RE.match(l) 1931cb0ef41Sopenharmony_ci if m is None: 1941cb0ef41Sopenharmony_ci continue 1951cb0ef41Sopenharmony_ci self.find(m.group(1), m.group(2), value) 1961cb0ef41Sopenharmony_ci 1971cb0ef41Sopenharmony_ci 1981cb0ef41Sopenharmony_ciFindAnywhere() 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci 2011cb0ef41Sopenharmony_ciclass Redirect(gdb.Command): 2021cb0ef41Sopenharmony_ci """Redirect the subcommand's stdout to a temporary file. 2031cb0ef41Sopenharmony_ci 2041cb0ef41Sopenharmony_ciUsage: redirect subcommand... 2051cb0ef41Sopenharmony_ciExample: 2061cb0ef41Sopenharmony_ci redirect job 0x123456789 2071cb0ef41Sopenharmony_ci redirect x/1024xg 0x12345678 2081cb0ef41Sopenharmony_ci 2091cb0ef41Sopenharmony_ciIf provided, the generated temporary file is directly openend with the 2101cb0ef41Sopenharmony_ciGDB_EXTERNAL_EDITOR environment variable. 2111cb0ef41Sopenharmony_ci """ 2121cb0ef41Sopenharmony_ci def __init__(self): 2131cb0ef41Sopenharmony_ci super(Redirect, self).__init__("redirect", gdb.COMMAND_USER) 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci def invoke(self, subcommand, from_tty): 2161cb0ef41Sopenharmony_ci old_stdout = gdb.execute("p (int)dup(1)", 2171cb0ef41Sopenharmony_ci to_string=True).split("=")[-1].strip() 2181cb0ef41Sopenharmony_ci try: 2191cb0ef41Sopenharmony_ci time_suffix = time.strftime("%Y%m%d-%H%M%S") 2201cb0ef41Sopenharmony_ci fd, file = tempfile.mkstemp(suffix="-%s.gdbout" % time_suffix) 2211cb0ef41Sopenharmony_ci try: 2221cb0ef41Sopenharmony_ci # Temporarily redirect stdout to the created tmp file for the 2231cb0ef41Sopenharmony_ci # duration of the subcommand. 2241cb0ef41Sopenharmony_ci gdb.execute('p (int)dup2((int)open("%s", 1), 1)' % file, 2251cb0ef41Sopenharmony_ci to_string=True) 2261cb0ef41Sopenharmony_ci # Execute subcommand non interactively. 2271cb0ef41Sopenharmony_ci result = gdb.execute(subcommand, from_tty=False, to_string=True) 2281cb0ef41Sopenharmony_ci # Write returned string results to the temporary file as well. 2291cb0ef41Sopenharmony_ci with open(file, 'a') as f: 2301cb0ef41Sopenharmony_ci f.write(result) 2311cb0ef41Sopenharmony_ci # Open generated result. 2321cb0ef41Sopenharmony_ci if 'GDB_EXTERNAL_EDITOR' in os.environ: 2331cb0ef41Sopenharmony_ci open_cmd = os.environ['GDB_EXTERNAL_EDITOR'] 2341cb0ef41Sopenharmony_ci print("Opening '%s' with %s" % (file, open_cmd)) 2351cb0ef41Sopenharmony_ci subprocess.call([open_cmd, file]) 2361cb0ef41Sopenharmony_ci else: 2371cb0ef41Sopenharmony_ci print("Output written to:\n '%s'" % file) 2381cb0ef41Sopenharmony_ci finally: 2391cb0ef41Sopenharmony_ci # Restore original stdout. 2401cb0ef41Sopenharmony_ci gdb.execute("p (int)dup2(%s, 1)" % old_stdout, to_string=True) 2411cb0ef41Sopenharmony_ci # Close the temporary file. 2421cb0ef41Sopenharmony_ci os.close(fd) 2431cb0ef41Sopenharmony_ci finally: 2441cb0ef41Sopenharmony_ci # Close the originally duplicated stdout descriptor. 2451cb0ef41Sopenharmony_ci gdb.execute("p (int)close(%s)" % old_stdout, to_string=True) 2461cb0ef41Sopenharmony_ci 2471cb0ef41Sopenharmony_ci 2481cb0ef41Sopenharmony_ciRedirect() 249