Enable -Wsuggest-override
[deliverable/binutils-gdb.git] / gdb / target.c
index e41a33858b4a7a710ccbb195aa97226b89549c31..e8d4ae7ea8e906a55a112001dbca8cb296e42345 100644 (file)
@@ -1,6 +1,6 @@
 /* Select target systems and architectures at runtime for GDB.
 
 /* Select target systems and architectures at runtime for GDB.
 
-   Copyright (C) 1990-2015 Free Software Foundation, Inc.
+   Copyright (C) 1990-2018 Free Software Foundation, Inc.
 
    Contributed by Cygnus Support.
 
 
    Contributed by Cygnus Support.
 
 #include "agent.h"
 #include "auxv.h"
 #include "target-debug.h"
 #include "agent.h"
 #include "auxv.h"
 #include "target-debug.h"
-
-static void target_info (char *, int);
+#include "top.h"
+#include "event-top.h"
+#include <algorithm>
+#include "byte-vector.h"
+#include "terminal.h"
+#include <algorithm>
 
 static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
 
 static void generic_tls_error (void) ATTRIBUTE_NORETURN;
 
@@ -86,9 +90,7 @@ static int return_zero (struct target_ops *);
 
 static int return_zero_has_execution (struct target_ops *, ptid_t);
 
 
 static int return_zero_has_execution (struct target_ops *, ptid_t);
 
-static void target_command (char *, int);
-
-static struct target_ops *find_default_run_target (char *);
+static struct target_ops *find_default_run_target (const char *);
 
 static struct gdbarch *default_thread_architecture (struct target_ops *ops,
                                                    ptid_t ptid);
 
 static struct gdbarch *default_thread_architecture (struct target_ops *ops,
                                                    ptid_t ptid);
@@ -100,7 +102,7 @@ static int dummy_find_memory_regions (struct target_ops *self,
 static char *dummy_make_corefile_notes (struct target_ops *self,
                                        bfd *ignore1, int *ignore2);
 
 static char *dummy_make_corefile_notes (struct target_ops *self,
                                        bfd *ignore1, int *ignore2);
 
-static char *default_pid_to_str (struct target_ops *ops, ptid_t ptid);
+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 enum exec_direction_kind default_execution_direction
     (struct target_ops *self);
@@ -167,7 +169,7 @@ int may_stop = 1;
 static unsigned int targetdebug = 0;
 
 static void
 static unsigned int targetdebug = 0;
 
 static void
-set_targetdebug  (char *args, int from_tty, struct cmd_list_element *c)
+set_targetdebug  (const char *args, int from_tty, struct cmd_list_element *c)
 {
   update_current_target ();
 }
 {
   update_current_target ();
 }
@@ -184,7 +186,7 @@ static void setup_target_debug (void);
 /* The user just typed 'target' without the name of a target.  */
 
 static void
 /* The user just typed 'target' without the name of a target.  */
 
 static void
-target_command (char *arg, int from_tty)
+target_command (const char *arg, int from_tty)
 {
   fputs_filtered ("Argument required (target name).  Try `help target'\n",
                  gdb_stdout);
 {
   fputs_filtered ("Argument required (target name).  Try `help target'\n",
                  gdb_stdout);
@@ -345,9 +347,9 @@ complete_target_initialization (struct target_ops *t)
 /* This is used to implement the various target commands.  */
 
 static void
 /* This is used to implement the various target commands.  */
 
 static void
-open_target (char *args, int from_tty, struct cmd_list_element *command)
+open_target (const char *args, int from_tty, struct cmd_list_element *command)
 {
 {
-  struct target_ops *ops = get_cmd_context (command);
+  struct target_ops *ops = (struct target_ops *) get_cmd_context (command);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog, "-> %s->to_open (...)\n",
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog, "-> %s->to_open (...)\n",
@@ -382,7 +384,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);
 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, NULL, t->to_doc, &targetlist);
+  c = add_cmd (t->to_shortname, no_class, t->to_doc, &targetlist);
   set_cmd_sfunc (c, open_target);
   set_cmd_context (c, t);
   if (completer != NULL)
   set_cmd_sfunc (c, open_target);
   set_cmd_context (c, t);
   if (completer != NULL)
@@ -400,14 +402,14 @@ add_target (struct target_ops *t)
 /* See target.h.  */
 
 void
 /* See target.h.  */
 
 void
-add_deprecated_target_alias (struct target_ops *t, char *alias)
+add_deprecated_target_alias (struct target_ops *t, 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.  */
 {
   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, NULL, t->to_doc, &targetlist);
+  c = add_cmd (alias, no_class, t->to_doc, &targetlist);
   set_cmd_sfunc (c, open_target);
   set_cmd_context (c, t);
   alt = xstrprintf ("target %s", t->to_shortname);
   set_cmd_sfunc (c, open_target);
   set_cmd_context (c, t);
   alt = xstrprintf ("target %s", t->to_shortname);
@@ -429,83 +431,183 @@ target_load (const char *arg, int from_tty)
   (*current_target.to_load) (&current_target, arg, from_tty);
 }
 
   (*current_target.to_load) (&current_target, arg, from_tty);
 }
 
-/* Possible terminal states.  */
+/* Define it.  */
 
 
-enum terminal_state
-  {
-    /* The inferior's terminal settings are in effect.  */
-    terminal_is_inferior = 0,
+target_terminal_state target_terminal::m_terminal_state
+  = target_terminal_state::is_ours;
 
 
-    /* Some of our terminal settings are in effect, enough to get
-       proper output.  */
-    terminal_is_ours_for_output = 1,
+/* See target/target.h.  */
 
 
-    /* Our terminal settings are in effect, for output and input.  */
-    terminal_is_ours = 2
-  };
+void
+target_terminal::init (void)
+{
+  (*current_target.to_terminal_init) (&current_target);
 
 
-static enum terminal_state terminal_state = terminal_is_ours;
+  m_terminal_state = target_terminal_state::is_ours;
+}
 
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
 
 void
-target_terminal_init (void)
+target_terminal::inferior (void)
 {
 {
-  (*current_target.to_terminal_init) (&current_target);
+  struct ui *ui = current_ui;
+
+  /* A background resume (``run&'') should leave GDB in control of the
+     terminal.  */
+  if (ui->prompt_state != PROMPT_BLOCKED)
+    return;
+
+  /* Since we always run the inferior in the main console (unless "set
+     inferior-tty" is in effect), when some UI other than the main one
+     calls target_terminal::inferior, then we leave the main UI's
+     terminal settings as is.  */
+  if (ui != main_ui)
+    return;
+
+  /* If GDB is resuming the inferior in the foreground, install
+     inferior's terminal modes.  */
+
+  struct inferior *inf = current_inferior ();
 
 
-  terminal_state = terminal_is_ours;
+  if (inf->terminal_state != target_terminal_state::is_inferior)
+    {
+      (*current_target.to_terminal_inferior) (&current_target);
+      inf->terminal_state = target_terminal_state::is_inferior;
+    }
+
+  m_terminal_state = target_terminal_state::is_inferior;
+
+  /* If the user hit C-c before, pretend that it was hit right
+     here.  */
+  if (check_quit_flag ())
+    target_pass_ctrlc ();
 }
 
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 
-int
-target_terminal_is_inferior (void)
+void
+target_terminal::restore_inferior (void)
 {
 {
-  return (terminal_state == terminal_is_inferior);
+  struct ui *ui = current_ui;
+
+  /* See target_terminal::inferior().  */
+  if (ui->prompt_state != PROMPT_BLOCKED || ui != main_ui)
+    return;
+
+  /* Restore the terminal settings of inferiors that were in the
+     foreground but are now ours_for_output due to a temporary
+     target_target::ours_for_output() call.  */
+
+  {
+    scoped_restore_current_inferior restore_inferior;
+    struct inferior *inf;
+
+    ALL_INFERIORS (inf)
+      {
+       if (inf->terminal_state == target_terminal_state::is_ours_for_output)
+         {
+           set_current_inferior (inf);
+           (*current_target.to_terminal_inferior) (&current_target);
+           inf->terminal_state = target_terminal_state::is_inferior;
+         }
+      }
+  }
+
+  m_terminal_state = target_terminal_state::is_inferior;
+
+  /* If the user hit C-c before, pretend that it was hit right
+     here.  */
+  if (check_quit_flag ())
+    target_pass_ctrlc ();
 }
 
 }
 
-/* See target.h.  */
+/* Switch terminal state to DESIRED_STATE, either is_ours, or
+   is_ours_for_output.  */
+
+static void
+target_terminal_is_ours_kind (target_terminal_state desired_state)
+{
+  scoped_restore_current_inferior restore_inferior;
+  struct inferior *inf;
+
+  /* Must do this in two passes.  First, have all inferiors save the
+     current terminal settings.  Then, after all inferiors have add a
+     chance to safely save the terminal settings, restore GDB's
+     terminal settings.  */
+
+  ALL_INFERIORS (inf)
+    {
+      if (inf->terminal_state == target_terminal_state::is_inferior)
+       {
+         set_current_inferior (inf);
+         (*current_target.to_terminal_save_inferior) (&current_target);
+       }
+    }
+
+  ALL_INFERIORS (inf)
+    {
+      /* Note we don't check is_inferior here like above because we
+        need to handle 'is_ours_for_output -> is_ours' too.  Careful
+        to never transition from 'is_ours' to 'is_ours_for_output',
+        though.  */
+      if (inf->terminal_state != target_terminal_state::is_ours
+         && inf->terminal_state != desired_state)
+       {
+         set_current_inferior (inf);
+         if (desired_state == target_terminal_state::is_ours)
+           (*current_target.to_terminal_ours) (&current_target);
+         else if (desired_state == target_terminal_state::is_ours_for_output)
+           (*current_target.to_terminal_ours_for_output) (&current_target);
+         else
+           gdb_assert_not_reached ("unhandled desired state");
+         inf->terminal_state = desired_state;
+       }
+    }
+}
+
+/* See target/target.h.  */
 
 void
 
 void
-target_terminal_inferior (void)
+target_terminal::ours ()
 {
 {
-  /* A background resume (``run&'') should leave GDB in control of the
-     terminal.  Use target_can_async_p, not target_is_async_p, since at
-     this point the target is not async yet.  However, if sync_execution
-     is not set, we know it will become async prior to resume.  */
-  if (target_can_async_p () && !sync_execution)
+  struct ui *ui = current_ui;
+
+  /* See target_terminal::inferior.  */
+  if (ui != main_ui)
     return;
 
     return;
 
-  if (terminal_state == terminal_is_inferior)
+  if (m_terminal_state == target_terminal_state::is_ours)
     return;
 
     return;
 
-  /* If GDB is resuming the inferior in the foreground, install
-     inferior's terminal modes.  */
-  (*current_target.to_terminal_inferior) (&current_target);
-  terminal_state = terminal_is_inferior;
+  target_terminal_is_ours_kind (target_terminal_state::is_ours);
+  m_terminal_state = target_terminal_state::is_ours;
 }
 
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
 
 void
-target_terminal_ours (void)
+target_terminal::ours_for_output ()
 {
 {
-  if (terminal_state == terminal_is_ours)
+  struct ui *ui = current_ui;
+
+  /* See target_terminal::inferior.  */
+  if (ui != main_ui)
     return;
 
     return;
 
-  (*current_target.to_terminal_ours) (&current_target);
-  terminal_state = terminal_is_ours;
+  if (!target_terminal::is_inferior ())
+    return;
+
+  target_terminal_is_ours_kind (target_terminal_state::is_ours_for_output);
+  target_terminal::m_terminal_state = target_terminal_state::is_ours_for_output;
 }
 
 }
 
-/* See target.h.  */
+/* See target/target.h.  */
 
 void
 
 void
-target_terminal_ours_for_output (void)
+target_terminal::info (const char *arg, int from_tty)
 {
 {
-  if (terminal_state != terminal_is_inferior)
-    return;
-  (*current_target.to_terminal_ours_for_output) (&current_target);
-  terminal_state = terminal_is_ours_for_output;
+  (*current_target.to_terminal_info) (&current_target, arg, from_tty);
 }
 
 /* See target.h.  */
 }
 
 /* See target.h.  */
@@ -525,40 +627,6 @@ target_supports_terminal_ours (void)
   return 0;
 }
 
   return 0;
 }
 
-/* Restore the terminal to its previous state (helper for
-   make_cleanup_restore_target_terminal). */
-
-static void
-cleanup_restore_target_terminal (void *arg)
-{
-  enum terminal_state *previous_state = arg;
-
-  switch (*previous_state)
-    {
-    case terminal_is_ours:
-      target_terminal_ours ();
-      break;
-    case terminal_is_ours_for_output:
-      target_terminal_ours_for_output ();
-      break;
-    case terminal_is_inferior:
-      target_terminal_inferior ();
-      break;
-    }
-}
-
-/* See target.h. */
-
-struct cleanup *
-make_cleanup_restore_target_terminal (void)
-{
-  enum terminal_state *ts = xmalloc (sizeof (*ts));
-
-  *ts = terminal_state;
-
-  return make_cleanup_dtor (cleanup_restore_target_terminal, ts, xfree);
-}
-
 static void
 tcomplain (void)
 {
 static void
 tcomplain (void)
 {
@@ -746,21 +814,35 @@ unpush_target (struct target_ops *t)
   return 1;
 }
 
   return 1;
 }
 
+/* Unpush TARGET and assert that it worked.  */
+
+static void
+unpush_target_and_assert (struct target_ops *target)
+{
+  if (!unpush_target (target))
+    {
+      fprintf_unfiltered (gdb_stderr,
+                         "pop_all_targets couldn't find target %s\n",
+                         target->to_shortname);
+      internal_error (__FILE__, __LINE__,
+                     _("failed internal consistency check"));
+    }
+}
+
 void
 pop_all_targets_above (enum strata above_stratum)
 {
   while ((int) (current_target.to_stratum) > (int) above_stratum)
 void
 pop_all_targets_above (enum strata above_stratum)
 {
   while ((int) (current_target.to_stratum) > (int) above_stratum)
-    {
-      if (!unpush_target (target_stack))
-       {
-         fprintf_unfiltered (gdb_stderr,
-                             "pop_all_targets couldn't find target %s\n",
-                             target_stack->to_shortname);
-         internal_error (__FILE__, __LINE__,
-                         _("failed internal consistency check"));
-         break;
-       }
-    }
+    unpush_target_and_assert (target_stack);
+}
+
+/* See target.h.  */
+
+void
+pop_all_targets_at_and_above (enum strata stratum)
+{
+  while ((int) (current_target.to_stratum) >= (int) stratum)
+    unpush_target_and_assert (target_stack);
 }
 
 void
 }
 
 void
@@ -912,7 +994,8 @@ target_xfer_status_to_string (enum target_xfer_status status)
    read.  */
 
 int
    read.  */
 
 int
-target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
+target_read_string (CORE_ADDR memaddr, gdb::unique_xmalloc_ptr<char> *string,
+                   int len, int *errnop)
 {
   int tlen, offset, i;
   gdb_byte buf[4];
 {
   int tlen, offset, i;
   gdb_byte buf[4];
@@ -926,7 +1009,7 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
 
   /* Small for testing.  */
   buffer_allocated = 4;
 
   /* Small for testing.  */
   buffer_allocated = 4;
-  buffer = xmalloc (buffer_allocated);
+  buffer = (char *) xmalloc (buffer_allocated);
   bufptr = buffer;
 
   while (len > 0)
   bufptr = buffer;
 
   while (len > 0)
@@ -953,7 +1036,7 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
 
          bytes = bufptr - buffer;
          buffer_allocated *= 2;
 
          bytes = bufptr - buffer;
          buffer_allocated *= 2;
-         buffer = xrealloc (buffer, buffer_allocated);
+         buffer = (char *) xrealloc (buffer, buffer_allocated);
          bufptr = buffer + bytes;
        }
 
          bufptr = buffer + bytes;
        }
 
@@ -972,7 +1055,7 @@ target_read_string (CORE_ADDR memaddr, char **string, int len, int *errnop)
       nbytes_read += tlen;
     }
 done:
       nbytes_read += tlen;
     }
 done:
