diff --git a/gdb/aarch64-fbsd-nat.c b/gdb/aarch64-fbsd-nat.c
index 5ffbf1fdb1..a50656353c 100644
--- a/gdb/aarch64-fbsd-nat.c
+++ b/gdb/aarch64-fbsd-nat.c
@@ -128,5 +128,5 @@ aarch64_fbsd_nat_target::store_registers (struct regcache *regcache,
 void
 _initialize_aarch64_fbsd_nat (void)
 {
-  add_target (&the_aarch64_fbsd_nat_target);
+  add_inf_child_target (&the_aarch64_fbsd_nat_target);
 }
diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 724ca9c3ff..5d46ccc70e 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -837,10 +837,8 @@ triggers a breakpoint or watchpoint."),
 void
 _initialize_aarch64_linux_nat (void)
 {
-  struct target_ops *t = &the_aarch64_linux_nat_target;
-
   add_show_debug_regs_command ();
 
   /* Register the target.  */
-  add_target (t);
+  add_inf_child_target (&the_aarch64_linux_nat_target);
 }
diff --git a/gdb/aix-thread.c b/gdb/aix-thread.c
index 410fb55e72..d328bdd872 100644
--- a/gdb/aix-thread.c
+++ b/gdb/aix-thread.c
@@ -108,18 +108,20 @@ struct pd_thread {
 
 /* This module's target-specific operations, active while pd_able is true.  */
 
+static const target_info aix_thread_target_info = {
+  "aix-threads",
+  N_("AIX pthread support"),
+  N_("AIX pthread support")
+};
+
 class aix_thread_target final : public target_ops
 {
 public:
   aix_thread_target ()
   { to_stratum = thread_stratum; }
 
-  const char *shortname () override
-  { return "aix-threads"; }
-  const char *longname () override
-  { return _("AIX pthread support"); }
-  const char *doc () override
-  { return _("AIX pthread support"); }
+  const target_info &info () const override
+  { return aix_thread_target_info; }
 
   void detach (inferior *, int) override;
   void resume (ptid_t, int, enum gdb_signal) override;
diff --git a/gdb/alpha-bsd-nat.c b/gdb/alpha-bsd-nat.c
index 5dc7a32235..5acc74611d 100644
--- a/gdb/alpha-bsd-nat.c
+++ b/gdb/alpha-bsd-nat.c
@@ -196,7 +196,7 @@ alphabsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 void
 _initialize_alphabsd_nat (void)
 {
-  add_target (&the_alpha_bsd_nat_target);
+  add_inf_child_target (&the_alpha_bsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (alphabsd_supply_pcb);
diff --git a/gdb/alpha-linux-nat.c b/gdb/alpha-linux-nat.c
index 70997e5f4a..4286db3318 100644
--- a/gdb/alpha-linux-nat.c
+++ b/gdb/alpha-linux-nat.c
@@ -103,5 +103,5 @@ alpha_linux_nat_target::register_u_offset (struct gdbarch *gdbarch,
 void
 _initialize_alpha_linux_nat (void)
 {
-  add_target (&the_alpha_linux_nat_target);
+  add_inf_child_target (&the_alpha_linux_nat_target);
 }
diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
index 9177c3eec2..1cb4c2c627 100644
--- a/gdb/amd64-linux-nat.c
+++ b/gdb/amd64-linux-nat.c
@@ -421,5 +421,5 @@ _initialize_amd64_linux_nat (void)
   linux_target = &the_amd64_linux_nat_target;
 
   /* Add the target.  */
-  add_target (linux_target);
+  add_inf_child_target (linux_target);
 }
diff --git a/gdb/amd64-nbsd-nat.c b/gdb/amd64-nbsd-nat.c
index e1c07dfb4c..f92983b4f5 100644
--- a/gdb/amd64-nbsd-nat.c
+++ b/gdb/amd64-nbsd-nat.c
@@ -63,5 +63,5 @@ _initialize_amd64nbsd_nat (void)
   amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64nbsd32_r_reg_offset);
   amd64_native_gregset64_reg_offset = amd64nbsd_r_reg_offset;
 
-  add_target (&the_amd64_nbsd_nat_target);
+  add_inf_child_target (&the_amd64_nbsd_nat_target);
 }
diff --git a/gdb/amd64-obsd-nat.c b/gdb/amd64-obsd-nat.c
index d6756d9463..0e89e3f574 100644
--- a/gdb/amd64-obsd-nat.c
+++ b/gdb/amd64-obsd-nat.c
@@ -135,7 +135,7 @@ _initialize_amd64obsd_nat (void)
   amd64_native_gregset32_num_regs = ARRAY_SIZE (amd64obsd32_r_reg_offset);
   amd64_native_gregset64_reg_offset = amd64obsd_r_reg_offset;
 
-  add_target (&the_amd64_obsd_nat_target);
+  add_inf_child_target (&the_amd64_obsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (amd64obsd_supply_pcb);
diff --git a/gdb/arm-fbsd-nat.c b/gdb/arm-fbsd-nat.c
index f31ee5fa1d..be733ff746 100644
--- a/gdb/arm-fbsd-nat.c
+++ b/gdb/arm-fbsd-nat.c
@@ -148,5 +148,5 @@ arm_fbsd_nat_target::read_description ()
 void
 _initialize_arm_fbsd_nat (void)
 {
-  add_target (&the_arm_fbsd_nat_target);
+  add_inf_child_target (&the_arm_fbsd_nat_target);
 }
diff --git a/gdb/arm-linux-nat.c b/gdb/arm-linux-nat.c
index aac90fd223..5df1ef1a86 100644
--- a/gdb/arm-linux-nat.c
+++ b/gdb/arm-linux-nat.c
@@ -1330,8 +1330,6 @@ arm_linux_nat_target::low_new_fork (struct lwp_info *parent, pid_t child_pid)
 void
 _initialize_arm_linux_nat (void)
 {
-  target_ops *t = &the_arm_linux_nat_target;
-
   /* Register the target.  */
-  add_target (t);
+  add_inf_child_target (&the_arm_linux_nat_target);
 }
diff --git a/gdb/arm-nbsd-nat.c b/gdb/arm-nbsd-nat.c
index 9d58b35a2a..3a1ddeaf4e 100644
--- a/gdb/arm-nbsd-nat.c
+++ b/gdb/arm-nbsd-nat.c
@@ -469,7 +469,7 @@ static struct core_fns arm_netbsd_elfcore_fns =
 void
 _initialize_arm_netbsd_nat (void)
 {
-  add_target (&the_arm_netbsd_nat_target);
+  add_inf_child_target (&the_arm_netbsd_nat_target);
 
   deprecated_add_core_fns (&arm_netbsd_elfcore_fns);
 }
diff --git a/gdb/bfd-target.c b/gdb/bfd-target.c
index 7ac8bc3c61..ba194d7b04 100644
--- a/gdb/bfd-target.c
+++ b/gdb/bfd-target.c
@@ -24,20 +24,21 @@
 #include "gdb_bfd.h"
 
 /* A target that wraps a BFD.  */
+
+static const target_info target_bfd_target_info = {
+  "bfd",
+  N_("BFD backed target"),
+  N_("You should never see this")
+};
+
 class target_bfd : public target_ops
 {
 public:
   explicit target_bfd (struct bfd *bfd);
   ~target_bfd () override;
 
-  const char *shortname () override
-  { return "bfd"; }
-
-  const char *longname () override
-  { return _("BFD backed target"); }
-
-  const char *doc () override
-  { return _("You should never see this"); }
+  const target_info &info () const override
+  { return target_bfd_target_info; }
 
   void close () override;
 
diff --git a/gdb/bsd-kvm.c b/gdb/bsd-kvm.c
index 804cddb927..7260799fac 100644
--- a/gdb/bsd-kvm.c
+++ b/gdb/bsd-kvm.c
@@ -63,25 +63,22 @@ static ptid_t bsd_kvm_ptid;
 
 /* The libkvm target.  */
 
+static const target_info bsd_kvm_target_info = {
+  "kvm",
+  N_("Kernel memory interface"),
+  N_("Use a kernel virtual memory image as a target.\n\
+Optionally specify the filename of a core dump.")
+};
+
 class bsd_kvm_target : public target_ops
 {
 public:
   bsd_kvm_target ()
   { this->to_stratum = process_stratum; }
 
-  const char *shortname () override
-  { return "kvm"; }
-
-  const char *longname () override
-  { return _("Kernel memory interface"); }
-
-  const char *doc () override
-  {
-    return _("Use a kernel virtual memory image as a target.\n\
-Optionally specify the filename of a core dump.");
-  }
+  const target_info &info () const override
+  { return bsd_kvm_target_info; }
 
-  void open (const char *, int) override;
   void close () override;
 
   void fetch_registers (struct regcache *, int) override;
@@ -105,7 +102,7 @@ Optionally specify the filename of a core dump.");
 static bsd_kvm_target bsd_kvm_ops;
 
 static void
-bsd_kvm_target::open (const char *arg, int from_tty)
+bsd_kvm_target_open (const char *arg, int from_tty)
 {
   char errbuf[_POSIX2_LINE_MAX];
   char *execfile = NULL;
@@ -388,7 +385,7 @@ bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *))
   gdb_assert (bsd_kvm_supply_pcb == NULL);
   bsd_kvm_supply_pcb = supply_pcb;
 
-  add_target (&bsd_kvm_ops);
+  add_target (bsd_kvm_target_info, bsd_kvm_target_open);
   
   add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, _("\
 Generic command for manipulating the kernel memory interface."),
diff --git a/gdb/bsd-uthread.c b/gdb/bsd-uthread.c
index efcec1e396..1505cfede7 100644
--- a/gdb/bsd-uthread.c
+++ b/gdb/bsd-uthread.c
@@ -33,19 +33,19 @@
 
 #include "bsd-uthread.h"
 
+static const target_info bsd_uthread_target_info = {
+  "bsd-uthreads",
+  N_("BSD user-level threads"),
+  N_("BSD user-level threads")
+};
+
 struct bsd_uthread_target final : public target_ops
 {
   bsd_uthread_target ()
   { to_stratum = thread_stratum; }
 
-  const char *shortname () override
-  { return "bsd-uthreads"; }
-
-  const char *longname () override
-  { return _("BSD user-level threads"); }
-
-  const char *doc () override
-  { return _("BSD user-level threads"); }
+  const target_info &info () const override
+  { return bsd_uthread_target_info; }
 
   void close () override;
 
diff --git a/gdb/corefile.c b/gdb/corefile.c
index c849a10646..114de83640 100644
--- a/gdb/corefile.c
+++ b/gdb/corefile.c
@@ -62,12 +62,14 @@ core_file_command (const char *filename, int from_tty)
 {
   dont_repeat ();		/* Either way, seems bogus.  */
 
-  gdb_assert (the_core_target != NULL);
-
   if (!filename)
-    the_core_target->detach (current_inferior (), from_tty);
+    {
+      gdb_assert (the_core_target != NULL);
+
+      the_core_target->detach (current_inferior (), from_tty);
+    }
   else
-    the_core_target->open (filename, from_tty);
+    core_target_open (filename, from_tty);
 }
 
 
diff --git a/gdb/corelow.c b/gdb/corelow.c
index e7d9a7ed51..97a957c8fc 100644
--- a/gdb/corelow.c
+++ b/gdb/corelow.c
@@ -52,25 +52,21 @@
 
 /* The core file target.  */
 
+static const target_info core_target_info = {
+  "core",
+  N_("Local core dump file"),
+  N_("Use a core file as a target.  Specify the filename of the core file.")
+};
+
 class core_target final : public target_ops
 {
 public:
   core_target ()
   { to_stratum = process_stratum; }
 
-  const char *shortname () override
-  { return "core"; }
-
-  const char *longname () override
-  { return _("Local core dump file"); }
+  const target_info &info () const override
+  { return core_target_info; }
 
-  const char *doc () override
-  {
-    return _("\
-Use a core file as a target.  Specify the filename of the core file.");
-  }
-
-  void open (const char *, int) override;
   void close () override;
   void detach (inferior *, int) override;
   void fetch_registers (struct regcache *, int) override;
@@ -313,10 +309,10 @@ add_to_thread_list (bfd *abfd, asection *asect, void *reg_sect_arg)
     inferior_ptid = ptid;			/* Yes, make it current.  */
 }
 
-/* This routine opens and sets up the core file bfd.  */
+/* See gdbcore.h.  */
 
 void
-core_target::open (const char *arg, int from_tty)
+core_target_open (const char *arg, int from_tty)
 {
   const char *p;
   int siggy;
@@ -1031,5 +1027,5 @@ _initialize_corelow (void)
 		    the_core_target->longname ());
   the_core_target = &core_ops;
 
-  add_target_with_completer (&core_ops, filename_completer);
+  add_target (core_target_info, core_target_open, filename_completer);
 }
diff --git a/gdb/ctf.c b/gdb/ctf.c
index 90d6f6c025..cae5d221cb 100644
--- a/gdb/ctf.c
+++ b/gdb/ctf.c
@@ -34,23 +34,19 @@
 
 /* The CTF target.  */
 
+static const target_info ctf_target_info = {
+  "ctf",
+  N_("CTF file"),
+  N_("(Use a CTF directory as a target.\n\
+Specify the filename of the CTF directory.")
+};
+
 class ctf_target final : public tracefile_target
 {
 public:
-  const char *shortname () override
-  { return "ctf"; }
-
-  const char *longname () override
-  { return _("CTF file"); }
+  const target_info &info () const override
+  { return ctf_target_info; }
 
-  const char *doc () override
-  {
-    return _("\
-Use a CTF directory as a target.\n\
-Specify the filename of the CTF directory.");
-  }
-
-  void open (const char *, int) override;
   void close () override;
   void fetch_registers (struct regcache *, int) override;
   enum target_xfer_status xfer_partial (enum target_object object,
@@ -1108,8 +1104,8 @@ ctf_read_tp (struct uploaded_tp **uploaded_tps)
    definitions from the first packet.  Set the start position at the
    second packet which contains events on trace blocks.  */
 
-void
-ctf_target::open (const char *dirname, int from_tty)
+static void
+ctf_target_open (const char *dirname, int from_tty)
 {
   struct bt_ctf_event *event;
   uint32_t event_id;
@@ -1724,6 +1720,6 @@ void
 _initialize_ctf (void)
 {
 #if HAVE_LIBBABELTRACE
-  add_target_with_completer (&ctf_ops, filename_completer);
+  add_target (ctf_target_info, ctf_target_open, filename_completer);
 #endif
 }
diff --git a/gdb/exec.c b/gdb/exec.c
index 4c71abd35f..9a9d904f36 100644
--- a/gdb/exec.c
+++ b/gdb/exec.c
@@ -49,6 +49,13 @@
 
 void (*deprecated_file_changed_hook) (const char *);
 
+static const target_info exec_target_info = {
+  "exec",
+  N_("Local exec file"),
+  N_("Use an executable file as a target.\n\
+Specify the filename of the executable file.")
+};
+
 /* The target vector for executable files.  */
 
 struct exec_target final : public target_ops
@@ -56,20 +63,9 @@ struct exec_target final : public target_ops
   exec_target ()
   { to_stratum = file_stratum; }
 
-  const char *shortname () override
-  { return "exec"; }
-
-  const char *longname () override
-  { return _("Local exec file"); }
+  const target_info &info () const override
+  { return exec_target_info; }
 
-  const char *doc () override
-  {
-    return _("\
-Use an executable file as a target.\n\
-Specify the filename of the executable file.");
-  }
-
-  void open (const char *, int) override;
   void close () override;
   enum target_xfer_status xfer_partial (enum target_object object,
 					const char *annex,
@@ -99,8 +95,8 @@ show_write_files (struct ui_file *file, int from_tty,
 }
 
 
-void
-exec_target::open (const char *args, int from_tty)
+static void
+exec_target_open (const char *args, int from_tty)
 {
   target_preopen (from_tty);
   exec_file_attach (args, from_tty);
@@ -1090,5 +1086,5 @@ Show writing into executable and core files."), NULL,
 			   show_write_files,
 			   &setlist, &showlist);
 
-  add_target_with_completer (&exec_ops, filename_completer);
+  add_target (exec_target_info, exec_target_open, filename_completer);
 }
diff --git a/gdb/gdbcore.h b/gdb/gdbcore.h
index 04a235dd90..401c213d48 100644
--- a/gdb/gdbcore.h
+++ b/gdb/gdbcore.h
@@ -143,6 +143,10 @@ extern struct target_ops *the_core_target;
 
 extern int write_files;
 
+/* Open and set up the core file bfd.  */
+
+extern void core_target_open (const char *arg, int from_tty);
+
 extern void core_file_command (const char *filename, int from_tty);
 
 extern void exec_file_attach (const char *filename, int from_tty);
diff --git a/gdb/go32-nat.c b/gdb/go32-nat.c
index 6f6aedea7e..22da20a4a0 100644
--- a/gdb/go32-nat.c
+++ b/gdb/go32-nat.c
@@ -2090,7 +2090,7 @@ _initialize_go32_nat (void)
   x86_dr_low.get_addr = go32_get_dr;
   x86_set_debug_register_length (4);
 
-  add_target (&the_go32_nat_target);
+  add_inf_child_target (&the_go32_nat_target);
 
   /* Initialize child's cwd as empty to be initialized when starting
      the child.  */
diff --git a/gdb/hppa-linux-nat.c b/gdb/hppa-linux-nat.c
index 36f6a19e67..1ddc5aeb14 100644
--- a/gdb/hppa-linux-nat.c
+++ b/gdb/hppa-linux-nat.c
@@ -390,5 +390,5 @@ void
 _initialize_hppa_linux_nat (void)
 {
   /* Register the target.  */
-  add_target (&the_hppa_linux_nat_target);
+  add_inf_child_target (&the_hppa_linux_nat_target);
 }
diff --git a/gdb/hppa-nbsd-nat.c b/gdb/hppa-nbsd-nat.c
index 1497166145..3547d65543 100644
--- a/gdb/hppa-nbsd-nat.c
+++ b/gdb/hppa-nbsd-nat.c
@@ -231,5 +231,5 @@ hppa_nbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
 void
 _initialize_hppanbsd_nat (void)
 {
-  add_target (&the_hppa_nbsd_nat_target);
+  add_inf_child_target (&the_hppa_nbsd_nat_target);
 }
diff --git a/gdb/hppa-obsd-nat.c b/gdb/hppa-obsd-nat.c
index 2bef638a31..3ca19adc75 100644
--- a/gdb/hppa-obsd-nat.c
+++ b/gdb/hppa-obsd-nat.c
@@ -255,5 +255,5 @@ hppa_obsd_nat_target::store_registers (struct regcache *regcache, int regnum)
 void
 _initialize_hppaobsd_nat (void)
 {
-  add_target (&the_hppa_obsd_nat_target);
+  add_inf_child_target (&the_hppa_obsd_nat_target);
 }
diff --git a/gdb/i386-darwin-nat.c b/gdb/i386-darwin-nat.c
index 48f1a7921d..e57b12693f 100644
--- a/gdb/i386-darwin-nat.c
+++ b/gdb/i386-darwin-nat.c
@@ -659,5 +659,5 @@ _initialize_i386_darwin_nat (void)
   x86_set_debug_register_length (4);
 #endif
 
-  add_target (&darwin_target);
+  add_inf_child_target (&darwin_target);
 }
diff --git a/gdb/i386-fbsd-nat.c b/gdb/i386-fbsd-nat.c
index f2bb82c4c0..6518b712c6 100644
--- a/gdb/i386-fbsd-nat.c
+++ b/gdb/i386-fbsd-nat.c
@@ -163,7 +163,7 @@ i386_fbsd_nat_traget::read_description ()
 void
 _initialize_i386fbsd_nat (void)
 {
-  add_target (&the_i386_fbsd_nat_target);
+  add_inf_child_target (&the_i386_fbsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (i386fbsd_supply_pcb);
diff --git a/gdb/i386-gnu-nat.c b/gdb/i386-gnu-nat.c
index de7d62a269..8bb036dac3 100644
--- a/gdb/i386-gnu-nat.c
+++ b/gdb/i386-gnu-nat.c
@@ -440,5 +440,5 @@ _initialize_i386gnu_nat (void)
 #endif /* i386_DEBUG_STATE */
 
   /* Register the target.  */
-  add_target (&the_i386_gnu_nat_target);
+  add_inf_child_target (&the_i386_gnu_nat_target);
 }
diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
index 786eec227f..6538324306 100644
--- a/gdb/i386-linux-nat.c
+++ b/gdb/i386-linux-nat.c
@@ -717,5 +717,5 @@ _initialize_i386_linux_nat (void)
   linux_target = &the_i386_linux_nat_target;
 
   /* Add the target.  */
-  add_target (linux_target);
+  add_inf_child_target (linux_target);
 }
diff --git a/gdb/i386-nbsd-nat.c b/gdb/i386-nbsd-nat.c
index 508abdc92e..bc875e07cd 100644
--- a/gdb/i386-nbsd-nat.c
+++ b/gdb/i386-nbsd-nat.c
@@ -76,7 +76,7 @@ static i386_bsd_nat_target<nbsd_nat_target> the_i386_nbsd_nat_target;
 void
 _initialize_i386nbsd_nat (void)
 {
-  add_target (&the_i386_nbsd_nat_target);
+  add_inf_child_target (&the_i386_nbsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (i386nbsd_supply_pcb);
diff --git a/gdb/i386-obsd-nat.c b/gdb/i386-obsd-nat.c
index 2a09f3e0d6..a3221edc85 100644
--- a/gdb/i386-obsd-nat.c
+++ b/gdb/i386-obsd-nat.c
@@ -93,7 +93,7 @@ static i386_bsd_nat_target<obsd_nat_target> the_i386_obsd_nat_target;
 void
 _initialize_i386obsd_nat (void)
 {
-  add_target (&i386_obsd_nat_target);
+  add_inf_child_target (&i386_obsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (i386obsd_supply_pcb);
diff --git a/gdb/ia64-linux-nat.c b/gdb/ia64-linux-nat.c
index 1e7ff6dcd5..315b3bbaef 100644
--- a/gdb/ia64-linux-nat.c
+++ b/gdb/ia64-linux-nat.c
@@ -929,8 +929,6 @@ ia64_linux_nat_target::low_status_is_event (int status)
 void
 _initialize_ia64_linux_nat (void)
 {
-  struct target_ops *t = &the_ia64_linux_nat_target;
-
   /* Register the target.  */
-  add_target (t);
+  add_inf_child_target (&the_ia64_linux_nat_target);
 }
diff --git a/gdb/inf-child.c b/gdb/inf-child.c
index 8e5ebfa2c2..2f5babebce 100644
--- a/gdb/inf-child.c
+++ b/gdb/inf-child.c
@@ -39,6 +39,18 @@
 #include <fcntl.h>
 #include <unistd.h>
 
+static const target_info inf_child_target_info = {
+  "native",
+  N_("Native process"),
+  N_("Native process (started by the \"run\" command).")
+};
+
+const target_info &
+inf_child_target::info () const
+{
+  return inf_child_target_info;
+}
+
 /* Helper function for child_wait and the derivatives of child_wait.
    HOSTSTATUS is the waitstatus from wait() or the equivalent; store our
    translation of that in OURSTATUS.  */
@@ -139,9 +151,14 @@ static int inf_child_explicitly_opened;
 /* See inf-child.h.  */
 
 void
-inf_child_open_target (struct target_ops *target, const char *arg,
-		       int from_tty)
+inf_child_open_target (const char *arg, int from_tty)
 {
+  target_ops *target = get_native_target ();
+
+  /* There's always only ever one native target, and if we get here,
+     it better be an inf-child target.  */
+  gdb_assert (dynamic_cast<inf_child_target *> (target) != NULL);
+
   target_preopen (from_tty);
   push_target (target);
   inf_child_explicitly_opened = 1;
@@ -149,12 +166,6 @@ inf_child_open_target (struct target_ops *target, const char *arg,
     printf_filtered ("Done.  Use the \"run\" command to start a process.\n");
 }
 
-void
-inf_child_target::open (const char *arg, int from_tty)
-{
-  inf_child_open_target (this, arg, from_tty);
-}
-
 /* Implement the to_disconnect target_ops method.  */
 
 void
@@ -426,3 +437,12 @@ inf_child_target::inf_child_target ()
 {
   this->to_stratum = process_stratum;
 }
+
+/* See inf-child.h.  */
+
+void
+add_inf_child_target (inf_child_target *target)
+{
+  set_native_target (target);
+  add_target (inf_child_target_info, inf_child_open_target);
+}
diff --git a/gdb/inf-child.h b/gdb/inf-child.h
index 755c462fb8..1b59fb5b7a 100644
--- a/gdb/inf-child.h
+++ b/gdb/inf-child.h
@@ -32,16 +32,8 @@ public:
   inf_child_target ();
   ~inf_child_target () override = 0;
 
-  const char *shortname () override
-  { return "native"; }
+  const target_info &info () const override;
 
-  const char *longname () override
-  { return _("Native process"); }
-
-  const char *doc () override
-  { return _("Native process (started by the \"run\" command)."); }
-
-  void open (const char *arg, int from_tty) override;
   void close () override;
 
   void disconnect (const char *, int) override;
@@ -123,4 +115,13 @@ protected:
 /* This is for native targets which use a unix/POSIX-style waitstatus.  */
 extern void store_waitstatus (struct target_waitstatus *, int);
 
+/* Register TARGET as native target and set it up to respond to the
+   "target native" command.  */
+extern void add_inf_child_target (inf_child_target *target);
+
+/* target_open_ftype callback for inf-child targets.  Used by targets
+   that want to register an alternative target_info object.  Most
+   targets use add_inf_child_target instead.  */
+extern void inf_child_open_target (const char *arg, int from_tty);
+
 #endif
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index a7b0772d45..324c59378c 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -75,17 +75,19 @@
    of the ptid_t prevents thread IDs changing when libpthread is
    loaded or unloaded.  */
 
+static const target_info thread_db_target_info = {
+  "multi-thread",
+  N_("multi-threaded child process."),
+  N_("Threads and pthreads support.")
+};
+
 class thread_db_target : public target_ops
 {
 public:
   thread_db_target ();
 
-  const char *shortname () override
-  { return "multi-thread"; }
-  const char *longname () override
-  { return _("multi-threaded child process."); }
-  const char *doc () override
-  { return _("Threads and pthreads support."); }
+  const target_info &info () const override
+  { return thread_db_target_info; }
 
   void detach (inferior *, int) override;
   ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
diff --git a/gdb/m32r-linux-nat.c b/gdb/m32r-linux-nat.c
index ccdea941e0..6bfef2303a 100644
--- a/gdb/m32r-linux-nat.c
+++ b/gdb/m32r-linux-nat.c
@@ -241,5 +241,5 @@ void
 _initialize_m32r_linux_nat (void)
 {
   /* Register the target.  */
-  add_target (&the_m32r_linux_nat_target);
+  add_inf_child_target (&the_m32r_linux_nat_target);
 }
diff --git a/gdb/m68k-bsd-nat.c b/gdb/m68k-bsd-nat.c
index 372ef2233a..c853ed6558 100644
--- a/gdb/m68k-bsd-nat.c
+++ b/gdb/m68k-bsd-nat.c
@@ -225,7 +225,7 @@ m68kbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 void
 _initialize_m68kbsd_nat (void)
 {
-  add_target (&the_m68k_bsd_nat_target);
+  add_inf_child_target (&the_m68k_bsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (m68kbsd_supply_pcb);
diff --git a/gdb/m68k-linux-nat.c b/gdb/m68k-linux-nat.c
index 536361f60d..938c9cc27a 100644
--- a/gdb/m68k-linux-nat.c
+++ b/gdb/m68k-linux-nat.c
@@ -519,5 +519,5 @@ void
 _initialize_m68k_linux_nat (void)
 {
   /* Register the target.  */
-  add_target (&the_m68k_linux_nat_target);
+  add_inf_child_target (&the_m68k_linux_nat_target);
 }
diff --git a/gdb/m88k-bsd-nat.c b/gdb/m88k-bsd-nat.c
index 255d2ffba9..ed38124e91 100644
--- a/gdb/m88k-bsd-nat.c
+++ b/gdb/m88k-bsd-nat.c
@@ -104,5 +104,5 @@ m88k_bsd_nat_target::store_registers (struct regcache *regcache, int regnum)
 void
 _initialize_m88kbsd_nat (void)
 {
-  add_target (&the_m88k_bsd_nat_target);
+  add_inf_child_target (&the_m88k_bsd_nat_target);
 }
diff --git a/gdb/make-target-delegates b/gdb/make-target-delegates
index 83a1afcadf..b8cf63cd0b 100755
--- a/gdb/make-target-delegates
+++ b/gdb/make-target-delegates
@@ -392,9 +392,7 @@ sub print_class($) {
     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 "  const target_info &info () const override;\n";
     print "\n";
 
     for $name (@delegators) {
diff --git a/gdb/mips-fbsd-nat.c b/gdb/mips-fbsd-nat.c
index 3b38b580a9..b67444b049 100644
--- a/gdb/mips-fbsd-nat.c
+++ b/gdb/mips-fbsd-nat.c
@@ -129,5 +129,5 @@ mips_fbsd_nat_target::store_registers (struct regcache *regcache, int regnum)
 void
 _initialize_mips_fbsd_nat (void)
 {
-  add_target (&the_mips_fbsd_nat_target);
+  add_inf_child_target (&the_mips_fbsd_nat_target);
 }
diff --git a/gdb/mips-linux-nat.c b/gdb/mips-linux-nat.c
index 8432171890..c697c57105 100644
--- a/gdb/mips-linux-nat.c
+++ b/gdb/mips-linux-nat.c
@@ -801,5 +801,5 @@ triggers a breakpoint or watchpoint."),
 			   &maintenance_set_cmdlist,
 			   &maintenance_show_cmdlist);
 
-  add_target (&the_mips_linux_nat_target);
+  add_inf_child_target (&the_mips_linux_nat_target);
 }
diff --git a/gdb/mips-nbsd-nat.c b/gdb/mips-nbsd-nat.c
index 74b2060c13..b9fc6279d0 100644
--- a/gdb/mips-nbsd-nat.c
+++ b/gdb/mips-nbsd-nat.c
@@ -116,5 +116,5 @@ mips_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
 void
 _initialize_mipsnbsd_nat (void)
 {
-  add_target (&the_mips_nbsd_nat_target);
+  add_inf_child_target (&the_mips_nbsd_nat_target);
 }
diff --git a/gdb/mips64-obsd-nat.c b/gdb/mips64-obsd-nat.c
index 2193972f07..bc411517b9 100644
--- a/gdb/mips64-obsd-nat.c
+++ b/gdb/mips64-obsd-nat.c
@@ -118,5 +118,5 @@ mips64_obsd_nat_target::store_registers (struct regcache *regcache, int regnum)
 void
 _initialize_mips64obsd_nat (void)
 {
-  add_target (&the_mips64_obsd_nat_target);
+  add_inf_child_target (&the_mips64_obsd_nat_target);
 }
diff --git a/gdb/nto-procfs.c b/gdb/nto-procfs.c
index f3ba877840..51559e6c3e 100644
--- a/gdb/nto-procfs.c
+++ b/gdb/nto-procfs.c
@@ -128,28 +128,31 @@ struct nto_procfs_target : public inf_child_target
 };
 
 /* For "target native".  */
-struct nto_procfs_target_native final : public nto_procfs_target
-{
-  /* Leave shortname as "native".  */
 
-  const char *longname () override
-  { return _("QNX Neutrino local process"); }
+static const target_info nto_native_target_info = {
+  "native",
+  N_("QNX Neutrino local process"),
+  N_("QNX Neutrino local process (started by the \"run\" command).")
+};
 
-  const char *doc () override
-  { return _("QNX Neutrino local process (started by the \"run\" command)."); }
+class nto_procfs_target_native final : public nto_procfs_target
+{
+  const target_info &info () const override
+  { return nto_native_target_info; }
 };
 
 /* For "target procfs <node>".  */
-struct nto_procfs_target_procfs final : public nto_procfs_target
-{
-  const char *shortname () override
-  { return "procfs"; }
 
-  const char *longname () override
-  { return _("QNX Neutrino local or remote process"); }
+static const target_info nto_procfs_target_info = {
+  "procfs",
+  N_("QNX Neutrino local or remote process"),
+  N_("QNX Neutrino process.  target procfs <node>")
+};
 
-  const char *doc () override
-  { return _("QNX Neutrino process.  target procfs <node>"); }
+struct nto_procfs_target_procfs final : public nto_procfs_target
+{
+  const target_info &info () const override
+  { return nto_procfs_target_info; }
 };
 
 static ptid_t do_attach (ptid_t ptid);
@@ -1519,10 +1522,11 @@ static void
 init_procfs_targets (void)
 {
   /* Register "target native".  This is the default run target.  */
-  add_target (&nto_native_ops);
+  add_target (nto_native_target_info, inf_child_open_target);
+  set_native_target (&nto_native_ops);
 
   /* Register "target procfs <node>".  */
-  add_target (&nto_procfs_ops);
+  add_target (nto_procfs_target_info, inf_child_open_target);
 }
 
 #define OSTYPE_NTO 1
diff --git a/gdb/ppc-fbsd-nat.c b/gdb/ppc-fbsd-nat.c
index e046fbb553..0329b024ee 100644
--- a/gdb/ppc-fbsd-nat.c
+++ b/gdb/ppc-fbsd-nat.c
@@ -204,7 +204,7 @@ ppcfbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 void
 _initialize_ppcfbsd_nat (void)
 {
-  add_target (&the_ppc_fbsd_nat_target);
+  add_inf_child_target (&the_ppc_fbsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (ppcfbsd_supply_pcb);
diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
index a1c3dc8fe3..1423339339 100644
--- a/gdb/ppc-linux-nat.c
+++ b/gdb/ppc-linux-nat.c
@@ -2509,5 +2509,5 @@ _initialize_ppc_linux_nat (void)
   gdb::observers::thread_exit.attach (ppc_linux_thread_exit);
 
   /* Register the target.  */
-  add_target (linux_target);
+  add_inf_child_target (linux_target);
 }
diff --git a/gdb/ppc-nbsd-nat.c b/gdb/ppc-nbsd-nat.c
index e2b8083ad0..6d468eef29 100644
--- a/gdb/ppc-nbsd-nat.c
+++ b/gdb/ppc-nbsd-nat.c
@@ -186,5 +186,5 @@ _initialize_ppcnbsd_nat (void)
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (ppcnbsd_supply_pcb);
 
-  add_target (&the_ppc_nbsd_nat_target);
+  add_inf_child_target (&the_ppc_nbsd_nat_target);
 }
diff --git a/gdb/ppc-obsd-nat.c b/gdb/ppc-obsd-nat.c
index 27c4e1f414..10da6367a9 100644
--- a/gdb/ppc-obsd-nat.c
+++ b/gdb/ppc-obsd-nat.c
@@ -190,7 +190,7 @@ ppcobsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 void
 _initialize_ppcobsd_nat (void)
 {
-  add_target (&the_ppc_obsd_nat_target);
+  add_inf_child_target (&the_ppc_obsd_nat_target);
 
   /* General-purpose registers.  */
   ppcobsd_reg_offsets.r0_offset = offsetof (struct reg, gpr);
diff --git a/gdb/ravenscar-thread.c b/gdb/ravenscar-thread.c
index 03cbe3d9e7..5f3e179dec 100644
--- a/gdb/ravenscar-thread.c
+++ b/gdb/ravenscar-thread.c
@@ -73,19 +73,19 @@ static const char first_task_name[] = "system__tasking__debug__first_task";
 static const char ravenscar_runtime_initializer[] =
   "system__bb__threads__initialize";
 
+static const target_info ravenscar_target_info = {
+  "ravenscar",
+  N_("Ravenscar tasks."),
+  N_("Ravenscar tasks support.")
+};
+
 struct ravenscar_thread_target final : public target_ops
 {
   ravenscar_thread_target ()
   { to_stratum = thread_stratum; }
 
-  const char *shortname () override
-  { return "ravenscar"; }
-
-  const char *longname () override
-  { return _("Ravenscar tasks."); }
-
-  const char *doc () override
-  { return _("Ravenscar tasks support."); }
+  const target_info &info () const override
+  { return ravenscar_target_info; }
 
   ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
   void resume (ptid_t, int, enum gdb_signal) override;
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 3c1cfb6601..a88c2cf3ae 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -41,6 +41,12 @@
 #include "vec.h"
 #include <algorithm>
 
+static const target_info record_btrace_target_info = {
+  "record-btrace",
+  N_("Branch tracing target"),
+  N_("Collect control-flow trace and provide the execution history.")
+};
+
 /* The target_ops of record-btrace.  */
 
 class record_btrace_target final : public target_ops
@@ -49,16 +55,9 @@ public:
   record_btrace_target ()
   { to_stratum = record_stratum; }
 
-  const char *shortname () override
-  { return "record-btrace"; }
-
-  const char *longname () override
-  { return _("Branch tracing target"); }
+  const target_info &info () const override
+  { return record_btrace_target_info; }
 
-  const char *doc () override
-  { return _("Collect control-flow trace and provide the execution history."); }
-
-  void open (const char *, int) override;
   void close () override;
   void async (int) override;
 
@@ -335,10 +334,10 @@ private:
   std::forward_list<thread_info *> m_threads;
 };
 
-/* The open method of target record-btrace.  */
+/* Open target record-btrace.  */
 
-void
-record_btrace_target::open (const char *args, int from_tty)
+static void
+record_btrace_target_open (const char *args, int from_tty)
 {
   /* If we fail to enable btrace for one thread, disable it for the threads for
      which it was successfully enabled.  */
@@ -3142,7 +3141,7 @@ to see the actual buffer size."), NULL, show_record_pt_buffer_size_value,
 			    &set_record_btrace_pt_cmdlist,
 			    &show_record_btrace_pt_cmdlist);
 
-  add_target (&record_btrace_ops);
+  add_target (record_btrace_target_info, record_btrace_target_open);
 
   bfcache = htab_create_alloc (50, bfcache_hash, bfcache_eq, NULL,
 			       xcalloc, xfree);
diff --git a/gdb/record-full.c b/gdb/record-full.c
index 58f4be4fea..79f5c0fa0a 100644
--- a/gdb/record-full.c
+++ b/gdb/record-full.c
@@ -206,6 +206,11 @@ static unsigned int record_full_insn_num = 0;
    than count of insns presently in execution log).  */
 static ULONGEST record_full_insn_count;
 
+static const char record_longname[]
+  = N_("Process record and replay target");
+static const char record_doc[]
+  = N_("Log program while executing and replay execution from log.");
+
 /* Base class implementing functionality common to both the
    "record-full" and "record-core" targets.  */
 
@@ -215,15 +220,8 @@ public:
   record_full_base_target ()
   { to_stratum = record_stratum; }
 
-  const char *shortname () override = 0;
-
-  const char *longname () override
-  { return _("Process record and replay target"); }
-
-  const char *doc () override
-  { return _("Log program while executing and replay execution from log."); }
+  const target_info &info () const override = 0;
 
-  void open (const char *, int) override;
   void close () override;
   void async (int) override;
   ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
@@ -257,11 +255,17 @@ public:
 
 /* The "record-full" target.  */
 
+static const target_info record_full_target_info = {
+  "record-full",
+  record_longname,
+  record_doc,
+};
+
 class record_full_target final : public record_full_base_target
 {
 public:
-  const char *shortname () override
-  { return "record-full"; }
+  const target_info &info () const override
+  { return record_full_target_info; }
 
   void commit_resume () override;
   void resume (ptid_t, int, enum gdb_signal) override;
@@ -285,11 +289,17 @@ public:
 
 /* The "record-core" target.  */
 
+static const target_info record_full_core_target_info = {
+  "record-core",
+  record_longname,
+  record_doc,
+};
+
 class record_full_core_target final : public record_full_base_target
 {
 public:
-  const char *shortname () override
-  { return "record-core"; }
+  const target_info &info () const override
+  { return record_full_core_target_info; }
 
   void resume (ptid_t, int, enum gdb_signal) override;
   void disconnect (const char *, int) override;
@@ -900,7 +910,7 @@ record_full_async_inferior_event_handler (gdb_client_data data)
   inferior_event_handler (INF_REG_EVENT, NULL);
 }
 
-/* Open the process record target.  */
+/* Open the process record target for 'core' files.  */
 
 static void
 record_full_core_open_1 (const char *name, int from_tty)
@@ -930,7 +940,7 @@ record_full_core_open_1 (const char *name, int from_tty)
   record_full_restore ();
 }
 
-/* "open" target method for 'live' processes.  */
+/* Open the process record target for 'live' processes.  */
 
 static void
 record_full_open_1 (const char *name, int from_tty)
@@ -954,10 +964,10 @@ record_full_open_1 (const char *name, int from_tty)
 
 static void record_full_init_record_breakpoints (void);
 
-/* "open" target method.  Open the process record target.  */
+/* Open the process record target.  */
 
-void
-record_full_base_target::open (const char *name, int from_tty)
+static void
+record_full_open (const char *name, int from_tty)
 {
   if (record_debug)
     fprintf_unfiltered (gdb_stdlog, "Process record: record_full_open\n");
@@ -2519,7 +2529,7 @@ static void
 cmd_record_full_restore (const char *args, int from_tty)
 {
   core_file_command (args, from_tty);
-  record_full_ops.open (args, from_tty);
+  record_full_open (args, from_tty);
 }
 
 /* Save the execution log to a file.  We use a modified elf corefile
@@ -2808,9 +2818,9 @@ _initialize_record_full (void)
   record_full_first.next = NULL;
   record_full_first.type = record_full_end;
 
-  add_target (&record_full_ops);
-  add_deprecated_target_alias (&record_full_ops, "record");
-  add_target (&record_full_core_ops);
+  add_target (record_full_target_info, record_full_open);
+  add_deprecated_target_alias (record_full_target_info, "record");
+  add_target (record_full_core_target_info, record_full_open);
 
   add_prefix_cmd ("full", class_obscure, cmd_record_full_start,
 		  _("Start full execution recording."), &record_full_cmdlist,
diff --git a/gdb/remote-sim.c b/gdb/remote-sim.c
index 91dbd7c7bb..d8ba0aa52d 100644
--- a/gdb/remote-sim.c
+++ b/gdb/remote-sim.c
@@ -75,22 +75,21 @@ void simulator_command (char *args, int from_tty);
    sim_* are the interface to the simulator (see remote-sim.h).
    gdbsim_* are stuff which is internal to gdb.  */
 
+static const target_info gdbsim_target_info = {
+  "sim",
+  N_("simulator"),
+  N_("Use the compiled-in simulator.")
+};
+
 struct gdbsim_target
   : public memory_breakpoint_target<target_ops>
 {
   gdbsim_target ()
   { to_stratum = process_stratum; }
 
-  const char *shortname () override
-  { return "sim"; }
-
-  const char *longname () override
-  { return _("simulator"); }
+  const target_info &info () const override
+  { return gdbsim_target_info; }
 
-  const char *doc () override
-  { return _("Use the compiled-in simulator."); }
-
-  void open (const char *, int) override;
   void close () override;
 
   void detach (inferior *inf, int) override;
@@ -701,8 +700,8 @@ gdbsim_target::create_inferior (const char *exec_file,
    Targets should supply this routine, if only to provide an error message.  */
 /* Called when selecting the simulator.  E.g. (gdb) target sim name.  */
 
-void
-gdbsim_target::open (const char *args, int from_tty)
+static void
+gdbsim_target_open (const char *args, int from_tty)
 {
   int len;
   char *arg_buf;
@@ -1344,7 +1343,7 @@ _initialize_remote_sim (void)
 {
   struct cmd_list_element *c;
 
-  add_target (&gdbsim_ops);
+  add_target (gdbsim_target_info, gdbsim_target_open);
 
   c = add_com ("sim", class_obscure, simulator_command,
 	       _("Send a command to the simulator."));
diff --git a/gdb/remote.c b/gdb/remote.c
index 4790bc7f5e..9e6a7f7f5a 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -78,6 +78,17 @@
 
 /* The remote target.  */
 
+static const char remote_doc[] = N_("\
+Use a remote computer via a serial line, using a gdb-specific protocol.\n\
+Specify the serial device it is connected to\n\
+(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).");
+
+static const target_info remote_target_info = {
+  "remote",
+  N_("Remote serial target in gdb-specific protocol"),
+  remote_doc
+};
+
 class remote_target : public target_ops
 {
 public:
@@ -86,24 +97,15 @@ public:
     to_stratum = process_stratum;
   }
 
-  const char *shortname () override
-  { return "remote"; }
-
-  const char *longname () override
-  { return _("Remote serial target in gdb-specific protocol"); }
-
-  const char *doc () override
-  {
-    return _("\
-Use a remote computer via a serial line, using a gdb-specific protocol.\n\
-Specify the serial device it is connected to\n\
-(e.g. /dev/ttyS0, /dev/ttya, COM1, etc.).");
-  }
+  const target_info &info () const override
+  { return remote_target_info; }
 
   thread_control_capabilities get_thread_control_capabilities () override
   { return tc_schedlock; }
 
-  void open (const char *, int) override;
+  /* Open a remote connection.  */
+  static void open (const char *, int);
+
   void close () override;
 
   void detach (inferior *, int) override;
@@ -376,23 +378,27 @@ Specify the serial device it is connected to\n\
   enum exec_direction_kind execution_direction () override;
 
 protected:
-  void open_1 (const char *name, int from_tty, int extended_p);
+  static void open_1 (const char *name, int from_tty, int extended_p);
   void start_remote (int from_tty, int extended_p);
 };
 
+static const target_info extended_remote_target_info = {
+  "extended-remote",
+  N_("Extended remote serial target in gdb-specific protocol"),
+  remote_doc
+};
+
 /* Set up the extended remote target by extending the standard remote
    target and adding to it.  */
 
 class extended_remote_target : public remote_target
 {
 public:
-  const char *shortname () override
-  { return "extended-remote"; }
+  const target_info &info () const override
+  { return extended_remote_target_info; }
 
-  const char *longname () override
-  { return _("Extended remote serial target in gdb-specific protocol"); }
-
-  void open (const char *, int) override;
+  /* Open an extended-remote connection.  */
+  static void open (const char *, int);
 
   bool can_create_inferior () override { return true; }
   void create_inferior (const char *, const std::string &,
@@ -5270,7 +5276,10 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
       puts_filtered (name);
       puts_filtered ("\n");
     }
-  push_target (this);		/* Switch to using remote target now.  */
+
+  remote_target *target
+    = extended_p ? &extended_remote_ops : &remote_ops;
+  push_target (target);		/* Switch to using remote target now.  */
 
   /* Register extra event sources in the event loop.  */
   remote_async_inferior_event_token
@@ -5338,7 +5347,7 @@ remote_target::open_1 (const char *name, int from_tty, int extended_p)
 
     TRY
       {
-	start_remote (from_tty, extended_p);
+	target->start_remote (from_tty, extended_p);
       }
     CATCH (ex, RETURN_MASK_ALL)
       {
@@ -14009,8 +14018,8 @@ _initialize_remote (void)
      time.  */
   remote_state = new_remote_state ();
 
-  add_target (&remote_ops);
-  add_target (&extended_remote_ops);
+  add_target (remote_target_info, remote_target::open);
+  add_target (extended_remote_target_info, extended_remote_target::open);
 
   /* Hook into new objfile notification.  */
   gdb::observers::new_objfile.attach (remote_new_objfile);
diff --git a/gdb/rs6000-nat.c b/gdb/rs6000-nat.c
index 0880d3748e..e9f064710a 100644
--- a/gdb/rs6000-nat.c
+++ b/gdb/rs6000-nat.c
@@ -671,5 +671,5 @@ rs6000_nat_target::xfer_shared_libraries
 void
 _initialize_rs6000_nat (void)
 {
-  add_target (&the_rs6000_nat_target);
+  add_inf_child_target (&the_rs6000_nat_target);
 }
diff --git a/gdb/s390-linux-nat.c b/gdb/s390-linux-nat.c
index 637d12f4b2..5ac635a8a4 100644
--- a/gdb/s390-linux-nat.c
+++ b/gdb/s390-linux-nat.c
@@ -1065,10 +1065,8 @@ s390_linux_nat_target::read_description ()
 void
 _initialize_s390_nat (void)
 {
-  struct target_ops *t = &the_s390_linux_nat_target;
-
   /* Register the target.  */
-  add_target (t);
+  add_inf_child_target (&the_s390_linux_nat_target);
 
   /* A maintenance command to enable showing the PER state.  */
   add_setshow_boolean_cmd ("show-debug-regs", class_maintenance,
diff --git a/gdb/sh-nbsd-nat.c b/gdb/sh-nbsd-nat.c
index dad4381c9c..ed5dce204f 100644
--- a/gdb/sh-nbsd-nat.c
+++ b/gdb/sh-nbsd-nat.c
@@ -99,5 +99,5 @@ sh_nbsd_nat_target::store_registers (struct regcache *regcache, int regno)
 void
 _initialize_shnbsd_nat (void)
 {
-  add_target (&the_sh_nbsd_nat_target);
+  add_inf_child_target (&the_sh_nbsd_nat_target);
 }
diff --git a/gdb/sol-thread.c b/gdb/sol-thread.c
index 8f2ac3a6a3..d628416066 100644
--- a/gdb/sol-thread.c
+++ b/gdb/sol-thread.c
@@ -69,18 +69,20 @@
 #include "minsyms.h"
 #include "objfiles.h"
 
+static const target_info thread_db_target_info = {
+  "solaris-threads",
+  N_("Solaris threads and pthread."),
+  N_("Solaris threads and pthread support.")
+};
+
 class sol_thread_target : public target_ops
 {
 public:
   sol_thread_target ()
   { this->to_stratum = thread_stratum; }
 
-  const char *shortname () override
-  { return "solaris-threads"; }
-  const char *longname () override
-  { return _("Solaris threads and pthread."); }
-  const char *doc () override
-  { return _("Solaris threads and pthread support."); }
+  const target_info &info () const override
+  { return thread_db_target_info; }
 
   void detach (inferior *, int) override;
   ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
diff --git a/gdb/sparc-linux-nat.c b/gdb/sparc-linux-nat.c
index de7dda3d14..2154821b19 100644
--- a/gdb/sparc-linux-nat.c
+++ b/gdb/sparc-linux-nat.c
@@ -72,5 +72,5 @@ _initialize_sparc_linux_nat (void)
   sparc_fpregmap = &sparc32_bsd_fpregmap;
 
   /* Register the target.  */
-  add_target (&the_sparc_linux_nat_target);
+  add_inf_child_target (&the_sparc_linux_nat_target);
 }
diff --git a/gdb/sparc-nbsd-nat.c b/gdb/sparc-nbsd-nat.c
index 5ff723d342..e1ed44202c 100644
--- a/gdb/sparc-nbsd-nat.c
+++ b/gdb/sparc-nbsd-nat.c
@@ -63,7 +63,7 @@ _initialize_sparcnbsd_nat (void)
   sparc_gregmap = &sparc32nbsd_gregmap;
   sparc_fpregmap = &sparc32_bsd_fpregmap;
 
-  add_target (&sparc_nbsd_nat_target);
+  add_inf_child_target (&sparc_nbsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (sparc32nbsd_supply_pcb);
diff --git a/gdb/sparc64-fbsd-nat.c b/gdb/sparc64-fbsd-nat.c
index 00c1ece2db..20c6a28d18 100644
--- a/gdb/sparc64-fbsd-nat.c
+++ b/gdb/sparc64-fbsd-nat.c
@@ -65,9 +65,7 @@ static sparc_target<fbsd_nat_target> the_sparc64_fbsd_nat_target;
 void
 _initialize_sparc64fbsd_nat (void)
 {
-  struct target_ops *t;
-
-  add_target (&the_sparc64_fbsd_nat_target);
+  add_inf_child_target (&the_sparc64_fbsd_nat_target);
 
   sparc_gregmap = &sparc64fbsd_gregmap;
 
diff --git a/gdb/sparc64-linux-nat.c b/gdb/sparc64-linux-nat.c
index bc7855acfa..8406df0a24 100644
--- a/gdb/sparc64-linux-nat.c
+++ b/gdb/sparc64-linux-nat.c
@@ -91,12 +91,10 @@ fill_fpregset (const struct regcache *regcache,
 void
 _initialize_sparc64_linux_nat (void)
 {
-  target_ops *t = &the_sparc64_linux_nat_target;
-
   sparc_fpregmap = &sparc64_bsd_fpregmap;
 
   /* Register the target.  */
-  add_target (t);
+  add_inf_child_target (&the_sparc64_linux_nat_target);
 
   sparc_gregmap = &sparc64_linux_ptrace_gregmap;
 }
diff --git a/gdb/sparc64-nbsd-nat.c b/gdb/sparc64-nbsd-nat.c
index a0bfd8138e..ac760b341d 100644
--- a/gdb/sparc64-nbsd-nat.c
+++ b/gdb/sparc64-nbsd-nat.c
@@ -180,7 +180,7 @@ _initialize_sparc64nbsd_nat (void)
   sparc_gregset_supplies_p = sparc64nbsd_gregset_supplies_p;
   sparc_fpregset_supplies_p = sparc64nbsd_fpregset_supplies_p;
 
-  add_target (&the_sparc64_nbsd_nat_target);
+  add_inf_child_target (&the_sparc64_nbsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (sparc64nbsd_supply_pcb);
diff --git a/gdb/sparc64-obsd-nat.c b/gdb/sparc64-obsd-nat.c
index 67629aa05e..eeef363036 100644
--- a/gdb/sparc64-obsd-nat.c
+++ b/gdb/sparc64-obsd-nat.c
@@ -123,7 +123,7 @@ _initialize_sparc64obsd_nat (void)
   sparc_fpregmap = &sparc64_bsd_fpregmap;
 
   /* Add some extra features to the generic SPARC target.  */
-  add_target (&the_sparc64_obsd_nat_target);
+  add_inf_child_target (&the_sparc64_obsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (sparc64obsd_supply_pcb);
diff --git a/gdb/spu-linux-nat.c b/gdb/spu-linux-nat.c
index 8b4c643b2c..c289bb75fe 100644
--- a/gdb/spu-linux-nat.c
+++ b/gdb/spu-linux-nat.c
@@ -658,5 +658,5 @@ spu_linux_nat_target::can_use_hw_breakpoint (enum bptype type,
 void 
 _initialize_spu_nat (void)
 {
-  add_target (&the_spu_linux_nat_target);
+  add_inf_child_target (&the_spu_linux_nat_target);
 }
diff --git a/gdb/spu-multiarch.c b/gdb/spu-multiarch.c
index 1886807d37..5da5e4e7fc 100644
--- a/gdb/spu-multiarch.c
+++ b/gdb/spu-multiarch.c
@@ -36,19 +36,19 @@
 
 /* The SPU multi-architecture support target.  */
 
+static const target_info spu_multiarch_target_info = {
+  "spu",
+  N_("SPU multi-architecture support."),
+  N_("SPU multi-architecture support.")
+};
+
 struct spu_multiarch_target final : public target_ops
 {
   spu_multiarch_target ()
   { to_stratum = arch_stratum; };
 
-  const char *shortname () override
-  { return "spu"; }
-
-  const char *longname () override
-  { return _("SPU multi-architecture support."); }
-
-  const char *doc () override
-  { return _("SPU multi-architecture support."); }
+  const target_info &info () const override
+  { return spu_multiarch_target_info; }
 
   void mourn_inferior () override;
 
diff --git a/gdb/target-delegates.c b/gdb/target-delegates.c
index c06b700d6f..da74347122 100644
--- a/gdb/target-delegates.c
+++ b/gdb/target-delegates.c
@@ -8,9 +8,7 @@ struct dummy_target : public target_ops
 {
   dummy_target ();
 
-  const char *shortname () override;
-  const char *longname () override;
-  const char *doc () override;
+  const target_info &info () const override;
 
   void post_attach (int arg0) override;
   void detach (inferior *arg0, int arg1) override;
@@ -178,9 +176,7 @@ struct debug_target : public target_ops
 {
   debug_target ();
 
-  const char *shortname () override;
-  const char *longname () override;
-  const char *doc () override;
+  const target_info &info () const override;
 
   void post_attach (int arg0) override;
   void detach (inferior *arg0, int arg1) override;
diff --git a/gdb/target.c b/gdb/target.c
index 3ed5537e2d..b957769a3f 100644
--- a/gdb/target.c
+++ b/gdb/target.c
@@ -49,6 +49,7 @@
 #include "byte-vector.h"
 #include "terminal.h"
 #include <algorithm>
+#include <unordered_map>
 
 static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
@@ -103,10 +104,14 @@ 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);
 
-/* Vector of existing target structures. */
-typedef struct target_ops *target_ops_p;
-DEF_VEC_P (target_ops_p);
-static VEC (target_ops_p) *target_structs;
+/* Mapping between target_info objects (which have address identity)
+   and corresponding open/factory function/callback.  Each add_target
+   call adds one entry to this map, and registers a "target
+   TARGET_NAME" command that when invoked calls the factory registered
+   here.  The target_info object is associated with the command via
+   the command's context.  */
+static std::unordered_map<const target_info *, target_open_ftype *>
+  target_factories;
 
 /* The initial current target, so that there is always a semi-valid
    current target.  */
@@ -179,6 +184,27 @@ target_command (const char *arg, int from_tty)
 		  gdb_stdout);
 }
 
+#if GDB_SELF_TEST
+namespace selftests {
+
+/* A mock process_stratum target_ops that doesn't read/write registers
+   anywhere.  */
+
+static const target_info test_target_info = {
+  "test",
+  N_("unit tests target"),
+  N_("You should never see this"),
+};
+
+const target_info &
+test_target_ops::info () const
+{
+  return test_target_info;
+}
+
+} /* namespace selftests */
+#endif /* GDB_SELF_TEST */
+
 /* Default target_has_* methods for process_stratum targets.  */
 
 int
@@ -304,30 +330,29 @@ target_has_execution_current (void)
 static void
 open_target (const char *args, int from_tty, struct cmd_list_element *command)
 {
-  struct target_ops *ops = (struct target_ops *) get_cmd_context (command);
+  auto *ti = static_cast<target_info *> (get_cmd_context (command));
+  target_open_ftype *func = target_factories[ti];
 
   if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "-> %s->to_open (...)\n",
-			ops->shortname ());
+    fprintf_unfiltered (gdb_stdlog, "-> %s->open (...)\n",
+			ti->shortname);
 
-  ops->open (args, from_tty);
+  func (args, from_tty);
 
   if (targetdebug)
-    fprintf_unfiltered (gdb_stdlog, "<- %s->to_open (%s, %d)\n",
-			ops->shortname (), args, from_tty);
+    fprintf_unfiltered (gdb_stdlog, "<- %s->open (%s, %d)\n",
+			ti->shortname, args, from_tty);
 }
 
-/* Add possible target architecture T to the list and add a new
-   command 'target T->shortname ()'.  Set COMPLETER as the command's
-   completer if not NULL.  */
+/* See target.h.  */
 
 void
-add_target_with_completer (struct target_ops *t,
-			   completer_ftype *completer)
+add_target (const target_info &t, target_open_ftype *func,
+	    completer_ftype *completer)
 {
   struct cmd_list_element *c;
 
-  VEC_safe_push (target_ops_p, target_structs, t);
+  target_factories[&t] = func;
 
   if (targetlist == NULL)
     add_prefix_cmd ("target", class_run, target_command, _("\
@@ -337,35 +362,27 @@ 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->shortname (), no_class, t->doc (), &targetlist);
+  c = add_cmd (t.shortname, no_class, t.doc, &targetlist);
+  set_cmd_context (c, (void *) &t);
   set_cmd_sfunc (c, open_target);
-  set_cmd_context (c, t);
   if (completer != NULL)
     set_cmd_completer (c, completer);
 }
 
-/* Add a possible target architecture to the list.  */
-
-void
-add_target (struct target_ops *t)
-{
-  add_target_with_completer (t, NULL);
-}
-
 /* See target.h.  */
 
 void
-add_deprecated_target_alias (struct target_ops *t, const char *alias)
+add_deprecated_target_alias (const target_info &tinfo, const char *alias)
 {
   struct cmd_list_element *c;
   char *alt;
 
   /* 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->doc (), &targetlist);
+  c = add_cmd (alias, no_class, tinfo.doc, &targetlist);
   set_cmd_sfunc (c, open_target);
-  set_cmd_context (c, t);
-  alt = xstrprintf ("target %s", t->shortname ());
+  set_cmd_context (c, (void *) &tinfo);
+  alt = xstrprintf ("target %s", tinfo.shortname);
   deprecate_cmd (c, alt);
 }
 
@@ -2420,6 +2437,27 @@ show_auto_connect_native_target (struct ui_file *file, int from_tty,
 		    value);
 }
 
+/* A pointer to the target that can respond to "run" or "attach".
+   Native targets are always singletons and instantiated early at GDB
+   startup.  */
+static target_ops *the_native_target;
+
+/* See target.h.  */
+
+void
+set_native_target (target_ops *target)
+{
+  the_native_target = target;
+}
+
+/* See target.h.  */
+
+target_ops *
+get_native_target ()
+{
+  return the_native_target;
+}
+
 /* Look through the list of possible targets for a target that can
    execute a run or attach command without any other data.  This is
    used to locate the default process stratum.
@@ -2430,36 +2468,12 @@ show_auto_connect_native_target (struct ui_file *file, int from_tty,
 static struct target_ops *
 find_default_run_target (const char *do_mesg)
 {
-  struct target_ops *runable = NULL;
-
-  if (auto_connect_native_target)
-    {
-      struct target_ops *t;
-      int count = 0;
-      int i;
-
-      for (i = 0; VEC_iterate (target_ops_p, target_structs, i, t); ++i)
-	{
-	  if (t->can_run ())
-	    {
-	      runable = t;
-	      ++count;
-	    }
-	}
-
-      if (count != 1)
-	runable = NULL;
-    }
-
-  if (runable == NULL)
-    {
-      if (do_mesg)
-	error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
-      else
-	return NULL;
-    }
+  if (auto_connect_native_target && the_native_target != NULL)
+    return the_native_target;
 
-  return runable;
+  if (do_mesg != NULL)
+    error (_("Don't know how to %s.  Try \"help target\"."), do_mesg);
+  return NULL;
 }
 
 /* See target.h.  */
@@ -2467,20 +2481,15 @@ find_default_run_target (const char *do_mesg)
 struct target_ops *
 find_attach_target (void)
 {
-  struct target_ops *t;
-
   /* If a target on the current stack can attach, use it.  */
-  for (t = target_stack; t != NULL; t = t->beneath)
+  for (target_ops *t = target_stack; t != NULL; t = t->beneath)
     {
       if (t->can_attach ())
-	break;
+	return t;
     }
 
   /* Otherwise, use the default run target for attaching.  */
-  if (t == NULL)
-    t = find_default_run_target ("attach");
-
-  return t;
+  return find_default_run_target ("attach");
 }
 
 /* See target.h.  */
@@ -2488,20 +2497,15 @@ find_attach_target (void)
 struct target_ops *
 find_run_target (void)
 {
-  struct target_ops *t;
-
   /* If a target on the current stack can run, use it.  */
-  for (t = target_stack; t != NULL; t = t->beneath)
+  for (target_ops *t = target_stack; t != NULL; t = t->beneath)
     {
       if (t->can_create_inferior ())
-	break;
+	return t;
     }
 
   /* Otherwise, use the default run target.  */
-  if (t == NULL)
-    t = find_default_run_target ("run");
-
-  return t;
+  return find_default_run_target ("run");
 }
 
 bool
@@ -2614,12 +2618,6 @@ target_thread_address_space (ptid_t ptid)
   return aspace;
 }
 
-void
-target_ops::open (const char *, int)
-{
-  gdb_assert_not_reached ("target_ops::open called");
-}
-
 void
 target_ops::close ()
 {
@@ -3332,50 +3330,32 @@ dummy_make_corefile_notes (struct target_ops *self,
 #include "target-delegates.c"
 
 
+static const target_info dummy_target_info = {
+  "None",
+  N_("None"),
+  ""
+};
+
 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 ()
+const target_info &
+dummy_target::info () const
 {
-  return beneath->shortname ();
+  return dummy_target_info;
 }
 
-const char *
-debug_target::longname ()
-{
-  return beneath->longname ();
-}
-
-const char *
-debug_target::doc ()
+const target_info &
+debug_target::info () const
 {
-  return beneath->doc ();
+  return beneath->info ();
 }
 
 
diff --git a/gdb/target.h b/gdb/target.h
index cd49fce92b..b37702b501 100644
--- a/gdb/target.h
+++ b/gdb/target.h
@@ -404,27 +404,44 @@ typedef void async_callback_ftype (enum inferior_event_type event_type,
 #define TARGET_DEFAULT_RETURN(ARG)
 #define TARGET_DEFAULT_FUNC(ARG)
 
+/* Each target that can be activated with "target TARGET_NAME" passes
+   the address of one of these objects to add_target, which uses the
+   object's address as unique identifier, and registers the "target
+   TARGET_NAME" command using SHORTNAME as target name.  */
+
+struct target_info
+{
+  /* Name of this target.  */
+  const char *shortname;
+
+  /* Name for printing.  */
+  const char *longname;
+
+  /* Documentation.  Does not include trailing newline, and starts
+     with a one-line description (probably similar to longname).  */
+  const char *doc;
+};
+
 struct target_ops
   {
     struct target_ops *beneath;	/* To the target under this one.  */
 
+    /* Free resources associated with the target.  Note that singleton
+       targets, like e.g., native targets, are global objects, not
+       heap allocated, and are thus only deleted on GDB exit.  The
+       main teardown entry point is the "close" method, below.  */
     virtual ~target_ops () {}
 
-    /* Name this target type.  */
-    virtual const char *shortname () = 0;
-
-    /* Name for printing.  */
-    virtual const char *longname () = 0;
+    /* Return a reference to this target's unique target_info
+       object.  */
+    virtual const target_info &info () const = 0;
 
-    /* Documentation.  Does not include trailing newline, and starts
-       ith a one-line description (probably similar to longname).  */
-    virtual const char *doc () = 0;
+    /* Name this target type.  */
+    const char *shortname ()
+    { return info ().shortname; }
 
-    /* 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.  */
-    virtual void open (const char *, int);
+    const char *longname ()
+    { return info ().longname; }
 
     /* Close the target.  This is where the target can handle
        teardown.  Heap-allocated targets should delete themselves
@@ -1226,6 +1243,15 @@ struct target_ops
       TARGET_DEFAULT_IGNORE ();
   };
 
+/* Native target backends call this once at initialization time to
+   inform the core about which is the target that can respond to "run"
+   or "attach".  Note: native targets are always singletons.  */
+extern void set_native_target (target_ops *target);
+
+/* Get the registered native target, if there's one.  Otherwise return
+   NULL.  */
+extern target_ops *get_native_target ();
+
 /* The ops structure for our "current" target process.  This should
    never be NULL.  If there is no target, it points to the dummy_target.  */
 
@@ -2207,15 +2233,25 @@ int target_verify_memory (const gdb_byte *data,
    no matter where it is on the list.  Returns 0 if no
    change, 1 if removed from stack.  */
 
-extern void add_target (struct target_ops *);
+/* Type of callback called when the user activates a target with
+   "target TARGET_NAME".  The callback routine takes the rest of the
+   parameters from the command, and (if successful) pushes a new
+   target onto the stack.  */
+typedef void target_open_ftype (const char *args, int from_tty);
+
+/* Add the target described by INFO to the list of possible targets
+   and add a new command 'target $(INFO->shortname)'.  Set COMPLETER
+   as the command's completer if not NULL.  */
 
-extern void add_target_with_completer (struct target_ops *t,
-				       completer_ftype *completer);
+extern void add_target (const target_info &info,
+			target_open_ftype *func,
+			completer_ftype *completer = NULL);
 
-/* Adds a command ALIAS for target T and marks it deprecated.  This is useful
-   for maintaining backwards compatibility when renaming targets.  */
+/* Adds a command ALIAS for the target described by INFO and marks it
+   deprecated.  This is useful for maintaining backwards compatibility
+   when renaming targets.  */
 
-extern void add_deprecated_target_alias (struct target_ops *t,
+extern void add_deprecated_target_alias (const target_info &info,
 					 const char *alias);
 
 extern void push_target (struct target_ops *);
@@ -2466,20 +2502,7 @@ public:
     to_stratum = process_stratum;
   }
 
-  const char *shortname () override
-  {
-    return NULL;
-  }
-
-  const char *longname () override
-  {
-    return NULL;
-  }
-
-  const char *doc () override
-  {
-    return NULL;
-  }
+  const target_info &info () const override;
 
   bool has_registers () override
   {
diff --git a/gdb/tilegx-linux-nat.c b/gdb/tilegx-linux-nat.c
index 0df98e6ffc..ad61ade520 100644
--- a/gdb/tilegx-linux-nat.c
+++ b/gdb/tilegx-linux-nat.c
@@ -167,5 +167,5 @@ tilegx_linux_nat_target::store_registers (struct regcache *regcache,
 void
 _initialize_tile_linux_nat (void)
 {
-  add_target (&the_tilegx_linux_nat_target);
+  add_inf_child_target (&the_tilegx_linux_nat_target);
 }
diff --git a/gdb/tracefile-tfile.c b/gdb/tracefile-tfile.c
index d224ad9760..f4fdd3674d 100644
--- a/gdb/tracefile-tfile.c
+++ b/gdb/tracefile-tfile.c
@@ -40,22 +40,18 @@
 
 /* The tfile target.  */
 
+static const target_info tfile_target_info = {
+  "tfile",
+  N_("Local trace dump file"),
+  N_("Use a trace file as a target.  Specify the filename of the trace file.")
+};
+
 class tfile_target final : public tracefile_target
 {
  public:
-  const char *shortname () override
-  { return "tfile"; }
-
-  const char *longname () override
-  { return _("Local trace dump file"); }
-
-  const char *doc () override
-  {
-    return _("\
-Use a trace file as a target.  Specify the filename of the trace file.");
-  }
+  const target_info &info () const override
+  { return tfile_target_info; }
 
-  void open (const char *, int) override;
   void close () override;
   void fetch_registers (struct regcache *, int) override;
   enum target_xfer_status xfer_partial (enum target_object object,
@@ -451,8 +447,10 @@ tfile_read (gdb_byte *readbuf, int size)
     error (_("Premature end of file while reading trace file"));
 }
 
-void
-tfile_target::open (const char *arg, int from_tty)
+/* Open the tfile target.  */
+
+static void
+tfile_target_open (const char *arg, int from_tty)
 {
   int flags;
   int scratch_chan;
@@ -1139,5 +1137,5 @@ tfile_append_tdesc_line (const char *line)
 void
 _initialize_tracefile_tfile (void)
 {
-  add_target_with_completer (&tfile_ops, filename_completer);
+  add_target (tfile_target_info, tfile_target_open, filename_completer);
 }
diff --git a/gdb/vax-bsd-nat.c b/gdb/vax-bsd-nat.c
index 19c7a33a8c..3fd16004b8 100644
--- a/gdb/vax-bsd-nat.c
+++ b/gdb/vax-bsd-nat.c
@@ -135,7 +135,7 @@ vaxbsd_supply_pcb (struct regcache *regcache, struct pcb *pcb)
 void
 _initialize_vaxbsd_nat (void)
 {
-  add_target (&the_vax_bsd_nat_target);
+  add_inf_child_target (&the_vax_bsd_nat_target);
 
   /* Support debugging kernel virtual memory images.  */
   bsd_kvm_add_target (vaxbsd_supply_pcb);
diff --git a/gdb/windows-nat.c b/gdb/windows-nat.c
index f5a66c1f1c..16ebd17607 100644
--- a/gdb/windows-nat.c
+++ b/gdb/windows-nat.c
@@ -3018,7 +3018,7 @@ _initialize_windows_nat (void)
      calling x86_set_debug_register_length function
      in processor windows specific native file.  */
 
-  add_target (&the_windows_nat_target);
+  add_inf_child_target (&the_windows_nat_target);
 
 #ifdef __CYGWIN__
   cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
diff --git a/gdb/xtensa-linux-nat.c b/gdb/xtensa-linux-nat.c
index 2acffbfbdf..f6ef6107fa 100644
--- a/gdb/xtensa-linux-nat.c
+++ b/gdb/xtensa-linux-nat.c
@@ -364,5 +364,5 @@ _initialize_xtensa_linux_nat (void)
 	xtreg_high = ptr->gdb_regnum;
     }
 
-  add_target (&the_xtensa_linux_nat_target);
+  add_inf_child_target (&the_xtensa_linux_nat_target);
 }
