123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253 |
- # 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 / V8_Fatal / OS::DebugBreak frame and moves the
- # frame to the one above it so it's immediately at the line of code that
- # triggered the stop condition.
- python
- def v8_stop_handler(event):
- frame = gdb.selected_frame()
- select_frame = None
- message = None
- count = 0
- # Limit stack scanning since the frames we look for are near the top anyway,
- # 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()
- if frame.name() == 'v8::base::OS::DebugBreak':
- 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(v8_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
|