v8/tools/gdbinit
Leszek Swirski 5e9afd645c [tools] Fix gdb frame skip over dummy frames
The gdb DCHECK frame skipping automatically skips over all the abort
etc. frames to get you to that DCHECK callsite you're actually looking
for.

However, this is annoying if you tried to call a function with a
breakpoint from the gdb prompt; the frame skipping wold skip over your
breakpoint back up to the failing DCHECK.

Now, we abort the frame walk on dummy frames inserted by gdb execution.

Change-Id: I2cf89ea9219374ad7c562c6eb13afe471038b033
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3229376
Commit-Queue: Leszek Swirski <leszeks@chromium.org>
Auto-Submit: Leszek Swirski <leszeks@chromium.org>
Reviewed-by: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/main@{#77436}
2021-10-18 14:49:13 +00:00

251 lines
6.8 KiB
Plaintext

# 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.
# Print tagged object.
define job
call (void) _v8_internal_Print_Object((void*)($arg0))
end
document job
Print a v8 JavaScript object
Usage: job tagged_ptr
end
# Print content of v8::internal::Handle.
define jh
call (void) _v8_internal_Print_Object(*((v8::internal::Object**)($arg0).location_))
end
document jh
Print content of a v8::internal::Handle
Usage: jh internal_handle
end
# Print content of v8::Local handle.
define jlh
call (void) _v8_internal_Print_Object(*((v8::internal::Object**)($arg0).val_))
end
document jlh
Print content of a v8::Local handle
Usage: jlh local_handle
end
# Print Code objects containing given PC.
define jco
if $argc == 0
call (void) _v8_internal_Print_Code((void*)($pc))
else
call (void) _v8_internal_Print_Code((void*)($arg0))
end
end
document jco
Print a v8 Code object from an internal code address
Usage: jco pc
end
# Print TransitionTree.
define jtt
call (void) _v8_internal_Print_TransitionTree((void*)($arg0))
end
document jtt
Print the complete transition tree of the given v8 Map.
Usage: jtt tagged_ptr
end
# Print JavaScript stack trace.
define jst
call (void) _v8_internal_Print_StackTrace()
end
document jst
Print the current JavaScript stack trace
Usage: jst
end
# 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
# 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
# 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
# Print stack trace with assertion scopes.
define bta
python
import re
frame_re = re.compile("^#(\d+)\s*(?:0x[a-f\d]+ in )?(.+) \(.+ at (.+)")
assert_re = re.compile("^\s*(\S+) = .+<v8::internal::Per\w+AssertScope<v8::internal::(\S*), (false|true)>")
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
end
document bta
Print stack trace with assertion scopes
Usage: bta
end
# Search for a pointer inside all valid pages.
define space_find
set $space = $arg0
set $current_page = $space->first_page()
while ($current_page != 0)
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
# 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
set disable-randomization off
# 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):
frame = gdb.selected_frame()
select_frame = None
message = None
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 < 7:
count += 1
# If we are in a frame created by gdb (e.g. for `(gdb) call foo()`), gdb
# emits a dummy frame between its stack and the program's stack. Abort the
# walk if we see this frame.
if frame.type() == gdb.DUMMY_FRAME: break
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
if frame.name() is not None and frame.name().startswith('V8_Fatal'):
select_frame = frame.older()
frame = frame.older()
if select_frame is not None:
select_frame.select()
gdb.execute('frame')
if message:
print('DCHECK error: {}'.format(message))
gdb.events.stop.connect(dcheck_stop_handler)
end
# 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)
gdb.execute("set environment V8_GDBINIT_SOURCED=1")
end