File Explorer

/proc/self/root/proc/thread-self/root/proc/self/task/17/root/node24/share/doc/node

This explorer reads the filesystem of the server it runs on, so /workspace/user isn't present here. Browsing and the terminal still work against this server's own disk from /.

gdbinit15.5 KB · 519 lines
# 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 jobcall (void) _v8_internal_Print_Object((void*)($arg0))enddocument jobPrint a v8 JavaScript objectUsage: job tagged_ptrend # Print content of V8 handles.pythonimport gdb class PrintV8HandleCommand(gdb.Command):  """Print content of a V8 object, accessed through a handle."""   def __init__(self, command_name):    self.command_name = command_name    super(PrintV8HandleCommand, self).__init__(command_name, gdb.COMMAND_DATA)   @staticmethod  def print_direct(value, from_tty):    CMD = "call (void) _v8_internal_Print_Object((v8::internal::Address*)({}))"    gdb.execute(CMD.format(value.format_string()), from_tty)    return True   @staticmethod  def print_indirect(value, from_tty):    CMD = "call (void) _v8_internal_Print_Object(*(v8::internal::Address**)({}))"    gdb.execute(CMD.format(value.format_string()), from_tty)    return True   def invoke(self, arg, from_tty):    argv = gdb.string_to_argv(arg)    if len(argv) != 1:      raise gdb.GdbError("{} takes exactly one argument.".format(          self.command_name))    value = gdb.parse_and_eval(argv[0])    if not self.print_handle(value, from_tty):      raise gdb.GdbError("{} cannot print a value of type {}".format(        self.command_name, value.type))  class PrintV8LocalCommand(PrintV8HandleCommand):  """Print content of v8::(Maybe)?Local."""   def __init__(self):    super(PrintV8LocalCommand, self).__init__("print-v8-local")   def print_handle(self, value, from_tty):    if gdb.types.get_basic_type(value.type).code != gdb.TYPE_CODE_STRUCT:      return False    # After https://crrev.com/c/4335544, v8::MaybeLocal contains a local_.    if gdb.types.has_field(value.type, "local_"):      value = value["local_"]    # After https://crrev.com/c/4335544, v8::Local contains a location_.    if gdb.types.has_field(value.type, "location_"):      return self.print_indirect(value["location_"], from_tty)    # Before https://crrev.com/c/4335544, v8::Local contained a val_.    if gdb.types.has_field(value.type, "val_"):      return self.print_indirect(value["val_"], from_tty)    # With v8_enable_direct_handle=true, v8::Local contains a ptr_.    if gdb.types.has_field(value.type, "ptr_"):      return self.print_direct(value["ptr_"], from_tty)    # We don't know how to print this...    return False class PrintV8InternalHandleCommand(PrintV8HandleCommand):  """Print content of v8::internal::(Maybe)?(Direct|Indirect)?Handle."""   def __init__(self):    super(PrintV8InternalHandleCommand, self).__init__("print-v8-internal-handle")   def print_handle(self, value, from_tty):    if gdb.types.get_basic_type(value.type).code != gdb.TYPE_CODE_STRUCT:      return False    # Indirect handles contain a location_.    if gdb.types.has_field(value.type, "location_"):      return self.print_indirect(value["location_"], from_tty)    # With v8_enable_direct_handle=true, direct handles contain a obj_.    if gdb.types.has_field(value.type, "obj_"):      return self.print_direct(value["obj_"], from_tty)    # Without v8_enable_direct_handle=true, direct handles contain a handle_.    if gdb.types.has_field(value.type, "handle_"):      return self.print_handle(value["handle_"], from_tty)    # We don't know how to print this...    return False PrintV8LocalCommand()PrintV8InternalHandleCommand()end alias jlh = print-v8-localalias jl = print-v8-localalias jh = print-v8-internal-handle # 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))  endenddocument jcoPrint a v8 Code object from an internal code addressUsage: jco pcend # Print JSDispatchEntry object in the JSDispatchTable with the given dispatch handledefine jdh  call (void) _v8_internal_Print_Dispatch_Handle((uint32_t)($arg0))enddocument jdhPrint JSDispatchEntry object in the JSDispatchTable with the given dispatch handleUsage: jdh dispatch_handleend # Print Code objects assembly code surrounding given PC.define jca  if $argc == 0    call (void) _v8_internal_Print_OnlyCode((void*)($pc), 30)  else    if $argc == 1      call (void) _v8_internal_Print_OnlyCode((void*)($arg0), 30)    else      call (void) _v8_internal_Print_OnlyCode((void*)($arg0), (size_t)($arg1))    end  endenddocument jcaPrint a v8 Code object assembly code from an internal code addressUsage: jca pcend # Print TransitionTree.define jttcall (void) _v8_internal_Print_TransitionTree((void*)($arg0), false)enddocument jttPrint the complete transition tree starting at the given v8 map.Usage: jtt tagged_ptrend # Print TransitionTree starting from the root map.define jttrcall (void) _v8_internal_Print_TransitionTree((void*)($arg0), true)enddocument jttrPrint the complete transition tree starting at the root map of the given v8 map.Usage: jttr tagged_ptrend # Print JavaScript stack trace.define jstcall (void) _v8_internal_Print_StackTrace()enddocument jstPrint the current JavaScript stack traceUsage: jstend # Print TurboFan graph node.define pncall _v8_internal_Node_Print((void*)($arg0))enddocument pnPrint a v8 TurboFan graph nodeUsage: pn node_addressend # Skip the JavaScript stack.define jssset $js_entry_sp=v8::internal::Isolate::Current()->thread_local_top()->js_entry_sp_set $rbp=*(void**)$js_entry_spset $rsp=$js_entry_sp + 2*sizeof(void*)set $pc=*(void**)($js_entry_sp+sizeof(void*))enddocument jssSkip the jitted stack on x64 to where we entered JS last.Usage: jssend # Print v8::FunctionCallbackInfo<T>& info.define jfcicall _v8_internal_Print_FunctionCallbackInfo((void*)(&$arg0))enddocument jfciPrint v8::FunctionCallbackInfo<T>& info.Usage: jfci infoend # Print v8::PropertyCallbackInfo<T>& info.define jpcicall _v8_internal_Print_PropertyCallbackInfo((void*)(&$arg0))enddocument jpciPrint v8::PropertyCallbackInfo<T>& info.Usage: jpci infoend # Print whether the object is marked, the mark-bit cell and index. The address# of the cell is handy for reverse debugging to check when the object was# marked/unmarked.define jombcall _v8_internal_Print_Object_MarkBit((void*)($arg0))enddocument jombPrint whether the object is marked, the markbit cell and index.Usage: jomb tagged_ptrend # Execute a simulator command.pythonimport 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_bytes = arg.encode("utf-8") + b'\0'    arg_c_string = gdb.Value(arg_bytes, gdb.lookup_type('char').array(len(arg_bytes) - 1))    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 btapythonimport reframe_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)))endenddocument btaPrint stack trace with assertion scopesUsage: btaend # 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()  endend 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() $arg0enddocument heap_findFind the location of a given address in V8 pages.Usage: heap_find addressend # The 'disassembly-flavor' command is only available on i386 and x84_64.pythontry:  gdb.execute("set disassembly-flavor intel")except gdb.error:  passend # Configuring ASLR may not be possible on some platforms, such running via the# `rr` debugger.pythontry:  gdb.execute("set disable-randomization off")except gdb.error:  passend # 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.pythondef 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 < 10:    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     frame_name = frame.name()    if frame_name is None:      frame = frame.older()      continue    if frame_name == 'V8_Dcheck' or frame_name.endswith('::DefaultDcheckHandler'):      try:        frame_message = gdb.lookup_symbol('message', frame.block())[0]        if frame_message:          message = frame_message.value(frame).string()      except:        pass      select_frame = frame.older()    if any([        frame_name.startswith('V8_Fatal'),        frame_name == 'v8::base::OS::DebugBreak',        frame_name == '__GI_abort',        frame_name == '__GI_raise',        frame_name == 'v8::base::OS::Abort',        frame_name == 'v8::Utils::ApiCheck',      ]):      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/gdbinitpython import osimport subprocessimport 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.htmlgdb.events.new_objfile.connect(newobj_handler) gdb.execute("set environment V8_GDBINIT_SOURCED=1") end ### CppGC helpers. # Pretty printer for cppgc::Member.python import re  class CppGCMemberPrinter(object):  """Print cppgc Member types."""   def __init__(self, val, category, pointee_type):    self.val = val    self.category = category    self.pointee_type = pointee_type   def to_string(self):    pointer = gdb.parse_and_eval(        "_cppgc_internal_Uncompress_Member((void*){})".format(            self.val.address))    return "{}Member<{}> pointing to {}".format(        '' if self.category is None else self.category, self.pointee_type,        pointer)   def display_hint(self):    return "{}Member<{}>".format('' if self.category is None else self.category,                                 self.pointee_type)  def cppgc_pretty_printers(val):  typename = val.type.name or val.type.tag or str(val.type)  regex = re.compile("^(cppgc|blink)::(Weak|Untraced)?Member<(.*)>$")  match = regex.match(typename)  if match is not None:    return CppGCMemberPrinter(        val, category=match.group(2), pointee_type=match.group(3))   # The member type might have been obscured by typedefs and template  # arguments. Fallback to using the underlying type.  real_type = val.type.strip_typedefs()  if (real_type.name is not None and      real_type.name.startswith('cppgc::internal::BasicMember')):    inner_type = real_type.template_argument(0)    return CppGCMemberPrinter(        val, category='Basic', pointee_type=inner_type.name)   return None  gdb.pretty_printers.append(cppgc_pretty_printers)class TaggedPrintCommand(gdb.Command):    """    The equivalent of the print command that deals with tagged objects     Usage: tp <expression>    Example: tp Isolate::Current()->context()->get(3)    """     def __init__(self):        super(TaggedPrintCommand, self).__init__("tp", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION)     def invoke(self, arg, from_tty):        """Called when the 'tp' command is invoked."""        try:            # Split the expression by '->' to handle chained calls.            parts = arg.split("->")            if not parts:                print("Error: No expression provided.")                return             if len(parts) == 1:              gdb.execute(f"print {parts[0]}")            else:              current_val = gdb.parse_and_eval(parts[0])              for part in parts[1:-1]:                  current_val = self._evaluate_part(current_val, part, False)                  if current_val is None:  # Early exit if an evaluation fails.                      return               self._evaluate_part(current_val, parts[-1], True)         except gdb.error as e:            print(f"Error: {e}")     def _evaluate_part(self, current_val, part, last):        """Evaluates a single part of the expression (method call or member access)."""         storage = None        target = f"(({current_val.type}){current_val})"         type = current_val.type        if type.tag and type.tag.startswith("v8::internal::Tagged<"):          storage = gdb.parse_and_eval(f"malloc({type.sizeof})").cast(type.pointer())          command = f"(({storage.type}){storage})->ptr_ = {current_val['ptr_']}"          gdb.parse_and_eval(command)          target = f"(({storage.type}){storage})->ToRawPtr()"         # Check for a method call (ends with parentheses).        command = f"{target}->{part}"        result = None        if last:          gdb.execute(f"print {command}")        else:          result = gdb.parse_and_eval(command)        if storage:          gdb.parse_and_eval(f"free({storage})")        return result TaggedPrintCommand() end