diff --git a/gdb/auxv.c b/gdb/auxv.c
index ce7a63b894..86a1ba88a6 100644
--- a/gdb/auxv.c
+++ b/gdb/auxv.c
@@ -283,16 +283,15 @@ default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
    Return -1 if there is insufficient buffer for a whole entry.
    Return 1 if an entry was read into *TYPEP and *VALP.  */
 int
-target_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
-                  gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+target_auxv_parse (gdb_byte **readptr,
+		   gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
 {
   struct gdbarch *gdbarch = target_gdbarch();
 
   if (gdbarch_auxv_parse_p (gdbarch))
     return gdbarch_auxv_parse (gdbarch, readptr, endptr, typep, valp);
 
-  return current_target.to_auxv_parse (&current_target, readptr, endptr,
-				       typep, valp);
+  return target_stack->auxv_parse (readptr, endptr, typep, valp);
 }
 
 
@@ -382,7 +381,7 @@ target_auxv_search (struct target_ops *ops, CORE_ADDR match, CORE_ADDR *valp)
   size_t len = info->data->size ();
 
   while (1)
-    switch (target_auxv_parse (ops, &ptr, data + len, &type, &val))
+    switch (target_auxv_parse (&ptr, data + len, &type, &val))
       {
       case 1:			/* Here's an entry, check it.  */
 	if (type == match)
@@ -532,7 +531,7 @@ fprint_target_auxv (struct ui_file *file, struct target_ops *ops)
   gdb_byte *ptr = data;
   size_t len = info->data->size ();
 
-  while (target_auxv_parse (ops, &ptr, data + len, &type, &val) > 0)
+  while (target_auxv_parse (&ptr, data + len, &type, &val) > 0)
     {
       gdbarch_print_auxv_entry (gdbarch, file, type, val);
       ++ents;
@@ -550,7 +549,7 @@ info_auxv_command (const char *cmd, int from_tty)
     error (_("The program has no auxiliary information now."));
   else
     {
-      int ents = fprint_target_auxv (gdb_stdout, &current_target);
+      int ents = fprint_target_auxv (gdb_stdout, target_stack);
 
       if (ents < 0)
 	error (_("No auxiliary vector found, or failed reading it."));
diff --git a/gdb/auxv.h b/gdb/auxv.h
index 4a1a95e692..29c75fbfe8 100644
--- a/gdb/auxv.h
+++ b/gdb/auxv.h
@@ -35,8 +35,7 @@ extern int default_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
    Return 0 if *READPTR is already at the end of the buffer.
    Return -1 if there is insufficient buffer for a whole entry.
    Return 1 if an entry was read into *TYPEP and *VALP.  */
-extern int target_auxv_parse (struct target_ops *ops,
-			      gdb_byte **readptr, gdb_byte *endptr,
+extern int target_auxv_parse (gdb_byte **readptr, gdb_byte *endptr,
 			      CORE_ADDR *typep, CORE_ADDR *valp);
 
 /* Extract the auxiliary vector entry with a_type matching MATCH.
diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c
index 2b9be5e313..5aa61ba2d9 100644
--- a/gdb/avr-tdep.c
+++ b/gdb/avr-tdep.c
@@ -1555,7 +1555,7 @@ avr_io_reg_read_command (const char *args, int from_tty)
 
   /* Find out how many io registers the target has.  */
   gdb::optional<gdb::byte_vector> buf
-    = target_read_alloc (&current_target, TARGET_OBJECT_AVR, "avr.io_reg");
+    = target_read_alloc (target_stack, TARGET_OBJECT_AVR, "avr.io_reg");
 
   if (!buf)
     {
@@ -1589,7 +1589,7 @@ avr_io_reg_read_command (const char *args, int from_tty)
         j = nreg - i;           /* last block is less than 8 registers */
 
       snprintf (query, sizeof (query) - 1, "avr.io_reg:%x,%x", i, j);
-      buf = target_read_alloc (&current_target, TARGET_OBJECT_AVR, query);
+      buf = target_read_alloc (target_stack, TARGET_OBJECT_AVR, query);
 
       if (!buf)
         {
diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
index 11b89bcf88..a5287128d0 100644
--- a/gdb/breakpoint.c
+++ b/gdb/breakpoint.c
@@ -3493,8 +3493,7 @@ create_exception_master_breakpoint (void)
 	}
 
       addr = BMSYMBOL_VALUE_ADDRESS (bp_objfile_data->exception_msym);
-      addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
-						 &current_target);
+      addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, target_stack);
       b = create_internal_breakpoint (gdbarch, addr, bp_exception_master,
 				      &internal_breakpoint_ops);
       initialize_explicit_location (&explicit_loc);
@@ -4753,7 +4752,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
       return 0;
     }
 
-  if (!target_stopped_data_address (&current_target, &addr))
+  if (!target_stopped_data_address (target_stack, &addr))
     {
       /* We were stopped by a watchpoint, but we don't know where.
 	 Mark all watchpoints as unknown.  */
@@ -4793,7 +4792,7 @@ watchpoints_triggered (struct target_waitstatus *ws)
 		  }
 	      }
 	    /* Exact match not required.  Within range is sufficient.  */
-	    else if (target_watchpoint_addr_within_range (&current_target,
+	    else if (target_watchpoint_addr_within_range (target_stack,
 							 addr, loc->address,
 							 loc->length))
 	      {
diff --git a/gdb/elfread.c b/gdb/elfread.c
index 260789062d..48404e111c 100644
--- a/gdb/elfread.c
+++ b/gdb/elfread.c
@@ -806,8 +806,7 @@ elf_gnu_ifunc_resolve_by_got (const char *name, CORE_ADDR *addr_p)
       if (target_read_memory (pointer_address, buf, ptr_size) != 0)
 	continue;
       addr = extract_typed_address (buf, ptr_type);
-      addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
-						 &current_target);
+      addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, target_stack);
       addr = gdbarch_addr_bits_remove (gdbarch, addr);
 
       if (addr_p)
@@ -872,13 +871,12 @@ elf_gnu_ifunc_resolve_addr (struct gdbarch *gdbarch, CORE_ADDR pc)
      parameter.  FUNCTION is the function entry address.  ADDRESS may be a
      function descriptor.  */
 
-  target_auxv_search (&current_target, AT_HWCAP, &hwcap);
+  target_auxv_search (target_stack, AT_HWCAP, &hwcap);
   hwcap_val = value_from_longest (builtin_type (gdbarch)
 				  ->builtin_unsigned_long, hwcap);
   address_val = call_function_by_hand (function, NULL, 1, &hwcap_val);
   address = value_as_address (address_val);
-  address = gdbarch_convert_from_func_ptr_addr (gdbarch, address,
-						&current_target);
+  address = gdbarch_convert_from_func_ptr_addr (gdbarch, address, target_stack);
   address = gdbarch_addr_bits_remove (gdbarch, address);
 
   if (name_at_pc)
@@ -985,7 +983,7 @@ elf_gnu_ifunc_resolver_return_stop (struct breakpoint *b)
   resolved_address = value_as_address (value);
   resolved_pc = gdbarch_convert_from_func_ptr_addr (gdbarch,
 						    resolved_address,
-						    &current_target);
+						    target_stack);
   resolved_pc = gdbarch_addr_bits_remove (gdbarch, resolved_pc);
 
   gdb_assert (current_program_space == b->pspace || b->pspace == NULL);
diff --git a/gdb/eval.c b/gdb/eval.c
index b6fbfcf6c9..26dc58d761 100644
--- a/gdb/eval.c
+++ b/gdb/eval.c
@@ -1742,7 +1742,7 @@ evaluate_subexp_standard (struct type *expect_type,
 	    /* The address might point to a function descriptor;
 	       resolve it to the actual code address instead.  */
 	    addr = gdbarch_convert_from_func_ptr_addr (exp->gdbarch, addr,
-						       &current_target);
+						       target_stack);
 
 	    /* Is it a high_level symbol?  */
 	    sym = find_pc_function (addr);
diff --git a/gdb/exceptions.c b/gdb/exceptions.c
index 49af8a2985..5abbaf2137 100644
--- a/gdb/exceptions.c
+++ b/gdb/exceptions.c
@@ -39,7 +39,11 @@ print_flush (void)
     deprecated_error_begin_hook ();
 
   gdb::optional<target_terminal::scoped_restore_terminal_state> term_state;
-  if (target_supports_terminal_ours ())
+  /* While normally there's always something pushed on the target
+     stack, the NULL check is needed here because we can get here very
+     early during startup, before the target stack is first
+     initialized.  */
+  if (target_stack != NULL && target_supports_terminal_ours ())
     {
       term_state.emplace ();
       target_terminal::ours_for_output ();
diff --git a/gdb/frame.c b/gdb/frame.c
index 90d0ac7b87..07fa2bc77d 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2217,7 +2217,7 @@ inside_main_func (struct frame_info *this_frame)
      returned.  */
   maddr = gdbarch_convert_from_func_ptr_addr (get_frame_arch (this_frame),
 					      BMSYMBOL_VALUE_ADDRESS (msymbol),
-					      &current_target);
+					      target_stack);
   return maddr == get_frame_func (this_frame);
 }
 
diff --git a/gdb/gdbarch-selftests.c b/gdb/gdbarch-selftests.c
index 1655f13b0e..23afe3d75e 100644
--- a/gdb/gdbarch-selftests.c
+++ b/gdb/gdbarch-selftests.c
@@ -71,8 +71,8 @@ register_to_value_test (struct gdbarch *gdbarch)
 
   /* Error out if debugging something, because we're going to push the
      test target, which would pop any existing target.  */
-  if (current_target.to_stratum >= process_stratum)
-    error (_("target already pushed"));
+  if (target_stack->to_stratum >= process_stratum)
+   error (_("target already pushed"));
 
   /* Create a mock environment.  An inferior with a thread, with a
      process_stratum target pushed.  */
diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c
index 859187f2e9..ddbec13891 100644
--- a/gdb/gnu-v3-abi.c
+++ b/gdb/gnu-v3-abi.c
@@ -1217,7 +1217,7 @@ gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc)
      of the real function from the function descriptor before passing on
      the address to other layers of GDB.  */
   func_addr = gdbarch_convert_from_func_ptr_addr (gdbarch, method_stop_pc,
-                                                  &current_target);
+						  target_stack);
   if (func_addr != 0)
     method_stop_pc = func_addr;
 
diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c
index 4f02f05375..26e112e7bc 100644
--- a/gdb/ia64-tdep.c
+++ b/gdb/ia64-tdep.c
@@ -2660,7 +2660,7 @@ getunwind_table (gdb_byte **buf_p)
      we should find a way to override the corefile layer's
      xfer_partial method.  */
 
-  x = target_read_alloc (&current_target, TARGET_OBJECT_UNWIND_TABLE,
+  x = target_read_alloc (target_stack, TARGET_OBJECT_UNWIND_TABLE,
 			 NULL, buf_p);
 
   return x;
diff --git a/gdb/ia64-vms-tdep.c b/gdb/ia64-vms-tdep.c
index c9565ce298..9b78576608 100644
--- a/gdb/ia64-vms-tdep.c
+++ b/gdb/ia64-vms-tdep.c
@@ -42,7 +42,7 @@ ia64_vms_find_proc_info_x (unw_addr_space_t as, unw_word_t ip,
   CORE_ADDR table_addr;
   unsigned int info_len;
 
-  res = target_read (&current_target, TARGET_OBJECT_OPENVMS_UIB,
+  res = target_read (target_stack, TARGET_OBJECT_OPENVMS_UIB,
                      annex + 2, buf, 0, sizeof (buf));
 
   if (res != sizeof (buf))
diff --git a/gdb/infcall.c b/gdb/infcall.c
index 9f02674bdf..d5a60eb55c 100644
--- a/gdb/infcall.c
+++ b/gdb/infcall.c
@@ -270,7 +270,7 @@ find_function_addr (struct value *function, struct type **retval_type)
       if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
 	  || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
 	funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
-						      &current_target);
+						      target_stack);
     }
   if (TYPE_CODE (ftype) == TYPE_CODE_FUNC
       || TYPE_CODE (ftype) == TYPE_CODE_METHOD)
@@ -306,7 +306,7 @@ find_function_addr (struct value *function, struct type **retval_type)
 	      funaddr = value_as_address (value_addr (function));
 	      nfunaddr = funaddr;
 	      funaddr = gdbarch_convert_from_func_ptr_addr (gdbarch, funaddr,
-							    &current_target);
+							    target_stack);
 	      if (funaddr != nfunaddr)
 		found_descriptor = 1;
 	    }
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index d43e7f202d..1a84ea817a 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -531,7 +531,7 @@ prepare_execution_command (struct target_ops *target, int background)
 {
   /* If we get a request for running in the bg but the target
      doesn't support it, error out.  */
-  if (background && !target->to_can_async_p (target))
+  if (background && !target->can_async_p ())
     error (_("Asynchronous execution not supported on this target."));
 
   if (!background)
@@ -600,7 +600,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
 
   prepare_execution_command (run_target, async_exec);
 
-  if (non_stop && !run_target->to_supports_non_stop (run_target))
+  if (non_stop && !run_target->supports_non_stop ())
     error (_("The target does not support running in non-stop mode."));
 
   /* Done.  Can now set breakpoints, change inferior args, etc.  */
@@ -639,10 +639,10 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
 
   /* We call get_inferior_args() because we might need to compute
      the value now.  */
-  run_target->to_create_inferior (run_target, exec_file,
-				  std::string (get_inferior_args ()),
-				  current_inferior ()->environment.envp (),
-				  from_tty);
+  run_target->create_inferior (exec_file,
+			       std::string (get_inferior_args ()),
+			       current_inferior ()->environment.envp (),
+			       from_tty);
   /* to_create_inferior should push the target, so after this point we
      shouldn't refer to run_target again.  */
   run_target = NULL;
@@ -660,7 +660,7 @@ run_command_1 (const char *args, int from_tty, enum run_how run_how)
 
   /* Pass zero for FROM_TTY, because at this point the "run" command
      has done its thing; now we are setting up the running program.  */
-  post_create_inferior (&current_target, 0);
+  post_create_inferior (target_stack, 0);
 
   /* Queue a pending event so that the program stops immediately.  */
   if (run_how == RUN_STOP_AT_FIRST_INSN)
@@ -896,7 +896,7 @@ continue_command (const char *args, int from_tty)
       ensure_not_running ();
     }
 
-  prepare_execution_command (&current_target, async_exec);
+  prepare_execution_command (target_stack, async_exec);
 
   if (from_tty)
     printf_filtered (_("Continuing.\n"));
@@ -1043,7 +1043,7 @@ step_1 (int skip_subroutines, int single_inst, const char *count_string)
     = strip_bg_char (count_string, &async_exec);
   count_string = stripped.get ();
 
-  prepare_execution_command (&current_target, async_exec);
+  prepare_execution_command (target_stack, async_exec);
 
   count = count_string ? parse_and_eval_long (count_string) : 1;
 
@@ -1232,7 +1232,7 @@ jump_command (const char *arg, int from_tty)
   gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
   arg = stripped.get ();
 
-  prepare_execution_command (&current_target, async_exec);
+  prepare_execution_command (target_stack, async_exec);
 
   if (!arg)
     error_no_arg (_("starting address"));
@@ -1312,7 +1312,7 @@ signal_command (const char *signum_exp, int from_tty)
     = strip_bg_char (signum_exp, &async_exec);
   signum_exp = stripped.get ();
 
-  prepare_execution_command (&current_target, async_exec);
+  prepare_execution_command (target_stack, async_exec);
 
   if (!signum_exp)
     error_no_arg (_("signal number"));
@@ -1585,7 +1585,7 @@ until_command (const char *arg, int from_tty)
   gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
   arg = stripped.get ();
 
-  prepare_execution_command (&current_target, async_exec);
+  prepare_execution_command (target_stack, async_exec);
 
   if (arg)
     until_break_command (arg, from_tty, 0);
@@ -1610,7 +1610,7 @@ advance_command (const char *arg, int from_tty)
   gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
   arg = stripped.get ();
 
-  prepare_execution_command (&current_target, async_exec);
+  prepare_execution_command (target_stack, async_exec);
 
   until_break_command (arg, from_tty, 1);
 }
@@ -1990,7 +1990,7 @@ finish_command (const char *arg, int from_tty)
   gdb::unique_xmalloc_ptr<char> stripped = strip_bg_char (arg, &async_exec);
   arg = stripped.get ();
 
-  prepare_execution_command (&current_target, async_exec);
+  prepare_execution_command (target_stack, async_exec);
 
   if (arg)
     error (_("The \"finish\" command does not take any arguments."));
@@ -2675,7 +2675,7 @@ setup_inferior (int from_tty)
   /* Take any necessary post-attaching actions for this platform.  */
   target_post_attach (ptid_get_pid (inferior_ptid));
 
-  post_create_inferior (&current_target, from_tty);
+  post_create_inferior (target_stack, from_tty);
 }
 
 /* What to do after the first program stops after attaching.  */
@@ -2838,10 +2838,10 @@ attach_command (const char *args, int from_tty)
 
   prepare_execution_command (attach_target, async_exec);
 
-  if (non_stop && !attach_target->to_supports_non_stop (attach_target))
+  if (non_stop && !attach_target->supports_non_stop ())
     error (_("Cannot attach to this target in non-stop mode"));
 
-  attach_target->to_attach (attach_target, args, from_tty);
+  attach_target->attach (args, from_tty);
   /* to_attach should push the target, so after this point we
      shouldn't refer to attach_target again.  */
   attach_target = NULL;
@@ -2892,7 +2892,7 @@ attach_command (const char *args, int from_tty)
 
   /* Some system don't generate traps when attaching to inferior.
      E.g. Mach 3 or GNU hurd.  */
-  if (!target_attach_no_wait)
+  if (!target_attach_no_wait ())
     {
       struct attach_command_continuation_args *a;
 
diff --git a/gdb/infrun.c b/gdb/infrun.c
index c1db689c1c..c51626d7df 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -3236,7 +3236,7 @@ start_remote (int from_tty)
   /* Now that the inferior has stopped, do any bookkeeping like
      loading shared libraries.  We want to do this before normal_stop,
      so that the displayed frame is up to date.  */
-  post_create_inferior (&current_target, from_tty);
+  post_create_inferior (target_stack, from_tty);
 
   normal_stop ();
 }
@@ -5693,7 +5693,7 @@ handle_signal_stop (struct execution_control_state *ecs)
 
 	  fprintf_unfiltered (gdb_stdlog, "infrun: stopped by watchpoint\n");
 
-          if (target_stopped_data_address (&current_target, &addr))
+	  if (target_stopped_data_address (target_stack, &addr))
             fprintf_unfiltered (gdb_stdlog,
                                 "infrun: stopped data address = %s\n",
                                 paddress (gdbarch, addr));
@@ -8727,7 +8727,7 @@ siginfo_value_read (struct value *v)
   validate_registers_access ();
 
   transferred =
-    target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO,
+    target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO,
 		 NULL,
 		 value_contents_all_raw (v),
 		 value_offset (v),
@@ -8749,7 +8749,7 @@ siginfo_value_write (struct value *v, struct value *fromval)
      vice versa.  */
   validate_registers_access ();
 
