gdbinit 6.84 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
call (void) _v8_internal_Print_Code((void*)($arg0))
35 36 37 38 39 40
end
document jco
Print a v8 Code object from an internal code address
Usage: jco pc
end

41 42
# Print LayoutDescriptor.
define jld
43
call (void) _v8_internal_Print_LayoutDescriptor((void*)($arg0))
44 45 46 47 48 49
end
document jld
Print a v8 LayoutDescriptor object
Usage: jld tagged_ptr
end

50 51
# Print TransitionTree.
define jtt
52
call (void) _v8_internal_Print_TransitionTree((void*)($arg0))
53 54 55 56 57 58
end
document jtt
Print the complete transition tree of the given v8 Map.
Usage: jtt tagged_ptr
end

59
# Print JavaScript stack trace.
60
define jst
61
call (void) _v8_internal_Print_StackTrace()
62 63 64 65 66 67
end
document jst
Print the current JavaScript stack trace
Usage: jst
end

68 69 70 71 72 73 74 75 76 77 78 79
# 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

80 81 82 83
# Print stack trace with assertion scopes.
define bta
python
import re
84
frame_re = re.compile("^#(\d+)\s*(?:0x[a-f\d]+ in )?(.+) \(.+ at (.+)")
85
assert_re = re.compile("^\s*(\S+) = .+<v8::internal::Per\w+AssertScope<v8::internal::(\S*), (false|true)>")
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
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
101
end
102 103 104 105 106
document bta
Print stack trace with assertion scopes
Usage: bta
end

107 108 109
# Search for a pointer inside all valid pages.
define space_find
  set $space = $arg0
Yang Guo's avatar
Yang Guo committed
110 111
  set $current_page = $space->first_page()
  while ($current_page != 0)
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
    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

132
set disassembly-flavor intel
133
set disable-randomization off
134 135 136 137 138 139

# 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):
140
  frame = gdb.selected_frame()
141
  select_frame = None
142
  message = None
143 144 145 146 147
  count = 0
  # limit stack scanning since they're usually shallow and otherwise stack
  # overflows can be very slow.
  while frame is not None and count < 5:
    count += 1
148 149 150 151 152 153
    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
154
    if frame.name() is not None and frame.name().startswith('V8_Fatal'):
155 156 157
      select_frame = frame.older()
    frame = frame.older()

158 159 160
  if select_frame is not None:
    select_frame.select()
    gdb.execute('frame')
161 162
    if message:
      print('DCHECK error: {}'.format(message))
163

164 165
gdb.events.stop.connect(dcheck_stop_handler)
end
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 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 243 244 245 246 247 248 249 250

# 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 load_libcxx_pretty_printers(src_dir):
  libcxx_pretty_printers = os.path.join(src_dir, 'third_party',
                                        'libcxx-pretty-printers')
  if not os.path.isdir(libcxx_pretty_printers):
    return
  sys.path.insert(1, libcxx_pretty_printers)
  from printers import register_libcxx_printers
  register_libcxx_printers(None)


def load_gdb_chrome(src_dir):
  tools_gdb = os.path.join(src_dir, 'tools', 'gdb')

  sys.path.insert(1, tools_gdb)
  import gdb_chrome

  gdb.execute('source %s' % os.path.join(tools_gdb, 'viewg.gdb'))


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)

  git = subprocess.Popen(
      ['git', '-C', compile_dir, 'rev-parse', '--show-toplevel'],
      stdout=subprocess.PIPE,
      stderr=subprocess.PIPE)
  src_dir, _ = git.communicate()
  if git.returncode:
    return
  src_dir = str(src_dir).rstrip()

  load_libcxx_pretty_printers(src_dir)

  load_gdb_chrome(src_dir)


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

gdb.execute("set environment CHROMIUM_GDBINIT_SOURCED=1")

end