gdbinit 6.56 KB
Newer Older
1 2 3 4
# Copyright 2014 the V8 project authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

5
# Print tagged object.
6
define job
7
call (void) _v8_internal_Print_Object((void*)($arg0))
8 9 10 11 12 13
end
document job
Print a v8 JavaScript object
Usage: job tagged_ptr
end

14 15
# Print content of v8::internal::Handle.
define jh
16
call (void) _v8_internal_Print_Object(*((v8::internal::Object**)($arg0).location_))
17 18 19 20 21 22 23
end
document jh
Print content of a v8::internal::Handle
Usage: jh internal_handle
end

# Print content of v8::Local handle.
24
define jlh
25
call (void) _v8_internal_Print_Object(*((v8::internal::Object**)($arg0).val_))
26 27 28 29 30 31
end
document jlh
Print content of a v8::Local handle
Usage: jlh local_handle
end

32 33
# Print Code objects containing given PC.
define jco
34 35 36 37 38
  if $argc == 0
    call (void) _v8_internal_Print_Code((void*)($pc))
  else
    call (void) _v8_internal_Print_Code((void*)($arg0))
  end
39 40 41 42 43 44
end
document jco
Print a v8 Code object from an internal code address
Usage: jco pc
end

45 46
# Print TransitionTree.
define jtt
47
call (void) _v8_internal_Print_TransitionTree((void*)($arg0))
48 49 50 51 52 53
end
document jtt
Print the complete transition tree of the given v8 Map.
Usage: jtt tagged_ptr
end

54
# Print JavaScript stack trace.
55
define jst
56
call (void) _v8_internal_Print_StackTrace()
57 58 59 60 61 62
end
document jst
Print the current JavaScript stack trace
Usage: jst
end

63 64 65 66 67 68 69 70 71
# Print TurboFan graph node.
define pn
call _v8_internal_Node_Print((void*)($arg0))
end
document pn
Print a v8 TurboFan graph node
Usage: pn node_address
end

72 73 74 75 76 77 78 79 80 81 82 83
# Skip the JavaScript stack.
define jss
set $js_entry_sp=v8::internal::Isolate::Current()->thread_local_top()->js_entry_sp_
set $rbp=*(void**)$js_entry_sp
set $rsp=$js_entry_sp + 2*sizeof(void*)
set $pc=*(void**)($js_entry_sp+sizeof(void*))
end
document jss
Skip the jitted stack on x64 to where we entered JS last.
Usage: jss
end

84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
# Execute a simulator command.
python
import gdb

class SimCommand(gdb.Command):
  """Sim the current program."""

  def __init__ (self):
    super (SimCommand, self).__init__ ("sim", gdb.COMMAND_SUPPORT)

  def invoke (self, arg, from_tty):
    arg_c_string = gdb.Value(arg)
    cmd_func = gdb.selected_frame().read_var("_v8_internal_Simulator_ExecDebugCommand")
    cmd_func(arg_c_string)

SimCommand()
end

102 103 104 105
# Print stack trace with assertion scopes.
define bta
python
import re
106
frame_re = re.compile("^#(\d+)\s*(?:0x[a-f\d]+ in )?(.+) \(.+ at (.+)")
107
assert_re = re.compile("^\s*(\S+) = .+<v8::internal::Per\w+AssertScope<v8::internal::(\S*), (false|true)>")
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
btl = gdb.execute("backtrace full", to_string = True).splitlines()
for l in btl:
  match = frame_re.match(l)
  if match:
    print("[%-2s] %-60s %-40s" % (match.group(1), match.group(2), match.group(3)))
  match = assert_re.match(l)
  if match:
    if match.group(3) == "false":
      prefix = "Disallow"
      color = "\033[91m"
    else:
      prefix = "Allow"
      color = "\033[92m"
    print("%s -> %s %s (%s)\033[0m" % (color, prefix, match.group(2), match.group(1)))
end
123
end
124 125 126 127 128
document bta
Print stack trace with assertion scopes
Usage: bta
end