-  transferred = target_write (&current_target,
+  transferred = target_write (target_stack,
 			      TARGET_OBJECT_SIGNAL_INFO,
 			      NULL,
 			      value_contents_all_raw (fromval),
@@ -8828,7 +8828,7 @@ save_infcall_suspend_state (void)
       siginfo_data = (gdb_byte *) xmalloc (len);
       back_to = make_cleanup (xfree, siginfo_data);
 
-      if (target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+      if (target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
 		       siginfo_data, 0, len) == len)
 	discard_cleanups (back_to);
       else
@@ -8878,7 +8878,7 @@ restore_infcall_suspend_state (struct infcall_suspend_state *inf_state)
       struct type *type = gdbarch_get_siginfo_type (gdbarch);
 
       /* Errors ignored.  */
-      target_write (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+      target_write (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
 		    inf_state->siginfo_data, 0, TYPE_LENGTH (type));
     }
 
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index 552a2a495b..145d05d923 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -402,8 +402,8 @@ linux_is_uclinux (void)
 {
   CORE_ADDR dummy;
 
-  return (target_auxv_search (&current_target, AT_NULL, &dummy) > 0
-	  && target_auxv_search (&current_target, AT_PAGESZ, &dummy) == 0);
+  return (target_auxv_search (target_stack, AT_NULL, &dummy) > 0
+	  && target_auxv_search (target_stack, AT_PAGESZ, &dummy) == 0);
 }
 
 static int
@@ -1423,7 +1423,7 @@ linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
 
   /* Determine list of SPU ids.  */
   gdb::optional<gdb::byte_vector>
-    spu_ids = target_read_alloc (&current_target, TARGET_OBJECT_SPU, NULL);
+    spu_ids = target_read_alloc (target_stack, TARGET_OBJECT_SPU, NULL);
 
   if (!spu_ids)
     return nullptr;
@@ -1439,7 +1439,7 @@ linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
 
 	  xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[j]);
 	  gdb::optional<gdb::byte_vector> spu_data
-	    = target_read_alloc (&current_target, TARGET_OBJECT_SPU, annex);
+	    = target_read_alloc (target_stack, TARGET_OBJECT_SPU, annex);
 
 	  if (spu_data && !spu_data->empty ())
 	    {
@@ -1661,7 +1661,7 @@ linux_get_siginfo_data (thread_info *thread, struct gdbarch *gdbarch)
 
   gdb::byte_vector buf (TYPE_LENGTH (siginfo_type));
 
-  bytes_read = target_read (&current_target, TARGET_OBJECT_SIGNAL_INFO, NULL,
+  bytes_read = target_read (target_stack, TARGET_OBJECT_SIGNAL_INFO, NULL,
 			    buf.data (), 0, TYPE_LENGTH (siginfo_type));
   if (bytes_read != TYPE_LENGTH (siginfo_type))
     buf.clear ();
@@ -1970,7 +1970,7 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size)
 
   /* Auxillary vector.  */
   gdb::optional<gdb::byte_vector> auxv =
-    target_read_alloc (&current_target, TARGET_OBJECT_AUXV, NULL);
+    target_read_alloc (target_stack, TARGET_OBJECT_AUXV, NULL);
   if (auxv && !auxv->empty ())
     {
       note_data = elfcore_write_note (obfd, note_data, note_size,
@@ -2253,7 +2253,7 @@ linux_vsyscall_range_raw (struct gdbarch *gdbarch, struct mem_range *range)
   char filename[100];
   long pid;
 
-  if (target_auxv_search (&current_target, AT_SYSINFO_EHDR, &range->start) <= 0)
+  if (target_auxv_search (target_stack, AT_SYSINFO_EHDR, &range->start) <= 0)
     return 0;
 
   /* It doesn't make sense to access the host's /proc when debugging a
@@ -2443,14 +2443,14 @@ linux_displaced_step_location (struct gdbarch *gdbarch)
      local-store address and is thus not usable as displaced stepping
      location.  The auxiliary vector gets us the PowerPC-side entry
      point address instead.  */
-  if (target_auxv_search (&current_target, AT_ENTRY, &addr) <= 0)
+  if (target_auxv_search (target_stack, AT_ENTRY, &addr) <= 0)
     throw_error (NOT_SUPPORTED_ERROR,
 		 _("Cannot find AT_ENTRY auxiliary vector entry."));
 
   /* Make certain that the address points at real code, and not a
      function descriptor.  */
   addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
-					     &current_target);
+					     target_stack);
 
   /* Inferior calls also use the entry point as a breakpoint location.
      We don't want displaced stepping to interfere with those
diff --git a/gdb/make-target-delegates b/gdb/make-target-delegates
index bf91ddc17c..10853e3e20 100755
--- a/gdb/make-target-delegates
+++ b/gdb/make-target-delegates
@@ -30,16 +30,27 @@ $ENDER = qr,^\s*};$,;
 # Match a C symbol.
 $SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_]*,;
 # Match the name part of a method in struct target_ops.
-$NAME_PART = qr,\(\*(?<name>${SYMBOL}+)\)\s,;
+$NAME_PART = qr,(?<name>${SYMBOL}+)\s,;
 # Match the arguments to a method.
 $ARGS_PART = qr,(?<args>\(.*\)),;
 # We strip the indentation so here we only need the caret.
 $INTRO_PART = qr,^,;
 
+$POINTER_PART = qr,\s*(\*)?\s*,;
+
+# Match a C++ symbol, including scope operators and template
+# parameters.  E.g., 'std::vector<something>'.
+$CP_SYMBOL = qr,[a-zA-Z_][a-zA-Z0-9_<>:]*,;
 # Match the return type when it is "ordinary".
-$SIMPLE_RETURN_PART = qr,[^\(]+,;
+$SIMPLE_RETURN_PART = qr,((struct|class|enum|union)\s+)?${CP_SYMBOL}+,;
 # Match the return type when it is a VEC.
-$VEC_RETURN_PART = qr,VEC\s*\([^\)]+\)[^\(]*,;
+$VEC_RETURN_PART = qr,VEC\s*\([^\)]+\),;
+
+# Match a return type.
+$RETURN_PART = qr,((const|volatile)\s+)?(${SIMPLE_RETURN_PART}|${VEC_RETURN_PART})${POINTER_PART},;
+
+# Match "virtual".
+$VIRTUAL_PART = qr,virtual\s,;
 
 # Match the TARGET_DEFAULT_* attribute for a method.
 $TARGET_DEFAULT_PART = qr,TARGET_DEFAULT_(?<style>[A-Z_]+)\s*\((?<default_arg>.*)\),;
@@ -49,8 +60,7 @@ $TARGET_DEFAULT_PART = qr,TARGET_DEFAULT_(?<style>[A-Z_]+)\s*\((?<default_arg>.*
 $METHOD_TRAILER = qr,\s*${TARGET_DEFAULT_PART}$,;
 
 # Match an entire method definition.
-$METHOD = ($INTRO_PART . "(?<return_type>" . $SIMPLE_RETURN_PART
-	   . "|" . $VEC_RETURN_PART . ")"
+$METHOD = ($INTRO_PART . $VIRTUAL_PART . "(?<return_type>" . $RETURN_PART . ")"
 	   . $NAME_PART . $ARGS_PART
 	   . $METHOD_TRAILER);
 
@@ -90,7 +100,7 @@ sub scan_target_h() {
 	next if /{/;
 	last if m/$ENDER/;
 
-	# Just in case somebody ever uses C99.
+	# Strip // comments.
 	$_ =~ s,//.*$,,;
 	$_ = trim ($_);
 
@@ -130,16 +140,24 @@ sub parse_argtypes($) {
 
 sub dname($) {
     my ($name) = @_;
-    $name =~ s/to_/delegate_/;
-    return $name;
+    return "target_ops::" . $name;
 }
 
 # Write function header given name, return type, and argtypes.
 # Returns a list of actual argument names.
-sub write_function_header($$@) {
-    my ($name, $return_type, @argtypes) = @_;
+sub write_function_header($$$@) {
+    my ($decl, $name, $return_type, @argtypes) = @_;
+
+    print $return_type;
+
+    if ($decl) {
+	if ($return_type !~ m,\*$,) {
+	    print " ";
+	}
+    } else {
+	print "\n";
+    }
 
-    print "static " . $return_type . "\n";
     print $name . ' (';
 
     my $iter;
@@ -156,12 +174,7 @@ sub write_function_header($$@) {
 	}
 
 	my $vname;
-	if ($i == 0) {
-	    # Just a random nicety.
-	    $vname = 'self';
-	} else {
-	    $vname .= "arg$i";
-	}
+	$vname .= "arg$i";
 	$val .= $vname;
 
 	push @argdecls, $val;
@@ -169,25 +182,36 @@ sub write_function_header($$@) {
 	++$i;
     }
 
-    print join (', ', @argdecls) . ")\n";
-    print "{\n";
+    print join (', ', @argdecls) . ")";
+
+    if ($decl) {
+	print " override;\n";
+    } else {
+	print "\n{\n";
+    }
 
     return @actuals;
 }
 
+# Write out a declaration.
+sub write_declaration($$@) {
+    my ($name, $return_type, @argtypes) = @_;
+
+    write_function_header (1, $name, $return_type, @argtypes);
+}
+
 # Write out a delegation function.
 sub write_delegator($$@) {
     my ($name, $return_type, @argtypes) = @_;
 
-    my (@names) = write_function_header (dname ($name), $return_type,
-					 @argtypes);
+    my (@names) = write_function_header (0, dname ($name),
+					 $return_type, @argtypes);
 
-    print "  $names[0] = $names[0]->beneath;\n";
     print "  ";
     if ($return_type ne 'void') {
 	print "return ";
     }
-    print "$names[0]->" . $name . " (";
+    print "this->beneath->" . $name . " (";
     print join (', ', @names);
     print ");\n";
     print "}\n\n";
@@ -195,21 +219,28 @@ sub write_delegator($$@) {
 
 sub tdname ($) {
     my ($name) = @_;
-    $name =~ s/to_/tdefault_/;
-    return $name;
+    return "dummy_target::" . $name;
 }
 
 # Write out a default function.
 sub write_tdefault($$$$@) {
     my ($content, $style, $name, $return_type, @argtypes) = @_;
 
-    if ($style eq 'FUNC') {
-	return $content;
-    }
+    my (@names) = write_function_header (0, tdname ($name),
+					 $return_type, @argtypes);
 
-    write_function_header (tdname ($name), $return_type, @argtypes);
-
-    if ($style eq 'RETURN') {
+    if ($style eq 'FUNC') {
+	print "  ";
+	if ($return_type ne 'void') {
+	    print "return ";
+	}
+	print $content . " (this";
+	if (@names) {
+	    print ", ";
+	}
+	print join (', ', @names);
+	print ");\n";
+    } elsif ($style eq 'RETURN') {
 	print "  return $content;\n";
     } elsif ($style eq 'NORETURN') {
 	print "  $content;\n";
@@ -252,39 +283,37 @@ sub munge_type($) {
 }
 
 # Write out a debug method.
-sub write_debugmethod($$$$@) {
-    my ($content, $style, $name, $return_type, @argtypes) = @_;
+sub write_debugmethod($$$@) {
+    my ($content, $name, $return_type, @argtypes) = @_;
 
-    my ($debugname) = $name;
-    $debugname =~ s/to_/debug_/;
+    my ($debugname) = "debug_target::" . $name;
     my ($targetname) = $name;
-    $targetname =~ s/to_/target_/;
 
-    my (@names) = write_function_header ($debugname, $return_type, @argtypes);
+    my (@names) = write_function_header (0, $debugname, $return_type, @argtypes);
 
     if ($return_type ne 'void') {
 	print "  $return_type result;\n";
     }
 
-    print "  fprintf_unfiltered (gdb_stdlog, \"-> %s->$name (...)\\n\", debug_target.to_shortname);\n";
+    print "  fprintf_unfiltered (gdb_stdlog, \"-> %s->$name (...)\\n\", this->beneath->shortname ());\n";
 
     # Delegate to the beneath target.
     print "  ";
     if ($return_type ne 'void') {
 	print "result = ";
     }
-    print "debug_target." . $name . " (";
-    my @names2 = @names;
-    @names2[0] = "&debug_target";
-    print join (', ', @names2);
+    print "this->beneath->" . $name . " (";
+    print join (', ', @names);
     print ");\n";
 
     # Now print the arguments.
-    print "  fprintf_unfiltered (gdb_stdlog, \"<- %s->$name (\", debug_target.to_shortname);\n";
+    print "  fprintf_unfiltered (gdb_stdlog, \"<- %s->$name (\", this->beneath->shortname ());\n";
     for my $i (0 .. $#argtypes) {
-	print "  fputs_unfiltered (\", \", gdb_stdlog);\n" if $i > 0;
+	if ($i > 0) {
+	    print "  fputs_unfiltered (\", \", gdb_stdlog);\n"
+	}
 	my $printer = munge_type ($argtypes[$i]);
-	print "  $printer ($names2[$i]);\n";
+	print "  $printer ($names[$i]);\n";
     }
     if ($return_type ne 'void') {
 	print "  fputs_unfiltered (\") = \", gdb_stdlog);\n";
@@ -308,61 +337,71 @@ print "/* THIS FILE IS GENERATED -*- buffer-read-only: t -*- */\n";
 print "/* vi:set ro: */\n\n";
 print "/* To regenerate this file, run:*/\n";
 print "/*      make-target-delegates target.h > target-delegates.c */\n";
+print "\n";
 
 @lines = scan_target_h();
 
-
-%tdefault_names = ();
-%debug_names = ();
 @delegators = ();
+@return_types = ();
+@tdefaults = ();
+@styles = ();
+@argtypes_array = ();
+
 foreach $current_line (@lines) {
     next unless $current_line =~ m/$METHOD/;
 
-    $name = $+{name};
-    $current_line = $+{args};
-    $return_type = trim ($+{return_type});
-    $current_args = $+{args};
-    $tdefault = $+{default_arg};
-    $style = $+{style};
+    my $name = $+{name};
+    my $current_line = $+{args};
+    my $return_type = trim ($+{return_type});
+    my $current_args = $+{args};
+    my $tdefault = $+{default_arg};
+    my $style = $+{style};
 
-    @argtypes = parse_argtypes ($current_args);
+    my @argtypes = parse_argtypes ($current_args);
 
-    # The first argument must be "this" to be delegatable.
-    if ($argtypes[0] =~ /\s*struct\s+target_ops\s*\*\s*/) {
-	write_delegator ($name, $return_type, @argtypes);
+    push @delegators, $name;
 
-	push @delegators, $name;
+    $return_types{$name} = $return_type;
+    $tdefaults{$name} = $tdefault;
+    $styles{$name} = $style;
+    $argtypes_array{$name} = \@argtypes;
+}
 
-	$tdefault_names{$name} = write_tdefault ($tdefault, $style,
-						 $name, $return_type,
-						 @argtypes);
+sub print_class($) {
+    my ($name) = @_;
 
-	$debug_names{$name} = write_debugmethod ($tdefault, $style,
-						 $name, $return_type,
-						 @argtypes);
+    print "struct " . $name . " : public target_ops\n";
+    print "{\n";
+    print "  $name ();\n";
+    print "\n";
+    print "  const char *shortname () override;\n";
+    print "  const char *longname () override;\n";
+    print "  const char *doc () override;\n";
+    print "\n";
+
+    for $name (@delegators) {
+	my $return_type = $return_types{$name};
+	my @argtypes = @{$argtypes_array{$name}};
+
+	print "  ";
+	write_declaration ($name, $return_type, @argtypes);
     }
+
+    print "};\n\n";
 }
 
-# Now the delegation code.
-print "static void\ninstall_delegators (struct target_ops *ops)\n{\n";
+print_class ("dummy_target");
+print_class ("debug_target");
 
-for $iter (@delegators) {
-    print "  if (ops->" . $iter . " == NULL)\n";
-    print "    ops->" . $iter . " = " . dname ($iter) . ";\n";
-}
-print "}\n\n";
+for $name (@delegators) {
+    my $tdefault = $tdefaults{$name};
+    my $return_type = $return_types{$name};
+    my $style = $styles{$name};
+    my @argtypes = @{$argtypes_array{$name}};
 
-# Now the default method code.
-print "static void\ninstall_dummy_methods (struct target_ops *ops)\n{\n";
+    write_delegator ($name, $return_type, @argtypes);
 
-for $iter (@delegators) {
-    print "  ops->" . $iter . " = " . $tdefault_names{$iter} . ";\n";
-}
-print "}\n\n";
+    write_tdefault ($tdefault, $style, $name, $return_type, @argtypes);
 
-# The debug method code.
-print "static void\ninit_debug_target (struct target_ops *ops)\n{\n";
-for $iter (@delegators) {
-    print "  ops->" . $iter . " = " . $debug_names{$iter} . ";\n";
+    write_debugmethod ($tdefault, $name, $return_type, @argtypes);
 }
-print "}\n";
diff --git a/gdb/mi/mi-main.c b/gdb/mi/mi-main.c
index d7354606b5..51d0a268c9 100644
--- a/gdb/mi/mi-main.c
+++ b/gdb/mi/mi-main.c
@@ -266,7 +266,7 @@ proceed_thread_callback (struct thread_info *thread, void *arg)
 static void
 exec_continue (char **argv, int argc)
 {
-  prepare_execution_command (&current_target, mi_async_p ());
+  prepare_execution_command (target_stack, mi_async_p ());
 
   if (non_stop)
     {
@@ -405,7 +405,7 @@ run_one_inferior (struct inferior *inf, void *arg)
   int start_p = *(int *) arg;
   const char *run_cmd = start_p ? "start" : "run";
   struct target_ops *run_target = find_run_target ();
-  int async_p = mi_async && run_target->to_can_async_p (run_target);
+  int async_p = mi_async && run_target->can_async_p ();
 
   if (inf->pid != 0)
     {
@@ -479,7 +479,7 @@ mi_cmd_exec_run (const char *command, char **argv, int argc)
     {
       const char *run_cmd = start_p ? "start" : "run";
       struct target_ops *run_target = find_run_target ();
-      int async_p = mi_async && run_target->to_can_async_p (run_target);
+      int async_p = mi_async && run_target->can_async_p ();
 
       mi_execute_cli_command (run_cmd, async_p,
 			      async_p ? "&" : NULL);
@@ -1353,10 +1353,7 @@ mi_cmd_data_read_memory (const char *command, char **argv, int argc)
 
   gdb::byte_vector mbuf (total_bytes);
 
-  /* Dispatch memory reads to the topmost target, not the flattened
-     current_target.  */
-  nr_bytes = target_read (current_target.beneath,
-			  TARGET_OBJECT_MEMORY, NULL, mbuf.data (),
+  nr_bytes = target_read (target_stack, TARGET_OBJECT_MEMORY, NULL, mbuf.data (),
 			  addr, total_bytes);
   if (nr_bytes <= 0)
     error (_("Unable to read memory."));
@@ -1476,7 +1473,7 @@ mi_cmd_data_read_memory_bytes (const char *command, char **argv, int argc)
   length = atol (argv[1]);
 
   std::vector<memory_read_result> result
-    = read_memory_robust (current_target.beneath, addr, length);
+    = read_memory_robust (target_stack, addr, length);
 
   if (result.size () == 0)
     error (_("Unable to read memory."));
diff --git a/gdb/minsyms.c b/gdb/minsyms.c
index 9d23c4fd4f..625d5e4260 100644
--- a/gdb/minsyms.c
+++ b/gdb/minsyms.c
@@ -73,7 +73,7 @@ msymbol_is_function (struct objfile *objfile, minimal_symbol *minsym,
       {
 	struct gdbarch *gdbarch = get_objfile_arch (objfile);
 	CORE_ADDR pc = gdbarch_convert_from_func_ptr_addr (gdbarch, msym_addr,
-							   &current_target);
+							   target_stack);
 	if (pc != msym_addr)
 	  {
 	    if (func_address_p != NULL)
@@ -1501,7 +1501,7 @@ find_solib_trampoline_target (struct frame_info *frame, CORE_ADDR pc)
 	    func = gdbarch_convert_from_func_ptr_addr
 		    (get_objfile_arch (objfile),
 		     MSYMBOL_VALUE_ADDRESS (objfile, msymbol),
-		     &current_target);
+		     target_stack);
 
 	    /* Ignore data symbols that are not function descriptors.  */
 	    if (func != MSYMBOL_VALUE_ADDRESS (objfile, msymbol))
diff --git a/gdb/parse.c b/gdb/parse.c
index 3abb9d4219..6f82d37fe2 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -474,7 +474,7 @@ find_minsym_type_and_address (minimal_symbol *msymbol,
 
   /* The minimal symbol might point to a function descriptor;
      resolve it to the actual code address instead.  */
-  pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, &current_target);
+  pc = gdbarch_convert_from_func_ptr_addr (gdbarch, addr, target_stack);
   if (pc != addr)
     {
       struct bound_minimal_symbol ifunc_msym = lookup_minimal_symbol_by_pc (pc);
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index 2cd8792d30..e1b728016c 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -1300,7 +1300,7 @@ ppc_linux_get_hwcap (void)
 {
   CORE_ADDR field;
 
-  if (target_auxv_search (&current_target, AT_HWCAP, &field))
+  if (target_auxv_search (target_stack, AT_HWCAP, &field))
     return (unsigned long) field;
 
   return 0;
diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c
index 04487e7b15..6d3a64c4f0 100644
--- a/gdb/ppc-linux-tdep.c
+++ b/gdb/ppc-linux-tdep.c
@@ -1203,7 +1203,7 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
   /* Look up cached address of thread-local variable.  */
   if (!ptid_equal (spe_context_cache_ptid, inferior_ptid))
     {
-      struct target_ops *target = &current_target;
+      struct target_ops *target = target_stack;
 
       TRY
 	{
@@ -1214,9 +1214,9 @@ ppc_linux_spe_context (int wordsize, enum bfd_endian byte_order,
 	     Instead, we have cached the lm_addr value, and use that to
 	     directly call the target's to_get_thread_local_address.  */
 	  spe_context_cache_address
-	    = target->to_get_thread_local_address (target, inferior_ptid,
-						   spe_context_lm_addr,
-						   spe_context_offset);
+	    = target->get_thread_local_address (inferior_ptid,
+						spe_context_lm_addr,
+						spe_context_offset);
 	  spe_context_cache_ptid = inferior_ptid;
 	}
 
@@ -1363,7 +1363,7 @@ ppu2spu_sniffer (const struct frame_unwind *self,
 	return 0;
 
       xsnprintf (annex, sizeof annex, "%d/regs", data.id);
-      if (target_read (&current_target, TARGET_OBJECT_SPU, annex,
+      if (target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		       data.gprs, 0, sizeof data.gprs)
 	  == sizeof data.gprs)
 	{
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 51c9ae8f00..478770d0fe 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -3936,7 +3936,7 @@ procfs_make_note_section (struct target_ops *self, bfd *obfd, int *note_size)
 			     &thread_args);
   note_data = thread_args.note_data;
 
-  auxv_len = target_read_alloc (&current_target, TARGET_OBJECT_AUXV,
+  auxv_len = target_read_alloc (target_stack, TARGET_OBJECT_AUXV,
 				NULL, &auxv);
   if (auxv_len > 0)
     {
diff --git a/gdb/regcache.c b/gdb/regcache.c
index 3af8ca9699..f8e0c49a7c 100644
--- a/gdb/regcache.c
+++ b/gdb/regcache.c
@@ -1488,30 +1488,12 @@ current_regcache_test (void)
   SELF_CHECK (regcache_access::current_regcache_size () == 2);
 }
 
-static void test_target_fetch_registers (target_ops *self, regcache *regs,
-					 int regno);
-static void test_target_store_registers (target_ops *self, regcache *regs,
-					 int regno);
-static enum target_xfer_status
-  test_target_xfer_partial (struct target_ops *ops,
-			    enum target_object object,
-			    const char *annex, gdb_byte *readbuf,
-			    const gdb_byte *writebuf,
-			    ULONGEST offset, ULONGEST len,
-			    ULONGEST *xfered_len);
-
 class target_ops_no_register : public test_target_ops
 {
 public:
   target_ops_no_register ()
     : test_target_ops {}
-  {
-    to_fetch_registers = test_target_fetch_registers;
-    to_store_registers = test_target_store_registers;
-    to_xfer_partial = test_target_xfer_partial;
-
-    to_data = this;
-  }
+  {}
 
   void reset ()
   {
@@ -1520,38 +1502,42 @@ public:
     xfer_partial_called = 0;
   }
 
+  void fetch_registers (regcache *regs, int regno) override;
+  void store_registers (regcache *regs, int regno) override;
+
+  enum target_xfer_status xfer_partial (enum target_object object,
+					const char *annex, gdb_byte *readbuf,
+					const gdb_byte *writebuf,
+					ULONGEST offset, ULONGEST len,
+					ULONGEST *xfered_len) override;
+
   unsigned int fetch_registers_called = 0;
   unsigned int store_registers_called = 0;
   unsigned int xfer_partial_called = 0;
 };
 
-static void
-test_target_fetch_registers (target_ops *self, regcache *regs, int regno)
+void
+target_ops_no_register::fetch_registers (regcache *regs, int regno)
 {
-  auto ops = static_cast<target_ops_no_register *> (self->to_data);
-
   /* Mark register available.  */
   regs->raw_supply_zeroed (regno);
-  ops->fetch_registers_called++;
+  this->fetch_registers_called++;
 }
 
-static void
-test_target_store_registers (target_ops *self, regcache *regs, int regno)
+void
+target_ops_no_register::store_registers (regcache *regs, int regno)
 {
-  auto ops = static_cast<target_ops_no_register *> (self->to_data);
-
-  ops->store_registers_called++;
+  this->store_registers_called++;
 }
 
-static enum target_xfer_status
-test_target_xfer_partial (struct target_ops *self, enum target_object object,
-			  const char *annex, gdb_byte *readbuf,
-			  const gdb_byte *writebuf,
-			  ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
+enum target_xfer_status
+target_ops_no_register::xfer_partial (enum target_object object,
+				      const char *annex, gdb_byte *readbuf,
+				      const gdb_byte *writebuf,
+				      ULONGEST offset, ULONGEST len,
+				      ULONGEST *xfered_len)
 {
-  auto ops = static_cast<target_ops_no_register *> (self->to_data);
-
-  ops->xfer_partial_called++;
+  this->xfer_partial_called++;
 
   *xfered_len = len;
   return TARGET_XFER_OK;
@@ -1573,7 +1559,7 @@ cooked_read_test (struct gdbarch *gdbarch)
 {
   /* Error out if debugging something, because we're going to push the
      test target, which would pop any existing target.  */
-  if (current_target.to_stratum >= process_stratum)
+  if (target_stack->to_stratum >= process_stratum)
     error (_("target already pushed"));
 
   /* Create a mock environment.  An inferior with a thread, with a
@@ -1747,7 +1733,7 @@ cooked_write_test (struct gdbarch *gdbarch)
 {
   /* Error out if debugging something, because we're going to push the
      test target, which would pop any existing target.  */
-  if (current_target.to_stratum >= process_stratum)
+  if (target_stack->to_stratum >= process_stratum)
     error (_("target already pushed"));
 
   /* Create a mock environment.  A process_stratum target pushed.  */
diff --git a/gdb/remote.c b/gdb/remote.c
index f54a38833b..e6d07a620c 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -4393,7 +4393,7 @@ remote_check_symbols (void)
 	     instead of any data function descriptor.  */
 	  sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
 							 sym_addr,
-							 &current_target);
+							 target_stack);
 
 	  xsnprintf (msg, get_remote_packet_size (), "qSymbol:%s:%s",
 		     phex_nz (sym_addr, addr_size), &reply[8]);
@@ -10791,7 +10791,7 @@ remote_memory_map (struct target_ops *ops)
 {
   std::vector<mem_region> result;
   gdb::optional<gdb::char_vector> text
-    = target_read_stralloc (&current_target, TARGET_OBJECT_MEMORY_MAP, NULL);
+    = target_read_stralloc (target_stack, TARGET_OBJECT_MEMORY_MAP, NULL);
 
   if (text)
     result = parse_memory_map (text->data ());
@@ -12905,7 +12905,7 @@ static traceframe_info_up
 remote_traceframe_info (struct target_ops *self)
 {
   gdb::optional<gdb::char_vector> text
-    = target_read_stralloc (&current_target, TARGET_OBJECT_TRACEFRAME_INFO,
+    = target_read_stralloc (target_stack, TARGET_OBJECT_TRACEFRAME_INFO,
 			    NULL);
   if (text)
     return parse_traceframe_info (text->data ());
@@ -13137,7 +13137,7 @@ static void
 btrace_read_config (struct btrace_config *conf)
 {
   gdb::optional<gdb::char_vector> xml
-    = target_read_stralloc (&current_target, TARGET_OBJECT_BTRACE_CONF, "");
+    = target_read_stralloc (target_stack, TARGET_OBJECT_BTRACE_CONF, "");
   if (xml)
     parse_xml_btrace_conf (conf, xml->data ());
 }
@@ -13337,7 +13337,7 @@ remote_read_btrace (struct target_ops *self,
     }
 
   gdb::optional<gdb::char_vector> xml
-    = target_read_stralloc (&current_target, TARGET_OBJECT_BTRACE, annex);
+    = target_read_stralloc (target_stack, TARGET_OBJECT_BTRACE, annex);
   if (!xml)
     return BTRACE_ERR_UNKNOWN;
 
@@ -13395,7 +13395,7 @@ remote_pid_to_exec_file (struct target_ops *self, int pid)
       xsnprintf (annex, annex_size, "%x", pid);
     }
 
-  filename = target_read_stralloc (&current_target,
+  filename = target_read_stralloc (target_stack,
 				   TARGET_OBJECT_EXEC_FILE, annex);
 
   return filename ? filename->data () : nullptr;
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 37cbcb672b..425c41df24 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -4885,7 +4885,7 @@ ppc_process_record_op31 (struct gdbarch *gdbarch, struct regcache *regcache,
       return 0;
 
     case 1014:		/* Data Cache Block set to Zero */
-      if (target_auxv_search (&current_target, AT_DCACHEBSIZE, &at_dcsz) <= 0
+      if (target_auxv_search (target_stack, AT_DCACHEBSIZE, &at_dcsz) <= 0
 	  || at_dcsz == 0)
 	at_dcsz = 128; /* Assume 128-byte cache line size (POWER8)  */
 
diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
index 14086faaa0..cc5e33340e 100644
--- a/gdb/s390-linux-nat.c
+++ b/gdb/s390-linux-nat.c
@@ -988,7 +988,7 @@ s390_read_description (struct target_ops *ops)
   {
     CORE_ADDR hwcap = 0;
 
-    target_auxv_search (&current_target, AT_HWCAP, &hwcap);
+    target_auxv_search (target_stack, AT_HWCAP, &hwcap);
     have_regset_tdb = (hwcap & HWCAP_S390_TE)
       && check_regset (tid, NT_S390_TDB, s390_sizeof_tdbregset);
 
diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c
index 408bb875d2..227c70909e 100644
--- a/gdb/s390-tdep.c
+++ b/gdb/s390-tdep.c
@@ -661,7 +661,7 @@ s390_load (struct s390_prologue_data *data,
   if (pv_is_constant (addr))
     {
       struct target_section *secp;
-      secp = target_section_by_addr (&current_target, addr.k);
+      secp = target_section_by_addr (target_stack, addr.k);
       if (secp != NULL
 	  && (bfd_get_section_flags (secp->the_bfd_section->owner,
 				     secp->the_bfd_section)
diff --git a/gdb/solib-aix.c b/gdb/solib-aix.c
index 608a702a9c..f3dfdb577c 100644
--- a/gdb/solib-aix.c
+++ b/gdb/solib-aix.c
@@ -280,7 +280,7 @@ solib_aix_get_library_list (struct inferior *inf, const char *warning_msg)
     return data->library_list;
 
   gdb::optional<gdb::char_vector> library_document
-    = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES_AIX,
+    = target_read_stralloc (target_stack, TARGET_OBJECT_LIBRARIES_AIX,
 			    NULL);
   if (!library_document && warning_msg != NULL)
     {
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index d66938fb90..557fb156b2 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -497,7 +497,7 @@ darwin_solib_read_all_image_info_addr (struct darwin_info *info)
   if (TYPE_LENGTH (ptr_type) > sizeof (buf))
     return;
 
-  len = target_read (&current_target, TARGET_OBJECT_DARWIN_DYLD_INFO, NULL,
+  len = target_read (target_stack, TARGET_OBJECT_DARWIN_DYLD_INFO, NULL,
 		     buf, 0, TYPE_LENGTH (ptr_type));
   if (len <= 0)
     return;
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index 7a9b75480a..9868606249 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -293,7 +293,7 @@ dsbt_get_initial_loadmaps (void)
 {
   struct dsbt_info *info = get_dsbt_info ();
   gdb::optional<gdb::byte_vector> buf
-    = target_read_alloc (&current_target, TARGET_OBJECT_FDPIC, "exec");
+    = target_read_alloc (target_stack, TARGET_OBJECT_FDPIC, "exec");
 
   if (!buf || buf->empty ())
     {
@@ -304,7 +304,7 @@ dsbt_get_initial_loadmaps (void)
   if (solib_dsbt_debug)
     dsbt_print_loadmap (info->exec_loadmap);
 
-  buf = target_read_alloc (&current_target, TARGET_OBJECT_FDPIC, "exec");
+  buf = target_read_alloc (target_stack, TARGET_OBJECT_FDPIC, "exec");
   if (!buf || buf->empty ())
     {
       info->interp_loadmap = NULL;
diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c
index cb735fd451..a0fe8965bf 100644
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -171,7 +171,7 @@ spu_current_sos (void)
     ;
 
   /* Determine list of SPU ids.  */
-  size = target_read (&current_target, TARGET_OBJECT_SPU, NULL,
+  size = target_read (target_stack, TARGET_OBJECT_SPU, NULL,
 		      buf, 0, sizeof buf);
 
   /* Do not add stand-alone SPE executable context as shared library,
@@ -206,7 +206,7 @@ spu_current_sos (void)
 	 already created the SPE context, but not installed the object-id
 	 yet.  Skip such entries; we'll be back for them later.  */
       xsnprintf (annex, sizeof annex, "%d/object-id", fd);
-      len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+      len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 			 (gdb_byte *) id, 0, sizeof id);
       if (len <= 0 || len >= sizeof id)
 	continue;
@@ -418,7 +418,7 @@ spu_enable_break (struct objfile *objfile)
       CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (spe_event_sym);
 
       addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (), addr,
-                                                 &current_target);
+						 target_stack);
       create_solib_event_breakpoint (target_gdbarch (), addr);
       return 1;
     }
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 3b0af668bd..f9936b36de 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -432,11 +432,11 @@ read_program_header (int type, int *p_sect_size, int *p_arch_size,
   int pt_phdr_p = 0;
 
   /* Get required auxv elements from target.  */
-  if (target_auxv_search (&current_target, AT_PHDR, &at_phdr) <= 0)
+  if (target_auxv_search (target_stack, AT_PHDR, &at_phdr) <= 0)
     return 0;
-  if (target_auxv_search (&current_target, AT_PHENT, &at_phent) <= 0)
+  if (target_auxv_search (target_stack, AT_PHENT, &at_phent) <= 0)
     return 0;
-  if (target_auxv_search (&current_target, AT_PHNUM, &at_phnum) <= 0)
+  if (target_auxv_search (target_stack, AT_PHNUM, &at_phnum) <= 0)
     return 0;
   if (!at_phdr || !at_phnum)
     return 0;
@@ -1244,7 +1244,7 @@ svr4_current_sos_via_xfer_libraries (struct svr4_library_list *list,
 
   /* Fetch the list of shared libraries.  */
   gdb::optional<gdb::char_vector> svr4_library_document
-    = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES_SVR4,
+    = target_read_stralloc (target_stack, TARGET_OBJECT_LIBRARIES_SVR4,
 			    annex);
   if (!svr4_library_document)
     return 0;
@@ -2219,7 +2219,7 @@ enable_break (struct svr4_info *info, int from_tty)
       sym_addr = gdbarch_addr_bits_remove
 	(target_gdbarch (), gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
 							     sym_addr,
-							     &current_target));
+							     target_stack));
 
       /* On at least some versions of Solaris there's a dynamic relocation
 	 on _r_debug.r_brk and SYM_ADDR may not be relocated yet, e.g., if
@@ -2334,7 +2334,7 @@ enable_break (struct svr4_info *info, int from_tty)
       /* If we were not able to find the base address of the loader
          from our so_list, then try using the AT_BASE auxilliary entry.  */
       if (!load_addr_found)
-        if (target_auxv_search (&current_target, AT_BASE, &load_addr) > 0)
+	if (target_auxv_search (target_stack, AT_BASE, &load_addr) > 0)
 	  {
 	    int addr_bit = gdbarch_addr_bit (target_gdbarch ());
 
@@ -2459,7 +2459,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	  sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
 	  sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
 							 sym_addr,
-							 &current_target);
+							 target_stack);
 	  svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
 	  return 1;
 	}
@@ -2476,7 +2476,7 @@ enable_break (struct svr4_info *info, int from_tty)
 	      sym_addr = BMSYMBOL_VALUE_ADDRESS (msymbol);
 	      sym_addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch (),
 							     sym_addr,
-							     &current_target);
+							     target_stack);
 	      svr4_create_solib_event_breakpoints (target_gdbarch (), sym_addr);
 	      return 1;
 	    }
@@ -2571,7 +2571,7 @@ svr4_exec_displacement (CORE_ADDR *displacementp)
   if ((bfd_get_file_flags (exec_bfd) & DYNAMIC) == 0)
     return 0;
 
-  if (target_auxv_search (&current_target, AT_ENTRY, &entry_point) <= 0)
+  if (target_auxv_search (target_stack, AT_ENTRY, &entry_point) <= 0)
     return 0;
 
   exec_displacement = entry_point - bfd_get_start_address (exec_bfd);
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index 7f96e80e1b..adbab7ea32 100644
--- a/gdb/solib-target.c
+++ b/gdb/solib-target.c
@@ -258,7 +258,7 @@ solib_target_current_sos (void)
 
   /* Fetch the list of shared libraries.  */
   gdb::optional<gdb::char_vector> library_document
-    = target_read_stralloc (&current_target, TARGET_OBJECT_LIBRARIES, NULL);
+    = target_read_stralloc (target_stack, TARGET_OBJECT_LIBRARIES, NULL);
   if (!library_document)
     return NULL;
 
diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c
index 633bd685bc..a4d5a7b27b 100644
--- a/gdb/sparc-tdep.c
+++ b/gdb/sparc-tdep.c
@@ -189,7 +189,7 @@ ULONGEST
 sparc_fetch_wcookie (struct gdbarch *gdbarch)
 {
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-  struct target_ops *ops = &current_target;
+  struct target_ops *ops = target_stack;
   gdb_byte buf[8];
   int len;
 
diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c
index 6f3ca198b3..9fd6a66199 100644
--- a/gdb/sparc64-tdep.c
+++ b/gdb/sparc64-tdep.c
@@ -222,10 +222,10 @@ adi_available (void)
     return proc->stat.is_avail;
 
   proc->stat.checked_avail = true;
-  if (target_auxv_search (&current_target, AT_ADI_BLKSZ, &value) <= 0)
+  if (target_auxv_search (target_stack, AT_ADI_BLKSZ, &value) <= 0)
     return false;
   proc->stat.blksize = value;
-  target_auxv_search (&current_target, AT_ADI_NBITS, &value);
+  target_auxv_search (target_stack, AT_ADI_NBITS, &value);
   proc->stat.nbits = value;
   proc->stat.max_version = (1 << proc->stat.nbits) - 2;
   proc->stat.is_avail = true;
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c
index 783ef5b247..60b04aed73 100644
--- a/gdb/spu-tdep.c
+++ b/gdb/spu-tdep.c
@@ -198,7 +198,7 @@ spu_pseudo_register_read_spu (readable_regcache *regcache, const char *regname,
     return status;
   xsnprintf (annex, sizeof annex, "%d/%s", (int) id, regname);
   memset (reg, 0, sizeof reg);
-  target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  target_read (target_stack, TARGET_OBJECT_SPU, annex,
 	       reg, 0, sizeof reg);
 
   ul = strtoulst ((char *) reg, NULL, 16);
@@ -229,7 +229,7 @@ spu_pseudo_register_read (struct gdbarch *gdbarch, readable_regcache *regcache,
       if (status != REG_VALID)
 	return status;
       xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id);
-      target_read (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 16);
+      target_read (target_stack, TARGET_OBJECT_SPU, annex, buf, 0, 16);
       return status;
 
     case SPU_SRR0_REGNUM:
@@ -263,7 +263,7 @@ spu_pseudo_register_write_spu (struct regcache *regcache, const char *regname,
   xsnprintf (annex, sizeof annex, "%d/%s", (int) id, regname);
   xsnprintf (reg, sizeof reg, "0x%s",
 	     phex_nz (extract_unsigned_integer (buf, 4, byte_order), 4));
-  target_write (&current_target, TARGET_OBJECT_SPU, annex,
+  target_write (target_stack, TARGET_OBJECT_SPU, annex,
 		(gdb_byte *) reg, 0, strlen (reg));
 }
 
@@ -286,7 +286,7 @@ spu_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
     case SPU_FPSCR_REGNUM:
       regcache_raw_read_unsigned (regcache, SPU_ID_REGNUM, &id);
       xsnprintf (annex, sizeof annex, "%d/fpcr", (int) id);
-      target_write (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 16);
+      target_write (target_stack, TARGET_OBJECT_SPU, annex, buf, 0, 16);
       break;
 
     case SPU_SRR0_REGNUM:
@@ -2079,7 +2079,7 @@ info_spu_event_command (const char *args, int from_tty)
   id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
 
   xsnprintf (annex, sizeof annex, "%d/event_status", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read event_status."));
@@ -2087,7 +2087,7 @@ info_spu_event_command (const char *args, int from_tty)
   event_status = strtoulst ((char *) buf, NULL, 16);
  
   xsnprintf (annex, sizeof annex, "%d/event_mask", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read event_mask."));
@@ -2133,7 +2133,7 @@ info_spu_signal_command (const char *args, int from_tty)
   id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
 
   xsnprintf (annex, sizeof annex, "%d/signal1", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 4);
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex, buf, 0, 4);
   if (len < 0)
     error (_("Could not read signal1."));
   else if (len == 4)
@@ -2143,7 +2143,7 @@ info_spu_signal_command (const char *args, int from_tty)
     }
     
   xsnprintf (annex, sizeof annex, "%d/signal1_type", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read signal1_type."));
@@ -2151,7 +2151,7 @@ info_spu_signal_command (const char *args, int from_tty)
   signal1_type = strtoulst ((char *) buf, NULL, 16);
 
   xsnprintf (annex, sizeof annex, "%d/signal2", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex, buf, 0, 4);
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex, buf, 0, 4);
   if (len < 0)
     error (_("Could not read signal2."));
   else if (len == 4)
@@ -2161,7 +2161,7 @@ info_spu_signal_command (const char *args, int from_tty)
     }
     
   xsnprintf (annex, sizeof annex, "%d/signal2_type", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, (sizeof (buf) - 1));
   if (len <= 0)
     error (_("Could not read signal2_type."));
@@ -2250,7 +2250,7 @@ info_spu_mailbox_command (const char *args, int from_tty)
   ui_out_emit_tuple tuple_emitter (current_uiout, "SPUInfoMailbox");
 
   xsnprintf (annex, sizeof annex, "%d/mbox_info", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, sizeof buf);
   if (len < 0)
     error (_("Could not read mbox_info."));
@@ -2259,7 +2259,7 @@ info_spu_mailbox_command (const char *args, int from_tty)
 			 "mbox", "SPU Outbound Mailbox");
 
   xsnprintf (annex, sizeof annex, "%d/ibox_info", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, sizeof buf);
   if (len < 0)
     error (_("Could not read ibox_info."));
@@ -2268,7 +2268,7 @@ info_spu_mailbox_command (const char *args, int from_tty)
 			 "ibox", "SPU Outbound Interrupt Mailbox");
 
   xsnprintf (annex, sizeof annex, "%d/wbox_info", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, sizeof buf);
   if (len < 0)
     error (_("Could not read wbox_info."));
@@ -2481,7 +2481,7 @@ info_spu_dma_command (const char *args, int from_tty)
   id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
 
   xsnprintf (annex, sizeof annex, "%d/dma_info", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, 40 + 16 * 32);
   if (len <= 0)
     error (_("Could not read dma_info."));
@@ -2558,7 +2558,7 @@ info_spu_proxydma_command (const char *args, int from_tty)
   id = get_frame_register_unsigned (frame, SPU_ID_REGNUM);
 
   xsnprintf (annex, sizeof annex, "%d/proxydma_info", id);
-  len = target_read (&current_target, TARGET_OBJECT_SPU, annex,
+  len = target_read (target_stack, TARGET_OBJECT_SPU, annex,
 		     buf, 0, 24 + 8 * 32);
   if (len <= 0)
     error (_("Could not read proxydma_info."));
diff --git a/gdb/symfile.c b/gdb/symfile.c
index 1e5297ee29..1122db672e 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -863,7 +863,7 @@ init_entry_point_info (struct objfile *objfile)
       entry_point
 	= gdbarch_convert_from_func_ptr_addr (get_objfile_arch (objfile),
 					      entry_point,
-					      &current_target);
+					      target_stack);
 
       /* Remove any ISA markers, so that this matches entries in the
 	 symbol table.  */
diff --git a/gdb/target-debug.h b/gdb/target-debug.h
index 233e4baf19..5f3001b89f 100644
--- a/gdb/target-debug.h
+++ b/gdb/target-debug.h
@@ -176,6 +176,12 @@
   target_debug_do_print (host_address_to_string (inf))
 #define target_debug_print_record_print_flags(X) \
   target_debug_do_print (plongest (X))
+#define target_debug_print_enum_info_proc_what(X) \
+  target_debug_do_print (plongest (X))
+#define target_debug_print_thread_control_capabilities(X) \
+  target_debug_do_print (plongest (X))
+#define target_debug_print_thread_info_p(X)	\
+  target_debug_do_print (host_address_to_string (X))
 
 static void
 target_debug_print_struct_target_waitstatus_p (struct target_waitstatus *status)
diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c
index 5d34e29a86..a5c9c6b67d 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -833,11 +833,11 @@ target_find_description (void)
   /* Next try to read the description from the current target using
      target objects.  */
   if (current_target_desc == NULL)
-    current_target_desc = target_read_description_xml (&current_target);
+    current_target_desc = target_read_description_xml (target_stack);
 
   /* If that failed try a target-specific hook.  */
   if (current_target_desc == NULL)
-    current_target_desc = target_read_description (&current_target);
+    current_target_desc = target_read_description (target_stack);
 
   /* If a non-NULL description was returned, then update the current
      architecture.  */
diff --git a/gdb/target-memory.c b/gdb/target-memory.c
index 395bf0bae9..8db64d7284 100644
--- a/gdb/target-memory.c
+++ b/gdb/target-memory.c
@@ -338,7 +338,7 @@ target_write_memory_blocks (const std::vector<memory_write_request> &requests,
     {
       LONGEST len;
 
-      len = target_write_with_progress (current_target.beneath,
+      len = target_write_with_progress (target_stack,
 					TARGET_OBJECT_MEMORY, NULL,
 					iter.data, iter.begin,
 					iter.end - iter.begin,
@@ -361,7 +361,7 @@ target_write_memory_blocks (const std::vector<memory_write_request> &requests,
 	{
 	  LONGEST len;
 
-	  len = target_write_with_progress (&current_target,
+	  len = target_write_with_progress (target_stack,
 					    TARGET_OBJECT_FLASH, NULL,
 					    iter.data, iter.begin,
 					    iter.end - iter.begin,
diff --git a/gdb/target.c b/gdb/target.c
index 2ff028cfa8..022da5919a 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -86,10 +86,6 @@ static struct address_space *default_thread_address_space
 
 static void tcomplain (void) ATTRIBUTE_NORETURN;
 
-static int return_zero (struct target_ops *);
-
-static int return_zero_has_execution (struct target_ops *, ptid_t);
-
 static struct target_ops *find_default_run_target (const char *);
 
 static struct gdbarch *default_thread_architecture (struct target_ops *ops,
@@ -107,14 +103,6 @@ static const char *default_pid_to_str (struct target_ops *ops, ptid_t ptid);
 static enum exec_direction_kind default_execution_direction
     (struct target_ops *self);
 
-static struct target_ops debug_target;
-
-#include "target-delegates.c"
-
-static void init_dummy_target (void);
-
-static void update_current_target (void);
-
 /* Vector of existing target structures. */
 typedef struct target_ops *target_ops_p;
 DEF_VEC_P (target_ops_p);
@@ -123,16 +111,14 @@ static VEC (target_ops_p) *target_structs;
 /* The initial current target, so that there is always a semi-valid
    current target.  */
 
-static struct target_ops dummy_target;
+static struct target_ops *the_dummy_target;
+static struct target_ops *the_debug_target;
 
 /* Top of target stack.  */
-
-static struct target_ops *target_stack;
-
 /* The target structure we are currently using to talk to a process
    or file or whatever "inferior" we have.  */
 
-struct target_ops current_target;
+struct target_ops *target_stack;
 
 /* Command list for target.  */
 
@@ -171,7 +157,10 @@ static unsigned int targetdebug = 0;
 static void
 set_targetdebug  (const char *args, int from_tty, struct cmd_list_element *c)
 {
-  update_current_target ();
+  if (targetdebug)
+    push_target (the_debug_target);
+  else
+    unpush_target (the_debug_target);
 }
 
 static void
@@ -181,8 +170,6 @@ show_targetdebug (struct ui_file *file, int from_tty,
   fprintf_filtered (file, _("Target debugging is %s.\n"), value);
 }
 
-static void setup_target_debug (void);
-
 /* The user just typed 'target' without the name of a target.  */
 
 static void
@@ -195,7 +182,7 @@ target_command (const char *arg, int from_tty)
 /* Default target_has_* methods for process_stratum targets.  */
 
 int
-default_child_has_all_memory (struct target_ops *ops)
+default_child_has_all_memory ()
 {
   /* If no inferior selected, then we can't read memory here.  */
   if (ptid_equal (inferior_ptid, null_ptid))
@@ -205,7 +192,7 @@ default_child_has_all_memory (struct target_ops *ops)
 }
 
 int
-default_child_has_memory (struct target_ops *ops)
+default_child_has_memory ()
 {
   /* If no inferior selected, then we can't read memory here.  */
   if (ptid_equal (inferior_ptid, null_ptid))
@@ -215,7 +202,7 @@ default_child_has_memory (struct target_ops *ops)
 }
 
 int
-default_child_has_stack (struct target_ops *ops)
+default_child_has_stack ()
 {
   /* If no inferior selected, there's no stack.  */
   if (ptid_equal (inferior_ptid, null_ptid))
@@ -225,7 +212,7 @@ default_child_has_stack (struct target_ops *ops)
 }
 
 int
-default_child_has_registers (struct target_ops *ops)
+default_child_has_registers ()
 {
   /* Can't read registers from no inferior.  */
   if (ptid_equal (inferior_ptid, null_ptid))
@@ -235,7 +222,7 @@ default_child_has_registers (struct target_ops *ops)
 }
 
 int
-default_child_has_execution (struct target_ops *ops, ptid_t the_ptid)
+default_child_has_execution (ptid_t the_ptid)
 {
   /* If there's no thread selected, then we can't make it run through
      hoops.  */
@@ -251,8 +238,8 @@ target_has_all_memory_1 (void)
 {
   struct target_ops *t;
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_all_memory (t))
+  for (t = target_stack; t != NULL; t = t->beneath)
+    if (t->has_all_memory ())
       return 1;
 
   return 0;
@@ -263,8 +250,8 @@ target_has_memory_1 (void)
 {
   struct target_ops *t;
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_memory (t))
+  for (t = target_stack; t != NULL; t = t->beneath)
+    if (t->has_memory ())
       return 1;
 
   return 0;
@@ -275,8 +262,8 @@ target_has_stack_1 (void)
 {
   struct target_ops *t;
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_stack (t))
+  for (t = target_stack; t != NULL; t = t->beneath)
+    if (t->has_stack ())
       return 1;
 
   return 0;
@@ -287,8 +274,8 @@ target_has_registers_1 (void)
 {
   struct target_ops *t;
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_registers (t))
+  for (t = target_stack; t != NULL; t = t->beneath)
+    if (t->has_registers ())
       return 1;
 
   return 0;
@@ -299,8 +286,8 @@ target_has_execution_1 (ptid_t the_ptid)
 {
   struct target_ops *t;
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_has_execution (t, the_ptid))
+  for (t = target_stack; t != NULL; t = t->beneath)
+    if (t->has_execution (the_ptid))
       return 1;
 
   return 0;
@@ -312,38 +299,6 @@ target_has_execution_current (void)
   return target_has_execution_1 (inferior_ptid);
 }
 
-/* Complete initialization of T.  This ensures that various fields in
-   T are set, if needed by the target implementation.  */
-
-void
-complete_target_initialization (struct target_ops *t)
-{
-  /* Provide default values for all "must have" methods.  */
-
-  if (t->to_has_all_memory == NULL)
-    t->to_has_all_memory = return_zero;
-
-  if (t->to_has_memory == NULL)
-    t->to_has_memory = return_zero;
-
-  if (t->to_has_stack == NULL)
-    t->to_has_stack = return_zero;
-
-  if (t->to_has_registers == NULL)
-    t->to_has_registers = return_zero;
-
-  if (t->to_has_execution == NULL)
-    t->to_has_execution = return_zero_has_execution;
-
-  /* These methods can be called on an unpushed target and so require
-     a default implementation if the target might plausibly be the
-     default run target.  */
-  gdb_assert (t->to_can_run == NULL || (t->to_can_async_p != NULL
-					&& t->to_supports_non_stop != NULL));
-
-  install_delegators (t);
-}
-
 /* This is used to implement the various target commands.  */
 
 static void
@@ -353,17 +308,17 @@ open_target (const char *args, int from_tty, struct cmd_list_element *command)
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog, "-> %s->to_open (...)\n",
-			ops->to_shortname);
+			ops->shortname ());
 
-  ops->to_open (args, from_tty);
+  ops->open (args, from_tty);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog, "<- %s->to_open (%s, %d)\n",
-			ops->to_shortname, args, from_tty);
+			ops->shortname (), args, from_tty);
 }
 
 /* Add possible target architecture T to the list and add a new
-   command 'target T->to_shortname'.  Set COMPLETER as the command's
+   command 'target T->shortname ()'.  Set COMPLETER as the command's
    completer if not NULL.  */
 
 void
@@ -372,8 +327,6 @@ add_target_with_completer (struct target_ops *t,
 {
   struct cmd_list_element *c;
 
-  complete_target_initialization (t);
-
   VEC_safe_push (target_ops_p, target_structs, t);
 
   if (targetlist == NULL)
@@ -384,7 +337,7 @@ Remaining arguments are interpreted by the target protocol.  For more\n\
 information on the arguments for a particular protocol, type\n\
 `help target ' followed by the protocol name."),
 		    &targetlist, "target ", 0, &cmdlist);
-  c = add_cmd (t->to_shortname, no_class, t->to_doc, &targetlist);
+  c = add_cmd (t->shortname (), no_class, t->doc (), &targetlist);
   set_cmd_sfunc (c, open_target);
   set_cmd_context (c, t);
   if (completer != NULL)
@@ -409,10 +362,10 @@ add_deprecated_target_alias (struct target_ops *t, const char *alias)
 
   /* If we use add_alias_cmd, here, we do not get the deprecated warning,
      see PR cli/15104.  */
-  c = add_cmd (alias, no_class, t->to_doc, &targetlist);
+  c = add_cmd (alias, no_class, t->doc (), &targetlist);
   set_cmd_sfunc (c, open_target);
   set_cmd_context (c, t);
-  alt = xstrprintf ("target %s", t->to_shortname);
+  alt = xstrprintf ("target %s", t->shortname ());
   deprecate_cmd (c, alt);
 }
 
@@ -421,14 +374,14 @@ add_deprecated_target_alias (struct target_ops *t, const char *alias)
 void
 target_kill (void)
 {
-  current_target.to_kill (&current_target);
+  target_stack->kill ();
 }
 
 void
 target_load (const char *arg, int from_tty)
 {
   target_dcache_invalidate ();
-  (*current_target.to_load) (&current_target, arg, from_tty);
+  target_stack->load (arg, from_tty);
 }
 
 /* Define it.  */
@@ -441,7 +394,7 @@ target_terminal_state target_terminal::m_terminal_state
 void
 target_terminal::init (void)
 {
-  (*current_target.to_terminal_init) (&current_target);
+  target_stack->terminal_init ();
 
   m_terminal_state = target_terminal_state::is_ours;
 }
@@ -472,7 +425,7 @@ target_terminal::inferior (void)
 
   if (inf->terminal_state != target_terminal_state::is_inferior)
     {
-      (*current_target.to_terminal_inferior) (&current_target);
+      target_stack->terminal_inferior ();
       inf->terminal_state = target_terminal_state::is_inferior;
     }
 
@@ -508,7 +461,7 @@ target_terminal::restore_inferior (void)
 	if (inf->terminal_state == target_terminal_state::is_ours_for_output)
 	  {
 	    set_current_inferior (inf);
-	    (*current_target.to_terminal_inferior) (&current_target);
+	    target_stack->terminal_inferior ();
 	    inf->terminal_state = target_terminal_state::is_inferior;
 	  }
       }
@@ -541,7 +494,7 @@ target_terminal_is_ours_kind (target_terminal_state desired_state)
       if (inf->terminal_state == target_terminal_state::is_inferior)
 	{
 	  set_current_inferior (inf);
-	  (*current_target.to_terminal_save_inferior) (&current_target);
+	  target_stack->terminal_save_inferior ();
 	}
     }
 
@@ -556,9 +509,9 @@ target_terminal_is_ours_kind (target_terminal_state desired_state)
 	{
 	  set_current_inferior (inf);
 	  if (desired_state == target_terminal_state::is_ours)
-	    (*current_target.to_terminal_ours) (&current_target);
+	    target_stack->terminal_ours ();
 	  else if (desired_state == target_terminal_state::is_ours_for_output)
-	    (*current_target.to_terminal_ours_for_output) (&current_target);
+	    target_stack->terminal_ours_for_output ();
 	  else
 	    gdb_assert_not_reached ("unhandled desired state");
 	  inf->terminal_state = desired_state;
@@ -607,7 +560,7 @@ target_terminal::ours_for_output ()
 void
 target_terminal::info (const char *arg, int from_tty)
 {
-  (*current_target.to_terminal_info) (&current_target, arg, from_tty);
+  target_stack->terminal_info (arg, from_tty);
 }
 
 /* See target.h.  */
@@ -615,23 +568,14 @@ target_terminal::info (const char *arg, int from_tty)
 int
 target_supports_terminal_ours (void)
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    {
-      if (t->to_terminal_ours != delegate_terminal_ours
-	  && t->to_terminal_ours != tdefault_terminal_ours)
-	return 1;
-    }
-
-  return 0;
+  return target_stack->supports_terminal_ours ();
 }
 
 static void
 tcomplain (void)
 {
   error (_("You can't do that when your target is `%s'"),
-	 current_target.to_shortname);
+	 target_stack->shortname ());
 }
 
 void
@@ -670,57 +614,6 @@ default_execution_direction (struct target_ops *self)
 to_execution_direction must be implemented for reverse async");
 }
 
-/* Go through the target stack from top to bottom, copying over zero
-   entries in current_target, then filling in still empty entries.  In
-   effect, we are doing class inheritance through the pushed target
-   vectors.
-
-   NOTE: cagney/2003-10-17: The problem with this inheritance, as it
-   is currently implemented, is that it discards any knowledge of
-   which target an inherited method originally belonged to.
-   Consequently, new new target methods should instead explicitly and
-   locally search the target stack for the target that can handle the
-   request.  */
-
-static void
-update_current_target (void)
-{
-  struct target_ops *t;
-
-  /* First, reset current's contents.  */
-  memset (&current_target, 0, sizeof (current_target));
-
-  /* Install the delegators.  */
-  install_delegators (&current_target);
-
-  current_target.to_stratum = target_stack->to_stratum;
-
-#define INHERIT(FIELD, TARGET) \
-      if (!current_target.FIELD) \
-	current_target.FIELD = (TARGET)->FIELD
-
-  /* Do not add any new INHERITs here.  Instead, use the delegation
-     mechanism provided by make-target-delegates.  */
-  for (t = target_stack; t; t = t->beneath)
-    {
-      INHERIT (to_shortname, t);
-      INHERIT (to_longname, t);
-      INHERIT (to_attach_no_wait, t);
-      INHERIT (to_have_steppable_watchpoint, t);
-      INHERIT (to_have_continuable_watchpoint, t);
-      INHERIT (to_has_thread_control, t);
-    }
-#undef INHERIT
-
-  /* Finally, position the target-stack beneath the squashed
-     "current_target".  That way code looking for a non-inherited
-     target method can quickly and simply find it.  */
-  current_target.beneath = target_stack;
-
-  if (targetdebug)
-    setup_target_debug ();
-}
-
 /* Push a new target type into the stack of the existing target accessors,
    possibly superseding some of the existing accessors.
 
@@ -733,17 +626,6 @@ push_target (struct target_ops *t)
 {
   struct target_ops **cur;
 
-  /* Check magic number.  If wrong, it probably means someone changed
-     the struct definition, but not all the places that initialize one.  */
-  if (t->to_magic != OPS_MAGIC)
-    {
-      fprintf_unfiltered (gdb_stderr,
-			  "Magic number of %s target struct wrong\n",
-			  t->to_shortname);
-      internal_error (__FILE__, __LINE__,
-		      _("failed internal consistency check"));
-    }
-
   /* Find the proper stratum to install this target in.  */
   for (cur = &target_stack; (*cur) != NULL; cur = &(*cur)->beneath)
     {
@@ -768,8 +650,6 @@ push_target (struct target_ops *t)
   /* We have removed all targets in our stratum, now add the new one.  */
   t->beneath = (*cur);
   (*cur) = t;
-
-  update_current_target ();
 }
 
 /* Remove a target_ops vector from the stack, wherever it may be.
@@ -804,8 +684,6 @@ unpush_target (struct target_ops *t)
   (*cur) = (*cur)->beneath;
   tmp->beneath = NULL;
 
-  update_current_target ();
-
   /* Finally close the target.  Note we do this after unchaining, so
      any target method calls from within the target_close
      implementation don't end up in T anymore.  */
@@ -823,7 +701,7 @@ unpush_target_and_assert (struct target_ops *target)
     {
       fprintf_unfiltered (gdb_stderr,
 			  "pop_all_targets couldn't find target %s\n",
-			  target->to_shortname);
+			  target->shortname ());
       internal_error (__FILE__, __LINE__,
 		      _("failed internal consistency check"));
     }
@@ -832,7 +710,7 @@ unpush_target_and_assert (struct target_ops *target)
 void
 pop_all_targets_above (enum strata above_stratum)
 {
-  while ((int) (current_target.to_stratum) > (int) above_stratum)
+  while ((int) (target_stack->to_stratum) > (int) above_stratum)
     unpush_target_and_assert (target_stack);
 }
 
@@ -841,7 +719,7 @@ pop_all_targets_above (enum strata above_stratum)
 void
 pop_all_targets_at_and_above (enum strata stratum)
 {
-  while ((int) (current_target.to_stratum) >= (int) stratum)
+  while ((int) (target_stack->to_stratum) >= (int) stratum)
     unpush_target_and_assert (target_stack);
 }
 
@@ -858,17 +736,6 @@ target_is_pushed (struct target_ops *t)
 {
   struct target_ops *cur;
 
-  /* Check magic number.  If wrong, it probably means someone changed
-     the struct definition, but not all the places that initialize one.  */
-  if (t->to_magic != OPS_MAGIC)
-    {
-      fprintf_unfiltered (gdb_stderr,
-			  "Magic number of %s target struct wrong\n",
-			  t->to_shortname);
-      internal_error (__FILE__, __LINE__,
-		      _("failed internal consistency check"));
-    }
-
   for (cur = target_stack; cur != NULL; cur = cur->beneath)
     if (cur == t)
       return 1;
@@ -891,7 +758,7 @@ CORE_ADDR
 target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
 {
   volatile CORE_ADDR addr = 0;
-  struct target_ops *target = &current_target;
+  struct target_ops *target = target_stack;
 
   if (gdbarch_fetch_tls_load_module_address_p (target_gdbarch ()))
     {
@@ -905,8 +772,7 @@ target_translate_tls_address (struct objfile *objfile, CORE_ADDR offset)
 	  lm_addr = gdbarch_fetch_tls_load_module_address (target_gdbarch (),
 	                                                   objfile);
 
-	  addr = target->to_get_thread_local_address (target, ptid,
-						      lm_addr, offset);
+	  addr = target->get_thread_local_address (ptid, lm_addr, offset);
 	}
       /* If an error occurred, print TLS related messages here.  Otherwise,
          throw the error to some higher catcher.  */
@@ -1064,7 +930,7 @@ done:
 struct target_section_table *
 target_get_section_table (struct target_ops *target)
 {
-  return (*target->to_get_section_table) (target);
+  return target->get_section_table ();
 }
 
 /* Find a section containing ADDR.  */
@@ -1152,9 +1018,9 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf,
 
   do
     {
-      res = ops->to_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-				  readbuf, writebuf, memaddr, len,
-				  xfered_len);
+      res = ops->xfer_partial (TARGET_OBJECT_MEMORY, NULL,
+			       readbuf, writebuf, memaddr, len,
+			       xfered_len);
       if (res == TARGET_XFER_OK)
 	break;
 
@@ -1164,7 +1030,7 @@ raw_memory_xfer_partial (struct target_ops *ops, gdb_byte *readbuf,
 
       /* We want to continue past core files to executables, but not
 	 past a running target's memory.  */
-      if (ops->to_has_all_memory (ops))
+      if (ops->has_all_memory ())
 	break;
 
       ops = ops->beneath;
@@ -1326,7 +1192,7 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
 	 shadow handling even though we only end up writing a small
 	 subset of it.  Cap writes to a limit specified by the target
 	 to mitigate this.  */
-      len = std::min (ops->to_get_memory_xfer_limit (ops), len);
+      len = std::min (ops->get_memory_xfer_limit (), len);
 
       gdb::byte_vector buf (writebuf, writebuf + len);
       breakpoint_xfer_memory (NULL, buf.data (), writebuf, memaddr, len);
@@ -1354,8 +1220,6 @@ target_xfer_partial (struct target_ops *ops,
 {
   enum target_xfer_status retval;
 
-  gdb_assert (ops->to_xfer_partial != NULL);
-
   /* Transfer is done when LEN is zero.  */
   if (len == 0)
     return TARGET_XFER_EOF;
@@ -1390,8 +1254,8 @@ target_xfer_partial (struct target_ops *ops,
 					xfered_len);
     }
   else
-    retval = ops->to_xfer_partial (ops, object, annex, readbuf,
-				   writebuf, offset, len, xfered_len);
+    retval = ops->xfer_partial (object, annex, readbuf,
+				writebuf, offset, len, xfered_len);
 
   if (targetdebug)
     {
@@ -1400,7 +1264,7 @@ target_xfer_partial (struct target_ops *ops,
       fprintf_unfiltered (gdb_stdlog,
 			  "%s:target_xfer_partial "
 			  "(%d, %s, %s, %s, %s, %s) = %d, %s",
-			  ops->to_shortname,
+			  ops->shortname (),
 			  (int) object,
 			  (annex ? annex : "(null)"),
 			  host_address_to_string (readbuf),
@@ -1460,10 +1324,7 @@ target_xfer_partial (struct target_ops *ops,
 int
 target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* Dispatch to the topmost target, not the flattened current_target.
-     Memory accesses check target->to_has_(all_)memory, and the
-     flattened target doesn't inherit those.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
+  if (target_read (target_stack, TARGET_OBJECT_MEMORY, NULL,
 		   myaddr, memaddr, len) == len)
     return 0;
   else
@@ -1493,9 +1354,7 @@ target_read_uint32 (CORE_ADDR memaddr, uint32_t *result)
 int
 target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL,
+  if (target_read (target_stack, TARGET_OBJECT_RAW_MEMORY, NULL,
 		   myaddr, memaddr, len) == len)
     return 0;
   else
@@ -1508,9 +1367,7 @@ target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 int
 target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_STACK_MEMORY, NULL,
+  if (target_read (target_stack, TARGET_OBJECT_STACK_MEMORY, NULL,
 		   myaddr, memaddr, len) == len)
     return 0;
   else
@@ -1523,9 +1380,7 @@ target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 int
 target_read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_read (current_target.beneath, TARGET_OBJECT_CODE_MEMORY, NULL,
+  if (target_read (target_stack, TARGET_OBJECT_CODE_MEMORY, NULL,
 		   myaddr, memaddr, len) == len)
     return 0;
   else
@@ -1541,9 +1396,7 @@ target_read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
 int
 target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_write (current_target.beneath, TARGET_OBJECT_MEMORY, NULL,
+  if (target_write (target_stack, TARGET_OBJECT_MEMORY, NULL,
 		    myaddr, memaddr, len) == len)
     return 0;
   else
@@ -1559,9 +1412,7 @@ target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
 int
 target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
 {
-  /* See comment in target_read_memory about why the request starts at
-     current_target.beneath.  */
-  if (target_write (current_target.beneath, TARGET_OBJECT_RAW_MEMORY, NULL,
+  if (target_write (target_stack, TARGET_OBJECT_RAW_MEMORY, NULL,
 		    myaddr, memaddr, len) == len)
     return 0;
   else
@@ -1573,8 +1424,7 @@ target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
 std::vector<mem_region>
 target_memory_map (void)
 {
-  std::vector<mem_region> result
-    = current_target.to_memory_map (&current_target);
+  std::vector<mem_region> result = target_stack->memory_map ();
   if (result.empty ())
     return result;
 
@@ -1604,13 +1454,13 @@ target_memory_map (void)
 void
 target_flash_erase (ULONGEST address, LONGEST length)
 {
-  current_target.to_flash_erase (&current_target, address, length);
+  target_stack->flash_erase (address, length);
 }
 
 void
 target_flash_done (void)
 {
-  current_target.to_flash_done (&current_target);
+  target_stack->flash_done ();
 }
 
 static void
@@ -2065,8 +1915,7 @@ target_insert_breakpoint (struct gdbarch *gdbarch,
       return 1;
     }
 
-  return current_target.to_insert_breakpoint (&current_target,
-					      gdbarch, bp_tgt);
+  return target_stack->insert_breakpoint (gdbarch, bp_tgt);
 }
 
 /* See target.h.  */
@@ -2086,8 +1935,7 @@ target_remove_breakpoint (struct gdbarch *gdbarch,
       return 1;
     }
 
-  return current_target.to_remove_breakpoint (&current_target,
-					      gdbarch, bp_tgt, reason);
+  return target_stack->remove_breakpoint (gdbarch, bp_tgt, reason);
 }
 
 static void
@@ -2102,7 +1950,7 @@ info_target_command (const char *args, int from_tty)
 
   for (t = target_stack; t != NULL; t = t->beneath)
     {
-      if (!(*t->to_has_memory) (t))
+      if (!t->has_memory ())
 	continue;
 
       if ((int) (t->to_stratum) <= (int) dummy_stratum)
@@ -2110,9 +1958,9 @@ info_target_command (const char *args, int from_tty)
       if (has_all_mem)
 	printf_unfiltered (_("\tWhile running this, "
 			     "GDB does not access memory from...\n"));
-      printf_unfiltered ("%s:\n", t->to_longname);
-      (t->to_files_info) (t);
-      has_all_mem = (*t->to_has_all_memory) (t);
+      printf_unfiltered ("%s:\n", t->longname ());
+      t->files_info ();
+      has_all_mem = t->has_all_memory ();
     }
 }
 
@@ -2236,7 +2084,7 @@ target_detach (inferior *inf, int from_tty)
 
   prepare_for_detach ();
 
-  current_target.to_detach (&current_target, inf, from_tty);
+  target_stack->detach (inf, from_tty);
 }
 
 void
@@ -2247,7 +2095,7 @@ target_disconnect (const char *args, int from_tty)
      disconnecting.  */
   remove_breakpoints ();
 
-  current_target.to_disconnect (&current_target, args, from_tty);
+  target_stack->disconnect (args, from_tty);
 }
 
 /* See target/target.h.  */
@@ -2255,7 +2103,7 @@ target_disconnect (const char *args, int from_tty)
 ptid_t
 target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
 {
-  return (current_target.to_wait) (&current_target, ptid, status, options);
+  return target_stack->wait (ptid, status, options);
 }
 
 /* See target.h.  */
@@ -2272,13 +2120,13 @@ default_target_wait (struct target_ops *ops,
 const char *
 target_pid_to_str (ptid_t ptid)
 {
-  return (*current_target.to_pid_to_str) (&current_target, ptid);
+  return target_stack->pid_to_str (ptid);
 }
 
 const char *
 target_thread_name (struct thread_info *info)
 {
-  return current_target.to_thread_name (&current_target, info);
+  return target_stack->thread_name (info);
 }
 
 struct thread_info *
@@ -2286,8 +2134,8 @@ target_thread_handle_to_thread_info (const gdb_byte *thread_handle,
 				     int handle_len,
 				     struct inferior *inf)
 {
-  return current_target.to_thread_handle_to_thread_info
-           (&current_target, thread_handle, handle_len, inf);
+  return target_stack->thread_handle_to_thread_info (thread_handle,
+						     handle_len, inf);
 }
 
 void
@@ -2295,7 +2143,7 @@ target_resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
   target_dcache_invalidate ();
 
-  current_target.to_resume (&current_target, ptid, step, signal);
+  target_stack->resume (ptid, step, signal);
 
   registers_changed_ptid (ptid);
   /* We only set the internal executing state here.  The user/frontend
@@ -2315,7 +2163,7 @@ target_commit_resume (void)
   if (defer_target_commit_resume)
     return;
 
-  current_target.to_commit_resume (&current_target);
+  target_stack->commit_resume ();
 }
 
 /* See target.h.  */
@@ -2329,14 +2177,13 @@ make_scoped_defer_target_commit_resume ()
 void
 target_pass_signals (int numsigs, unsigned char *pass_signals)
 {
-  (*current_target.to_pass_signals) (&current_target, numsigs, pass_signals);
+  target_stack->pass_signals (numsigs, pass_signals);
 }
 
 void
 target_program_signals (int numsigs, unsigned char *program_signals)
 {
-  (*current_target.to_program_signals) (&current_target,
-					numsigs, program_signals);
+  target_stack->program_signals (numsigs, program_signals);
 }
 
 static int
@@ -2354,8 +2201,7 @@ default_follow_fork (struct target_ops *self, int follow_child,
 int
 target_follow_fork (int follow_child, int detach_fork)
 {
-  return current_target.to_follow_fork (&current_target,
-					follow_child, detach_fork);
+  return target_stack->follow_fork (follow_child, detach_fork);
 }
 
 /* Target wrapper for follow exec hook.  */
@@ -2363,7 +2209,7 @@ target_follow_fork (int follow_child, int detach_fork)
 void
 target_follow_exec (struct inferior *inf, char *execd_pathname)
 {
-  current_target.to_follow_exec (&current_target, inf, execd_pathname);
+  target_stack->follow_exec (inf, execd_pathname);
 }
 
 static void
@@ -2377,7 +2223,7 @@ void
 target_mourn_inferior (ptid_t ptid)
 {
   gdb_assert (ptid_equal (ptid, inferior_ptid));
-  current_target.to_mourn_inferior (&current_target);
+  target_stack->mourn_inferior ();
 
   /* We no longer need to keep handles on any of the object files.
      Make sure to release them to avoid unnecessarily locking any
@@ -2391,7 +2237,7 @@ target_mourn_inferior (ptid_t ptid)
 const struct target_desc *
 target_read_description (struct target_ops *target)
 {
-  return target->to_read_description (target);
+  return target->read_description ();
 }
 
 /* This implements a basic search of memory, reading target memory and
@@ -2504,7 +2350,7 @@ default_search_memory (struct target_ops *self,
 		       CORE_ADDR *found_addrp)
 {
   /* Start over from the top of the target stack.  */
-  return simple_search_memory (current_target.beneath,
+  return simple_search_memory (target_stack,
 			       start_addr, search_space_len,
 			       pattern, pattern_len, found_addrp);
 }
@@ -2521,9 +2367,8 @@ target_search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
 		      const gdb_byte *pattern, ULONGEST pattern_len,
 		      CORE_ADDR *found_addrp)
 {
-  return current_target.to_search_memory (&current_target, start_addr,
-					  search_space_len,
-					  pattern, pattern_len, found_addrp);
+  return target_stack->search_memory (start_addr, search_space_len,
+				      pattern, pattern_len, found_addrp);
 }
 
 /* Look through the currently pushed targets.  If none of them will
@@ -2541,20 +2386,18 @@ target_require_runnable (void)
 	 assume we will still be able to after killing the current
 	 one.  Either killing and mourning will not pop T, or else
 	 find_default_run_target will find it again.  */
-      if (t->to_create_inferior != NULL)
+      if (t->can_create_inferior ())
 	return;
 
       /* Do not worry about targets at certain strata that can not
 	 create inferiors.  Assume they will be pushed again if
 	 necessary, and continue to the process_stratum.  */
-      if (t->to_stratum == thread_stratum
-	  || t->to_stratum == record_stratum
-	  || t->to_stratum == arch_stratum)
+      if (t->to_stratum > process_stratum)
 	continue;
 
       error (_("The \"%s\" target does not support \"run\".  "
 	       "Try \"help target\" or \"continue\"."),
-	     t->to_shortname);
+	     t->shortname ());
     }
 
   /* This function is only called if the target is running.  In that
@@ -2597,7 +2440,7 @@ find_default_run_target (const char *do_mesg)
 
       for (i = 0; VEC_iterate (target_ops_p, target_structs, i, t); ++i)
 	{
-	  if (t->to_can_run != delegate_can_run && target_can_run (t))
+	  if (t->can_run ())
 	    {
 	      runable = t;
 	      ++count;
@@ -2627,9 +2470,9 @@ find_attach_target (void)
   struct target_ops *t;
 
   /* If a target on the current stack can attach, use it.  */
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
+  for (t = target_stack; t != NULL; t = t->beneath)
     {
-      if (t->to_attach != NULL)
+      if (t->can_attach ())
 	break;
     }
 
@@ -2647,10 +2490,10 @@ find_run_target (void)
 {
   struct target_ops *t;
 
-  /* If a target on the current stack can attach, use it.  */
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
+  /* If a target on the current stack can run, use it.  */
+  for (t = target_stack; t != NULL; t = t->beneath)
     {
-      if (t->to_create_inferior != NULL)
+      if (t->can_create_inferior ())
 	break;
     }
 
@@ -2661,6 +2504,12 @@ find_run_target (void)
   return t;
 }
 
+bool
+target_ops::info_proc (const char *args, enum info_proc_what what)
+{
+  return false;
+}
+
 /* Implement the "info proc" command.  */
 
 int
@@ -2671,17 +2520,14 @@ target_info_proc (const char *args, enum info_proc_what what)
   /* If we're already connected to something that can get us OS
      related data, use it.  Otherwise, try using the native
      target.  */
-  if (current_target.to_stratum >= process_stratum)
-    t = current_target.beneath;
-  else
+  t = find_target_at (process_stratum);
+  if (t == NULL)
     t = find_default_run_target (NULL);
 
   for (; t != NULL; t = t->beneath)
     {
-      if (t->to_info_proc != NULL)
+      if (t->info_proc (args, what))
 	{
-	  t->to_info_proc (t, args, what);
-
 	  if (targetdebug)
 	    fprintf_unfiltered (gdb_stdlog,
 				"target_info_proc (\"%s\", %d)\n", args, what);
@@ -2699,21 +2545,15 @@ find_default_supports_disable_randomization (struct target_ops *self)
   struct target_ops *t;
 
   t = find_default_run_target (NULL);
-  if (t && t->to_supports_disable_randomization)
-    return (t->to_supports_disable_randomization) (t);
+  if (t != NULL)
+    return t->supports_disable_randomization ();
   return 0;
 }
 
 int
 target_supports_disable_randomization (void)
 {
-  struct target_ops *t;
-
-  for (t = &current_target; t != NULL; t = t->beneath)
-    if (t->to_supports_disable_randomization)
-      return t->to_supports_disable_randomization (t);
-
-  return 0;
+  return target_stack->supports_disable_randomization ();
 }
 
 /* See target/target.h.  */
@@ -2721,7 +2561,7 @@ target_supports_disable_randomization (void)
 int
 target_supports_multi_process (void)
 {
-  return (*current_target.to_supports_multi_process) (&current_target);
+  return target_stack->supports_multi_process ();
 }
 
 /* See target.h.  */
@@ -2734,9 +2574,8 @@ target_get_osdata (const char *type)
   /* If we're already connected to something that can get us OS
      related data, use it.  Otherwise, try using the native
      target.  */
-  if (current_target.to_stratum >= process_stratum)
-    t = current_target.beneath;
-  else
+  t = find_target_at (process_stratum);
+  if (t == NULL)
     t = find_default_run_target ("get OS data");
 
   if (!t)
@@ -2769,24 +2608,81 @@ target_thread_address_space (ptid_t ptid)
 {
   struct address_space *aspace;
 
-  aspace = current_target.to_thread_address_space (&current_target, ptid);
+  aspace = target_stack->thread_address_space (ptid);
   gdb_assert (aspace != NULL);
 
   return aspace;
 }
 
+void
+target_ops::open (const char *, int)
+{
+  gdb_assert_not_reached ("target_ops::open called");
+}
+
+void
+target_ops::close ()
+{
+}
+
+bool
+target_ops::can_attach ()
+{
+  return 0;
+}
+
+void
+target_ops::attach (const char *, int)
+{
+  gdb_assert_not_reached ("target_ops::attach called");
+}
+
+bool
+target_ops::can_create_inferior ()
+{
+  return 0;
+}
+
+void
+target_ops::create_inferior (const char *, const std::string &,
+			     char **, int)
+{
+  gdb_assert_not_reached ("target_ops::create_inferior called");
+}
+
+int
+target_ops::can_run ()
+{
+  return 0;
+}
+
+int
+target_can_run ()
+{
+  struct target_ops *t;
+
+  for (t = target_stack; t != NULL; t = t->beneath)
+    {
+      if (t->can_run ())
+	return 1;
+    }
+
+  return 0;
+}
 
 /* Target file operations.  */
 
 static struct target_ops *
 default_fileio_target (void)
 {
+  struct target_ops *t;
+
   /* If we're already connected to something that can perform
      file I/O, use it. Otherwise, try using the native target.  */
-  if (current_target.to_stratum >= process_stratum)
-    return current_target.beneath;
-  else
-    return find_default_run_target ("file I/O");
+  t = find_target_at (process_stratum);
+  if (t != NULL)
+    return t;
+  return find_default_run_target ("file I/O");
 }
 
 /* File handle for target file operations.  */
@@ -2878,6 +2774,67 @@ fileio_fd_to_fh (int fd)
   return &fileio_fhandles[fd];
 }
 
+
+/* Default implementations of file i/o methods.  We don't want these
+   to delegate automatically, because we need to know which target
+   supported the method, in order to call it directly from within
+   pread/pwrite, etc.  */
+
+int
+target_ops::fileio_open (struct inferior *inf, const char *filename,
+			 int flags, int mode, int warn_if_slow,
+			 int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+int
+target_ops::fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+			   ULONGEST offset, int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+int
+target_ops::fileio_pread (int fd, gdb_byte *read_buf, int len,
+			  ULONGEST offset, int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+int
+target_ops::fileio_fstat (int fd, struct stat *sb, int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+int
+target_ops::fileio_close (int fd, int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+int
+target_ops::fileio_unlink (struct inferior *inf, const char *filename,
+			   int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return -1;
+}
+
+gdb::optional<std::string>
+target_ops::fileio_readlink (struct inferior *inf, const char *filename,
+			     int *target_errno)
+{
+  *target_errno = FILEIO_ENOSYS;
+  return {};
+}
+
 /* Helper for target_fileio_open and
    target_fileio_open_warn_if_slow.  */
 
@@ -2890,26 +2847,26 @@ target_fileio_open_1 (struct inferior *inf, const char *filename,
 
   for (t = default_fileio_target (); t != NULL; t = t->beneath)
     {
-      if (t->to_fileio_open != NULL)
-	{
-	  int fd = t->to_fileio_open (t, inf, filename, flags, mode,
-				      warn_if_slow, target_errno);
+      int fd = t->fileio_open (inf, filename, flags, mode,
+			       warn_if_slow, target_errno);
 
-	  if (fd < 0)
-	    fd = -1;
-	  else
-	    fd = acquire_fileio_fd (t, fd);
+      if (fd == -1 && *target_errno == FILEIO_ENOSYS)
+	continue;
 
-	  if (targetdebug)
-	    fprintf_unfiltered (gdb_stdlog,
+      if (fd < 0)
+	fd = -1;
+      else
+	fd = acquire_fileio_fd (t, fd);
+
+      if (targetdebug)
+	fprintf_unfiltered (gdb_stdlog,
 				"target_fileio_open (%d,%s,0x%x,0%o,%d)"
 				" = %d (%d)\n",
 				inf == NULL ? 0 : inf->num,
 				filename, flags, mode,
 				warn_if_slow, fd,
 				fd != -1 ? 0 : *target_errno);
-	  return fd;
-	}
+      return fd;
     }
 
   *target_errno = FILEIO_ENOSYS;
@@ -2951,8 +2908,8 @@ target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
   else if (fh->target == NULL)
     *target_errno = EIO;
   else
-    ret = fh->target->to_fileio_pwrite (fh->target, fh->target_fd, write_buf,
-					len, offset, target_errno);
+    ret = fh->target->fileio_pwrite (fh->target_fd, write_buf,
+				     len, offset, target_errno);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
@@ -2977,8 +2934,8 @@ target_fileio_pread (int fd, gdb_byte *read_buf, int len,
   else if (fh->target == NULL)
     *target_errno = EIO;
   else
-    ret = fh->target->to_fileio_pread (fh->target, fh->target_fd, read_buf,
-				       len, offset, target_errno);
+    ret = fh->target->fileio_pread (fh->target_fd, read_buf,
+				    len, offset, target_errno);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
@@ -3002,8 +2959,7 @@ target_fileio_fstat (int fd, struct stat *sb, int *target_errno)
   else if (fh->target == NULL)
     *target_errno = EIO;
   else
-    ret = fh->target->to_fileio_fstat (fh->target, fh->target_fd,
-				       sb, target_errno);
+    ret = fh->target->fileio_fstat (fh->target_fd, sb, target_errno);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
@@ -3025,8 +2981,8 @@ target_fileio_close (int fd, int *target_errno)
   else
     {
       if (fh->target != NULL)
-	ret = fh->target->to_fileio_close (fh->target, fh->target_fd,
-					   target_errno);
+	ret = fh->target->fileio_close (fh->target_fd,
+					target_errno);
       else
 	ret = 0;
       release_fileio_fd (fd, fh);
@@ -3049,19 +3005,18 @@ target_fileio_unlink (struct inferior *inf, const char *filename,
 
   for (t = default_fileio_target (); t != NULL; t = t->beneath)
     {
-      if (t->to_fileio_unlink != NULL)
-	{
-	  int ret = t->to_fileio_unlink (t, inf, filename,
-					 target_errno);
+      int ret = t->fileio_unlink (inf, filename, target_errno);
 
-	  if (targetdebug)
-	    fprintf_unfiltered (gdb_stdlog,
-				"target_fileio_unlink (%d,%s)"
-				" = %d (%d)\n",
-				inf == NULL ? 0 : inf->num, filename,
-				ret, ret != -1 ? 0 : *target_errno);
-	  return ret;
-	}
+      if (ret == -1 && *target_errno == FILEIO_ENOSYS)
+	continue;
+
+      if (targetdebug)
+	fprintf_unfiltered (gdb_stdlog,
+			    "target_fileio_unlink (%d,%s)"
+			    " = %d (%d)\n",
+			    inf == NULL ? 0 : inf->num, filename,
+			    ret, ret != -1 ? 0 : *target_errno);
+      return ret;
     }
 
   *target_errno = FILEIO_ENOSYS;
@@ -3078,20 +3033,20 @@ target_fileio_readlink (struct inferior *inf, const char *filename,
 
   for (t = default_fileio_target (); t != NULL; t = t->beneath)
     {
-      if (t->to_fileio_readlink != NULL)
-	{
-	  gdb::optional<std::string> ret
-	    = t->to_fileio_readlink (t, inf, filename, target_errno);
+      gdb::optional<std::string> ret
+	= t->fileio_readlink (inf, filename, target_errno);
 
-	  if (targetdebug)
-	    fprintf_unfiltered (gdb_stdlog,
-				"target_fileio_readlink (%d,%s)"
-				" = %s (%d)\n",
-				inf == NULL ? 0 : inf->num,
-				filename, ret ? ret->c_str () : "(nil)",
-				ret ? 0 : *target_errno);
-	  return ret;
-	}
+      if (!ret.has_value () && *target_errno == FILEIO_ENOSYS)
+	continue;
+
+      if (targetdebug)
+	fprintf_unfiltered (gdb_stdlog,
+			    "target_fileio_readlink (%d,%s)"
+			    " = %s (%d)\n",
+			    inf == NULL ? 0 : inf->num,
+			    filename, ret ? ret->c_str () : "(nil)",
+			    ret ? 0 : *target_errno);
+      return ret;
     }
 
   *target_errno = FILEIO_ENOSYS;
@@ -3256,18 +3211,6 @@ default_thread_architecture (struct target_ops *ops, ptid_t ptid)
   return inf->gdbarch;
 }
 
-static int
-return_zero (struct target_ops *ignore)
-{
-  return 0;
-}
-
-static int
-return_zero_has_execution (struct target_ops *ignore, ptid_t ignore2)
-{
-  return 0;
-}
-
 /*
  * Find the next target down the stack from the specified target.
  */
@@ -3285,7 +3228,7 @@ find_target_at (enum strata stratum)
 {
   struct target_ops *t;
 
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
+  for (t = target_stack; t != NULL; t = t->beneath)
     if (t->to_stratum == stratum)
       return t;
 
@@ -3386,27 +3329,55 @@ dummy_make_corefile_notes (struct target_ops *self,
   return NULL;
 }
 
-/* Set up the handful of non-empty slots needed by the dummy target
-   vector.  */
+#include "target-delegates.c"
+
 
-static void
-init_dummy_target (void)
-{
-  dummy_target.to_shortname = "None";
-  dummy_target.to_longname = "None";
-  dummy_target.to_doc = "";
-  dummy_target.to_supports_disable_randomization
-    = find_default_supports_disable_randomization;
-  dummy_target.to_stratum = dummy_stratum;
-  dummy_target.to_has_all_memory = return_zero;
-  dummy_target.to_has_memory = return_zero;
-  dummy_target.to_has_stack = return_zero;
-  dummy_target.to_has_registers = return_zero;
-  dummy_target.to_has_execution = return_zero_has_execution;
-  dummy_target.to_magic = OPS_MAGIC;
-
-  install_dummy_methods (&dummy_target);
+dummy_target::dummy_target ()
+{
+  to_stratum = dummy_stratum;
+}
+
+const char *
+dummy_target::shortname ()
+{
+  return "None";
+}
+
+const char *
+dummy_target::longname ()
+{
+  return _("None");
 }
+
+const char *
+dummy_target::doc ()
+{
+  return "";
+}
+
+debug_target::debug_target ()
+{
+  to_stratum = debug_stratum;
+}
+
+const char *
+debug_target::shortname ()
+{
+  return beneath->shortname ();
+}
+
+const char *
+debug_target::longname ()
+{
+  return beneath->longname ();
+}
+
+const char *
+debug_target::doc ()
+{
+  return beneath->doc ();
+}
+
 
 
 void
@@ -3416,8 +3387,7 @@ target_close (struct target_ops *targ)
 
   fileio_handles_invalidate_target (targ);
 
-  if (targ->to_close != NULL)
-    targ->to_close (targ);
+  targ->close ();
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog, "target_close ()\n");
@@ -3426,13 +3396,13 @@ target_close (struct target_ops *targ)
 int
 target_thread_alive (ptid_t ptid)
 {
-  return current_target.to_thread_alive (&current_target, ptid);
+  return target_stack->thread_alive (ptid);
 }
 
 void
 target_update_thread_list (void)
 {
-  current_target.to_update_thread_list (&current_target);
+  target_stack->update_thread_list ();
 }
 
 void
@@ -3444,7 +3414,7 @@ target_stop (ptid_t ptid)
       return;
     }
 
-  (*current_target.to_stop) (&current_target, ptid);
+  target_stack->stop (ptid);
 }
 
 void
@@ -3456,7 +3426,7 @@ target_interrupt ()
       return;
     }
 
-  (*current_target.to_interrupt) (&current_target);
+  target_stack->interrupt ();
 }
 
 /* See target.h.  */
@@ -3464,7 +3434,7 @@ target_interrupt ()
 void
 target_pass_ctrlc (void)
 {
-  (*current_target.to_pass_ctrlc) (&current_target);
+  target_stack->pass_ctrlc ();
 }
 
 /* See target.h.  */
@@ -3559,7 +3529,7 @@ target_options_to_string (int target_options)
 void
 target_fetch_registers (struct regcache *regcache, int regno)
 {
-  current_target.to_fetch_registers (&current_target, regcache, regno);
+  target_stack->fetch_registers (regcache, regno);
   if (targetdebug)
     regcache->debug_print_register ("target_fetch_registers", regno);
 }
@@ -3570,7 +3540,7 @@ target_store_registers (struct regcache *regcache, int regno)
   if (!may_write_registers)
     error (_("Writing to registers is not allowed (regno %d)"), regno);
 
-  current_target.to_store_registers (&current_target, regcache, regno);
+  target_stack->store_registers (regcache, regno);
   if (targetdebug)
     {
       regcache->debug_print_register ("target_store_registers", regno);
@@ -3580,7 +3550,7 @@ target_store_registers (struct regcache *regcache, int regno)
 int
 target_core_of_thread (ptid_t ptid)
 {
-  return current_target.to_core_of_thread (&current_target, ptid);
+  return target_stack->core_of_thread (ptid);
 }
 
 int
@@ -3618,15 +3588,14 @@ default_verify_memory (struct target_ops *self,
 		       const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
 {
   /* Start over from the top of the target stack.  */
-  return simple_verify_memory (current_target.beneath,
+  return simple_verify_memory (target_stack,
 			       data, memaddr, size);
 }
 
 int
 target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
 {
-  return current_target.to_verify_memory (&current_target,
-					  data, memaddr, size);
+  return target_stack->verify_memory (data, memaddr, size);
 }
 
 /* The documentation for this function is in its prototype declaration in
@@ -3636,8 +3605,7 @@ int
 target_insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
 			       enum target_hw_bp_type rw)
 {
-  return current_target.to_insert_mask_watchpoint (&current_target,
-						   addr, mask, rw);
+  return target_stack->insert_mask_watchpoint (addr, mask, rw);
 }
 
 /* The documentation for this function is in its prototype declaration in
@@ -3647,8 +3615,7 @@ int
 target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
 			       enum target_hw_bp_type rw)
 {
-  return current_target.to_remove_mask_watchpoint (&current_target,
-						   addr, mask, rw);
+  return target_stack->remove_mask_watchpoint (addr, mask, rw);
 }
 
 /* The documentation for this function is in its prototype declaration
@@ -3657,8 +3624,7 @@ target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask,
 int
 target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask)
 {
-  return current_target.to_masked_watch_num_registers (&current_target,
-						       addr, mask);
+  return target_stack->masked_watch_num_registers (addr, mask);
 }
 
 /* The documentation for this function is in its prototype declaration
@@ -3667,7 +3633,7 @@ target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask)
 int
 target_ranged_break_num_registers (void)
 {
-  return current_target.to_ranged_break_num_registers (&current_target);
+  return target_stack->ranged_break_num_registers ();
 }
 
 /* See target.h.  */
@@ -3675,7 +3641,7 @@ target_ranged_break_num_registers (void)
 struct btrace_target_info *
 target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 {
-  return current_target.to_enable_btrace (&current_target, ptid, conf);
+  return target_stack->enable_btrace (ptid, conf);
 }
 
 /* See target.h.  */
@@ -3683,7 +3649,7 @@ target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 void
 target_disable_btrace (struct btrace_target_info *btinfo)
 {
-  current_target.to_disable_btrace (&current_target, btinfo);
+  target_stack->disable_btrace (btinfo);
 }
 
 /* See target.h.  */
@@ -3691,7 +3657,7 @@ target_disable_btrace (struct btrace_target_info *btinfo)
 void
 target_teardown_btrace (struct btrace_target_info *btinfo)
 {
-  current_target.to_teardown_btrace (&current_target, btinfo);
+  target_stack->teardown_btrace (btinfo);
 }
 
 /* See target.h.  */
@@ -3701,7 +3667,7 @@ target_read_btrace (struct btrace_data *btrace,
 		    struct btrace_target_info *btinfo,
 		    enum btrace_read_type type)
 {
-  return current_target.to_read_btrace (&current_target, btrace, btinfo, type);
+  return target_stack->read_btrace (btrace, btinfo, type);
 }
 
 /* See target.h.  */
@@ -3709,7 +3675,7 @@ target_read_btrace (struct btrace_data *btrace,
 const struct btrace_config *
 target_btrace_conf (const struct btrace_target_info *btinfo)
 {
-  return current_target.to_btrace_conf (&current_target, btinfo);
+  return target_stack->btrace_conf (btinfo);
 }
 
 /* See target.h.  */
@@ -3717,7 +3683,7 @@ target_btrace_conf (const struct btrace_target_info *btinfo)
 void
 target_stop_recording (void)
 {
-  current_target.to_stop_recording (&current_target);
+  target_stack->stop_recording ();
 }
 
 /* See target.h.  */
@@ -3725,22 +3691,15 @@ target_stop_recording (void)
 void
 target_save_record (const char *filename)
 {
-  current_target.to_save_record (&current_target, filename);
+  target_stack->save_record (filename);
 }
 
 /* See target.h.  */
 
 int
-target_supports_delete_record (void)
+target_supports_delete_record ()
 {
-  struct target_ops *t;
-
-  for (t = current_target.beneath; t != NULL; t = t->beneath)
-    if (t->to_delete_record != delegate_delete_record
-	&& t->to_delete_record != tdefault_delete_record)
-      return 1;
-
-  return 0;
+  return target_stack->supports_delete_record ();
 }
 
 /* See target.h.  */
@@ -3748,7 +3707,7 @@ target_supports_delete_record (void)
 void
 target_delete_record (void)
 {
-  current_target.to_delete_record (&current_target);
+  target_stack->delete_record ();
 }
 
 /* See target.h.  */
@@ -3756,7 +3715,7 @@ target_delete_record (void)
 enum record_method
 target_record_method (ptid_t ptid)
 {
-  return current_target.to_record_method (&current_target, ptid);
+  return target_stack->record_method (ptid);
 }
 
 /* See target.h.  */
@@ -3764,7 +3723,7 @@ target_record_method (ptid_t ptid)
 int
 target_record_is_replaying (ptid_t ptid)
 {
-  return current_target.to_record_is_replaying (&current_target, ptid);
+  return target_stack->record_is_replaying (ptid);
 }
 
 /* See target.h.  */
@@ -3772,7 +3731,7 @@ target_record_is_replaying (ptid_t ptid)
 int
 target_record_will_replay (ptid_t ptid, int dir)
 {
-  return current_target.to_record_will_replay (&current_target, ptid, dir);
+  return target_stack->record_will_replay (ptid, dir);
 }
 
 /* See target.h.  */
@@ -3780,7 +3739,7 @@ target_record_will_replay (ptid_t ptid, int dir)
 void
 target_record_stop_replaying (void)
 {
-  current_target.to_record_stop_replaying (&current_target);
+  target_stack->record_stop_replaying ();
 }
 
 /* See target.h.  */
@@ -3788,7 +3747,7 @@ target_record_stop_replaying (void)
 void
 target_goto_record_begin (void)
 {
-  current_target.to_goto_record_begin (&current_target);
+  target_stack->goto_record_begin ();
 }
 
 /* See target.h.  */
@@ -3796,7 +3755,7 @@ target_goto_record_begin (void)
 void
 target_goto_record_end (void)
 {
-  current_target.to_goto_record_end (&current_target);
+  target_stack->goto_record_end ();
 }
 
 /* See target.h.  */
@@ -3804,7 +3763,7 @@ target_goto_record_end (void)
 void
 target_goto_record (ULONGEST insn)
 {
-  current_target.to_goto_record (&current_target, insn);
+  target_stack->goto_record (insn);
 }
 
 /* See target.h.  */
@@ -3812,7 +3771,7 @@ target_goto_record (ULONGEST insn)
 void
 target_insn_history (int size, gdb_disassembly_flags flags)
 {
-  current_target.to_insn_history (&current_target, size, flags);
+  target_stack->insn_history (size, flags);
 }
 
 /* See target.h.  */
@@ -3821,7 +3780,7 @@ void
 target_insn_history_from (ULONGEST from, int size,
 			  gdb_disassembly_flags flags)
 {
-  current_target.to_insn_history_from (&current_target, from, size, flags);
+  target_stack->insn_history_from (from, size, flags);
 }
 
 /* See target.h.  */
@@ -3830,7 +3789,7 @@ void
 target_insn_history_range (ULONGEST begin, ULONGEST end,
 			   gdb_disassembly_flags flags)
 {
-  current_target.to_insn_history_range (&current_target, begin, end, flags);
+  target_stack->insn_history_range (begin, end, flags);
 }
 
 /* See target.h.  */
@@ -3838,7 +3797,7 @@ target_insn_history_range (ULONGEST begin, ULONGEST end,
 void
 target_call_history (int size, record_print_flags flags)
 {
-  current_target.to_call_history (&current_target, size, flags);
+  target_stack->call_history (size, flags);
 }
 
 /* See target.h.  */
@@ -3846,7 +3805,7 @@ target_call_history (int size, record_print_flags flags)
 void
 target_call_history_from (ULONGEST begin, int size, record_print_flags flags)
 {
-  current_target.to_call_history_from (&current_target, begin, size, flags);
+  target_stack->call_history_from (begin, size, flags);
 }
 
 /* See target.h.  */
@@ -3854,7 +3813,7 @@ target_call_history_from (ULONGEST begin, int size, record_print_flags flags)
 void
 target_call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
 {
-  current_target.to_call_history_range (&current_target, begin, end, flags);
+  target_stack->call_history_range (begin, end, flags);
 }
 
 /* See target.h.  */
@@ -3862,7 +3821,7 @@ target_call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flag
 const struct frame_unwind *
 target_get_unwinder (void)
 {
-  return current_target.to_get_unwinder (&current_target);
+  return target_stack->get_unwinder ();
 }
 
 /* See target.h.  */
@@ -3870,7 +3829,7 @@ target_get_unwinder (void)
 const struct frame_unwind *
 target_get_tailcall_unwinder (void)
 {
-  return current_target.to_get_tailcall_unwinder (&current_target);
+  return target_stack->get_tailcall_unwinder ();
 }
 
 /* See target.h.  */
@@ -3878,7 +3837,7 @@ target_get_tailcall_unwinder (void)
 void
 target_prepare_to_generate_core (void)
 {
-  current_target.to_prepare_to_generate_core (&current_target);
+  target_stack->prepare_to_generate_core ();
 }
 
 /* See target.h.  */
@@ -3886,16 +3845,9 @@ target_prepare_to_generate_core (void)
 void
 target_done_generating_core (void)
 {
-  current_target.to_done_generating_core (&current_target);
+  target_stack->done_generating_core ();
 }
 
-static void
-setup_target_debug (void)
-{
-  memcpy (&debug_target, &current_target, sizeof debug_target);
-
-  init_debug_target (&current_target);
-}
 
 
 static char targ_desc[] =
@@ -3965,7 +3917,9 @@ maintenance_print_target_stack (const char *cmd, int from_tty)
 
   for (t = target_stack; t != NULL; t = t->beneath)
     {
-      printf_filtered ("  - %s (%s)\n", t->to_shortname, t->to_longname);
+      if (t->to_stratum == debug_stratum)
+	continue;
+      printf_filtered ("  - %s (%s)\n", t->shortname (), t->longname ());
     }
 }
 
@@ -3975,7 +3929,7 @@ void
 target_async (int enable)
 {
   infrun_async (enable);
-  current_target.to_async (&current_target, enable);
+  target_stack->async (enable);
 }
 
 /* See target.h.  */
@@ -3983,7 +3937,7 @@ target_async (int enable)
 void
 target_thread_events (int enable)
 {
-  current_target.to_thread_events (&current_target, enable);
+  target_stack->thread_events (enable);
 }
 
 /* Controls if targets can report that they can/are async.  This is
@@ -4023,7 +3977,7 @@ maint_show_target_async_command (struct ui_file *file, int from_tty,
 static int
 target_always_non_stop_p (void)
 {
-  return current_target.to_always_non_stop_p (&current_target);
+  return target_stack->always_non_stop_p ();
 }
 
 /* See target.h.  */
@@ -4133,59 +4087,13 @@ set_write_memory_permission (const char *args, int from_tty,
   update_observer_mode ();
 }
 
-#if GDB_SELF_TEST
-namespace selftests {
-
-static int
-test_target_has_registers (target_ops *self)
-{
-  return 1;
-}
-
-static int
-test_target_has_stack (target_ops *self)
-{
-  return 1;
-}
-
-static int
-test_target_has_memory (target_ops *self)
-{
-  return 1;
-}
-
-static void
-test_target_prepare_to_store (target_ops *self, regcache *regs)
-{
-}
-
-static void
-test_target_store_registers (target_ops *self, regcache *regs, int regno)
-{
-}
-
-test_target_ops::test_target_ops ()
-  : target_ops {}
-{
-  to_magic = OPS_MAGIC;
-  to_stratum = process_stratum;
-  to_has_memory = test_target_has_memory;
-  to_has_stack = test_target_has_stack;
-  to_has_registers = test_target_has_registers;
-  to_prepare_to_store = test_target_prepare_to_store;
-  to_store_registers = test_target_store_registers;
-
-  complete_target_initialization (this);
-}
-
-} // namespace selftests
-#endif /* GDB_SELF_TEST */
-
 void
 initialize_targets (void)
 {
-  init_dummy_target ();
-  push_target (&dummy_target);
+  the_dummy_target = new dummy_target ();
+  push_target (the_dummy_target);
+
+  the_debug_target = new debug_target ();
 
   add_info ("target", info_target_command, targ_desc);
   add_info ("files", info_target_command, targ_desc);
diff --git a/gdb/target.h b/gdb/target.h
index f329362285..b23b7625be 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -87,7 +87,8 @@ enum strata
     process_stratum,		/* Executing processes or core dump files */
     thread_stratum,		/* Executing threads */
     record_stratum,		/* Support record debugging */
-    arch_stratum		/* Architecture overrides */
+    arch_stratum,		/* Architecture overrides */
+    debug_stratum		/* Target debug.  Must be last.  */
   };
 
 enum thread_control_capabilities
@@ -406,65 +407,71 @@ typedef void async_callback_ftype (enum inferior_event_type event_type,
 struct target_ops
   {
     struct target_ops *beneath;	/* To the target under this one.  */
-    const char *to_shortname;	/* Name this target type */
-    const char *to_longname;	/* Name for printing */
-    const char *to_doc;		/* Documentation.  Does not include trailing
-				   newline, and starts with a one-line descrip-
-				   tion (probably similar to to_longname).  */
-    /* Per-target scratch pad.  */
-    void *to_data;
+
+    virtual ~target_ops () {}
+
+    /* Name this target type.  */
+    virtual const char *shortname () = 0;
+
+    /* Name for printing.  */
+    virtual const char *longname () = 0;
+
+    /* Documentation.  Does not include trailing newline, and starts
+       ith a one-line description (probably similar to longname).  */
+    virtual const char *doc () = 0;
+
     /* The open routine takes the rest of the parameters from the
        command, and (if successful) pushes a new target onto the
        stack.  Targets should supply this routine, if only to provide
        an error message.  */
-    void (*to_open) (const char *, int);
+    virtual void open (const char *, int);
 
     /* Close the target.  This is where the target can handle
        teardown.  Heap-allocated targets should delete themselves
        before returning.  */
-    void (*to_close) (struct target_ops *);
+    virtual void close ();
 
     /* Attaches to a process on the target side.  Arguments are as
        passed to the `attach' command by the user.  This routine can
        be called when the target is not on the target-stack, if the
-       target_can_run routine returns 1; in that case, it must push
+       target_ops::can_run method returns 1; in that case, it must push
        itself onto the stack.  Upon exit, the target should be ready
        for normal operations, and should be ready to deliver the
        status of the process immediately (without waiting) to an
        upcoming target_wait call.  */
-    void (*to_attach) (struct target_ops *ops, const char *, int);
-    void (*to_post_attach) (struct target_ops *, int)
+    virtual bool can_attach ();
+    virtual void attach (const char *, int);
+    virtual void post_attach (int)
       TARGET_DEFAULT_IGNORE ();
-    void (*to_detach) (struct target_ops *ops, inferior *, int)
+    virtual void detach (inferior *, int)
       TARGET_DEFAULT_IGNORE ();
-    void (*to_disconnect) (struct target_ops *, const char *, int)
+    virtual void disconnect (const char *, int)
       TARGET_DEFAULT_NORETURN (tcomplain ());
-    void (*to_resume) (struct target_ops *, ptid_t,
-		       int TARGET_DEBUG_PRINTER (target_debug_print_step),
-		       enum gdb_signal)
+    virtual void resume (ptid_t,
+			 int TARGET_DEBUG_PRINTER (target_debug_print_step),
+			 enum gdb_signal)
       TARGET_DEFAULT_NORETURN (noprocess ());
-    void (*to_commit_resume) (struct target_ops *)
+    virtual void commit_resume ()
       TARGET_DEFAULT_IGNORE ();
-    ptid_t (*to_wait) (struct target_ops *,
-		       ptid_t, struct target_waitstatus *,
-		       int TARGET_DEBUG_PRINTER (target_debug_print_options))
+    virtual ptid_t wait (ptid_t, struct target_waitstatus *,
+			 int TARGET_DEBUG_PRINTER (target_debug_print_options))
       TARGET_DEFAULT_FUNC (default_target_wait);
-    void (*to_fetch_registers) (struct target_ops *, struct regcache *, int)
+    virtual void fetch_registers (struct regcache *, int)
       TARGET_DEFAULT_IGNORE ();
-    void (*to_store_registers) (struct target_ops *, struct regcache *, int)
+    virtual void store_registers (struct regcache *, int)
       TARGET_DEFAULT_NORETURN (noprocess ());
-    void (*to_prepare_to_store) (struct target_ops *, struct regcache *)
+    virtual void prepare_to_store (struct regcache *)
       TARGET_DEFAULT_NORETURN (noprocess ());
 
-    void (*to_files_info) (struct target_ops *)
+    virtual void files_info ()
       TARGET_DEFAULT_IGNORE ();
-    int (*to_insert_breakpoint) (struct target_ops *, struct gdbarch *,
+    virtual int insert_breakpoint (struct gdbarch *,
 				 struct bp_target_info *)
-      TARGET_DEFAULT_FUNC (memory_insert_breakpoint);
-    int (*to_remove_breakpoint) (struct target_ops *, struct gdbarch *,
+      TARGET_DEFAULT_NORETURN (noprocess ());
+    virtual int remove_breakpoint (struct gdbarch *,
 				 struct bp_target_info *,
 				 enum remove_bp_reason)
-      TARGET_DEFAULT_FUNC (memory_remove_breakpoint);
+      TARGET_DEFAULT_NORETURN (noprocess ());
 
     /* Returns true if the target stopped because it executed a
        software breakpoint.  This is necessary for correct background
@@ -475,10 +482,10 @@ struct target_ops
        done from the target, so GDB needs to be able to tell whether
        it should ignore the event and whether it should adjust the PC.
        See adjust_pc_after_break.  */
-    int (*to_stopped_by_sw_breakpoint) (struct target_ops *)
+    virtual int stopped_by_sw_breakpoint ()
       TARGET_DEFAULT_RETURN (0);
     /* Returns true if the above method is supported.  */
-    int (*to_supports_stopped_by_sw_breakpoint) (struct target_ops *)
+    virtual int supports_stopped_by_sw_breakpoint ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Returns true if the target stopped for a hardware breakpoint.
@@ -488,204 +495,203 @@ struct target_ops
        require PC adjustment, GDB needs to be able to tell whether the
        hardware breakpoint event is a delayed event for a breakpoint
        that is already gone and should thus be ignored.  */
-    int (*to_stopped_by_hw_breakpoint) (struct target_ops *)
+    virtual int stopped_by_hw_breakpoint ()
       TARGET_DEFAULT_RETURN (0);
     /* Returns true if the above method is supported.  */
-    int (*to_supports_stopped_by_hw_breakpoint) (struct target_ops *)
+    virtual int supports_stopped_by_hw_breakpoint ()
       TARGET_DEFAULT_RETURN (0);
 
-    int (*to_can_use_hw_breakpoint) (struct target_ops *,
-				     enum bptype, int, int)
+    virtual int can_use_hw_breakpoint (enum bptype, int, int)
       TARGET_DEFAULT_RETURN (0);
-    int (*to_ranged_break_num_registers) (struct target_ops *)
+    virtual int ranged_break_num_registers ()
       TARGET_DEFAULT_RETURN (-1);
-    int (*to_insert_hw_breakpoint) (struct target_ops *,
-				    struct gdbarch *, struct bp_target_info *)
+    virtual int insert_hw_breakpoint (struct gdbarch *,
+				      struct bp_target_info *)
       TARGET_DEFAULT_RETURN (-1);
-    int (*to_remove_hw_breakpoint) (struct target_ops *,
-				    struct gdbarch *, struct bp_target_info *)
+    virtual int remove_hw_breakpoint (struct gdbarch *,
+				      struct bp_target_info *)
       TARGET_DEFAULT_RETURN (-1);
 
     /* Documentation of what the two routines below are expected to do is
        provided with the corresponding target_* macros.  */
-    int (*to_remove_watchpoint) (struct target_ops *, CORE_ADDR, int,
+    virtual int remove_watchpoint (CORE_ADDR, int,
 				 enum target_hw_bp_type, struct expression *)
       TARGET_DEFAULT_RETURN (-1);
-    int (*to_insert_watchpoint) (struct target_ops *, CORE_ADDR, int,
+    virtual int insert_watchpoint (CORE_ADDR, int,
 				 enum target_hw_bp_type, struct expression *)
       TARGET_DEFAULT_RETURN (-1);
 
-    int (*to_insert_mask_watchpoint) (struct target_ops *,
-				      CORE_ADDR, CORE_ADDR,
-				      enum target_hw_bp_type)
+    virtual int insert_mask_watchpoint (CORE_ADDR, CORE_ADDR,
+					enum target_hw_bp_type)
       TARGET_DEFAULT_RETURN (1);
-    int (*to_remove_mask_watchpoint) (struct target_ops *,
-				      CORE_ADDR, CORE_ADDR,
-				      enum target_hw_bp_type)
+    virtual int remove_mask_watchpoint (CORE_ADDR, CORE_ADDR,
+					enum target_hw_bp_type)
       TARGET_DEFAULT_RETURN (1);
-    int (*to_stopped_by_watchpoint) (struct target_ops *)
+    virtual int stopped_by_watchpoint ()
       TARGET_DEFAULT_RETURN (0);
-    int to_have_steppable_watchpoint;
-    int to_have_continuable_watchpoint;
-    int (*to_stopped_data_address) (struct target_ops *, CORE_ADDR *)
+    virtual int have_steppable_watchpoint ()
       TARGET_DEFAULT_RETURN (0);
-    int (*to_watchpoint_addr_within_range) (struct target_ops *,
-					    CORE_ADDR, CORE_ADDR, int)
+    virtual bool have_continuable_watchpoint ()
+      TARGET_DEFAULT_RETURN (0);
+    virtual int stopped_data_address (CORE_ADDR *)
+      TARGET_DEFAULT_RETURN (0);
+    virtual int watchpoint_addr_within_range (CORE_ADDR, CORE_ADDR, int)
       TARGET_DEFAULT_FUNC (default_watchpoint_addr_within_range);
 
     /* Documentation of this routine is provided with the corresponding
        target_* macro.  */
-    int (*to_region_ok_for_hw_watchpoint) (struct target_ops *,
-					   CORE_ADDR, int)
+    virtual int region_ok_for_hw_watchpoint (CORE_ADDR, int)
       TARGET_DEFAULT_FUNC (default_region_ok_for_hw_watchpoint);
 
-    int (*to_can_accel_watchpoint_condition) (struct target_ops *,
-					      CORE_ADDR, int, int,
-					      struct expression *)
+    virtual int can_accel_watchpoint_condition (CORE_ADDR, int, int,
+						struct expression *)
       TARGET_DEFAULT_RETURN (0);
-    int (*to_masked_watch_num_registers) (struct target_ops *,
-					  CORE_ADDR, CORE_ADDR)
+    virtual int masked_watch_num_registers (CORE_ADDR, CORE_ADDR)
       TARGET_DEFAULT_RETURN (-1);
 
     /* Return 1 for sure target can do single step.  Return -1 for
        unknown.  Return 0 for target can't do.  */
-    int (*to_can_do_single_step) (struct target_ops *)
+    virtual int can_do_single_step ()
       TARGET_DEFAULT_RETURN (-1);
 
-    void (*to_terminal_init) (struct target_ops *)
+    virtual bool supports_terminal_ours ()
+      TARGET_DEFAULT_RETURN (0);
+    virtual void terminal_init ()
       TARGET_DEFAULT_IGNORE ();
-    void (*to_terminal_inferior) (struct target_ops *)
+    virtual void terminal_inferior ()
       TARGET_DEFAULT_IGNORE ();
-    void (*to_terminal_save_inferior) (struct target_ops *)
+    virtual void terminal_save_inferior ()
       TARGET_DEFAULT_IGNORE ();
-    void (*to_terminal_ours_for_output) (struct target_ops *)
+    virtual void terminal_ours_for_output ()
       TARGET_DEFAULT_IGNORE ();
-    void (*to_terminal_ours) (struct target_ops *)
+    virtual void terminal_ours ()
       TARGET_DEFAULT_IGNORE ();
-    void (*to_terminal_info) (struct target_ops *, const char *, int)
+    virtual void terminal_info (const char *, int)
       TARGET_DEFAULT_FUNC (default_terminal_info);
-    void (*to_kill) (struct target_ops *)
+    virtual void kill ()
       TARGET_DEFAULT_NORETURN (noprocess ());
-    void (*to_load) (struct target_ops *, const char *, int)
+    virtual void load (const char *, int)
       TARGET_DEFAULT_NORETURN (tcomplain ());
     /* Start an inferior process and set inferior_ptid to its pid.
        EXEC_FILE is the file to run.
        ALLARGS is a string containing the arguments to the program.
        ENV is the environment vector to pass.  Errors reported with error().
        On VxWorks and various standalone systems, we ignore exec_file.  */
-    void (*to_create_inferior) (struct target_ops *, 
-				const char *, const std::string &,
-				char **, int);
-    void (*to_post_startup_inferior) (struct target_ops *, ptid_t)
+    virtual bool can_create_inferior ();
+    virtual void create_inferior (const char *, const std::string &,
+				  char **, int);
+    virtual void post_startup_inferior (ptid_t)
       TARGET_DEFAULT_IGNORE ();
-    int (*to_insert_fork_catchpoint) (struct target_ops *, int)
+    virtual int insert_fork_catchpoint (int)
       TARGET_DEFAULT_RETURN (1);
-    int (*to_remove_fork_catchpoint) (struct target_ops *, int)
+    virtual int remove_fork_catchpoint (int)
       TARGET_DEFAULT_RETURN (1);
-    int (*to_insert_vfork_catchpoint) (struct target_ops *, int)
+    virtual int insert_vfork_catchpoint (int)
       TARGET_DEFAULT_RETURN (1);
-    int (*to_remove_vfork_catchpoint) (struct target_ops *, int)
+    virtual int remove_vfork_catchpoint (int)
       TARGET_DEFAULT_RETURN (1);
-    int (*to_follow_fork) (struct target_ops *, int, int)
+    virtual int follow_fork (int, int)
       TARGET_DEFAULT_FUNC (default_follow_fork);
-    int (*to_insert_exec_catchpoint) (struct target_ops *, int)
+    virtual int insert_exec_catchpoint (int)
       TARGET_DEFAULT_RETURN (1);
-    int (*to_remove_exec_catchpoint) (struct target_ops *, int)
+    virtual int remove_exec_catchpoint (int)
       TARGET_DEFAULT_RETURN (1);
-    void (*to_follow_exec) (struct target_ops *, struct inferior *, char *)
+    virtual void follow_exec (struct inferior *, char *)
       TARGET_DEFAULT_IGNORE ();
-    int (*to_set_syscall_catchpoint) (struct target_ops *,
-				      int, bool, int,
-				      gdb::array_view<const int>)
+    virtual int set_syscall_catchpoint (int, bool, int,
+					gdb::array_view<const int>)
       TARGET_DEFAULT_RETURN (1);
-    void (*to_mourn_inferior) (struct target_ops *)
+    virtual void mourn_inferior ()
       TARGET_DEFAULT_FUNC (default_mourn_inferior);
-    /* Note that to_can_run is special and can be invoked on an
-       unpushed target.  Targets defining this method must also define
+
+    /* Note that can_run is special and can be invoked on an unpushed
+       target.  Targets defining this method must also define
        to_can_async_p and to_supports_non_stop.  */
-    int (*to_can_run) (struct target_ops *)
-      TARGET_DEFAULT_RETURN (0);
+    virtual int can_run ();
 
     /* Documentation of this routine is provided with the corresponding
        target_* macro.  */
-    void (*to_pass_signals) (struct target_ops *, int,
-			     unsigned char * TARGET_DEBUG_PRINTER (target_debug_print_signals))
+    virtual void pass_signals (int,
+			       unsigned char * TARGET_DEBUG_PRINTER (target_debug_print_signals))
       TARGET_DEFAULT_IGNORE ();
 
     /* Documentation of this routine is provided with the
        corresponding target_* function.  */
-    void (*to_program_signals) (struct target_ops *, int,
-				unsigned char * TARGET_DEBUG_PRINTER (target_debug_print_signals))
+    virtual void program_signals (int,
+				  unsigned char * TARGET_DEBUG_PRINTER (target_debug_print_signals))
       TARGET_DEFAULT_IGNORE ();
 
-    int (*to_thread_alive) (struct target_ops *, ptid_t ptid)
+    virtual int thread_alive (ptid_t ptid)
       TARGET_DEFAULT_RETURN (0);
-    void (*to_update_thread_list) (struct target_ops *)
+    virtual void update_thread_list ()
       TARGET_DEFAULT_IGNORE ();
-    const char *(*to_pid_to_str) (struct target_ops *, ptid_t)
+    virtual const char *pid_to_str (ptid_t)
       TARGET_DEFAULT_FUNC (default_pid_to_str);
-    const char *(*to_extra_thread_info) (struct target_ops *, struct thread_info *)
+    virtual const char *extra_thread_info (thread_info *)
       TARGET_DEFAULT_RETURN (NULL);
-    const char *(*to_thread_name) (struct target_ops *, struct thread_info *)
+    virtual const char *thread_name (thread_info *)
       TARGET_DEFAULT_RETURN (NULL);
-    struct thread_info *(*to_thread_handle_to_thread_info) (struct target_ops *,
-                                                            const gdb_byte *,
-							    int,
-							    struct inferior *inf)
+    virtual thread_info *thread_handle_to_thread_info (const gdb_byte *,
+						       int,
+						       inferior *inf)
       TARGET_DEFAULT_RETURN (NULL);
-    void (*to_stop) (struct target_ops *, ptid_t)
+    virtual void stop (ptid_t)
       TARGET_DEFAULT_IGNORE ();
-    void (*to_interrupt) (struct target_ops *)
+    virtual void interrupt ()
       TARGET_DEFAULT_IGNORE ();
-    void (*to_pass_ctrlc) (struct target_ops *)
+    virtual void pass_ctrlc ()
       TARGET_DEFAULT_FUNC (default_target_pass_ctrlc);
-    void (*to_rcmd) (struct target_ops *,
-		     const char *command, struct ui_file *output)
+    virtual void rcmd (const char *command, struct ui_file *output)
       TARGET_DEFAULT_FUNC (default_rcmd);
-    char *(*to_pid_to_exec_file) (struct target_ops *, int pid)
+    virtual char *pid_to_exec_file (int pid)
       TARGET_DEFAULT_RETURN (NULL);
-    void (*to_log_command) (struct target_ops *, const char *)
+    virtual void log_command (const char *)
       TARGET_DEFAULT_IGNORE ();
-    struct target_section_table *(*to_get_section_table) (struct target_ops *)
+    virtual struct target_section_table *get_section_table ()
       TARGET_DEFAULT_RETURN (NULL);
     enum strata to_stratum;
-    int (*to_has_all_memory) (struct target_ops *);
-    int (*to_has_memory) (struct target_ops *);
-    int (*to_has_stack) (struct target_ops *);
-    int (*to_has_registers) (struct target_ops *);
-    int (*to_has_execution) (struct target_ops *, ptid_t);
-    int to_has_thread_control;	/* control thread execution */
-    int to_attach_no_wait;
+
+    /* Provide default values for all "must have" methods.  */
+    virtual int has_all_memory () { return 0; }
+    virtual int has_memory () { return 0; }
+    virtual int has_stack () { return 0; }
+    virtual int has_registers () { return 0; }
+    virtual int has_execution (ptid_t) { return 0; }
+
+    /* Control thread execution.  */
+    virtual thread_control_capabilities get_thread_control_capabilities ()
+      TARGET_DEFAULT_RETURN (tc_none);
+    virtual bool attach_no_wait ()
+      TARGET_DEFAULT_RETURN (0);
     /* This method must be implemented in some situations.  See the
-       comment on 'to_can_run'.  */
-    int (*to_can_async_p) (struct target_ops *)
+       comment on 'can_run'.  */
+    virtual int can_async_p ()
       TARGET_DEFAULT_RETURN (0);
-    int (*to_is_async_p) (struct target_ops *)
+    virtual int is_async_p ()
       TARGET_DEFAULT_RETURN (0);
-    void (*to_async) (struct target_ops *, int)
+    virtual void async (int)
       TARGET_DEFAULT_NORETURN (tcomplain ());
-    void (*to_thread_events) (struct target_ops *, int)
+    virtual void thread_events (int)
       TARGET_DEFAULT_IGNORE ();
     /* This method must be implemented in some situations.  See the
-       comment on 'to_can_run'.  */
-    int (*to_supports_non_stop) (struct target_ops *)
+       comment on 'can_run'.  */
+    virtual int supports_non_stop ()
       TARGET_DEFAULT_RETURN (0);
     /* Return true if the target operates in non-stop mode even with
        "set non-stop off".  */
-    int (*to_always_non_stop_p) (struct target_ops *)
+    virtual int always_non_stop_p ()
       TARGET_DEFAULT_RETURN (0);
     /* find_memory_regions support method for gcore */
-    int (*to_find_memory_regions) (struct target_ops *,
-				   find_memory_region_ftype func, void *data)
+    virtual int find_memory_regions (find_memory_region_ftype func, void *data)
       TARGET_DEFAULT_FUNC (dummy_find_memory_regions);
     /* make_corefile_notes support method for gcore */
-    char * (*to_make_corefile_notes) (struct target_ops *, bfd *, int *)
+    virtual char *make_corefile_notes (bfd *, int *)
       TARGET_DEFAULT_FUNC (dummy_make_corefile_notes);
     /* get_bookmark support method for bookmarks */
-    gdb_byte * (*to_get_bookmark) (struct target_ops *, const char *, int)
+    virtual gdb_byte *get_bookmark (const char *, int)
       TARGET_DEFAULT_NORETURN (tcomplain ());
     /* goto_bookmark support method for bookmarks */
-    void (*to_goto_bookmark) (struct target_ops *, const gdb_byte *, int)
+    virtual void goto_bookmark (const gdb_byte *, int)
       TARGET_DEFAULT_NORETURN (tcomplain ());
     /* Return the thread-local address at OFFSET in the
        thread-local storage for the thread PTID and the shared library
@@ -693,10 +699,9 @@ struct target_ops
        thread-local storage hasn't been allocated yet, this function
        may return an error.  LOAD_MODULE_ADDR may be zero for statically
        linked multithreaded inferiors.  */
-    CORE_ADDR (*to_get_thread_local_address) (struct target_ops *ops,
-					      ptid_t ptid,
-					      CORE_ADDR load_module_addr,
-					      CORE_ADDR offset)
+    virtual CORE_ADDR get_thread_local_address (ptid_t ptid,
+						CORE_ADDR load_module_addr,
+						CORE_ADDR offset)
       TARGET_DEFAULT_NORETURN (generic_tls_error ());
 
     /* Request that OPS transfer up to LEN addressable units of the target's
@@ -731,19 +736,18 @@ struct target_ops
        See target_read and target_write for more information.  One,
        and only one, of readbuf or writebuf must be non-NULL.  */
 
-    enum target_xfer_status (*to_xfer_partial) (struct target_ops *ops,
-						enum target_object object,
-						const char *annex,
-						gdb_byte *readbuf,
-						const gdb_byte *writebuf,
-						ULONGEST offset, ULONGEST len,
-						ULONGEST *xfered_len)
+    virtual enum target_xfer_status xfer_partial (enum target_object object,
+						  const char *annex,
+						  gdb_byte *readbuf,
+						  const gdb_byte *writebuf,
+						  ULONGEST offset, ULONGEST len,
+						  ULONGEST *xfered_len)
       TARGET_DEFAULT_RETURN (TARGET_XFER_E_IO);
 
     /* Return the limit on the size of any single memory transfer
        for the target.  */
 
-    ULONGEST (*to_get_memory_xfer_limit) (struct target_ops *)
+    virtual ULONGEST get_memory_xfer_limit ()
       TARGET_DEFAULT_RETURN (ULONGEST_MAX);
 
     /* Returns the memory map for the target.  A return value of NULL
@@ -759,7 +763,7 @@ struct target_ops
        This method should not cache data; if the memory map could
        change unexpectedly, it should be invalidated, and higher
        layers will re-fetch it.  */
-    std::vector<mem_region> (*to_memory_map) (struct target_ops *)
+    virtual std::vector<mem_region> memory_map ()
       TARGET_DEFAULT_RETURN (std::vector<mem_region> ());
 
     /* Erases the region of flash memory starting at ADDRESS, of
@@ -767,38 +771,36 @@ struct target_ops
 
        Precondition: both ADDRESS and ADDRESS+LENGTH should be aligned
        on flash block boundaries, as reported by 'to_memory_map'.  */
-    void (*to_flash_erase) (struct target_ops *,
-                           ULONGEST address, LONGEST length)
+    virtual void flash_erase (ULONGEST address, LONGEST length)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Finishes a flash memory write sequence.  After this operation
        all flash memory should be available for writing and the result
        of reading from areas written by 'to_flash_write' should be
        equal to what was written.  */
-    void (*to_flash_done) (struct target_ops *)
+    virtual void flash_done ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Describe the architecture-specific features of this target.  If
        OPS doesn't have a description, this should delegate to the
        "beneath" target.  Returns the description found, or NULL if no
        description was available.  */
-    const struct target_desc *(*to_read_description) (struct target_ops *ops)
+    virtual const struct target_desc *read_description ()
 	 TARGET_DEFAULT_RETURN (NULL);
 
     /* Build the PTID of the thread on which a given task is running,
        based on LWP and THREAD.  These values are extracted from the
        task Private_Data section of the Ada Task Control Block, and
        their interpretation depends on the target.  */
-    ptid_t (*to_get_ada_task_ptid) (struct target_ops *,
-				    long lwp, long thread)
+    virtual ptid_t get_ada_task_ptid (long lwp, long thread)
       TARGET_DEFAULT_FUNC (default_get_ada_task_ptid);
 
     /* Read one auxv entry from *READPTR, not reading locations >= ENDPTR.
        Return 0 if *READPTR is already at the end of the buffer.
        Return -1 if there is insufficient buffer for a whole entry.
        Return 1 if an entry was read into *TYPEP and *VALP.  */
-    int (*to_auxv_parse) (struct target_ops *ops, gdb_byte **readptr,
-                         gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
+    virtual int auxv_parse (gdb_byte **readptr,
+			    gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
       TARGET_DEFAULT_FUNC (default_auxv_parse);
 
     /* Search SEARCH_SPACE_LEN bytes beginning at START_ADDR for the
@@ -807,47 +809,47 @@ struct target_ops
        The result is 1 if found, 0 if not found, and -1 if there was an error
        requiring halting of the search (e.g. memory read error).
        If the pattern is found the address is recorded in FOUND_ADDRP.  */
-    int (*to_search_memory) (struct target_ops *ops,
-			     CORE_ADDR start_addr, ULONGEST search_space_len,
-			     const gdb_byte *pattern, ULONGEST pattern_len,
-			     CORE_ADDR *found_addrp)
+    virtual int search_memory (CORE_ADDR start_addr, ULONGEST search_space_len,
+			       const gdb_byte *pattern, ULONGEST pattern_len,
+			       CORE_ADDR *found_addrp)
       TARGET_DEFAULT_FUNC (default_search_memory);
 
     /* Can target execute in reverse?  */
-    int (*to_can_execute_reverse) (struct target_ops *)
+    virtual int can_execute_reverse ()
       TARGET_DEFAULT_RETURN (0);
 
     /* The direction the target is currently executing.  Must be
        implemented on targets that support reverse execution and async
        mode.  The default simply returns forward execution.  */
-    enum exec_direction_kind (*to_execution_direction) (struct target_ops *)
+    virtual enum exec_direction_kind execution_direction ()
       TARGET_DEFAULT_FUNC (default_execution_direction);
 
     /* Does this target support debugging multiple processes
        simultaneously?  */
-    int (*to_supports_multi_process) (struct target_ops *)
+    virtual int supports_multi_process ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Does this target support enabling and disabling tracepoints while a trace
        experiment is running?  */
-    int (*to_supports_enable_disable_tracepoint) (struct target_ops *)
+    virtual int supports_enable_disable_tracepoint ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Does this target support disabling address space randomization?  */
-    int (*to_supports_disable_randomization) (struct target_ops *);
+    virtual int supports_disable_randomization ()
+      TARGET_DEFAULT_FUNC (find_default_supports_disable_randomization);
 
     /* Does this target support the tracenz bytecode for string collection?  */
-    int (*to_supports_string_tracing) (struct target_ops *)
+    virtual int supports_string_tracing ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Does this target support evaluation of breakpoint conditions on its
        end?  */
-    int (*to_supports_evaluation_of_breakpoint_conditions) (struct target_ops *)
+    virtual int supports_evaluation_of_breakpoint_conditions ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Does this target support evaluation of breakpoint commands on its
        end?  */
-    int (*to_can_run_breakpoint_commands) (struct target_ops *)
+    virtual int can_run_breakpoint_commands ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Determine current architecture of thread PTID.
@@ -860,22 +862,21 @@ struct target_ops
        ptrace operations need to operate according to target_gdbarch ().
 
        The default implementation always returns target_gdbarch ().  */
-    struct gdbarch *(*to_thread_architecture) (struct target_ops *, ptid_t)
+    virtual struct gdbarch *thread_architecture (ptid_t)
       TARGET_DEFAULT_FUNC (default_thread_architecture);
 
     /* Determine current address space of thread PTID.
 
        The default implementation always returns the inferior's
        address space.  */
-    struct address_space *(*to_thread_address_space) (struct target_ops *,
-						      ptid_t)
+    virtual struct address_space *thread_address_space (ptid_t)
       TARGET_DEFAULT_FUNC (default_thread_address_space);
 
     /* Target file operations.  */
 
     /* Return nonzero if the filesystem seen by the current inferior
        is the local filesystem, zero otherwise.  */
-    int (*to_filesystem_is_local) (struct target_ops *)
+    virtual int filesystem_is_local ()
       TARGET_DEFAULT_RETURN (1);
 
     /* Open FILENAME on the target, in the filesystem as seen by INF,
@@ -885,111 +886,99 @@ struct target_ops
        is being accessed over a link that may be slow.  Return a
        target file descriptor, or -1 if an error occurs (and set
        *TARGET_ERRNO).  */
-    int (*to_fileio_open) (struct target_ops *,
-			   struct inferior *inf, const char *filename,
-			   int flags, int mode, int warn_if_slow,
-			   int *target_errno);
+    virtual int fileio_open (struct inferior *inf, const char *filename,
+			     int flags, int mode, int warn_if_slow,
+			     int *target_errno);
 
     /* Write up to LEN bytes from WRITE_BUF to FD on the target.
        Return the number of bytes written, or -1 if an error occurs
        (and set *TARGET_ERRNO).  */
-    int (*to_fileio_pwrite) (struct target_ops *,
-			     int fd, const gdb_byte *write_buf, int len,
-			     ULONGEST offset, int *target_errno);
+    virtual int fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
+			       ULONGEST offset, int *target_errno);
 
     /* Read up to LEN bytes FD on the target into READ_BUF.
        Return the number of bytes read, or -1 if an error occurs
        (and set *TARGET_ERRNO).  */
-    int (*to_fileio_pread) (struct target_ops *,
-			    int fd, gdb_byte *read_buf, int len,
-			    ULONGEST offset, int *target_errno);
+    virtual int fileio_pread (int fd, gdb_byte *read_buf, int len,
+			      ULONGEST offset, int *target_errno);
 
     /* Get information about the file opened as FD and put it in
        SB.  Return 0 on success, or -1 if an error occurs (and set
        *TARGET_ERRNO).  */
-    int (*to_fileio_fstat) (struct target_ops *,
-			    int fd, struct stat *sb, int *target_errno);
+    virtual int fileio_fstat (int fd, struct stat *sb, int *target_errno);
 
     /* Close FD on the target.  Return 0, or -1 if an error occurs
        (and set *TARGET_ERRNO).  */
-    int (*to_fileio_close) (struct target_ops *, int fd, int *target_errno);
+    virtual int fileio_close (int fd, int *target_errno);
 
     /* Unlink FILENAME on the target, in the filesystem as seen by
        INF.  If INF is NULL, use the filesystem seen by the debugger
        (GDB or, for remote targets, the remote stub).  Return 0, or
        -1 if an error occurs (and set *TARGET_ERRNO).  */
-    int (*to_fileio_unlink) (struct target_ops *,
-			     struct inferior *inf,
-			     const char *filename,
-			     int *target_errno);
+    virtual int fileio_unlink (struct inferior *inf,
+			       const char *filename,
+			       int *target_errno);
 
     /* Read value of symbolic link FILENAME on the target, in the
        filesystem as seen by INF.  If INF is NULL, use the filesystem
        seen by the debugger (GDB or, for remote targets, the remote
        stub).  Return a string, or an empty optional if an error
        occurs (and set *TARGET_ERRNO).  */
-    gdb::optional<std::string> (*to_fileio_readlink) (struct target_ops *,
-						      struct inferior *inf,
-						      const char *filename,
-						      int *target_errno);
+    virtual gdb::optional<std::string> fileio_readlink (struct inferior *inf,
+							const char *filename,
+							int *target_errno);
 
-
-    /* Implement the "info proc" command.  */
-    void (*to_info_proc) (struct target_ops *, const char *,
-			  enum info_proc_what);
+    /* Implement the "info proc" command.  Returns true if the target
+       actually implemented the command, false otherwise.  */
+    virtual bool info_proc (const char *, enum info_proc_what);
 
     /* Tracepoint-related operations.  */
 
     /* Prepare the target for a tracing run.  */
-    void (*to_trace_init) (struct target_ops *)
+    virtual void trace_init ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Send full details of a tracepoint location to the target.  */
-    void (*to_download_tracepoint) (struct target_ops *,
-				    struct bp_location *location)
+    virtual void download_tracepoint (struct bp_location *location)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Is the target able to download tracepoint locations in current
        state?  */
-    int (*to_can_download_tracepoint) (struct target_ops *)
+    virtual int can_download_tracepoint ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Send full details of a trace state variable to the target.  */
-    void (*to_download_trace_state_variable) (struct target_ops *,
-					      const trace_state_variable &tsv)
+    virtual void download_trace_state_variable (const trace_state_variable &tsv)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Enable a tracepoint on the target.  */
-    void (*to_enable_tracepoint) (struct target_ops *,
-				  struct bp_location *location)
+    virtual void enable_tracepoint (struct bp_location *location)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Disable a tracepoint on the target.  */
-    void (*to_disable_tracepoint) (struct target_ops *,
-				   struct bp_location *location)
+    virtual void disable_tracepoint (struct bp_location *location)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Inform the target info of memory regions that are readonly
        (such as text sections), and so it should return data from
        those rather than look in the trace buffer.  */
-    void (*to_trace_set_readonly_regions) (struct target_ops *)
+    virtual void trace_set_readonly_regions ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Start a trace run.  */
-    void (*to_trace_start) (struct target_ops *)
+    virtual void trace_start ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Get the current status of a tracing run.  */
-    int (*to_get_trace_status) (struct target_ops *, struct trace_status *ts)
+    virtual int get_trace_status (struct trace_status *ts)
       TARGET_DEFAULT_RETURN (-1);
 
-    void (*to_get_tracepoint_status) (struct target_ops *,
-				      struct breakpoint *tp,
-				      struct uploaded_tp *utp)
+    virtual void get_tracepoint_status (struct breakpoint *tp,
+					struct uploaded_tp *utp)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Stop a trace run.  */
-    void (*to_trace_stop) (struct target_ops *)
+    virtual void trace_stop ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
    /* Ask the target to find a trace frame of the given type TYPE,
@@ -997,55 +986,50 @@ struct target_ops
       number of the trace frame, and also the tracepoint number at
       TPP.  If no trace frame matches, return -1.  May throw if the
       operation fails.  */
-    int (*to_trace_find) (struct target_ops *,
-			  enum trace_find_type type, int num,
-			  CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
+    virtual int trace_find (enum trace_find_type type, int num,
+			    CORE_ADDR addr1, CORE_ADDR addr2, int *tpp)
       TARGET_DEFAULT_RETURN (-1);
 
     /* Get the value of the trace state variable number TSV, returning
        1 if the value is known and writing the value itself into the
        location pointed to by VAL, else returning 0.  */
-    int (*to_get_trace_state_variable_value) (struct target_ops *,
-					      int tsv, LONGEST *val)
+    virtual int get_trace_state_variable_value (int tsv, LONGEST *val)
       TARGET_DEFAULT_RETURN (0);
 
-    int (*to_save_trace_data) (struct target_ops *, const char *filename)
+    virtual int save_trace_data (const char *filename)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
-    int (*to_upload_tracepoints) (struct target_ops *,
-				  struct uploaded_tp **utpp)
+    virtual int upload_tracepoints (struct uploaded_tp **utpp)
       TARGET_DEFAULT_RETURN (0);
 
-    int (*to_upload_trace_state_variables) (struct target_ops *,
-					    struct uploaded_tsv **utsvp)
+    virtual int upload_trace_state_variables (struct uploaded_tsv **utsvp)
       TARGET_DEFAULT_RETURN (0);
 
-    LONGEST (*to_get_raw_trace_data) (struct target_ops *, gdb_byte *buf,
-				      ULONGEST offset, LONGEST len)
+    virtual LONGEST get_raw_trace_data (gdb_byte *buf,
+					ULONGEST offset, LONGEST len)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Get the minimum length of instruction on which a fast tracepoint
        may be set on the target.  If this operation is unsupported,
        return -1.  If for some reason the minimum length cannot be
        determined, return 0.  */
-    int (*to_get_min_fast_tracepoint_insn_len) (struct target_ops *)
+    virtual int get_min_fast_tracepoint_insn_len ()
       TARGET_DEFAULT_RETURN (-1);
 
     /* Set the target's tracing behavior in response to unexpected
        disconnection - set VAL to 1 to keep tracing, 0 to stop.  */
-    void (*to_set_disconnected_tracing) (struct target_ops *, int val)
+    virtual void set_disconnected_tracing (int val)
       TARGET_DEFAULT_IGNORE ();
-    void (*to_set_circular_trace_buffer) (struct target_ops *, int val)
+    virtual void set_circular_trace_buffer (int val)
       TARGET_DEFAULT_IGNORE ();
     /* Set the size of trace buffer in the target.  */
-    void (*to_set_trace_buffer_size) (struct target_ops *, LONGEST val)
+    virtual void set_trace_buffer_size (LONGEST val)
       TARGET_DEFAULT_IGNORE ();
 
     /* Add/change textual notes about the trace run, returning 1 if
        successful, 0 otherwise.  */
-    int (*to_set_trace_notes) (struct target_ops *,
-			       const char *user, const char *notes,
-			       const char *stopnotes)
+    virtual int set_trace_notes (const char *user, const char *notes,
+				 const char *stopnotes)
       TARGET_DEFAULT_RETURN (0);
 
     /* Return the processor core that thread PTID was last seen on.
@@ -1055,222 +1039,201 @@ struct target_ops
        If the core cannot be determined -- either for the specified
        thread, or right now, or in this debug session, or for this
        target -- return -1.  */
-    int (*to_core_of_thread) (struct target_ops *, ptid_t ptid)
+    virtual int core_of_thread (ptid_t ptid)
       TARGET_DEFAULT_RETURN (-1);
 
     /* Verify that the memory in the [MEMADDR, MEMADDR+SIZE) range
        matches the contents of [DATA,DATA+SIZE).  Returns 1 if there's
        a match, 0 if there's a mismatch, and -1 if an error is
        encountered while reading memory.  */
-    int (*to_verify_memory) (struct target_ops *, const gdb_byte *data,
-			     CORE_ADDR memaddr, ULONGEST size)
+    virtual int verify_memory (const gdb_byte *data,
+			       CORE_ADDR memaddr, ULONGEST size)
       TARGET_DEFAULT_FUNC (default_verify_memory);
 
     /* Return the address of the start of the Thread Information Block
        a Windows OS specific feature.  */
-    int (*to_get_tib_address) (struct target_ops *,
-			       ptid_t ptid, CORE_ADDR *addr)
+    virtual int get_tib_address (ptid_t ptid, CORE_ADDR *addr)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Send the new settings of write permission variables.  */
-    void (*to_set_permissions) (struct target_ops *)
+    virtual void set_permissions ()
       TARGET_DEFAULT_IGNORE ();
 
     /* Look for a static tracepoint marker at ADDR, and fill in MARKER
        with its details.  Return true on success, false on failure.  */
-    bool (*to_static_tracepoint_marker_at) (struct target_ops *, CORE_ADDR,
-					    static_tracepoint_marker *marker)
+    virtual bool static_tracepoint_marker_at (CORE_ADDR,
+					      static_tracepoint_marker *marker)
       TARGET_DEFAULT_RETURN (false);
 
     /* Return a vector of all tracepoints markers string id ID, or all
        markers if ID is NULL.  */
-    std::vector<static_tracepoint_marker>
-      (*to_static_tracepoint_markers_by_strid) (struct target_ops *,
-						const char *id)
+    virtual std::vector<static_tracepoint_marker> static_tracepoint_markers_by_strid (const char *id)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Return a traceframe info object describing the current
        traceframe's contents.  This method should not cache data;
        higher layers take care of caching, invalidating, and
        re-fetching when necessary.  */
-    traceframe_info_up (*to_traceframe_info) (struct target_ops *)
+    virtual traceframe_info_up traceframe_info ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Ask the target to use or not to use agent according to USE.  Return 1
        successful, 0 otherwise.  */
-    int (*to_use_agent) (struct target_ops *, int use)
+    virtual int use_agent (int use)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Is the target able to use agent in current state?  */
-    int (*to_can_use_agent) (struct target_ops *)
+    virtual int can_use_agent ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Enable branch tracing for PTID using CONF configuration.
        Return a branch trace target information struct for reading and for
        disabling branch trace.  */
-    struct btrace_target_info *(*to_enable_btrace) (struct target_ops *,
-						    ptid_t ptid,
-						    const struct btrace_config *conf)
+    virtual struct btrace_target_info *enable_btrace (ptid_t ptid,
+						      const struct btrace_config *conf)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Disable branch tracing and deallocate TINFO.  */
-    void (*to_disable_btrace) (struct target_ops *,
-			       struct btrace_target_info *tinfo)
+    virtual void disable_btrace (struct btrace_target_info *tinfo)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Disable branch tracing and deallocate TINFO.  This function is similar
        to to_disable_btrace, except that it is called during teardown and is
        only allowed to perform actions that are safe.  A counter-example would
        be attempting to talk to a remote target.  */
-    void (*to_teardown_btrace) (struct target_ops *,
-				struct btrace_target_info *tinfo)
+    virtual void teardown_btrace (struct btrace_target_info *tinfo)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Read branch trace data for the thread indicated by BTINFO into DATA.
        DATA is cleared before new trace is added.  */
-    enum btrace_error (*to_read_btrace) (struct target_ops *self,
-					 struct btrace_data *data,
-					 struct btrace_target_info *btinfo,
-					 enum btrace_read_type type)
+    virtual enum btrace_error read_btrace (struct btrace_data *data,
+					   struct btrace_target_info *btinfo,
+					   enum btrace_read_type type)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Get the branch trace configuration.  */
-    const struct btrace_config *(*to_btrace_conf) (struct target_ops *self,
-						   const struct btrace_target_info *)
+    virtual const struct btrace_config *btrace_conf (const struct btrace_target_info *)
       TARGET_DEFAULT_RETURN (NULL);
 
     /* Current recording method.  */
-    enum record_method (*to_record_method) (struct target_ops *, ptid_t ptid)
+    virtual enum record_method record_method (ptid_t ptid)
       TARGET_DEFAULT_RETURN (RECORD_METHOD_NONE);
 
     /* Stop trace recording.  */
-    void (*to_stop_recording) (struct target_ops *)
+    virtual void stop_recording ()
       TARGET_DEFAULT_IGNORE ();
 
     /* Print information about the recording.  */
-    void (*to_info_record) (struct target_ops *)
+    virtual void info_record ()
       TARGET_DEFAULT_IGNORE ();
 
     /* Save the recorded execution trace into a file.  */
-    void (*to_save_record) (struct target_ops *, const char *filename)
+    virtual void save_record (const char *filename)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Delete the recorded execution trace from the current position
        onwards.  */
-    void (*to_delete_record) (struct target_ops *)
+    virtual bool supports_delete_record ()
+      TARGET_DEFAULT_RETURN (false);
+    virtual void delete_record ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Query if the record target is currently replaying PTID.  */
-    int (*to_record_is_replaying) (struct target_ops *, ptid_t ptid)
+    virtual int record_is_replaying (ptid_t ptid)
       TARGET_DEFAULT_RETURN (0);
 
     /* Query if the record target will replay PTID if it were resumed in
        execution direction DIR.  */
-    int (*to_record_will_replay) (struct target_ops *, ptid_t ptid, int dir)
+    virtual int record_will_replay (ptid_t ptid, int dir)
       TARGET_DEFAULT_RETURN (0);
 
     /* Stop replaying.  */
-    void (*to_record_stop_replaying) (struct target_ops *)
+    virtual void record_stop_replaying ()
       TARGET_DEFAULT_IGNORE ();
 
     /* Go to the begin of the execution trace.  */
-    void (*to_goto_record_begin) (struct target_ops *)
+    virtual void goto_record_begin ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Go to the end of the execution trace.  */
-    void (*to_goto_record_end) (struct target_ops *)
+    virtual void goto_record_end ()
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Go to a specific location in the recorded execution trace.  */
-    void (*to_goto_record) (struct target_ops *, ULONGEST insn)
+    virtual void goto_record (ULONGEST insn)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Disassemble SIZE instructions in the recorded execution trace from
        the current position.
        If SIZE < 0, disassemble abs (SIZE) preceding instructions; otherwise,
        disassemble SIZE succeeding instructions.  */
-    void (*to_insn_history) (struct target_ops *, int size,
-			     gdb_disassembly_flags flags)
+    virtual void insn_history (int size, gdb_disassembly_flags flags)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Disassemble SIZE instructions in the recorded execution trace around
        FROM.
        If SIZE < 0, disassemble abs (SIZE) instructions before FROM; otherwise,
        disassemble SIZE instructions after FROM.  */
-    void (*to_insn_history_from) (struct target_ops *,
-				  ULONGEST from, int size,
-				  gdb_disassembly_flags flags)
+    virtual void insn_history_from (ULONGEST from, int size,
+				    gdb_disassembly_flags flags)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Disassemble a section of the recorded execution trace from instruction
        BEGIN (inclusive) to instruction END (inclusive).  */
-    void (*to_insn_history_range) (struct target_ops *,
-				   ULONGEST begin, ULONGEST end,
-				   gdb_disassembly_flags flags)
+    virtual void insn_history_range (ULONGEST begin, ULONGEST end,
+				     gdb_disassembly_flags flags)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Print a function trace of the recorded execution trace.
        If SIZE < 0, print abs (SIZE) preceding functions; otherwise, print SIZE
        succeeding functions.  */
-    void (*to_call_history) (struct target_ops *, int size, record_print_flags flags)
+    virtual void call_history (int size, record_print_flags flags)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Print a function trace of the recorded execution trace starting
        at function FROM.
        If SIZE < 0, print abs (SIZE) functions before FROM; otherwise, print
        SIZE functions after FROM.  */
-    void (*to_call_history_from) (struct target_ops *,
-				  ULONGEST begin, int size, record_print_flags flags)
+    virtual void call_history_from (ULONGEST begin, int size, record_print_flags flags)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Print a function trace of an execution trace section from function BEGIN
        (inclusive) to function END (inclusive).  */
-    void (*to_call_history_range) (struct target_ops *,
-				   ULONGEST begin, ULONGEST end, record_print_flags flags)
+    virtual void call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
       TARGET_DEFAULT_NORETURN (tcomplain ());
 
     /* Nonzero if TARGET_OBJECT_LIBRARIES_SVR4 may be read with a
        non-empty annex.  */
-    int (*to_augmented_libraries_svr4_read) (struct target_ops *)
+    virtual int augmented_libraries_svr4_read ()
       TARGET_DEFAULT_RETURN (0);
 
     /* Those unwinders are tried before any other arch unwinders.  If
        SELF doesn't have unwinders, it should delegate to the
        "beneath" target.  */
-    const struct frame_unwind *(*to_get_unwinder) (struct target_ops *self)
+    virtual const struct frame_unwind *get_unwinder ()
       TARGET_DEFAULT_RETURN (NULL);
 
-    const struct frame_unwind *(*to_get_tailcall_unwinder) (struct target_ops *self)
+    virtual const struct frame_unwind *get_tailcall_unwinder ()
       TARGET_DEFAULT_RETURN (NULL);
 
     /* Prepare to generate a core file.  */
-    void (*to_prepare_to_generate_core) (struct target_ops *)
+    virtual void prepare_to_generate_core ()
       TARGET_DEFAULT_IGNORE ();
 
     /* Cleanup after generating a core file.  */
-    void (*to_done_generating_core) (struct target_ops *)
+    virtual void done_generating_core ()
       TARGET_DEFAULT_IGNORE ();
-
-    int to_magic;
-    /* Need sub-structure for target machine related rather than comm related?
-     */
   };
 
-/* Magic number for checking ops size.  If a struct doesn't end with this
-   number, somebody changed the declaration but didn't change all the
-   places that initialize one.  */
-
-#define	OPS_MAGIC	3840
-
 /* The ops structure for our "current" target process.  This should
    never be NULL.  If there is no target, it points to the dummy_target.  */
 
-extern struct target_ops current_target;
+extern struct target_ops *target_stack;
 
 /* Define easy words for doing these operations on our current target.  */
 
-#define	target_shortname	(current_target.to_shortname)
-#define	target_longname		(current_target.to_longname)
+#define	target_shortname	(target_stack->shortname ())
+#define	target_longname		(target_stack->longname ())
 
 /* Does whatever cleanup is required for a target that we are no
    longer going to be calling.  This routine is automatically always
@@ -1297,8 +1260,8 @@ extern struct target_ops *find_run_target (void);
    or their target_attach implementation takes care of the waiting.
    These targets must set to_attach_no_wait.  */
 
-#define target_attach_no_wait \
-     (current_target.to_attach_no_wait)
+#define target_attach_no_wait() \
+  (target_stack->attach_no_wait ())
 
 /* The target_attach operation places a process under debugger control,
    and stops the process.
@@ -1306,7 +1269,7 @@ extern struct target_ops *find_run_target (void);
    This operation provides a target-specific hook that allows the
    necessary bookkeeping to be performed after an attach completes.  */
 #define target_post_attach(pid) \
-     (*current_target.to_post_attach) (&current_target, pid)
+     (target_stack->post_attach) (pid)
 
 /* Display a message indicating we're about to detach from the current
    inferior process.  */
@@ -1388,7 +1351,7 @@ extern void target_store_registers (struct regcache *regcache, int regs);
    debugged.  */
 
 #define	target_prepare_to_store(regcache)	\
-     (*current_target.to_prepare_to_store) (&current_target, regcache)
+     (target_stack->prepare_to_store) (regcache)
 
 /* Determine current address space of thread PTID.  */
 
@@ -1409,22 +1372,22 @@ int target_supports_disable_randomization (void);
    while a trace experiment is running.  */
 
 #define target_supports_enable_disable_tracepoint() \
-  (*current_target.to_supports_enable_disable_tracepoint) (&current_target)
+  (target_stack->supports_enable_disable_tracepoint) ()
 
 #define target_supports_string_tracing() \
-  (*current_target.to_supports_string_tracing) (&current_target)
+  (target_stack->supports_string_tracing) ()
 
 /* Returns true if this target can handle breakpoint conditions
    on its end.  */
 
 #define target_supports_evaluation_of_breakpoint_conditions() \
-  (*current_target.to_supports_evaluation_of_breakpoint_conditions) (&current_target)
+  (target_stack->supports_evaluation_of_breakpoint_conditions) ()
 
 /* Returns true if this target can handle breakpoint commands
    on its end.  */
 
 #define target_can_run_breakpoint_commands() \
-  (*current_target.to_can_run_breakpoint_commands) (&current_target)
+  (target_stack->can_run_breakpoint_commands) ()
 
 extern int target_read_string (CORE_ADDR, gdb::unique_xmalloc_ptr<char> *,
 			       int, int *);
@@ -1507,7 +1470,7 @@ int target_write_memory_blocks
 /* Print a line about the current target.  */
 
 #define	target_files_info()	\
-     (*current_target.to_files_info) (&current_target)
+     (target_stack->files_info) ()
 
 /* Insert a breakpoint at address BP_TGT->placed_address in
    the target machine.  Returns 0 for success, and returns non-zero or
@@ -1525,7 +1488,7 @@ extern int target_remove_breakpoint (struct gdbarch *gdbarch,
 				     enum remove_bp_reason reason);
 
 /* Return true if the target stack has a non-default
-  "to_terminal_ours" method.  */
+  "terminal_ours" method.  */
 
 extern int target_supports_terminal_ours (void);
 
@@ -1557,7 +1520,7 @@ extern void target_load (const char *arg, int from_tty);
    Such targets will supply an appropriate definition for this function.  */
 
 #define target_post_startup_inferior(ptid) \
-     (*current_target.to_post_startup_inferior) (&current_target, ptid)
+     (target_stack->post_startup_inferior) (ptid)
 
 /* On some targets, we can catch an inferior fork or vfork event when
    it occurs.  These functions insert/remove an already-created
@@ -1565,16 +1528,16 @@ extern void target_load (const char *arg, int from_tty);
    catchpoint type is not supported and -1 for failure.  */
 
 #define target_insert_fork_catchpoint(pid) \
-     (*current_target.to_insert_fork_catchpoint) (&current_target, pid)
+     (target_stack->insert_fork_catchpoint) (pid)
 
 #define target_remove_fork_catchpoint(pid) \
-     (*current_target.to_remove_fork_catchpoint) (&current_target, pid)
+     (target_stack->remove_fork_catchpoint) (pid)
 
 #define target_insert_vfork_catchpoint(pid) \
-     (*current_target.to_insert_vfork_catchpoint) (&current_target, pid)
+     (target_stack->insert_vfork_catchpoint) (pid)
 
 #define target_remove_vfork_catchpoint(pid) \
-     (*current_target.to_remove_vfork_catchpoint) (&current_target, pid)
+     (target_stack->remove_vfork_catchpoint) (pid)
 
 /* If the inferior forks or vforks, this function will be called at
    the next resume in order to perform any bookkeeping and fiddling
@@ -1597,10 +1560,10 @@ void target_follow_exec (struct inferior *inf, char *execd_pathname);
    catchpoint type is not supported and -1 for failure.  */
 
 #define target_insert_exec_catchpoint(pid) \
-     (*current_target.to_insert_exec_catchpoint) (&current_target, pid)
+     (target_stack->insert_exec_catchpoint) (pid)
 
 #define target_remove_exec_catchpoint(pid) \
-     (*current_target.to_remove_exec_catchpoint) (&current_target, pid)
+     (target_stack->remove_exec_catchpoint) (pid)
 
 /* Syscall catch.
 
@@ -1619,9 +1582,8 @@ void target_follow_exec (struct inferior *inf, char *execd_pathname);
    for failure.  */
 
 #define target_set_syscall_catchpoint(pid, needed, any_count, syscall_counts) \
-     (*current_target.to_set_syscall_catchpoint) (&current_target,	\
-						  pid, needed, any_count, \
-						  syscall_counts)
+     (target_stack->set_syscall_catchpoint) (pid, needed, any_count, \
+					     syscall_counts)
 
 /* The debugger has completed a blocking wait() call.  There is now
    some process event that must be processed.  This function should
@@ -1630,10 +1592,9 @@ void target_follow_exec (struct inferior *inf, char *execd_pathname);
 
 /* For target_mourn_inferior see target/target.h.  */
 
-/* Does target have enough data to do a run or attach command? */
+/* Does target have enough data to do a run or attach command?  */
 
-#define target_can_run(t) \
-     ((t)->to_can_run) (t)
+extern int target_can_run ();
 
 /* Set list of signals to be handled in the target.
 
@@ -1705,7 +1666,7 @@ extern void default_target_pass_ctrlc (struct target_ops *ops);
    placed in OUTBUF.  */
 
 #define target_rcmd(command, outbuf) \
-     (*current_target.to_rcmd) (&current_target, command, outbuf)
+     (target_stack->rcmd) (command, outbuf)
 
 
 /* Does the target include all of memory, or only part of it?  This
@@ -1750,27 +1711,26 @@ extern int target_has_execution_current (void);
 /* Default implementations for process_stratum targets.  Return true
    if there's a selected inferior, false otherwise.  */
 
-extern int default_child_has_all_memory (struct target_ops *ops);
-extern int default_child_has_memory (struct target_ops *ops);
-extern int default_child_has_stack (struct target_ops *ops);
-extern int default_child_has_registers (struct target_ops *ops);
-extern int default_child_has_execution (struct target_ops *ops,
-					ptid_t the_ptid);
+extern int default_child_has_all_memory ();
+extern int default_child_has_memory ();
+extern int default_child_has_stack ();
+extern int default_child_has_registers ();
+extern int default_child_has_execution (ptid_t the_ptid);
 
 /* Can the target support the debugger control of thread execution?
    Can it lock the thread scheduler?  */
 
 #define target_can_lock_scheduler \
-     (current_target.to_has_thread_control & tc_schedlock)
+  (target_stack->get_thread_control_capabilities () & tc_schedlock)
 
 /* Controls whether async mode is permitted.  */
 extern int target_async_permitted;
 
 /* Can the target support asynchronous execution?  */
-#define target_can_async_p() (current_target.to_can_async_p (&current_target))
+#define target_can_async_p() (target_stack->can_async_p ())
 
 /* Is the target in asynchronous execution mode?  */
-#define target_is_async_p() (current_target.to_is_async_p (&current_target))
+#define target_is_async_p() (target_stack->is_async_p ())
 
 /* Enables/disabled async target events.  */
 extern void target_async (int enable);
@@ -1788,7 +1748,7 @@ extern enum auto_boolean target_non_stop_enabled;
 extern int target_is_non_stop_p (void);
 
 #define target_execution_direction() \
-  (current_target.to_execution_direction (&current_target))
+  (target_stack->execution_direction ())
 
 /* Converts a process id to a string.  Usually, the string just contains
    `process xyz', but on some systems it may contain
@@ -1803,7 +1763,7 @@ extern const char *normal_pid_to_str (ptid_t ptid);
    is okay.  */
 
 #define target_extra_thread_info(TP) \
-     (current_target.to_extra_thread_info (&current_target, TP))
+     (target_stack->extra_thread_info (TP))
 
 /* Return the thread's name, or NULL if the target is unable to determine it.
    The returned value must not be freed by the caller.  */
@@ -1829,12 +1789,12 @@ extern struct thread_info *target_thread_handle_to_thread_info
    it must persist.  */
 
 #define target_pid_to_exec_file(pid) \
-     (current_target.to_pid_to_exec_file) (&current_target, pid)
+     (target_stack->pid_to_exec_file) (pid)
 
 /* See the to_thread_architecture description in struct target_ops.  */
 
 #define target_thread_architecture(ptid) \
-     (current_target.to_thread_architecture (&current_target, ptid))
+     (target_stack->thread_architecture (ptid))
 
 /*
  * Iterator function for target memory regions.
@@ -1844,21 +1804,21 @@ extern struct thread_info *target_thread_handle_to_thread_info
  */
 
 #define target_find_memory_regions(FUNC, DATA) \
-     (current_target.to_find_memory_regions) (&current_target, FUNC, DATA)
+     (target_stack->find_memory_regions) (FUNC, DATA)
 
 /*
  * Compose corefile .note section.
  */
 
 #define target_make_corefile_notes(BFD, SIZE_P) \
-     (current_target.to_make_corefile_notes) (&current_target, BFD, SIZE_P)
+     (target_stack->make_corefile_notes) (BFD, SIZE_P)
 
 /* Bookmark interfaces.  */
 #define target_get_bookmark(ARGS, FROM_TTY) \
-     (current_target.to_get_bookmark) (&current_target, ARGS, FROM_TTY)
+     (target_stack->get_bookmark) (ARGS, FROM_TTY)
 
 #define target_goto_bookmark(ARG, FROM_TTY) \
-     (current_target.to_goto_bookmark) (&current_target, ARG, FROM_TTY)
+     (target_stack->goto_bookmark) (ARG, FROM_TTY)
 
 /* Hardware watchpoint interfaces.  */
 
@@ -1866,32 +1826,32 @@ extern struct thread_info *target_thread_handle_to_thread_info
    write).  Only the INFERIOR_PTID task is being queried.  */
 
 #define target_stopped_by_watchpoint()		\
-  ((*current_target.to_stopped_by_watchpoint) (&current_target))
+  ((target_stack->stopped_by_watchpoint) ())
 
 /* Returns non-zero if the target stopped because it executed a
    software breakpoint instruction.  */
 
 #define target_stopped_by_sw_breakpoint()		\
-  ((*current_target.to_stopped_by_sw_breakpoint) (&current_target))
+  ((target_stack->stopped_by_sw_breakpoint) ())
 
 #define target_supports_stopped_by_sw_breakpoint() \
-  ((*current_target.to_supports_stopped_by_sw_breakpoint) (&current_target))
+  ((target_stack->supports_stopped_by_sw_breakpoint) ())
 
 #define target_stopped_by_hw_breakpoint()				\
-  ((*current_target.to_stopped_by_hw_breakpoint) (&current_target))
+  ((target_stack->stopped_by_hw_breakpoint) ())
 
 #define target_supports_stopped_by_hw_breakpoint() \
-  ((*current_target.to_supports_stopped_by_hw_breakpoint) (&current_target))
+  ((target_stack->supports_stopped_by_hw_breakpoint) ())
 
 /* Non-zero if we have steppable watchpoints  */
 
 #define target_have_steppable_watchpoint \
-   (current_target.to_have_steppable_watchpoint)
+  (target_stack->have_steppable_watchpoint ())
 
 /* Non-zero if we have continuable watchpoints  */
 
 #define target_have_continuable_watchpoint \
-   (current_target.to_have_continuable_watchpoint)
+  (target_stack->have_continuable_watchpoint ())
 
 /* Provide defaults for hardware watchpoint functions.  */
 
@@ -1908,19 +1868,18 @@ extern struct thread_info *target_thread_handle_to_thread_info
    this one used so far.  */
 
 #define target_can_use_hardware_watchpoint(TYPE,CNT,OTHERTYPE) \
- (*current_target.to_can_use_hw_breakpoint) (&current_target,  \
+ (target_stack->can_use_hw_breakpoint) ( \
 					     TYPE, CNT, OTHERTYPE)
 
 /* Returns the number of debug registers needed to watch the given
    memory region, or zero if not supported.  */
 
 #define target_region_ok_for_hw_watchpoint(addr, len) \
-    (*current_target.to_region_ok_for_hw_watchpoint) (&current_target,	\
-						      addr, len)
+    (target_stack->region_ok_for_hw_watchpoint) (addr, len)
 
 
 #define target_can_do_single_step() \
-  (*current_target.to_can_do_single_step) (&current_target)
+  (target_stack->can_do_single_step) ()
 
 /* Set/clear a hardware watchpoint starting at ADDR, for LEN bytes.
    TYPE is 0 for write, 1 for read, and 2 for read/write accesses.
@@ -1929,12 +1888,10 @@ extern struct thread_info *target_thread_handle_to_thread_info
    -1 for failure.  */
 
 #define	target_insert_watchpoint(addr, len, type, cond) \
-     (*current_target.to_insert_watchpoint) (&current_target,	\
-					     addr, len, type, cond)
+     (target_stack->insert_watchpoint) (addr, len, type, cond)
 
 #define	target_remove_watchpoint(addr, len, type, cond) \
-     (*current_target.to_remove_watchpoint) (&current_target,	\
-					     addr, len, type, cond)
+     (target_stack->remove_watchpoint) (addr, len, type, cond)
 
 /* Insert a new masked watchpoint at ADDR using the mask MASK.
    RW may be hw_read for a read watchpoint, hw_write for a write watchpoint
@@ -1958,12 +1915,10 @@ extern int target_remove_mask_watchpoint (CORE_ADDR, CORE_ADDR,
    message) otherwise.  */
 
 #define target_insert_hw_breakpoint(gdbarch, bp_tgt) \
-     (*current_target.to_insert_hw_breakpoint) (&current_target,	\
-						gdbarch, bp_tgt)
+     (target_stack->insert_hw_breakpoint) (gdbarch, bp_tgt)
 
 #define target_remove_hw_breakpoint(gdbarch, bp_tgt) \
-     (*current_target.to_remove_hw_breakpoint) (&current_target,	\
-						gdbarch, bp_tgt)
+     (target_stack->remove_hw_breakpoint) (gdbarch, bp_tgt)
 
 /* Return number of debug registers needed for a ranged breakpoint,
    or -1 if ranged breakpoints are not supported.  */
@@ -1974,12 +1929,12 @@ extern int target_ranged_break_num_registers (void);
    target_stopped_by_watchpoint, in such case place it to *ADDR_P.  Only the
    INFERIOR_PTID task is being queried.  */
 #define target_stopped_data_address(target, addr_p) \
-    (*(target)->to_stopped_data_address) (target, addr_p)
+  (target)->stopped_data_address (addr_p)
 
 /* Return non-zero if ADDR is within the range of a watchpoint spanning
    LENGTH bytes beginning at START.  */
 #define target_watchpoint_addr_within_range(target, addr, start, length) \
-  (*(target)->to_watchpoint_addr_within_range) (target, addr, start, length)
+  (target)->watchpoint_addr_within_range (addr, start, length)
 
 /* Return non-zero if the target is capable of using hardware to evaluate
    the condition expression.  In this case, if the condition is false when
@@ -1992,8 +1947,7 @@ extern int target_ranged_break_num_registers (void);
    For this reason, GDB will still evaluate the condition expression when
    the watchpoint triggers.  */
 #define target_can_accel_watchpoint_condition(addr, len, type, cond) \
-  (*current_target.to_can_accel_watchpoint_condition) (&current_target,	\
-						       addr, len, type, cond)
+  (target_stack->can_accel_watchpoint_condition) (addr, len, type, cond)
 
 /* Return number of debug registers needed for a masked watchpoint,
    -1 if masked watchpoints are not supported or -2 if the given address
@@ -2003,12 +1957,12 @@ extern int target_masked_watch_num_registers (CORE_ADDR addr, CORE_ADDR mask);
 
 /* Target can execute in reverse?  */
 #define target_can_execute_reverse \
-      current_target.to_can_execute_reverse (&current_target)
+      target_stack->can_execute_reverse ()
 
 extern const struct target_desc *target_read_description (struct target_ops *);
 
 #define target_get_ada_task_ptid(lwp, tid) \
-     (*current_target.to_get_ada_task_ptid) (&current_target, lwp,tid)
+     (target_stack->get_ada_task_ptid) (lwp,tid)
 
 /* Utility implementation of searching memory.  */
 extern int simple_search_memory (struct target_ops* ops,
@@ -2030,7 +1984,7 @@ extern int target_search_memory (CORE_ADDR start_addr,
 /* Return nonzero if the filesystem seen by the current inferior
    is the local filesystem, zero otherwise.  */
 #define target_filesystem_is_local() \
-  current_target.to_filesystem_is_local (&current_target)
+  target_stack->filesystem_is_local ()
 
 /* Open FILENAME on the target, in the filesystem as seen by INF,
    using FLAGS and MODE.  If INF is NULL, use the filesystem seen
@@ -2117,105 +2071,100 @@ extern gdb::unique_xmalloc_ptr<char> target_fileio_read_stralloc
 /* Tracepoint-related operations.  */
 
 #define target_trace_init() \
-  (*current_target.to_trace_init) (&current_target)
+  (target_stack->trace_init) ()
 
 #define target_download_tracepoint(t) \
-  (*current_target.to_download_tracepoint) (&current_target, t)
+  (target_stack->download_tracepoint) (t)
 
 #define target_can_download_tracepoint() \
-  (*current_target.to_can_download_tracepoint) (&current_target)
+  (target_stack->can_download_tracepoint) ()
 
 #define target_download_trace_state_variable(tsv) \
-  (*current_target.to_download_trace_state_variable) (&current_target, tsv)
+  (target_stack->download_trace_state_variable) (tsv)
 
 #define target_enable_tracepoint(loc) \
-  (*current_target.to_enable_tracepoint) (&current_target, loc)
+  (target_stack->enable_tracepoint) (loc)
 
 #define target_disable_tracepoint(loc) \
-  (*current_target.to_disable_tracepoint) (&current_target, loc)
+  (target_stack->disable_tracepoint) (loc)
 
 #define target_trace_start() \
-  (*current_target.to_trace_start) (&current_target)
+  (target_stack->trace_start) ()
 
 #define target_trace_set_readonly_regions() \
-  (*current_target.to_trace_set_readonly_regions) (&current_target)
+  (target_stack->trace_set_readonly_regions) ()
 
 #define target_get_trace_status(ts) \
-  (*current_target.to_get_trace_status) (&current_target, ts)
+  (target_stack->get_trace_status) (ts)
 
 #define target_get_tracepoint_status(tp,utp)		\
-  (*current_target.to_get_tracepoint_status) (&current_target, tp, utp)
+  (target_stack->get_tracepoint_status) (tp, utp)
 
 #define target_trace_stop() \
-  (*current_target.to_trace_stop) (&current_target)
+  (target_stack->trace_stop) ()
 
 #define target_trace_find(type,num,addr1,addr2,tpp) \
-  (*current_target.to_trace_find) (&current_target, \
+  (target_stack->trace_find) (\
 				   (type), (num), (addr1), (addr2), (tpp))
 
 #define target_get_trace_state_variable_value(tsv,val) \
-  (*current_target.to_get_trace_state_variable_value) (&current_target,	\
-						       (tsv), (val))
+  (target_stack->get_trace_state_variable_value) ((tsv), (val))
 
 #define target_save_trace_data(filename) \
-  (*current_target.to_save_trace_data) (&current_target, filename)
+  (target_stack->save_trace_data) (filename)
 
 #define target_upload_tracepoints(utpp) \
-  (*current_target.to_upload_tracepoints) (&current_target, utpp)
+  (target_stack->upload_tracepoints) (utpp)
 
 #define target_upload_trace_state_variables(utsvp) \
-  (*current_target.to_upload_trace_state_variables) (&current_target, utsvp)
+  (target_stack->upload_trace_state_variables) (utsvp)
 
 #define target_get_raw_trace_data(buf,offset,len) \
-  (*current_target.to_get_raw_trace_data) (&current_target,	\
-					   (buf), (offset), (len))
+  (target_stack->get_raw_trace_data) ((buf), (offset), (len))
 
 #define target_get_min_fast_tracepoint_insn_len() \
-  (*current_target.to_get_min_fast_tracepoint_insn_len) (&current_target)
+  (target_stack->get_min_fast_tracepoint_insn_len) ()
 
 #define target_set_disconnected_tracing(val) \
-  (*current_target.to_set_disconnected_tracing) (&current_target, val)
+  (target_stack->set_disconnected_tracing) (val)
 
 #define	target_set_circular_trace_buffer(val)	\
-  (*current_target.to_set_circular_trace_buffer) (&current_target, val)
+  (target_stack->set_circular_trace_buffer) (val)
 
 #define	target_set_trace_buffer_size(val)	\
-  (*current_target.to_set_trace_buffer_size) (&current_target, val)
+  (target_stack->set_trace_buffer_size) (val)
 
 #define	target_set_trace_notes(user,notes,stopnotes)		\
-  (*current_target.to_set_trace_notes) (&current_target,	\
-					(user), (notes), (stopnotes))
+  (target_stack->set_trace_notes) ((user), (notes), (stopnotes))
 
 #define target_get_tib_address(ptid, addr) \
-  (*current_target.to_get_tib_address) (&current_target, (ptid), (addr))
+  (target_stack->get_tib_address) ((ptid), (addr))
 
 #define target_set_permissions() \
-  (*current_target.to_set_permissions) (&current_target)
+  (target_stack->set_permissions) ()
 
 #define target_static_tracepoint_marker_at(addr, marker) \
-  (*current_target.to_static_tracepoint_marker_at) (&current_target,	\
-						    addr, marker)
+  (target_stack->static_tracepoint_marker_at) (addr, marker)
 
 #define target_static_tracepoint_markers_by_strid(marker_id) \
-  (*current_target.to_static_tracepoint_markers_by_strid) (&current_target, \
-							   marker_id)
+  (target_stack->static_tracepoint_markers_by_strid) (marker_id)
 
 #define target_traceframe_info() \
-  (*current_target.to_traceframe_info) (&current_target)
+  (target_stack->traceframe_info) ()
 
 #define target_use_agent(use) \
-  (*current_target.to_use_agent) (&current_target, use)
+  (target_stack->use_agent) (use)
 
 #define target_can_use_agent() \
-  (*current_target.to_can_use_agent) (&current_target)
+  (target_stack->can_use_agent) ()
 
 #define target_augmented_libraries_svr4_read() \
-  (*current_target.to_augmented_libraries_svr4_read) (&current_target)
+  (target_stack->augmented_libraries_svr4_read) ()
 
 /* Command logging facility.  */
 
 #define target_log_command(p)					\
-  (*current_target.to_log_command) (&current_target, p)
+  (target_stack->log_command) (p)
 
 
 extern int target_core_of_thread (ptid_t ptid);
@@ -2244,11 +2193,6 @@ int target_verify_memory (const gdb_byte *data,
 
 /* Routines for maintenance of the target structures...
 
-   complete_target_initialization: Finalize a target_ops by filling in
-   any fields needed by the target implementation.  Unnecessary for
-   targets which are registered via add_target, as this part gets
-   taken care of then.
-
    add_target:   Add a target to the list of all possible targets.
    This only makes sense for targets that should be activated using
    the "target TARGET_NAME ..." command.
@@ -2267,8 +2211,6 @@ extern void add_target (struct target_ops *);
 extern void add_target_with_completer (struct target_ops *t,
 				       completer_ftype *completer);
 
-extern void complete_target_initialization (struct target_ops *t);
-
 /* Adds a command ALIAS for target T and marks it deprecated.  This is useful
    for maintaining backwards compatibility when renaming targets.  */
 
@@ -2338,12 +2280,28 @@ extern struct target_section_table *target_get_section_table
 
 /* From mem-break.c */
 
-extern int memory_remove_breakpoint (struct target_ops *, struct gdbarch *,
-				     struct bp_target_info *,
+extern int memory_remove_breakpoint (struct target_ops *,
+				     struct gdbarch *, struct bp_target_info *,
 				     enum remove_bp_reason);
 
-extern int memory_insert_breakpoint (struct target_ops *, struct gdbarch *,
-				     struct bp_target_info *);
+extern int memory_insert_breakpoint (struct target_ops *,
+				     struct gdbarch *, struct bp_target_info *);
+
+/* Convenience template use to add memory breakpoints support to a
+   target.  */
+
+template <typename BaseTarget>
+struct memory_breakpoint_target : public BaseTarget
+{
+  int insert_breakpoint (struct gdbarch *gdbarch,
+			 struct bp_target_info *bp_tgt) override
+  { return memory_insert_breakpoint (this, gdbarch, bp_tgt); }
+
+  int remove_breakpoint (struct gdbarch *gdbarch,
+			 struct bp_target_info *bp_tgt,
+			 enum remove_bp_reason reason) override
+  { return memory_remove_breakpoint (this, gdbarch, bp_tgt, reason); }
+};
 
 /* Check whether the memory at the breakpoint's placed address still
    contains the expected breakpoint instruction.  */
@@ -2501,8 +2459,52 @@ namespace selftests {
 class test_target_ops : public target_ops
 {
 public:
-  test_target_ops ();
+  test_target_ops ()
+    : target_ops {}
+  {
+    to_stratum = process_stratum;
+  }
+
+  const char *shortname () override
+  {
+    return NULL;
+  }
+
+  const char *longname () override
+  {
+    return NULL;
+  }
+
+  const char *doc () override
+  {
+    return NULL;
+  }
+
+  int has_registers () override
+  {
+    return 1;
+  }
+
+  int has_stack () override
+  {
+    return 1;
+  }
+
+  int has_memory () override
+  {
+    return 1;
+  }
+
+  void prepare_to_store (regcache *regs) override
+  {
+  }
+
+  void store_registers (regcache *regs, int regno) override
+  {
+  }
 };
+
+
 } // namespace selftests
 #endif /* GDB_SELF_TEST */
 
diff --git a/gdb/testsuite/gdb.base/breakpoint-in-ro-region.exp b/gdb/testsuite/gdb.base/breakpoint-in-ro-region.exp
index e888e17a02..61a6319c45 100644
--- a/gdb/testsuite/gdb.base/breakpoint-in-ro-region.exp
+++ b/gdb/testsuite/gdb.base/breakpoint-in-ro-region.exp
@@ -40,7 +40,7 @@ proc probe_target_hardware_step {} {
     gdb_test_no_output "set debug target 1"
     set test "probe target hardware step"
     gdb_test_multiple "si" $test {
-	-re "to_resume \\(\[^\r\n\]+, step, .*$gdb_prompt $" {
+	-re "resume \\(\[^\r\n\]+, step, .*$gdb_prompt $" {
 	    set hw_step 1
 	    pass $test
 	}
@@ -48,7 +48,7 @@ proc probe_target_hardware_step {} {
 	    pass $test
 	}
     }
-    gdb_test "set debug target 0" "->to_log_command.*\\).*"
+    gdb_test "set debug target 0" "->log_command.*\\).*"
     return $hw_step
 }
 
diff --git a/gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.exp b/gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.exp
index 54ff015556..3775954713 100644
--- a/gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.exp
+++ b/gdb/testsuite/gdb.base/sss-bp-on-user-bp-2.exp
@@ -62,7 +62,7 @@ gdb_test_no_output "set debug target 1"
 set hardware_step 0
 set test "probe target hardware step"
 gdb_test_multiple "si" $test {
-    -re "to_resume \\(\[^\r\n\]+, step, .*$gdb_prompt $" {
+    -re "resume \\(\[^\r\n\]+, step, .*$gdb_prompt $" {
 	set hardware_step 1
 	pass $test
     }
@@ -76,7 +76,7 @@ if { $hardware_step } {
     return
 }
 
-gdb_test "set debug target 0" "->to_log_command.*\\)"
+gdb_test "set debug target 0" "->log_command.*\\)"
 
 set line_re "\[^\r\n\]*"
 
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index 7e173ce75d..d358927915 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -3811,7 +3811,7 @@ sdata_make_value (struct gdbarch *gdbarch, struct internalvar *var,
 {
   /* We need to read the whole object before we know its size.  */
   gdb::optional<gdb::byte_vector> buf
-    = target_read_alloc (&current_target, TARGET_OBJECT_STATIC_TRACE_DATA,
+    = target_read_alloc (target_stack, TARGET_OBJECT_STATIC_TRACE_DATA,
 			 NULL);
   if (buf)
     {
diff --git a/gdb/valops.c b/gdb/valops.c
index 1f655b5187..62a86c06a3 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -964,7 +964,7 @@ read_value_memory (struct value *val, LONGEST bit_offset,
       enum target_xfer_status status;
       ULONGEST xfered_partial;
 
-      status = target_xfer_partial (current_target.beneath,
+      status = target_xfer_partial (target_stack,
 				    object, NULL,
 				    buffer + xfered_total * unit_size, NULL,
 				    memaddr + xfered_total,
@@ -1208,7 +1208,7 @@ value_assign (struct value *toval, struct value *fromval)
     case lval_register:
     case lval_computed:
 
-      gdb::observers::target_changed.notify (&current_target);
+      gdb::observers::target_changed.notify (target_stack);
 
       /* Having destroyed the frame cache, restore the selected
 	 frame.  */
diff --git a/gdb/valprint.c b/gdb/valprint.c
index 3104e0b45e..bed2cecf2c 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -1885,7 +1885,7 @@ print_function_pointer_address (const struct value_print_options *options,
 {
   CORE_ADDR func_addr
     = gdbarch_convert_from_func_ptr_addr (gdbarch, address,
-					  &current_target);
+					  target_stack);
 
   /* If the function pointer is represented by a description, print
      the address of the description.  */
diff --git a/gdb/value.c b/gdb/value.c
index 12aa2b8bb4..c1acbecc5b 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -3071,7 +3071,7 @@ value_fn_field (struct value **arg1p, struct fn_field *f,
 
       set_value_address (v,
 	gdbarch_convert_from_func_ptr_addr
-	   (gdbarch, BMSYMBOL_VALUE_ADDRESS (msym), &current_target));
+	   (gdbarch, BMSYMBOL_VALUE_ADDRESS (msym), target_stack));
     }
 
   if (arg1p)
diff --git a/gdb/windows-tdep.c b/gdb/windows-tdep.c
index 8b3db5d168..eb44d8d407 100644
--- a/gdb/windows-tdep.c
+++ b/gdb/windows-tdep.c
@@ -331,7 +331,7 @@ display_one_tib (ptid_t ptid)
       return -1;
     }
 
-  if (target_read (&current_target, TARGET_OBJECT_MEMORY,
+  if (target_read (target_stack, TARGET_OBJECT_MEMORY,
 		   NULL, tib, thread_local_base, tib_size) != tib_size)
     {
       printf_filtered (_("Unable to read thread information "