-  *string = buffer;
+  string->reset (buffer);
   if (errnop != NULL)
     *errnop = errcode;
   return nbytes_read;
   if (errnop != NULL)
     *errnop = errcode;
   return nbytes_read;
@@ -1222,6 +1305,8 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
   if (len == 0)
     return TARGET_XFER_EOF;
 
   if (len == 0)
     return TARGET_XFER_EOF;
 
+  memaddr = address_significant (target_gdbarch (), memaddr);
+
   /* Fill in READBUF with breakpoint shadows, or WRITEBUF with
      breakpoint insns, thus hiding out from higher layers whether
      there are software breakpoints inserted in the code stream.  */
   /* Fill in READBUF with breakpoint shadows, or WRITEBUF with
      breakpoint insns, thus hiding out from higher layers whether
      there are software breakpoints inserted in the code stream.  */
@@ -1235,44 +1320,27 @@ memory_xfer_partial (struct target_ops *ops, enum target_object object,
     }
   else
     {
     }
   else
     {
-      void *buf;
-      struct cleanup *old_chain;
-
       /* A large write request is likely to be partially satisfied
         by memory_xfer_partial_1.  We will continually malloc
         and free a copy of the entire write request for breakpoint
         shadow handling even though we only end up writing a small
       /* A large write request is likely to be partially satisfied
         by memory_xfer_partial_1.  We will continually malloc
         and free a copy of the entire write request for breakpoint
         shadow handling even though we only end up writing a small
-        subset of it.  Cap writes to 4KB to mitigate this.  */
-      len = min (4096, len);
-
-      buf = xmalloc (len);
-      old_chain = make_cleanup (xfree, buf);
-      memcpy (buf, writebuf, len);
+        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);
 
 
-      breakpoint_xfer_memory (NULL, buf, writebuf, memaddr, len);
-      res = memory_xfer_partial_1 (ops, object, NULL, buf, memaddr, len,
+      gdb::byte_vector buf (writebuf, writebuf + len);
+      breakpoint_xfer_memory (NULL, buf.data (), writebuf, memaddr, len);
+      res = memory_xfer_partial_1 (ops, object, NULL, buf.data (), memaddr, len,
                                   xfered_len);
                                   xfered_len);
-
-      do_cleanups (old_chain);
     }
 
   return res;
 }
 
     }
 
   return res;
 }
 
-static void
-restore_show_memory_breakpoints (void *arg)
-{
-  show_memory_breakpoints = (uintptr_t) arg;
-}
-
-struct cleanup *
-make_show_memory_breakpoints_cleanup (int show)
+scoped_restore_tmpl<int>
+make_scoped_restore_show_memory_breakpoints (int show)
 {
 {
-  int current = show_memory_breakpoints;
-
-  show_memory_breakpoints = show;
-  return make_cleanup (restore_show_memory_breakpoints,
-                      (void *) (uintptr_t) current);
+  return make_scoped_restore (&show_memory_breakpoints, show);
 }
 
 /* For docs see target.h, to_xfer_partial.  */
 }
 
 /* For docs see target.h, to_xfer_partial.  */
@@ -1380,7 +1448,7 @@ target_xfer_partial (struct target_ops *ops,
 
 /* Read LEN bytes of target memory at address MEMADDR, placing the
    results in GDB's memory at MYADDR.  Returns either 0 for success or
 
 /* Read LEN bytes of target memory at address MEMADDR, placing the
    results in GDB's memory at MYADDR.  Returns either 0 for success or
-   TARGET_XFER_E_IO if any error occurs.
+   -1 if any error occurs.
 
    If an error occurs, no guarantee is made about the contents of the data at
    MYADDR.  In particular, the caller should not depend upon partial reads
 
    If an error occurs, no guarantee is made about the contents of the data at
    MYADDR.  In particular, the caller should not depend upon partial reads
@@ -1399,7 +1467,7 @@ target_read_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
                   myaddr, memaddr, len) == len)
     return 0;
   else
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* See target/target.h.  */
 }
 
 /* See target/target.h.  */
@@ -1431,7 +1499,7 @@ target_read_raw_memory (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
                   myaddr, memaddr, len) == len)
     return 0;
   else
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Like target_read_memory, but specify explicitly that this is a read from
 }
 
 /* Like target_read_memory, but specify explicitly that this is a read from
@@ -1446,7 +1514,7 @@ target_read_stack (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
                   myaddr, memaddr, len) == len)
     return 0;
   else
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Like target_read_memory, but specify explicitly that this is a read from
 }
 
 /* Like target_read_memory, but specify explicitly that this is a read from
@@ -1461,14 +1529,14 @@ target_read_code (CORE_ADDR memaddr, gdb_byte *myaddr, ssize_t len)
                   myaddr, memaddr, len) == len)
     return 0;
   else
                   myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Write LEN bytes from MYADDR to target memory at address MEMADDR.
 }
 
 /* Write LEN bytes from MYADDR to target memory at address MEMADDR.
-   Returns either 0 for success or TARGET_XFER_E_IO if any
-   error occurs.  If an error occurs, no guarantee is made about how
-   much data got written.  Callers that can deal with partial writes
-   should call target_write.  */
+   Returns either 0 for success or -1 if any error occurs.  If an
+   error occurs, no guarantee is made about how much data got written.
+   Callers that can deal with partial writes should call
+   target_write.  */
 
 int
 target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
 
 int
 target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
@@ -1479,14 +1547,14 @@ target_write_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
                    myaddr, memaddr, len) == len)
     return 0;
   else
                    myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Write LEN bytes from MYADDR to target raw memory at address
 }
 
 /* Write LEN bytes from MYADDR to target raw memory at address
-   MEMADDR.  Returns either 0 for success or TARGET_XFER_E_IO
-   if any error occurs.  If an error occurs, no guarantee is made
-   about how much data got written.  Callers that can deal with
-   partial writes should call target_write.  */
+   MEMADDR.  Returns either 0 for success or -1 if any error occurs.
+   If an error occurs, no guarantee is made about how much data got
+   written.  Callers that can deal with partial writes should call
+   target_write.  */
 
 int
 target_write_raw_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)
