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