129 130 131
# Search for a pointer inside all valid pages.
define space_find
  set $space = $arg0
Yang Guo's avatar
Yang Guo committed
132 133
  set $current_page = $space->first_page()
  while ($current_page != 0)
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
    printf "#   Searching in %p - %p\n", $current_page->area_start(), $current_page->area_end()-1
    find $current_page->area_start(), $current_page->area_end()-1, $arg1
    set $current_page = $current_page->next_page()
  end
end

define heap_find
  set $heap = v8::internal::Isolate::Current()->heap()
  printf "# Searching for %p in old_space  ===============================\n", $arg0
  space_find $heap->old_space() ($arg0)
  printf "# Searching for %p in map_space  ===============================\n", $arg0
  space_find $heap->map_space() $arg0
  printf "# Searching for %p in code_space ===============================\n", $arg0
  space_find $heap->code_space() $arg0
end
document heap_find
Find the location of a given address in V8 pages.
Usage: heap_find address
end

154 155 156 157 158 159 160
# The 'disassembly-flavor' command is only available on i386 and x84_64.
python
try:
  gdb.execute("set disassembly-flavor intel")
except gdb.error:
  pass
end
161
set disable-randomization off
162 163 164 165 166 167

# Install a handler whenever the debugger stops due to a signal. It walks up the
# stack looking for V8_Dcheck and moves the frame to the one above it so it's
# immediately at the line of code that triggered the DCHECK.
python
def dcheck_stop_handler(event):
168
  frame = gdb.selected_frame()
169
  select_frame = None
170
  message = None
171 172 173
  count = 0
  # limit stack scanning since they're usually shallow and otherwise stack
  # overflows can be very slow.
174
  while frame is not None and count < 7:
175
    count += 1
176 177 178 179 180 181
    if frame.name() == 'V8_Dcheck':
      frame_message = gdb.lookup_symbol('message', frame.block())[0]
      if frame_message:
        message = frame_message.value(frame).string()
      select_frame = frame.older()
      break
182
    if frame.name() is not None and frame.name().startswith('V8_Fatal'):
183 184 185
      select_frame = frame.older()
    frame = frame.older()

186 187 188
  if select_frame is not None:
    select_frame.select()
    gdb.execute('frame')
189 190
    if message:
      print('DCHECK error: {}'.format(message))
191

192 193
gdb.events.stop.connect(dcheck_stop_handler)
end
194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242

# Code imported from chromium/src/tools/gdb/gdbinit
python

import os
import subprocess
import sys

compile_dirs = set()


def get_current_debug_file_directories():
  dir = gdb.execute("show debug-file-directory", to_string=True)
  dir = dir[
      len('The directory where separate debug symbols are searched for is "'
         ):-len('".') - 1]
  return set(dir.split(":"))


def add_debug_file_directory(dir):
  # gdb has no function to add debug-file-directory, simulates that by using
  # `show debug-file-directory` and `set debug-file-directory <directories>`.
  current_dirs = get_current_debug_file_directories()
  current_dirs.add(dir)
  gdb.execute(
      "set debug-file-directory %s" % ":".join(current_dirs), to_string=True)


def newobj_handler(event):
  global compile_dirs
  compile_dir = os.path.dirname(event.new_objfile.filename)
  if not compile_dir:
    return
  if compile_dir in compile_dirs:
    return
  compile_dirs.add(compile_dir)

  # Add source path
  gdb.execute("dir %s" % compile_dir)

  # Need to tell the location of .dwo files.
  # https://sourceware.org/gdb/onlinedocs/gdb/Separate-Debug-Files.html
  # https://crbug.com/603286#c35
  add_debug_file_directory(compile_dir)

# Event hook for newly loaded objfiles.
# https://sourceware.org/gdb/onlinedocs/gdb/Events-In-Python.html
gdb.events.new_objfile.connect(newobj_handler)

243
gdb.execute("set environment V8_GDBINIT_SOURCED=1")
244 245

end