@@ -1497,41 +1565,36 @@ target_write_raw_memory (CORE_ADDR memaddr, const gdb_byte *myaddr, ssize_t len)
                    myaddr, memaddr, len) == len)
     return 0;
   else
                    myaddr, memaddr, len) == len)
     return 0;
   else
-    return TARGET_XFER_E_IO;
+    return -1;
 }
 
 /* Fetch the target's memory map.  */
 
 }
 
 /* Fetch the target's memory map.  */
 
-VEC(mem_region_s) *
+std::vector<mem_region>
 target_memory_map (void)
 {
 target_memory_map (void)
 {
-  VEC(mem_region_s) *result;
-  struct mem_region *last_one, *this_one;
-  int ix;
-  struct target_ops *t;
+  std::vector<mem_region> result
+    = current_target.to_memory_map (&current_target);
+  if (result.empty ())
+    return result;
 
 
-  result = current_target.to_memory_map (&current_target);
-  if (result == NULL)
-    return NULL;
-
-  qsort (VEC_address (mem_region_s, result),
-        VEC_length (mem_region_s, result),
-        sizeof (struct mem_region), mem_region_cmp);
+  std::sort (result.begin (), result.end ());
 
   /* Check that regions do not overlap.  Simultaneously assign
      a numbering for the "mem" commands to use to refer to
      each region.  */
 
   /* Check that regions do not overlap.  Simultaneously assign
      a numbering for the "mem" commands to use to refer to
      each region.  */
-  last_one = NULL;
-  for (ix = 0; VEC_iterate (mem_region_s, result, ix, this_one); ix++)
+  mem_region *last_one = NULL;
+  for (size_t ix = 0; ix < result.size (); ix++)
     {
     {
+      mem_region *this_one = &result[ix];
       this_one->number = ix;
 
       this_one->number = ix;
 
-      if (last_one && last_one->hi > this_one->lo)
+      if (last_one != NULL && last_one->hi > this_one->lo)
        {
          warning (_("Overlapping regions in memory map: ignoring"));
        {
          warning (_("Overlapping regions in memory map: ignoring"));
-         VEC_free (mem_region_s, result);
-         return NULL;
+         return std::vector<mem_region> ();
        }
        }
+
       last_one = this_one;
     }
 
       last_one = this_one;
     }
 
@@ -1653,43 +1716,37 @@ static void
 read_whatever_is_readable (struct target_ops *ops,
                           const ULONGEST begin, const ULONGEST end,
                           int unit_size,
 read_whatever_is_readable (struct target_ops *ops,
                           const ULONGEST begin, const ULONGEST end,
                           int unit_size,
-                          VEC(memory_read_result_s) **result)
+                          std::vector<memory_read_result> *result)
 {
 {
-  gdb_byte *buf = xmalloc (end - begin);
   ULONGEST current_begin = begin;
   ULONGEST current_end = end;
   int forward;
   ULONGEST current_begin = begin;
   ULONGEST current_end = end;
   int forward;
-  memory_read_result_s r;
   ULONGEST xfered_len;
 
   /* If we previously failed to read 1 byte, nothing can be done here.  */
   if (end - begin <= 1)
   ULONGEST xfered_len;
 
   /* If we previously failed to read 1 byte, nothing can be done here.  */
   if (end - begin <= 1)
-    {
-      xfree (buf);
-      return;
-    }
+    return;
+
+  gdb::unique_xmalloc_ptr<gdb_byte> buf ((gdb_byte *) xmalloc (end - begin));
 
   /* Check that either first or the last byte is readable, and give up
      if not.  This heuristic is meant to permit reading accessible memory
      at the boundary of accessible region.  */
   if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
 
   /* Check that either first or the last byte is readable, and give up
      if not.  This heuristic is meant to permit reading accessible memory
      at the boundary of accessible region.  */
   if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                          buf, begin, 1, &xfered_len) == TARGET_XFER_OK)
+                          buf.get (), begin, 1, &xfered_len) == TARGET_XFER_OK)
     {
       forward = 1;
       ++current_begin;
     }
   else if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
     {
       forward = 1;
       ++current_begin;
     }
   else if (target_read_partial (ops, TARGET_OBJECT_MEMORY, NULL,
-                               buf + (end - begin) - 1, end - 1, 1,
+                               buf.get () + (end - begin) - 1, end - 1, 1,
                                &xfered_len) == TARGET_XFER_OK)
     {
       forward = 0;
       --current_end;
     }
   else
                                &xfered_len) == TARGET_XFER_OK)
     {
       forward = 0;
       --current_end;
     }
   else
-    {
-      xfree (buf);
-      return;
-    }
+    return;
 
   /* Loop invariant is that the [current_begin, current_end) was previously
      found to be not readable as a whole.
 
   /* Loop invariant is that the [current_begin, current_end) was previously
      found to be not readable as a whole.
@@ -1719,7 +1776,7 @@ read_whatever_is_readable (struct target_ops *ops,
        }
 
       xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
        }
 
       xfer = target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                         buf + (first_half_begin - begin) * unit_size,
+                         buf.get () + (first_half_begin - begin) * unit_size,
                          first_half_begin,
                          first_half_end - first_half_begin);
 
                          first_half_begin,
                          first_half_end - first_half_begin);
 
@@ -1746,44 +1803,26 @@ read_whatever_is_readable (struct target_ops *ops,
   if (forward)
     {
       /* The [begin, current_begin) range has been read.  */
   if (forward)
     {
       /* The [begin, current_begin) range has been read.  */
-      r.begin = begin;
-      r.end = current_begin;
-      r.data = buf;
+      result->emplace_back (begin, current_end, std::move (buf));
     }
   else
     {
       /* The [current_end, end) range has been read.  */
       LONGEST region_len = end - current_end;
 
     }
   else
     {
       /* The [current_end, end) range has been read.  */
       LONGEST region_len = end - current_end;
 
-      r.data = xmalloc (region_len * unit_size);
-      memcpy (r.data, buf + (current_end - begin) * unit_size,
+      gdb::unique_xmalloc_ptr<gdb_byte> data
+       ((gdb_byte *) xmalloc (region_len * unit_size));
+      memcpy (data.get (), buf.get () + (current_end - begin) * unit_size,
              region_len * unit_size);
              region_len * unit_size);
-      r.begin = current_end;
-      r.end = end;
-      xfree (buf);
-    }
-  VEC_safe_push(memory_read_result_s, (*result), &r);
-}
-
-void
-free_memory_read_result_vector (void *x)
-{
-  VEC(memory_read_result_s) *v = x;
-  memory_read_result_s *current;
-  int ix;
-
-  for (ix = 0; VEC_iterate (memory_read_result_s, v, ix, current); ++ix)
-    {
-      xfree (current->data);
+      result->emplace_back (current_end, end, std::move (data));
     }
     }
-  VEC_free (memory_read_result_s, v);
 }
 
 }
 
-VEC(memory_read_result_s) *
+std::vector<memory_read_result>
 read_memory_robust (struct target_ops *ops,
                    const ULONGEST offset, const LONGEST len)
 {
 read_memory_robust (struct target_ops *ops,
                    const ULONGEST offset, const LONGEST len)
 {
-  VEC(memory_read_result_s) *result = 0;
+  std::vector<memory_read_result> result;
   int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
 
   LONGEST xfered_total = 0;
   int unit_size = gdbarch_addressable_memory_unit_size (target_gdbarch ());
 
   LONGEST xfered_total = 0;
@@ -1809,35 +1848,34 @@ read_memory_robust (struct target_ops *ops,
        }
       else
        {
        }
       else
        {
-         LONGEST to_read = min (len - xfered_total, region_len);
-         gdb_byte *buffer = (gdb_byte *) xmalloc (to_read * unit_size);
+         LONGEST to_read = std::min (len - xfered_total, region_len);
+         gdb::unique_xmalloc_ptr<gdb_byte> buffer
+           ((gdb_byte *) xmalloc (to_read * unit_size));
 
          LONGEST xfered_partial =
 
          LONGEST xfered_partial =
-             target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                          (gdb_byte *) buffer,
+             target_read (ops, TARGET_OBJECT_MEMORY, NULL, buffer.get (),
                           offset + xfered_total, to_read);
          /* Call an observer, notifying them of the xfer progress?  */
          if (xfered_partial <= 0)
            {
              /* Got an error reading full chunk.  See if maybe we can read
                 some subrange.  */
                           offset + xfered_total, to_read);
          /* Call an observer, notifying them of the xfer progress?  */
          if (xfered_partial <= 0)
            {
              /* Got an error reading full chunk.  See if maybe we can read
                 some subrange.  */
-             xfree (buffer);
-             read_whatever_is_readable (ops, offset + xfered_total, unit_size,
-                                        offset + xfered_total + to_read, &result);
+             read_whatever_is_readable (ops, offset + xfered_total,
+                                        offset + xfered_total + to_read,
+                                        unit_size, &result);
              xfered_total += to_read;
            }
          else
            {
              xfered_total += to_read;
            }
          else
            {
-             struct memory_read_result r;
-             r.data = buffer;
-             r.begin = offset + xfered_total;
-             r.end = r.begin + xfered_partial;
-             VEC_safe_push (memory_read_result_s, result, &r);
+             result.emplace_back (offset + xfered_total,
+                                  offset + xfered_total + xfered_partial,
+                                  std::move (buffer));
              xfered_total += xfered_partial;
            }
          QUIT;
        }
     }
              xfered_total += xfered_partial;
            }
          QUIT;
        }
     }
+
   return result;
 }
 
   return result;
 }
 
@@ -1900,18 +1938,17 @@ target_write (struct target_ops *ops,
                                     NULL, NULL);
 }
 
                                     NULL, NULL);
 }
 
-/* Read OBJECT/ANNEX using OPS.  Store the result in *BUF_P and return
-   the size of the transferred data.  PADDING additional bytes are
-   available in *BUF_P.  This is a helper function for
-   target_read_alloc; see the declaration of that function for more
-   information.  */
+/* Help for target_read_alloc and target_read_stralloc.  See their comments
+   for details.  */
 
 
-static LONGEST
+template <typename T>
+gdb::optional<gdb::def_vector<T>>
 target_read_alloc_1 (struct target_ops *ops, enum target_object object,
 target_read_alloc_1 (struct target_ops *ops, enum target_object object,
-                    const char *annex, gdb_byte **buf_p, int padding)
+                    const char *annex)
 {
 {
-  size_t buf_alloc, buf_pos;
-  gdb_byte *buf;
+  gdb::def_vector<T> buf;
+  size_t buf_pos = 0;
+  const int chunk = 4096;
 
   /* This function does not have a length parameter; it reads the
      entire OBJECT).  Also, it doesn't support objects fetched partly
 
   /* This function does not have a length parameter; it reads the
      entire OBJECT).  Also, it doesn't support objects fetched partly
@@ -1922,86 +1959,64 @@ target_read_alloc_1 (struct target_ops *ops, enum target_object object,
 
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
 
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
-  buf_alloc = 4096;
-  buf = xmalloc (buf_alloc);
-  buf_pos = 0;
   while (1)
     {
       ULONGEST xfered_len;
       enum target_xfer_status status;
 
   while (1)
     {
       ULONGEST xfered_len;
       enum target_xfer_status status;
 
-      status = target_read_partial (ops, object, annex, &buf[buf_pos],
-                                   buf_pos, buf_alloc - buf_pos - padding,
+      buf.resize (buf_pos + chunk);
+
+      status = target_read_partial (ops, object, annex,
+                                   (gdb_byte *) &buf[buf_pos],
+                                   buf_pos, chunk,
                                    &xfered_len);
 
       if (status == TARGET_XFER_EOF)
        {
          /* Read all there was.  */
                                    &xfered_len);
 
       if (status == TARGET_XFER_EOF)
        {
          /* Read all there was.  */
-         if (buf_pos == 0)
-           xfree (buf);
-         else
-           *buf_p = buf;
-         return buf_pos;
+         buf.resize (buf_pos);
+         return buf;
        }
       else if (status != TARGET_XFER_OK)
        {
          /* An error occurred.  */
        }
       else if (status != TARGET_XFER_OK)
        {
          /* An error occurred.  */
-         xfree (buf);
-         return TARGET_XFER_E_IO;
+         return {};
        }
 
       buf_pos += xfered_len;
 
        }
 
       buf_pos += xfered_len;
 
-      /* If the buffer is filling up, expand it.  */
-      if (buf_alloc < buf_pos * 2)
-       {
-         buf_alloc *= 2;
-         buf = xrealloc (buf, buf_alloc);
-       }
-
       QUIT;
     }
 }
 
       QUIT;
     }
 }
 
-/* Read OBJECT/ANNEX using OPS.  Store the result in *BUF_P and return
-   the size of the transferred data.  See the declaration in "target.h"
-   function for more information about the return value.  */
+/* See target.h  */
 
 
-LONGEST
+gdb::optional<gdb::byte_vector>
 target_read_alloc (struct target_ops *ops, enum target_object object,
 target_read_alloc (struct target_ops *ops, enum target_object object,
-                  const char *annex, gdb_byte **buf_p)
+                  const char *annex)
 {
 {
-  return target_read_alloc_1 (ops, object, annex, buf_p, 0);
+  return target_read_alloc_1<gdb_byte> (ops, object, annex);
 }
 
 }
 
-/* Read OBJECT/ANNEX using OPS.  The result is NUL-terminated and
-   returned as a string, allocated using xmalloc.  If an error occurs
-   or the transfer is unsupported, NULL is returned.  Empty objects
-   are returned as allocated but empty strings.  A warning is issued
-   if the result contains any embedded NUL bytes.  */
+/* See target.h.  */
 
 
-char *
+gdb::optional<gdb::char_vector>
 target_read_stralloc (struct target_ops *ops, enum target_object object,
                      const char *annex)
 {
 target_read_stralloc (struct target_ops *ops, enum target_object object,
                      const char *annex)
 {
-  gdb_byte *buffer;
-  char *bufstr;
-  LONGEST i, transferred;
+  gdb::optional<gdb::char_vector> buf
+    = target_read_alloc_1<char> (ops, object, annex);
 
 
-  transferred = target_read_alloc_1 (ops, object, annex, &buffer, 1);
-  bufstr = (char *) buffer;
+  if (!buf)
+    return {};
 
 
-  if (transferred < 0)
-    return NULL;
-
-  if (transferred == 0)
-    return xstrdup ("");
-
-  bufstr[transferred] = 0;
+  if (buf->back () != '\0')
+    buf->push_back ('\0');
 
   /* Check for embedded NUL bytes; but allow trailing NULs.  */
 
   /* Check for embedded NUL bytes; but allow trailing NULs.  */
-  for (i = strlen (bufstr); i < transferred; i++)
-    if (bufstr[i] != 0)
+  for (auto it = std::find (buf->begin (), buf->end (), '\0');
+       it != buf->end (); it++)
+    if (*it != '\0')
       {
        warning (_("target object %d, annex %s, "
                   "contained unexpected null characters"),
       {
        warning (_("target object %d, annex %s, "
                   "contained unexpected null characters"),
@@ -2009,7 +2024,7 @@ target_read_stralloc (struct target_ops *ops, enum target_object object,
        break;
       }
 
        break;
       }
 
-  return bufstr;
+  return buf;
 }
 
 /* Memory transfer methods.  */
 }
 
 /* Memory transfer methods.  */
@@ -2058,7 +2073,8 @@ target_insert_breakpoint (struct gdbarch *gdbarch,
 
 int
 target_remove_breakpoint (struct gdbarch *gdbarch,
 
 int
 target_remove_breakpoint (struct gdbarch *gdbarch,
-                         struct bp_target_info *bp_tgt)
+                         struct bp_target_info *bp_tgt,
+                         enum remove_bp_reason reason)
 {
   /* This is kind of a weird case to handle, but the permission might
      have been changed after breakpoints were inserted - in which case
 {
   /* This is kind of a weird case to handle, but the permission might
      have been changed after breakpoints were inserted - in which case
@@ -2071,11 +2087,11 @@ target_remove_breakpoint (struct gdbarch *gdbarch,
     }
 
   return current_target.to_remove_breakpoint (&current_target,
     }
 
   return current_target.to_remove_breakpoint (&current_target,
-                                             gdbarch, bp_tgt);
+                                             gdbarch, bp_tgt, reason);
 }
 
 static void
 }
 
 static void
-target_info (char *args, int from_tty)
+info_target_command (const char *args, int from_tty)
 {
   struct target_ops *t;
   int has_all_mem = 0;
 {
   struct target_ops *t;
   int has_all_mem = 0;
@@ -2138,6 +2154,12 @@ target_pre_inferior (int from_tty)
       target_clear_description ();
     }
 
       target_clear_description ();
     }
 
+  /* attach_flag may be set if the previous process associated with
+     the inferior was attached to.  */
+  current_inferior ()->attach_flag = 0;
+
+  current_inferior ()->highest_thread_num = 0;
+
   agent_capability_invalidate ();
 }
 
   agent_capability_invalidate ();
 }
 
@@ -2158,7 +2180,7 @@ dispose_inferior (struct inferior *inf, void *args)
       if (target_has_execution)
        target_kill ();
       else
       if (target_has_execution)
        target_kill ();
       else
-       target_detach (NULL, 0);
+       target_detach (inf, 0);
     }
 
   return 0;
     }
 
   return 0;
@@ -2191,13 +2213,18 @@ target_preopen (int from_tty)
   target_pre_inferior (from_tty);
 }
 
   target_pre_inferior (from_tty);
 }
 
-/* Detach a target after doing deferred register stores.  */
+/* See target.h.  */
 
 void
 
 void
-target_detach (const char *args, int from_tty)
+target_detach (inferior *inf, int from_tty)
 {
 {
-  struct target_ops* t;
-  
+  /* As long as some to_detach implementations rely on the current_inferior
+     (either directly, or indirectly, like through target_gdbarch or by
+     reading memory), INF needs to be the current inferior.  When that
+     requirement will become no longer true, then we can remove this
+     assertion.  */
+  gdb_assert (inf == current_inferior ());
+
   if (gdbarch_has_global_breakpoints (target_gdbarch ()))
     /* Don't remove global breakpoints here.  They're removed on
        disconnection from the target.  */
   if (gdbarch_has_global_breakpoints (target_gdbarch ()))
     /* Don't remove global breakpoints here.  They're removed on
        disconnection from the target.  */
@@ -2209,7 +2236,7 @@ target_detach (const char *args, int from_tty)
 
   prepare_for_detach ();
 
 
   prepare_for_detach ();
 
-  current_target.to_detach (&current_target, args, from_tty);
+  current_target.to_detach (&current_target, inf, from_tty);
 }
 
 void
 }
 
 void
@@ -2223,29 +2250,49 @@ target_disconnect (const char *args, int from_tty)
   current_target.to_disconnect (&current_target, args, from_tty);
 }
 
   current_target.to_disconnect (&current_target, args, from_tty);
 }
 
+/* See target/target.h.  */
+
 ptid_t
 target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
 {
   return (current_target.to_wait) (&current_target, ptid, status, options);
 }
 
 ptid_t
 target_wait (ptid_t ptid, struct target_waitstatus *status, int options)
 {
   return (current_target.to_wait) (&current_target, ptid, status, options);
 }
 
-char *
+/* See target.h.  */
+
+ptid_t
+default_target_wait (struct target_ops *ops,
+                    ptid_t ptid, struct target_waitstatus *status,
+                    int options)
+{
+  status->kind = TARGET_WAITKIND_IGNORE;
+  return minus_one_ptid;
+}
+
+const char *
 target_pid_to_str (ptid_t ptid)
 {
   return (*current_target.to_pid_to_str) (&current_target, ptid);
 }
 
 target_pid_to_str (ptid_t ptid)
 {
   return (*current_target.to_pid_to_str) (&current_target, ptid);
 }
 
-char *
+const char *
 target_thread_name (struct thread_info *info)
 {
   return current_target.to_thread_name (&current_target, info);
 }
 
 target_thread_name (struct thread_info *info)
 {
   return current_target.to_thread_name (&current_target, info);
 }
 
+struct thread_info *
+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);
+}
+
 void
 target_resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
 void
 target_resume (ptid_t ptid, int step, enum gdb_signal signal)
 {
-  struct target_ops *t;
-
   target_dcache_invalidate ();
 
   current_target.to_resume (&current_target, ptid, step, signal);
   target_dcache_invalidate ();
 
   current_target.to_resume (&current_target, ptid, step, signal);
@@ -2257,6 +2304,28 @@ target_resume (ptid_t ptid, int step, enum gdb_signal signal)
   clear_inline_frame_state (ptid);
 }
 
   clear_inline_frame_state (ptid);
 }
 
+/* If true, target_commit_resume is a nop.  */
+static int defer_target_commit_resume;
+
+/* See target.h.  */
+
+void
+target_commit_resume (void)
+{
+  if (defer_target_commit_resume)
+    return;
+
+  current_target.to_commit_resume (&current_target);
+}
+
+/* See target.h.  */
+
+scoped_restore_tmpl<int>
+make_scoped_defer_target_commit_resume ()
+{
+  return make_scoped_restore (&defer_target_commit_resume, 1);
+}
+
 void
 target_pass_signals (int numsigs, unsigned char *pass_signals)
 {
 void
 target_pass_signals (int numsigs, unsigned char *pass_signals)
 {
@@ -2289,6 +2358,14 @@ target_follow_fork (int follow_child, int detach_fork)
                                        follow_child, detach_fork);
 }
 
                                        follow_child, detach_fork);
 }
 
+/* Target wrapper for follow exec hook.  */
+
+void
+target_follow_exec (struct inferior *inf, char *execd_pathname)
+{
+  current_target.to_follow_exec (&current_target, inf, execd_pathname);
+}
+
 static void
 default_mourn_inferior (struct target_ops *self)
 {
 static void
 default_mourn_inferior (struct target_ops *self)
 {
@@ -2297,8 +2374,9 @@ default_mourn_inferior (struct target_ops *self)
 }
 
 void
 }
 
 void
-target_mourn_inferior (void)
+target_mourn_inferior (ptid_t ptid)
 {
 {
+  gdb_assert (ptid_equal (ptid, inferior_ptid));
   current_target.to_mourn_inferior (&current_target);
 
   /* We no longer need to keep handles on any of the object files.
   current_target.to_mourn_inferior (&current_target);
 
   /* We no longer need to keep handles on any of the object files.
@@ -2330,9 +2408,7 @@ simple_search_memory (struct target_ops *ops,
 #define SEARCH_CHUNK_SIZE 16000
   const unsigned chunk_size = SEARCH_CHUNK_SIZE;
   /* Buffer to hold memory contents for searching.  */
 #define SEARCH_CHUNK_SIZE 16000
   const unsigned chunk_size = SEARCH_CHUNK_SIZE;
   /* Buffer to hold memory contents for searching.  */
-  gdb_byte *search_buf;
   unsigned search_buf_size;
   unsigned search_buf_size;
-  struct cleanup *old_cleanups;
 
   search_buf_size = chunk_size + pattern_len - 1;
 
 
   search_buf_size = chunk_size + pattern_len - 1;
 
@@ -2340,20 +2416,17 @@ simple_search_memory (struct target_ops *ops,
   if (search_space_len < search_buf_size)
     search_buf_size = search_space_len;
 
   if (search_space_len < search_buf_size)
     search_buf_size = search_space_len;
 
-  search_buf = malloc (search_buf_size);
-  if (search_buf == NULL)
-    error (_("Unable to allocate memory to perform the search."));
-  old_cleanups = make_cleanup (free_current_contents, &search_buf);
+  gdb::byte_vector search_buf (search_buf_size);
 
   /* Prime the search buffer.  */
 
   if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
 
   /* Prime the search buffer.  */
 
   if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                  search_buf, start_addr, search_buf_size) != search_buf_size)
+                  search_buf.data (), start_addr, search_buf_size)
+      != search_buf_size)
     {
       warning (_("Unable to access %s bytes of target "
                 "memory at %s, halting search."),
               pulongest (search_buf_size), hex_string (start_addr));
     {
       warning (_("Unable to access %s bytes of target "
                 "memory at %s, halting search."),
               pulongest (search_buf_size), hex_string (start_addr));
-      do_cleanups (old_cleanups);
       return -1;
     }
 
       return -1;
     }
 
@@ -2366,17 +2439,17 @@ simple_search_memory (struct target_ops *ops,
   while (search_space_len >= pattern_len)
     {
       gdb_byte *found_ptr;
   while (search_space_len >= pattern_len)
     {
       gdb_byte *found_ptr;
-      unsigned nr_search_bytes = min (search_space_len, search_buf_size);
+      unsigned nr_search_bytes
+       = std::min (search_space_len, (ULONGEST) search_buf_size);
 
 
-      found_ptr = memmem (search_buf, nr_search_bytes,
-                         pattern, pattern_len);
+      found_ptr = (gdb_byte *) memmem (search_buf.data (), nr_search_bytes,
+                                      pattern, pattern_len);
 
       if (found_ptr != NULL)
        {
 
       if (found_ptr != NULL)
        {
-         CORE_ADDR found_addr = start_addr + (found_ptr - search_buf);
+         CORE_ADDR found_addr = start_addr + (found_ptr - search_buf.data ());
 
          *found_addrp = found_addr;
 
          *found_addrp = found_addr;
-         do_cleanups (old_cleanups);
          return 1;
        }
 
          return 1;
        }
 
@@ -2397,19 +2470,19 @@ simple_search_memory (struct target_ops *ops,
          /* Copy the trailing part of the previous iteration to the front
             of the buffer for the next iteration.  */
          gdb_assert (keep_len == pattern_len - 1);
          /* Copy the trailing part of the previous iteration to the front
             of the buffer for the next iteration.  */
          gdb_assert (keep_len == pattern_len - 1);
-         memcpy (search_buf, search_buf + chunk_size, keep_len);
+         memcpy (&search_buf[0], &search_buf[chunk_size], keep_len);
 
 
-         nr_to_read = min (search_space_len - keep_len, chunk_size);
+         nr_to_read = std::min (search_space_len - keep_len,
+                                (ULONGEST) chunk_size);
 
          if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
 
          if (target_read (ops, TARGET_OBJECT_MEMORY, NULL,
-                          search_buf + keep_len, read_addr,
+                          &search_buf[keep_len], read_addr,
                           nr_to_read) != nr_to_read)
            {
              warning (_("Unable to access %s bytes of target "
                         "memory at %s, halting search."),
                       plongest (nr_to_read),
                       hex_string (read_addr));
                           nr_to_read) != nr_to_read)
            {
              warning (_("Unable to access %s bytes of target "
                         "memory at %s, halting search."),
                       plongest (nr_to_read),
                       hex_string (read_addr));
-             do_cleanups (old_cleanups);
              return -1;
            }
 
              return -1;
            }
 
@@ -2419,7 +2492,6 @@ simple_search_memory (struct target_ops *ops,
 
   /* Not found.  */
 
 
   /* Not found.  */
 
-  do_cleanups (old_cleanups);
   return 0;
 }
 
   return 0;
 }
 
@@ -2513,7 +2585,7 @@ show_auto_connect_native_target (struct ui_file *file, int from_tty,
    called for errors); else, return NULL on error.  */
 
 static struct target_ops *
    called for errors); else, return NULL on error.  */
 
 static struct target_ops *
-find_default_run_target (char *do_mesg)
+find_default_run_target (const char *do_mesg)
 {
   struct target_ops *runable = NULL;
 
 {
   struct target_ops *runable = NULL;
 
@@ -2644,7 +2716,17 @@ target_supports_disable_randomization (void)
   return 0;
 }
 
   return 0;
 }
 
-char *
+/* See target/target.h.  */
+
+int
+target_supports_multi_process (void)
+{
+  return (*current_target.to_supports_multi_process) (&current_target);
+}
+
+/* See target.h.  */
+
+gdb::optional<gdb::char_vector>
 target_get_osdata (const char *type)
 {
   struct target_ops *t;
 target_get_osdata (const char *type)
 {
   struct target_ops *t;
@@ -2658,7 +2740,7 @@ target_get_osdata (const char *type)
     t = find_default_run_target ("get OS data");
 
   if (!t)
     t = find_default_run_target ("get OS data");
 
   if (!t)
-    return NULL;
+    return {};
 
   return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
 }
 
   return target_read_stralloc (t, TARGET_OBJECT_OSDATA, type);
 }
@@ -2709,56 +2791,70 @@ default_fileio_target (void)
 
 /* File handle for target file operations.  */
 
 
 /* File handle for target file operations.  */
 
-typedef struct
+struct fileio_fh_t
 {
 {
-  /* The target on which this file is open.  */
-  struct target_ops *t;
+  /* The target on which this file is open.  NULL if the target is
+     meanwhile closed while the handle is open.  */
+  target_ops *target;
 
   /* The file descriptor on the target.  */
 
   /* The file descriptor on the target.  */
-  int fd;
-} fileio_fh_t;
+  int target_fd;
 
 
-DEF_VEC_O (fileio_fh_t);
+  /* Check whether this fileio_fh_t represents a closed file.  */
+  bool is_closed ()
+  {
+    return target_fd < 0;
+  }
+};
 
 /* Vector of currently open file handles.  The value returned by
    target_fileio_open and passed as the FD argument to other
    target_fileio_* functions is an index into this vector.  This
    vector's entries are never freed; instead, files are marked as
    closed, and the handle becomes available for reuse.  */
 
 /* Vector of currently open file handles.  The value returned by
    target_fileio_open and passed as the FD argument to other
    target_fileio_* functions is an index into this vector.  This
    vector's entries are never freed; instead, files are marked as
    closed, and the handle becomes available for reuse.  */
-static VEC (fileio_fh_t) *fileio_fhandles;
-
-/* Macro to check whether a fileio_fh_t represents a closed file.  */
-#define is_closed_fileio_fh(fd) ((fd) < 0)
+static std::vector<fileio_fh_t> fileio_fhandles;
 
 /* Index into fileio_fhandles of the lowest handle that might be
    closed.  This permits handle reuse without searching the whole
    list each time a new file is opened.  */
 static int lowest_closed_fd;
 
 
 /* Index into fileio_fhandles of the lowest handle that might be
    closed.  This permits handle reuse without searching the whole
    list each time a new file is opened.  */
 static int lowest_closed_fd;
 
-/* Acquire a target fileio file descriptor.  */
+/* Invalidate the target associated with open handles that were open
+   on target TARG, since we're about to close (and maybe destroy) the
+   target.  The handles remain open from the client's perspective, but
+   trying to do anything with them other than closing them will fail
+   with EIO.  */
 
 
-static int
-acquire_fileio_fd (struct target_ops *t, int fd)
+static void
+fileio_handles_invalidate_target (target_ops *targ)
 {
 {
-  fileio_fh_t *fh, buf;
+  for (fileio_fh_t &fh : fileio_fhandles)
+    if (fh.target == targ)
+      fh.target = NULL;
+}
 
 
-  gdb_assert (!is_closed_fileio_fh (fd));
+/* Acquire a target fileio file descriptor.  */
 
 
+static int
+acquire_fileio_fd (target_ops *target, int target_fd)
+{
   /* Search for closed handles to reuse.  */
   /* Search for closed handles to reuse.  */
-  for (;
-       VEC_iterate (fileio_fh_t, fileio_fhandles,
-                    lowest_closed_fd, fh);
-       lowest_closed_fd++)
-    if (is_closed_fileio_fh (fh->fd))
-      break;
+  for (; lowest_closed_fd < fileio_fhandles.size (); lowest_closed_fd++)
+    {
+      fileio_fh_t &fh = fileio_fhandles[lowest_closed_fd];
+
+      if (fh.is_closed ())
+       break;
+    }
 
   /* Push a new handle if no closed handles were found.  */
 
   /* Push a new handle if no closed handles were found.  */
-  if (lowest_closed_fd == VEC_length (fileio_fh_t, fileio_fhandles))
-    fh = VEC_safe_push (fileio_fh_t, fileio_fhandles, NULL);
+  if (lowest_closed_fd == fileio_fhandles.size ())
+    fileio_fhandles.push_back (fileio_fh_t {target, target_fd});
+  else
+    fileio_fhandles[lowest_closed_fd] = {target, target_fd};
 
 
-  /* Fill in the handle.  */
-  fh->t = t;
-  fh->fd = fd;
+  /* Should no longer be marked closed.  */
+  gdb_assert (!fileio_fhandles[lowest_closed_fd].is_closed ());
 
   /* Return its index, and start the next lookup at
      the next index.  */
 
   /* Return its index, and start the next lookup at
      the next index.  */
@@ -2770,20 +2866,25 @@ acquire_fileio_fd (struct target_ops *t, int fd)
 static void
 release_fileio_fd (int fd, fileio_fh_t *fh)
 {
 static void
 release_fileio_fd (int fd, fileio_fh_t *fh)
 {
-  fh->fd = -1;
-  lowest_closed_fd = min (lowest_closed_fd, fd);
+  fh->target_fd = -1;
+  lowest_closed_fd = std::min (lowest_closed_fd, fd);
 }
 
 /* Return a pointer to the fileio_fhandle_t corresponding to FD.  */
 
 }
 
 /* Return a pointer to the fileio_fhandle_t corresponding to FD.  */
 
-#define fileio_fd_to_fh(fd) \
-  VEC_index (fileio_fh_t, fileio_fhandles, (fd))
+static fileio_fh_t *
+fileio_fd_to_fh (int fd)
+{
+  return &fileio_fhandles[fd];
+}
 
 
-/* See target.h.  */
+/* Helper for target_fileio_open and
+   target_fileio_open_warn_if_slow.  */
 
 
-int
-target_fileio_open (struct inferior *inf, const char *filename,
-                   int flags, int mode, int *target_errno)
+static int
+target_fileio_open_1 (struct inferior *inf, const char *filename,
+                     int flags, int mode, int warn_if_slow,
+                     int *target_errno)
 {
   struct target_ops *t;
 
 {
   struct target_ops *t;
 
@@ -2792,7 +2893,7 @@ target_fileio_open (struct inferior *inf, const char *filename,
       if (t->to_fileio_open != NULL)
        {
          int fd = t->to_fileio_open (t, inf, filename, flags, mode,
       if (t->to_fileio_open != NULL)
        {
          int fd = t->to_fileio_open (t, inf, filename, flags, mode,
-                                     target_errno);
+                                     warn_if_slow, target_errno);
 
          if (fd < 0)
            fd = -1;
 
          if (fd < 0)
            fd = -1;
@@ -2801,11 +2902,12 @@ target_fileio_open (struct inferior *inf, const char *filename,
 
          if (targetdebug)
            fprintf_unfiltered (gdb_stdlog,
 
          if (targetdebug)
            fprintf_unfiltered (gdb_stdlog,
-                               "target_fileio_open (%d,%s,0x%x,0%o)"
+                               "target_fileio_open (%d,%s,0x%x,0%o,%d)"
                                " = %d (%d)\n",
                                inf == NULL ? 0 : inf->num,
                                filename, flags, mode,
                                " = %d (%d)\n",
                                inf == NULL ? 0 : inf->num,
                                filename, flags, mode,
-                               fd, fd != -1 ? 0 : *target_errno);
+                               warn_if_slow, fd,
+                               fd != -1 ? 0 : *target_errno);
          return fd;
        }
     }
          return fd;
        }
     }
@@ -2816,6 +2918,27 @@ target_fileio_open (struct inferior *inf, const char *filename,
 
 /* See target.h.  */
 
 
 /* See target.h.  */
 
+int
+target_fileio_open (struct inferior *inf, const char *filename,
+                   int flags, int mode, int *target_errno)
+{
+  return target_fileio_open_1 (inf, filename, flags, mode, 0,
+                              target_errno);
+}
+
+/* See target.h.  */
+
+int
+target_fileio_open_warn_if_slow (struct inferior *inf,
+                                const char *filename,
+                                int flags, int mode, int *target_errno)
+{
+  return target_fileio_open_1 (inf, filename, flags, mode, 1,
+                              target_errno);
+}
+
+/* See target.h.  */
+
 int
 target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
                      ULONGEST offset, int *target_errno)
 int
 target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
                      ULONGEST offset, int *target_errno)
@@ -2823,11 +2946,13 @@ target_fileio_pwrite (int fd, const gdb_byte *write_buf, int len,
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
-  if (is_closed_fileio_fh (fh->fd))
+  if (fh->is_closed ())
     *target_errno = EBADF;
     *target_errno = EBADF;
+  else if (fh->target == NULL)
+    *target_errno = EIO;
   else
   else
-    ret = fh->t->to_fileio_pwrite (fh->t, fh->fd, write_buf,
-                                  len, offset, target_errno);
+    ret = fh->target->to_fileio_pwrite (fh->target, fh->target_fd, write_buf,
+                                       len, offset, target_errno);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
@@ -2847,11 +2972,13 @@ target_fileio_pread (int fd, gdb_byte *read_buf, int len,
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
-  if (is_closed_fileio_fh (fh->fd))
+  if (fh->is_closed ())
     *target_errno = EBADF;
     *target_errno = EBADF;
+  else if (fh->target == NULL)
+    *target_errno = EIO;
   else
   else
-    ret = fh->t->to_fileio_pread (fh->t, fh->fd, read_buf,
-                                 len, offset, target_errno);
+    ret = fh->target->to_fileio_pread (fh->target, fh->target_fd, read_buf,
+                                      len, offset, target_errno);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
@@ -2870,10 +2997,13 @@ target_fileio_fstat (int fd, struct stat *sb, int *target_errno)
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
-  if (is_closed_fileio_fh (fh->fd))
+  if (fh->is_closed ())
     *target_errno = EBADF;
     *target_errno = EBADF;
+  else if (fh->target == NULL)
+    *target_errno = EIO;
   else
   else
-    ret = fh->t->to_fileio_fstat (fh->t, fh->fd, sb, target_errno);
+    ret = fh->target->to_fileio_fstat (fh->target, fh->target_fd,
+                                      sb, target_errno);
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
 
   if (targetdebug)
     fprintf_unfiltered (gdb_stdlog,
@@ -2890,11 +3020,15 @@ target_fileio_close (int fd, int *target_errno)
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
   fileio_fh_t *fh = fileio_fd_to_fh (fd);
   int ret = -1;
 
-  if (is_closed_fileio_fh (fh->fd))
+  if (fh->is_closed ())
     *target_errno = EBADF;
   else
     {
     *target_errno = EBADF;
   else
     {
-      ret = fh->t->to_fileio_close (fh->t, fh->fd, target_errno);
+      if (fh->target != NULL)
+       ret = fh->target->to_fileio_close (fh->target, fh->target_fd,
+                                          target_errno);
+      else
+       ret = 0;
       release_fileio_fd (fd, fh);
     }
 
       release_fileio_fd (fd, fh);
     }
 
@@ -2936,7 +3070,7 @@ target_fileio_unlink (struct inferior *inf, const char *filename,
 
 /* See target.h.  */
 
 
 /* See target.h.  */
 
-char *
+gdb::optional<std::string>
 target_fileio_readlink (struct inferior *inf, const char *filename,
                        int *target_errno)
 {
 target_fileio_readlink (struct inferior *inf, const char *filename,
                        int *target_errno)
 {
@@ -2946,32 +3080,54 @@ target_fileio_readlink (struct inferior *inf, const char *filename,
     {
       if (t->to_fileio_readlink != NULL)
        {
     {
       if (t->to_fileio_readlink != NULL)
        {
-         char *ret = t->to_fileio_readlink (t, inf, filename,
-                                            target_errno);
+         gdb::optional<std::string> ret
+           = t->to_fileio_readlink (t, inf, filename, target_errno);
 
          if (targetdebug)
            fprintf_unfiltered (gdb_stdlog,
                                "target_fileio_readlink (%d,%s)"
                                " = %s (%d)\n",
                                inf == NULL ? 0 : inf->num,
 
          if (targetdebug)
            fprintf_unfiltered (gdb_stdlog,
                                "target_fileio_readlink (%d,%s)"
                                " = %s (%d)\n",
                                inf == NULL ? 0 : inf->num,
-                               filename, ret? ret : "(nil)",
-                               ret? 0 : *target_errno);
+                               filename, ret ? ret->c_str () : "(nil)",
+                               ret ? 0 : *target_errno);
          return ret;
        }
     }
 
   *target_errno = FILEIO_ENOSYS;
          return ret;
        }
     }
 
   *target_errno = FILEIO_ENOSYS;
-  return NULL;
+  return {};
 }
 
 }
 
-static void
-target_fileio_close_cleanup (void *opaque)
+/* Like scoped_fd, but specific to target fileio.  */
+
+class scoped_target_fd
 {
 {
-  int fd = *(int *) opaque;
-  int target_errno;
+public:
+  explicit scoped_target_fd (int fd) noexcept
+    : m_fd (fd)
+  {
+  }
 
 
-  target_fileio_close (fd, &target_errno);
-}
+  ~scoped_target_fd ()
+  {
+    if (m_fd >= 0)
+      {
+       int target_errno;
+
+       target_fileio_close (m_fd, &target_errno);
+      }
+  }
+
+  DISABLE_COPY_AND_ASSIGN (scoped_target_fd);
+
+  int get () const noexcept
+  {
+    return m_fd;
+  }
+
+private:
+  int m_fd;
+};
 
 /* Read target file FILENAME, in the filesystem as seen by INF.  If
    INF is NULL, use the filesystem seen by the debugger (GDB or, for
 
 /* Read target file FILENAME, in the filesystem as seen by INF.  If
    INF is NULL, use the filesystem seen by the debugger (GDB or, for
@@ -2985,41 +3141,35 @@ static LONGEST
 target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
                            gdb_byte **buf_p, int padding)
 {
 target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
                            gdb_byte **buf_p, int padding)
 {
-  struct cleanup *close_cleanup;
   size_t buf_alloc, buf_pos;
   gdb_byte *buf;
   LONGEST n;
   size_t buf_alloc, buf_pos;
   gdb_byte *buf;
   LONGEST n;
-  int fd;
   int target_errno;
 
   int target_errno;
 
-  fd = target_fileio_open (inf, filename, FILEIO_O_RDONLY, 0700,
-                          &target_errno);
-  if (fd == -1)
+  scoped_target_fd fd (target_fileio_open (inf, filename, FILEIO_O_RDONLY,
+                                          0700, &target_errno));
+  if (fd.get () == -1)
     return -1;
 
     return -1;
 
-  close_cleanup = make_cleanup (target_fileio_close_cleanup, &fd);
-
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
   buf_alloc = 4096;
   /* Start by reading up to 4K at a time.  The target will throttle
      this number down if necessary.  */
   buf_alloc = 4096;
-  buf = xmalloc (buf_alloc);
+  buf = (gdb_byte *) xmalloc (buf_alloc);
   buf_pos = 0;
   while (1)
     {
   buf_pos = 0;
   while (1)
     {
-      n = target_fileio_pread (fd, &buf[buf_pos],
+      n = target_fileio_pread (fd.get (), &buf[buf_pos],
                               buf_alloc - buf_pos - padding, buf_pos,
                               &target_errno);
       if (n < 0)
        {
          /* An error occurred.  */
                               buf_alloc - buf_pos - padding, buf_pos,
                               &target_errno);
       if (n < 0)
        {
          /* An error occurred.  */
-         do_cleanups (close_cleanup);
          xfree (buf);
          return -1;
        }
       else if (n == 0)
        {
          /* Read all there was.  */
          xfree (buf);
          return -1;
        }
       else if (n == 0)
        {
          /* Read all there was.  */
-         do_cleanups (close_cleanup);
          if (buf_pos == 0)
            xfree (buf);
          else
          if (buf_pos == 0)
            xfree (buf);
          else
@@ -3033,7 +3183,7 @@ target_fileio_read_alloc_1 (struct inferior *inf, const char *filename,
       if (buf_alloc < buf_pos * 2)
        {
          buf_alloc *= 2;
       if (buf_alloc < buf_pos * 2)
        {
          buf_alloc *= 2;
-         buf = xrealloc (buf, buf_alloc);
+         buf = (gdb_byte *) xrealloc (buf, buf_alloc);
        }
 
       QUIT;
        }
 
       QUIT;
@@ -3051,7 +3201,7 @@ target_fileio_read_alloc (struct inferior *inf, const char *filename,
 
 /* See target.h.  */
 
 
 /* See target.h.  */
 
-char *
+gdb::unique_xmalloc_ptr<char> 
 target_fileio_read_stralloc (struct inferior *inf, const char *filename)
 {
   gdb_byte *buffer;
 target_fileio_read_stralloc (struct inferior *inf, const char *filename)
 {
   gdb_byte *buffer;
@@ -3062,10 +3212,10 @@ target_fileio_read_stralloc (struct inferior *inf, const char *filename)
   bufstr = (char *) buffer;
 
   if (transferred < 0)
   bufstr = (char *) buffer;
 
   if (transferred < 0)
-    return NULL;
+    return gdb::unique_xmalloc_ptr<char> (nullptr);
 
   if (transferred == 0)
 
   if (transferred == 0)
-    return xstrdup ("");
+    return gdb::unique_xmalloc_ptr<char> (xstrdup (""));
 
   bufstr[transferred] = 0;
 
 
   bufstr[transferred] = 0;
 
@@ -3079,7 +3229,7 @@ target_fileio_read_stralloc (struct inferior *inf, const char *filename)
        break;
       }
 
        break;
       }
 
-  return bufstr;
+  return gdb::unique_xmalloc_ptr<char> (bufstr);
 }
 
 
 }
 
 
@@ -3101,7 +3251,9 @@ default_watchpoint_addr_within_range (struct target_ops *target,
 static struct gdbarch *
 default_thread_architecture (struct target_ops *ops, ptid_t ptid)
 {
 static struct gdbarch *
 default_thread_architecture (struct target_ops *ops, ptid_t ptid)
 {
-  return target_gdbarch ();
+  inferior *inf = find_inferior_ptid (ptid);
+  gdb_assert (inf != NULL);
+  return inf->gdbarch;
 }
 
 static int
 }
 
 static int
@@ -3141,6 +3293,28 @@ find_target_at (enum strata stratum)
 }
 
 \f
 }
 
 \f
+
+/* See target.h  */
+
+void
+target_announce_detach (int from_tty)
+{
+  pid_t pid;
+  const char *exec_file;
+
+  if (!from_tty)
+    return;
+
+  exec_file = get_exec_file (0);
+  if (exec_file == NULL)
+    exec_file = "";
+
+  pid = ptid_get_pid (inferior_ptid);
+  printf_unfiltered (_("Detaching from program: %s, %s\n"), exec_file,
+                    target_pid_to_str (pid_to_ptid (pid)));
+  gdb_flush (gdb_stdout);
+}
+
 /* The inferior process has died.  Long live the inferior!  */
 
 void
 /* The inferior process has died.  Long live the inferior!  */
 
 void
@@ -3179,7 +3353,7 @@ generic_mourn_inferior (void)
 /* Convert a normal process ID to a string.  Returns the string in a
    static buffer.  */
 
 /* Convert a normal process ID to a string.  Returns the string in a
    static buffer.  */
 
-char *
+const char *
 normal_pid_to_str (ptid_t ptid)
 {
   static char buf[32];
 normal_pid_to_str (ptid_t ptid)
 {
   static char buf[32];
@@ -3188,7 +3362,7 @@ normal_pid_to_str (ptid_t ptid)
   return buf;
 }
 
   return buf;
 }
 
-static char *
+static const char *
 default_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
   return normal_pid_to_str (ptid);
 default_pid_to_str (struct target_ops *ops, ptid_t ptid)
 {
   return normal_pid_to_str (ptid);
@@ -3240,6 +3414,8 @@ target_close (struct target_ops *targ)
 {
   gdb_assert (!target_is_pushed (targ));
 
 {
   gdb_assert (!target_is_pushed (targ));
 
+  fileio_handles_invalidate_target (targ);
+
   if (targ->to_xclose != NULL)
     targ->to_xclose (targ);
   else if (targ->to_close != NULL)
   if (targ->to_xclose != NULL)
     targ->to_xclose (targ);
   else if (targ->to_close != NULL)
@@ -3274,7 +3450,7 @@ target_stop (ptid_t ptid)
 }
 
 void
 }
 
 void
-target_interrupt (ptid_t ptid)
+target_interrupt ()
 {
   if (!may_stop)
     {
 {
   if (!may_stop)
     {
@@ -3282,7 +3458,23 @@ target_interrupt (ptid_t ptid)
       return;
     }
 
       return;
     }
 
-  (*current_target.to_interrupt) (&current_target, ptid);
+  (*current_target.to_interrupt) (&current_target);
+}
+
+/* See target.h.  */
+
+void
+target_pass_ctrlc (void)
+{
+  (*current_target.to_pass_ctrlc) (&current_target);
+}
+
+/* See target.h.  */
+
+void
+default_target_pass_ctrlc (struct target_ops *ops)
+{
+  target_interrupt ();
 }
 
 /* See target/target.h.  */
 }
 
 /* See target/target.h.  */
@@ -3310,6 +3502,14 @@ target_continue_no_signal (ptid_t ptid)
   target_resume (ptid, 0, GDB_SIGNAL_0);
 }
 
   target_resume (ptid, 0, GDB_SIGNAL_0);
 }
 
+/* See target/target.h.  */
+
+void
+target_continue (ptid_t ptid, enum gdb_signal signal)
+{
+  target_resume (ptid, 0, signal);
+}
+
 /* Concatenate ELEM to LIST, a comma separate list, and return the
    result.  The LIST incoming argument is released.  */
 
 /* Concatenate ELEM to LIST, a comma separate list, and return the
    result.  The LIST incoming argument is released.  */
 
@@ -3329,7 +3529,7 @@ str_comma_list_concat_elem (char *list, const char *elem)
 
 static char *
 do_option (int *target_options, char *ret,
 
 static char *
 do_option (int *target_options, char *ret,
-          int opt, char *opt_str)
+          int opt, const char *opt_str)
 {
   if ((*target_options & opt) != 0)
     {
 {
   if ((*target_options & opt) != 0)
     {
@@ -3358,63 +3558,24 @@ target_options_to_string (int target_options)
   return ret;
 }
 
   return ret;
 }
 
-static void
-debug_print_register (const char * func,
-                     struct regcache *regcache, int regno)
-{
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
-
-  fprintf_unfiltered (gdb_stdlog, "%s ", func);
-  if (regno >= 0 && regno < gdbarch_num_regs (gdbarch)
-      && gdbarch_register_name (gdbarch, regno) != NULL
-      && gdbarch_register_name (gdbarch, regno)[0] != '\0')
-    fprintf_unfiltered (gdb_stdlog, "(%s)",
-                       gdbarch_register_name (gdbarch, regno));
-  else
-    fprintf_unfiltered (gdb_stdlog, "(%d)", regno);
-  if (regno >= 0 && regno < gdbarch_num_regs (gdbarch))
-    {
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-      int i, size = register_size (gdbarch, regno);
-      gdb_byte buf[MAX_REGISTER_SIZE];
-
-      regcache_raw_collect (regcache, regno, buf);
-      fprintf_unfiltered (gdb_stdlog, " = ");
-      for (i = 0; i < size; i++)
-       {
-         fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
-       }
-      if (size <= sizeof (LONGEST))
-       {
-         ULONGEST val = extract_unsigned_integer (buf, size, byte_order);
-
-         fprintf_unfiltered (gdb_stdlog, " %s %s",
-                             core_addr_to_string_nz (val), plongest (val));
-       }
-    }
-  fprintf_unfiltered (gdb_stdlog, "\n");
-}
-
 void
 target_fetch_registers (struct regcache *regcache, int regno)
 {
   current_target.to_fetch_registers (&current_target, regcache, regno);
   if (targetdebug)
 void
 target_fetch_registers (struct regcache *regcache, int regno)
 {
   current_target.to_fetch_registers (&current_target, regcache, regno);
   if (targetdebug)
-    debug_print_register ("target_fetch_registers", regcache, regno);
+    regcache->debug_print_register ("target_fetch_registers", regno);
 }
 
 void
 target_store_registers (struct regcache *regcache, int regno)
 {
 }
 
 void
 target_store_registers (struct regcache *regcache, int regno)
 {
-  struct target_ops *t;
-
   if (!may_write_registers)
     error (_("Writing to registers is not allowed (regno %d)"), regno);
 
   current_target.to_store_registers (&current_target, regcache, regno);
   if (targetdebug)
     {
   if (!may_write_registers)
     error (_("Writing to registers is not allowed (regno %d)"), regno);
 
   current_target.to_store_registers (&current_target, regcache, regno);
   if (targetdebug)
     {
-      debug_print_register ("target_store_registers", regcache, regno);
+      regcache->debug_print_register ("target_store_registers", regno);
     }
 }
 
     }
 }
 
@@ -3435,7 +3596,7 @@ simple_verify_memory (struct target_ops *ops,
       ULONGEST xfered_len;
       enum target_xfer_status status;
       gdb_byte buf[1024];
       ULONGEST xfered_len;
       enum target_xfer_status status;
       gdb_byte buf[1024];
-      ULONGEST howmuch = min (sizeof (buf), size - total_xfered);
+      ULONGEST howmuch = std::min<ULONGEST> (sizeof (buf), size - total_xfered);
 
       status = target_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
                                    buf, NULL, lma + total_xfered, howmuch,
 
       status = target_xfer_partial (ops, TARGET_OBJECT_MEMORY, NULL,
                                    buf, NULL, lma + total_xfered, howmuch,
@@ -3474,7 +3635,8 @@ target_verify_memory (const gdb_byte *data, CORE_ADDR memaddr, ULONGEST size)
    target.h.  */
 
 int
    target.h.  */
 
 int
-target_insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, int rw)
+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 current_target.to_insert_mask_watchpoint (&current_target,
                                                   addr, mask, rw);
@@ -3484,7 +3646,8 @@ target_insert_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, int rw)
    target.h.  */
 
 int
    target.h.  */
 
 int
-target_remove_mask_watchpoint (CORE_ADDR addr, CORE_ADDR mask, int rw)
+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 current_target.to_remove_mask_watchpoint (&current_target,
                                                   addr, mask, rw);
@@ -3511,14 +3674,6 @@ target_ranged_break_num_registers (void)
 
 /* See target.h.  */
 
 
 /* See target.h.  */
 
-int
-target_supports_btrace (enum btrace_format format)
-{
-  return current_target.to_supports_btrace (&current_target, format);
-}
-
-/* See target.h.  */
-
 struct btrace_target_info *
 target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 {
 struct btrace_target_info *
 target_enable_btrace (ptid_t ptid, const struct btrace_config *conf)
 {
@@ -3600,10 +3755,34 @@ target_delete_record (void)
 
 /* See target.h.  */
 
 
 /* See target.h.  */
 
+enum record_method
+target_record_method (ptid_t ptid)
+{
+  return current_target.to_record_method (&current_target, ptid);
+}
+
+/* See target.h.  */
+
 int
 int
-target_record_is_replaying (void)
+target_record_is_replaying (ptid_t ptid)
 {
 {
-  return current_target.to_record_is_replaying (&current_target);
+  return current_target.to_record_is_replaying (&current_target, ptid);
+}
+
+/* See target.h.  */
+
+int
+target_record_will_replay (ptid_t ptid, int dir)
+{
+  return current_target.to_record_will_replay (&current_target, ptid, dir);
+}
+
+/* See target.h.  */
+
+void
+target_record_stop_replaying (void)
+{
+  current_target.to_record_stop_replaying (&current_target);
 }
 
 /* See target.h.  */
 }
 
 /* See target.h.  */
@@ -3633,7 +3812,7 @@ target_goto_record (ULONGEST insn)
 /* See target.h.  */
 
 void
 /* See target.h.  */
 
 void
-target_insn_history (int size, int flags)
+target_insn_history (int size, gdb_disassembly_flags flags)
 {
   current_target.to_insn_history (&current_target, size, flags);
 }
 {
   current_target.to_insn_history (&current_target, size, flags);
 }
@@ -3641,7 +3820,8 @@ target_insn_history (int size, int flags)
 /* See target.h.  */
 
 void
 /* See target.h.  */
 
 void
-target_insn_history_from (ULONGEST from, int size, int flags)
+target_insn_history_from (ULONGEST from, int size,
+                         gdb_disassembly_flags flags)
 {
   current_target.to_insn_history_from (&current_target, from, size, flags);
 }
 {
   current_target.to_insn_history_from (&current_target, from, size, flags);
 }
@@ -3649,7 +3829,8 @@ target_insn_history_from (ULONGEST from, int size, int flags)
 /* See target.h.  */
 
 void
 /* See target.h.  */
 
 void
-target_insn_history_range (ULONGEST begin, ULONGEST end, int flags)
+target_insn_history_range (ULONGEST begin, ULONGEST end,
+                          gdb_disassembly_flags flags)
 {
   current_target.to_insn_history_range (&current_target, begin, end, flags);
 }
 {
   current_target.to_insn_history_range (&current_target, begin, end, flags);
 }
@@ -3657,7 +3838,7 @@ target_insn_history_range (ULONGEST begin, ULONGEST end, int flags)
 /* See target.h.  */
 
 void
 /* See target.h.  */
 
 void
-target_call_history (int size, int flags)
+target_call_history (int size, record_print_flags flags)
 {
   current_target.to_call_history (&current_target, size, flags);
 }
 {
   current_target.to_call_history (&current_target, size, flags);
 }
@@ -3665,7 +3846,7 @@ target_call_history (int size, int flags)
 /* See target.h.  */
 
 void
 /* See target.h.  */
 
 void
-target_call_history_from (ULONGEST begin, int size, int flags)
+target_call_history_from (ULONGEST begin, int size, record_print_flags flags)
 {
   current_target.to_call_history_from (&current_target, begin, size, flags);
 }
 {
   current_target.to_call_history_from (&current_target, begin, size, flags);
 }
@@ -3673,7 +3854,7 @@ target_call_history_from (ULONGEST begin, int size, int flags)
 /* See target.h.  */
 
 void
 /* See target.h.  */
 
 void
-target_call_history_range (ULONGEST begin, ULONGEST end, int flags)
+target_call_history_range (ULONGEST begin, ULONGEST end, record_print_flags flags)
 {
   current_target.to_call_history_range (&current_target, begin, end, flags);
 }
 {
   current_target.to_call_history_range (&current_target, begin, end, flags);
 }
@@ -3732,16 +3913,53 @@ default_rcmd (struct target_ops *self, const char *command,
 }
 
 static void
 }
 
 static void
-do_monitor_command (char *cmd,
-                int from_tty)
+do_monitor_command (const char *cmd, int from_tty)
 {
   target_rcmd (cmd, gdb_stdtarg);
 }
 
 {
   target_rcmd (cmd, gdb_stdtarg);
 }
 
+/* Erases all the memory regions marked as flash.  CMD and FROM_TTY are
+   ignored.  */
+
+void
+flash_erase_command (const char *cmd, int from_tty)
+{
+  /* Used to communicate termination of flash operations to the target.  */
+  bool found_flash_region = false;
+  struct gdbarch *gdbarch = target_gdbarch ();
+
+  std::vector<mem_region> mem_regions = target_memory_map ();
+
+  /* Iterate over all memory regions.  */
+  for (const mem_region &m : mem_regions)
+    {
+      /* Is this a flash memory region?  */
+      if (m.attrib.mode == MEM_FLASH)
+        {
+          found_flash_region = true;
+          target_flash_erase (m.lo, m.hi - m.lo);
+
+         ui_out_emit_tuple tuple_emitter (current_uiout, "erased-regions");
+
+          current_uiout->message (_("Erasing flash memory region at address "));
+          current_uiout->field_fmt ("address", "%s", paddress (gdbarch, m.lo));
+          current_uiout->message (", size = ");
+          current_uiout->field_fmt ("size", "%s", hex_string (m.hi - m.lo));
+          current_uiout->message ("\n");
+        }
+    }
+
+  /* Did we do any flash operations?  If so, we need to finalize them.  */
+  if (found_flash_region)
+    target_flash_done ();
+  else
+    current_uiout->message (_("No flash memory regions found.\n"));
+}
+
 /* Print the name of each layers of our target stack.  */
 
 static void
 /* Print the name of each layers of our target stack.  */
 
 static void
-maintenance_print_target_stack (char *cmd, int from_tty)
+maintenance_print_target_stack (const char *cmd, int from_tty)
 {
   struct target_ops *t;
 
 {
   struct target_ops *t;
 
@@ -3762,6 +3980,14 @@ target_async (int enable)
   current_target.to_async (&current_target, enable);
 }
 
   current_target.to_async (&current_target, enable);
 }
 
+/* See target.h.  */
+
+void
+target_thread_events (int enable)
+{
+  current_target.to_thread_events (&current_target, enable);
+}
+
 /* Controls if targets can report that they can/are async.  This is
    just for maintainers to use when debugging gdb.  */
 int target_async_permitted = 1;
 /* Controls if targets can report that they can/are async.  This is
    just for maintainers to use when debugging gdb.  */
 int target_async_permitted = 1;
@@ -3771,7 +3997,7 @@ int target_async_permitted = 1;
 static int target_async_permitted_1 = 1;
 
 static void
 static int target_async_permitted_1 = 1;
 
 static void
-maint_set_target_async_command (char *args, int from_tty,
+maint_set_target_async_command (const char *args, int from_tty,
                                struct cmd_list_element *c)
 {
   if (have_live_inferiors ())
                                struct cmd_list_element *c)
 {
   if (have_live_inferiors ())
@@ -3824,7 +4050,7 @@ static enum auto_boolean target_non_stop_enabled_1 = AUTO_BOOLEAN_AUTO;
 /* Implementation of "maint set target-non-stop".  */
 
 static void
 /* Implementation of "maint set target-non-stop".  */
 
 static void
-maint_set_target_non_stop_command (char *args, int from_tty,
+maint_set_target_non_stop_command (const char *args, int from_tty,
                                   struct cmd_list_element *c)
 {
   if (have_live_inferiors ())
                                   struct cmd_list_element *c)
 {
   if (have_live_inferiors ())
@@ -3880,7 +4106,7 @@ update_target_permissions (void)
    way.  */
 
 static void
    way.  */
 
 static void
-set_target_permissions (char *args, int from_tty,
+set_target_permissions (const char *args, int from_tty,
                        struct cmd_list_element *c)
 {
   if (target_has_execution)
                        struct cmd_list_element *c)
 {
   if (target_has_execution)
@@ -3901,7 +4127,7 @@ set_target_permissions (char *args, int from_tty,
 /* Set memory write permission independently of observer mode.  */
 
 static void
 /* Set memory write permission independently of observer mode.  */
 
 static void
-set_write_memory_permission (char *args, int from_tty,
+set_write_memory_permission (const char *args, int from_tty,
                        struct cmd_list_element *c)
 {
   /* Make the real values match the user-changed values.  */
                        struct cmd_list_element *c)
 {
   /* Make the real values match the user-changed values.  */
@@ -3909,6 +4135,53 @@ set_write_memory_permission (char *args, int from_tty,
   update_observer_mode ();
 }
 
   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)
 
 void
 initialize_targets (void)
@@ -3916,8 +4189,8 @@ initialize_targets (void)
   init_dummy_target ();
   push_target (&dummy_target);
 
   init_dummy_target ();
   push_target (&dummy_target);
 
-  add_info ("target", target_info, targ_desc);
-  add_info ("files", target_info, targ_desc);
+  add_info ("target", info_target_command, targ_desc);
+  add_info ("files", info_target_command, targ_desc);
 
   add_setshow_zuinteger_cmd ("target", class_maintenance, &targetdebug, _("\
 Set target debugging."), _("\
 
   add_setshow_zuinteger_cmd ("target", class_maintenance, &targetdebug, _("\
 Set target debugging."), _("\
@@ -4020,6 +4293,9 @@ Otherwise, any attempt to interrupt or stop will be ignored."),
                           set_target_permissions, NULL,
                           &setlist, &showlist);
 
                           set_target_permissions, NULL,
                           &setlist, &showlist);
 
+  add_com ("flash-erase", no_class, flash_erase_command,
+           _("Erase all flash memory regions."));
+
   add_setshow_boolean_cmd ("auto-connect-native-target", class_support,
                           &auto_connect_native_target, _("\
 Set whether GDB may automatically connect to the native target."), _("\
   add_setshow_boolean_cmd ("auto-connect-native-target", class_support,
                           &auto_connect_native_target, _("\
 Set whether GDB may automatically connect to the native target."), _("\
This page took 0.049797 seconds and 4 git commands to generate.