[PATCH 5/6] Share fork_inferior et al with gdbserver

Luis Machado lgustavo@codesourcery.com
Tue Jan 3 23:32:00 GMT 2017


Not a lot of comments at this point, but a few.

On 12/22/2016 09:39 PM, Sergio Durigan Junior wrote:
> This is the most important (and the biggest, sorry) patch of the
> series.  It moves fork_inferior from gdb/fork-child.c to
> common/common-fork-child.c and makes all the necessary adjustments to
> both GDB and gdbserver to make sure everything works OK.
>
> There is no "most important change" with this patch; all changes are
> made in a progressive way, making sure that gdbserver had the
> necessary features while not breaking GDB at the same time.  For some
> feature, like the target_terminal_* functions, I chose to just use
> placeholders for the real functions on gdbserver, that should be
> implemented in the future.  For now, we don't need them in order to
> make things work.
>
> I've had to take into account the fact that gdbserver uses global
> variables to control which thread is currently running, so you will
> see a few modifications to accomodate that: for example, the new
> argument added to "startup_inferior", or the one added to
> "set_executing".
>
> Last, but not least, I did a major revamp on the way gdbserver
> computes and stores the inferior's arguments.  It's now using a
> std::vector<char *> and std::string where applicable, which makes
> things much easier even to understand.  This simplification was also
> interesting for the "create_inferior" method of gdbserver's target.c;
> now, it only needs one argument (a vector containing the full inferior
> argv) instead of two char * that were confusing to
> manipulate/generate.
>
> I decided to go ahead and implement a partial support for starting the
> inferior with a shell on gdbserver, although the full feature comes in
> the next patch.  For now, the user won't have the option to disable
> the startup-with-shell, and also won't be able to change which shell
> gdbserver will use (other than setting the $SHELL environment
> variable, that is).
>
> Everything is working as expected, and no regressions were present
> during the tests.
>
> gdb/ChangeLog:
> 2016-12-22  Sergio Durigan Junior  <sergiodj@redhat.com>
>
> 	* Makefile.in (SFILES): Add "common/common-fork-child.c".
> 	(HFILES_NO_SRCDIR): Add "common/common-inferior.h" and
> 	"common/common-top.h".
> 	(COMMON_OBS): Add "common-fork-child.o".
> 	* common-fork-child.c: New file, with the majority of
> 	"gdb/fork-child.c".
> 	* common/common-inferior.h: New file, with contents from
> 	"gdb/inferior.h".
> 	* common/common-top.h: New file.
> 	* common/common-utils.h (gdb_flush_out_err): New prototype.
> 	* corefile.c (get_exec_file): Update comment.
> 	* darwin-nat.c (darwin_ptrace_him): Update call of
> 	"startup_inferior".
> 	* fork-child.c: Cleanup unnecessary includes.
> 	(SHELL_FILE): Move to "common/common-fork-child.c".
> 	(environ): Likewise.
> 	(exec_wrapper): Initialize.
> 	(get_exec_wrapper): New function.
> 	(breakup_args): Move to "common/common-fork-child.c"; rename to
> 	"breakup_args_for_exec".
> 	(escape_bang_in_quoted_argument): Move to
> 	"common/common-fork-child.c".
> 	(fork_inferior): Likewise.  Update function to support gdbserver.
> 	(startup_inferior): Likewise.
> 	(_initialize_fork_child): Update documentation for "set/show
> 	startup-with-shell" command.
> 	* gnu-nat.c (gnu_create_inferior): Update call to
> 	"startup_inferior".
> 	* inf-ptrace.c (inf_ptrace_create_inferior): Likewise.
> 	* inferior.h: Include "common-inferior.h".
> 	(fork_inferior): Move prototype to "common-inferior.h".
> 	(startup_inferior): Likewise.
> 	* procfs.c (procfs_init_inferior): Update call to
> 	"startup_inferior".
> 	* target.h (target_terminal_init): Move prototype to
> 	"target/target.h".
> 	(target_terminal_inferior): Likewise.
> 	(target_terminal_ours): Likewise.
> 	* target/target.h (target_terminal_init): New prototype, moved
> 	from "target.h".
> 	(target_terminal_inferior): Likewise.
> 	(target_terminal_ours): Likewise.
> 	* top.h: Include "common-top.h".
> 	(main_ui): Move
> 	(current_ui): Move
> 	* utils.c (gdb_flush_out_err): New function.
>
> gdb/gdbserver/ChangeLog:
> 2016-12-22  Sergio Durigan Junior  <sergiodj@redhat.com>
>
> 	* Makefile.in (SFILES): Add "terminal.c" and
> 	"common/common-fork-child.c".
> 	(OBS): Add common-fork-child.o and terminal.o.
> 	(common-fork-child.o): New rule.
> 	* inferiors (inferior_ptid): New variable.
> 	(inferior_appeared): New function.
> 	(current_inferior): Likewise.
> 	(have_inferiors): Likewise.
> 	* linux-low.c: Include "common-inferior.h" and "environ.h".
> 	(linux_update_process): New function.
> 	(linux_add_process): Update comment.  Adjust function to call
> 	"linux_update_process".
> 	(update_thread_lwp): New function.
> 	(linux_ptrace_fun): Likewise.
> 	(linux_create_inferior): Adjust function prototype to reflect
> 	change on "target.h".  Adjust function code to use
> 	"fork_inferior".
> 	* lynx-low.c (lynx_update_process): New function.
> 	(lynx_add_process): Update comment.  Adjust function to call
> 	"lynx_update_process".
> 	(lynx_ptrace_fun): New function.
> 	(lynx_create_inferior): Adjust function prototype to reflect
> 	change on "target.h".  Adjust function code to use
> 	"fork_inferior".
> 	* nto-low.c (nto_create_inferior): Adjust function prototype and
> 	code to reflect change on "target.h".
> 	* server.c: Include "common-inferior.h", "common-terminal.h",
> 	"common-top.h", "environ.h".
> 	(main_ui): New variable.
> 	(current_ui): Likewise.
> 	(our_environ): Likewise.
> 	(startup_with_shell): Likewise.
> 	(startup_shell): Likewise.
> 	(program_argv): Convert to std::vector<char *>.
> 	(wrapper_argv): Likewise.
> 	(get_exec_wrapper): New function.
> 	(get_exec_file): Likewise.
> 	(get_environ): Likewise.
> 	(pre_fork_inferior): New function, with parts of "start_inferior".
> 	(post_fork_inferior): Likewise.
> 	(handle_v_run): Update code to deal with arguments coming from the
> 	remote host.  Update calls from "start_inferior" to
> 	"create_inferior".
> 	(captured_main): Likewise.  Initialize environment variable.  Call
> 	"have_job_control".
> 	* server.h (startup_shell): New variable.
> 	(pre_fork_inferior): New prototype.
> 	(post_fork_inferior): Likewise.
> 	(get_environ): Likewise.
> 	* spu-low.c (spu_ptrace_fun): New function.
> 	(spu_create_inferior): Adjust function prototype to reflect change
> 	on "target.h".  Adjust function code to use "fork_inferior".
> 	* target.c (target_terminal_init): New function.
> 	(target_terminal_inferior): Likewise.
> 	(target_terminal_ours): Likewise.
> 	* target.h (struct target_ops) <create_inferior>: Update prototype
> 	to accept one std::vector<char *> representing the full program
> 	argv.
> 	(create_inferior): Update macro.
> 	* utils.c (gdb_flush_out_err): New function.
> 	(free_vector_argv): Likewise.
> 	(stringify_argv): Likewise.
> 	* utils.h (free_vector_argv): New prototype.
> 	(stringify_argv): Likewise.
> 	* win32-low.c (win32_create_inferior): Adjust function prototype
> 	and code to reflect change on "target.h".
>
> gdb/testsuite/ChangeLog:
> 2016-12-22  Sergio Durigan Junior  <sergiodj@redhat.com>
>
> 	* gdb.server/non-existing-program.exp: Update regex in order to
> 	reflect the fact that gdbserver is now using fork_inferior (with a
> 	shell) to startup the inferior.
> ---
>  gdb/Makefile.in                                   |   4 +
>  gdb/{fork-child.c => common/common-fork-child.c}  | 318 ++++++-------
>  gdb/common/common-inferior.h                      | 113 +++++
>  gdb/{gdbserver/utils.h => common/common-top.h}    |  20 +-
>  gdb/common/common-utils.h                         |   5 +
>  gdb/corefile.c                                    |   4 +-
>  gdb/darwin-nat.c                                  |   2 +-
>  gdb/fork-child.c                                  | 530 +---------------------
>  gdb/gdbserver/Makefile.in                         |   7 +
>  gdb/gdbserver/inferiors.c                         |  27 ++
>  gdb/gdbserver/linux-low.c                         | 124 +++--
>  gdb/gdbserver/lynx-low.c                          |  66 +--
>  gdb/gdbserver/nto-low.c                           |   9 +-
>  gdb/gdbserver/server.c                            | 279 +++++++-----
>  gdb/gdbserver/server.h                            |  19 +
>  gdb/gdbserver/spu-low.c                           |  43 +-
>  gdb/gdbserver/target.c                            |  24 +
>  gdb/gdbserver/target.h                            |   7 +-
>  gdb/gdbserver/utils.c                             |  37 ++
>  gdb/gdbserver/utils.h                             |  12 +
>  gdb/gdbserver/win32-low.c                         |  25 +-
>  gdb/gnu-nat.c                                     |   2 +-
>  gdb/inf-ptrace.c                                  |   2 +-
>  gdb/inferior.h                                    |  12 +-
>  gdb/procfs.c                                      |   2 +-
>  gdb/target.h                                      |  17 -
>  gdb/target/target.h                               |  17 +
>  gdb/testsuite/gdb.server/non-existing-program.exp |  10 +-
>  gdb/top.h                                         |   9 +-
>  gdb/utils.c                                       |   9 +
>  30 files changed, 796 insertions(+), 959 deletions(-)
>  copy gdb/{fork-child.c => common/common-fork-child.c} (76%)
>  create mode 100644 gdb/common/common-inferior.h
>  copy gdb/{gdbserver/utils.h => common/common-top.h} (62%)
>
> diff --git a/gdb/Makefile.in b/gdb/Makefile.in
> index ca13a80..a7d06f9 100644
> --- a/gdb/Makefile.in
> +++ b/gdb/Makefile.in
> @@ -1195,6 +1195,7 @@ SFILES = \
>  	common/fileio.c \
>  	common/filestuff.c \
>  	common/format.c \
> +	common/common-fork-child.c \
>  	common/common-inflow.c \
>  	common/gdb_vecs.c \
>  	common/new-op.c \
> @@ -1483,6 +1484,8 @@ HFILES_NO_SRCDIR = \
>  	common/gdb_sys_time.h \
>  	common/gdb_vecs.h \
>  	common/gdb_wait.h \
> +	common/common-inferior.h \
> +	common/common-top.h \
>  	common/host-defs.h \
>  	common/print-utils.h \
>  	common/ptid.h \
> @@ -1624,6 +1627,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \
>  	common-agent.o \
>  	common-debug.o \
>  	common-exceptions.o \
> +	common-fork-child.o \
>  	common-inflow.o \
>  	common-regcache.o \
>  	common-utils.o \
> diff --git a/gdb/fork-child.c b/gdb/common/common-fork-child.c
> similarity index 76%
> copy from gdb/fork-child.c
> copy to gdb/common/common-fork-child.c
> index 38fca60..ab0cafc 100644
> --- a/gdb/fork-child.c
> +++ b/gdb/common/common-fork-child.c
> @@ -19,28 +19,22 @@
>     You should have received a copy of the GNU General Public License
>     along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
>
> -#include "defs.h"
> -#include "inferior.h"
> -#include "terminal.h"
> -#include "target.h"
> -#include "gdb_wait.h"
> -#include "gdb_vfork.h"
> -#include "gdbcore.h"
> -#include "gdbthread.h"
> -#include "command.h" /* for dont_repeat () */
> -#include "gdbcmd.h"
> -#include "solib.h"
> +#include "common-defs.h"
> +#include "target/waitstatus.h"
> +#include "common-terminal.h"
>  #include "filestuff.h"
> -#include "top.h"
> +#include "target/target.h"
> +#include "common-inferior.h"
> +#include "common-gdbthread.h"
> +#include "common-top.h"
>  #include "signals-state-save-restore.h"
> -#include <signal.h>
> -
> -/* This just gets used as a default if we can't find SHELL.  */
> -#define SHELL_FILE "/bin/sh"
>
>  extern char **environ;
>
> -static char *exec_wrapper;
> +/* Default shell file to be used if 'startup-with-shell' is set but
> +   $SHELL is not.  */
> +
> +#define SHELL_FILE "/bin/sh"
>
>  /* Break up SCRATCH into an argument vector suitable for passing to
>     execvp and store it in ARGV.  E.g., on "run a b c d" this routine
> @@ -48,7 +42,7 @@ static char *exec_wrapper;
>     fill in ARGV with the four arguments "a", "b", "c", "d".  */
>
>  static void
> -breakup_args (char *scratch, char **argv)
> +breakup_args_for_exec (char *scratch, char **argv)
>  {
>    char *cp = scratch, *tmp;
>
> @@ -109,15 +103,120 @@ escape_bang_in_quoted_argument (const char *shell_file)
>    return 0;
>  }
>
> -/* Start an inferior Unix child process and sets inferior_ptid to its
> -   pid.  EXEC_FILE is the file to run.  ALLARGS is a string containing
> -   the arguments to the program.  ENV is the environment vector to
> -   pass.  SHELL_FILE is the shell file, or NULL if we should pick
> -   one.  EXEC_FUN is the exec(2) function to use, or NULL for the default
> -   one.  */
> +/* See common/common-inferior.h.  */
> +
> +char *
> +get_startup_shell (void)
> +{
> +  static char *ret;
> +
> +  ret = getenv ("SHELL");
> +  if (ret == NULL)
> +    ret = SHELL_FILE;
> +
> +  return ret;
> +}
> +
> +/* Quote the shell command that will be executed.  This function is
> +   called when the inferior is going to be executed under a shell
> +   (i.e., when 'startup-with-shell' is set).
> +
> +   SHELL_FILE is the shell which will be used to execute the inferior
> +   (e.g., /bin/sh).
> +
> +   EXEC_FILE is the inferior executable itself.
> +
> +   ALLARGS contains all the arguments that will be passed to the
> +   inferior.
> +
> +   EXEC_WRAPPER, if set, is the wrapper that will be used to execute
> +   the inferior.
> +
> +   SHELL_CMD is a pointer to the resulting shell command that will be
> +   executed.  The resulting shell command will be returned in it.  It
> +   must be pre-allocated and have a reasonable size.  For an example
> +   on how to determine its size, see 'fork_inferior' on
> +   fork-child.c.  */
> +
> +static void
> +quote_shell_command (const char *shell_file, const char *exec_file,
> +		     const char *allargs, const char *exec_wrapper,
> +		     char **shell_cmd)
> +{
> +  char *shell_command = *shell_cmd;
> +  const char *p;
> +  int need_to_quote;
> +  const int escape_bang = escape_bang_in_quoted_argument (shell_file);
> +
> +  shell_command[0] = '\0';
> +  strcat (shell_command, "exec ");
> +
> +  /* Add any exec wrapper.  That may be a program name with arguments, so
> +     the user must handle quoting.  */
> +  if (exec_wrapper != NULL)
> +    {
> +      strcat (shell_command, exec_wrapper);
> +      strcat (shell_command, " ");
> +    }
> +
> +  /* Now add exec_file, quoting as necessary.  */
> +
> +  /* Quoting in this style is said to work with all shells.  But
> +     csh on IRIX 4.0.1 can't deal with it.  So we only quote it if
> +     we need to.  */
> +  p = exec_file;
> +  while (1)
> +    {
> +      switch (*p)
> +	{
> +	case '\'':
> +	case '!':
> +	case '"':
> +	case '(':
> +	case ')':
> +	case '$':
> +	case '&':
> +	case ';':
> +	case '<':
> +	case '>':
> +	case ' ':
> +	case '\n':
> +	case '\t':
> +	  need_to_quote = 1;
> +	  goto end_scan;
> +
> +	case '\0':
> +	  need_to_quote = 0;
> +	  goto end_scan;
> +
> +	default:
> +	  break;
> +	}
> +      ++p;
> +    }
> + end_scan:
> +  if (need_to_quote)
> +    {
> +      strcat (shell_command, "'");
> +      for (p = exec_file; *p != '\0'; ++p)
> +	{
> +	  if (*p == '\'')
> +	    strcat (shell_command, "'\\''");
> +	  else if (*p == '!' && escape_bang)
> +	    strcat (shell_command, "\\!");
> +	  else
> +	    strncat (shell_command, p, 1);
> +	}
> +      strcat (shell_command, "'");
> +    }
> +  else
> +    strcat (shell_command, exec_file);
> +
> +  strcat (shell_command, " ");
> +  strcat (shell_command, allargs);
> +}
>
> -/* This function is NOT reentrant.  Some of the variables have been
> -   made static to ensure that they survive the vfork call.  */
> +/* See common/common-inferior.h.  */
>
>  int
>  fork_inferior (char *exec_file_arg, char *allargs, char **env,
> @@ -127,7 +226,6 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
>                                  char * const *env))
>  {
>    int pid;
> -  static char default_shell_file[] = SHELL_FILE;
>    /* Set debug_fork then attach to the child while it sleeps, to debug.  */
>    static int debug_fork = 0;
>    /* This is set to the result of setpgrp, which if vforked, will be visible
> @@ -158,9 +256,9 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
>      {
>        /* Figure out what shell to start up the user program under.  */
>        if (shell_file == NULL)
> -	shell_file = getenv ("SHELL");
> -      if (shell_file == NULL)
> -	shell_file = default_shell_file;
> +	shell_file = get_startup_shell ();
> +
> +      gdb_assert (shell_file != NULL);
>        shell = 1;
>      }
>
> @@ -174,92 +272,28 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
>
>        argv = XALLOCAVEC (char *, argc);
>        argv[0] = exec_file;
> -      breakup_args (allargs, &argv[1]);
> +      breakup_args_for_exec (allargs, &argv[1]);
>      }
>    else
>      {
>        /* We're going to call a shell.  */
>        char *shell_command;
> -      int len;
> -      char *p;
> -      int need_to_quote;
> -      const int escape_bang = escape_bang_in_quoted_argument (shell_file);
> +      char *exec_wrapper = get_exec_wrapper ();
> +      size_t len;
>
>        /* Multiplying the length of exec_file by 4 is to account for the
>           fact that it may expand when quoted; it is a worst-case number
>           based on every character being '.  */
>        len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
> -      if (exec_wrapper)
> +      if (exec_wrapper != NULL)
>          len += strlen (exec_wrapper) + 1;
>
>        shell_command = (char *) alloca (len);
>        shell_command[0] = '\0';
>
> -      strcat (shell_command, "exec ");
> -
> -      /* Add any exec wrapper.  That may be a program name with arguments, so
> -	 the user must handle quoting.  */
> -      if (exec_wrapper)
> -	{
> -	  strcat (shell_command, exec_wrapper);
> -	  strcat (shell_command, " ");
> -	}
> -
> -      /* Now add exec_file, quoting as necessary.  */
> -
> -      /* Quoting in this style is said to work with all shells.  But
> -         csh on IRIX 4.0.1 can't deal with it.  So we only quote it if
> -         we need to.  */
> -      p = exec_file;
> -      while (1)
> -	{
> -	  switch (*p)
> -	    {
> -	    case '\'':
> -	    case '!':
> -	    case '"':
> -	    case '(':
> -	    case ')':
> -	    case '$':
> -	    case '&':
> -	    case ';':
> -	    case '<':
> -	    case '>':
> -	    case ' ':
> -	    case '\n':
> -	    case '\t':
> -	      need_to_quote = 1;
> -	      goto end_scan;
> -
> -	    case '\0':
> -	      need_to_quote = 0;
> -	      goto end_scan;
> -
> -	    default:
> -	      break;
> -	    }
> -	  ++p;
> -	}
> -    end_scan:
> -      if (need_to_quote)
> -	{
> -	  strcat (shell_command, "'");
> -	  for (p = exec_file; *p != '\0'; ++p)
> -	    {
> -	      if (*p == '\'')
> -		strcat (shell_command, "'\\''");
> -	      else if (*p == '!' && escape_bang)
> -		strcat (shell_command, "\\!");
> -	      else
> -		strncat (shell_command, p, 1);
> -	    }
> -	  strcat (shell_command, "'");
> -	}
> -      else
> -	strcat (shell_command, exec_file);
> -
> -      strcat (shell_command, " ");
> -      strcat (shell_command, allargs);
> +      quote_shell_command (shell_file, exec_file,
> +			   allargs,
> +			   exec_wrapper, &shell_command);
>
>        /* If we decided above to start up with a shell, we exec the
>  	 shell, "-c" says to interpret the next arg as a shell command
> @@ -287,8 +321,7 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
>    /* It is generally good practice to flush any possible pending stdio
>       output prior to doing a fork, to avoid the possibility of both
>       the parent and child flushing the same data after the fork.  */
> -  gdb_flush (main_ui->m_gdb_stdout);
> -  gdb_flush (main_ui->m_gdb_stderr);
> +  gdb_flush_out_err ();
>
>    /* If there's any initialization of the target layers that must
>       happen to prepare to handle the child we're about fork, do it
> @@ -382,13 +415,13 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
>
>        /* If we get here, it's an error.  */
>        save_errno = errno;
> -      fprintf_unfiltered (gdb_stderr, "Cannot exec %s", argv[0]);
> +      warning ("Cannot exec %s", argv[0]);
> +
>        for (i = 1; argv[i] != NULL; i++)
> -	fprintf_unfiltered (gdb_stderr, " %s", argv[i]);
> -      fprintf_unfiltered (gdb_stderr, ".\n");
> -      fprintf_unfiltered (gdb_stderr, "Error: %s\n",
> -			  safe_strerror (save_errno));
> -      gdb_flush (gdb_stderr);
> +	warning (" %s", argv[i]);
> +
> +      warning ("Error: %s\n", safe_strerror (save_errno));
> +
>        _exit (0177);
>      }
>
> @@ -428,10 +461,12 @@ fork_inferior (char *exec_file_arg, char *allargs, char **env,
>    return pid;
>  }
>
> -/* Accept NTRAPS traps from the inferior.  */
> +/* See common/common-inferior.h.  */
>
>  void
> -startup_inferior (int ntraps)
> +startup_inferior (int ntraps,
> +		  struct target_waitstatus *last_waitstatus,
> +		  ptid_t *last_ptid)
>  {
>    int pending_execs = ntraps;
>    int terminal_initted = 0;
> @@ -451,8 +486,7 @@ startup_inferior (int ntraps)
>    /* The process was started by the fork that created it, but it will
>       have stopped one instruction after execing the shell.  Here we
>       must get it up to actual execution of the real program.  */
> -
> -  if (exec_wrapper)
> +  if (get_exec_wrapper () != NULL)
>      pending_execs++;
>
>    while (1)
> @@ -464,6 +498,11 @@ startup_inferior (int ntraps)
>        memset (&ws, 0, sizeof (ws));
>        event_ptid = target_wait (resume_ptid, &ws, 0);
>
> +      if (last_waitstatus != NULL)
> +	*last_waitstatus = ws;
> +      if (last_ptid != NULL)
> +	*last_ptid = event_ptid;
> +
>        if (ws.kind == TARGET_WAITKIND_IGNORE)
>  	/* The inferior didn't really stop, keep waiting.  */
>  	continue;
> @@ -476,6 +515,12 @@ startup_inferior (int ntraps)
>  	  case TARGET_WAITKIND_VFORKED:
>  	  case TARGET_WAITKIND_SYSCALL_ENTRY:
>  	  case TARGET_WAITKIND_SYSCALL_RETURN:
> +	  case TARGET_WAITKIND_VFORK_DONE:
> +	  case TARGET_WAITKIND_IGNORE:
> +	  case TARGET_WAITKIND_NO_HISTORY:
> +	  case TARGET_WAITKIND_NO_RESUMED:
> +	  case TARGET_WAITKIND_THREAD_CREATED:
> +	  case TARGET_WAITKIND_THREAD_EXITED:
>  	    /* Ignore gracefully during startup of the inferior.  */
>  	    switch_to_thread (event_ptid);
>  	    break;
> @@ -545,50 +590,5 @@ startup_inferior (int ntraps)
>      }
>
>    /* Mark all threads non-executing.  */
> -  set_executing (resume_ptid, 0, NULL);
> -}
> -
> -/* Implement the "unset exec-wrapper" command.  */
> -
> -static void
> -unset_exec_wrapper_command (char *args, int from_tty)
> -{
> -  xfree (exec_wrapper);
> -  exec_wrapper = NULL;
> -}
> -
> -static void
> -show_startup_with_shell (struct ui_file *file, int from_tty,
> -			 struct cmd_list_element *c, const char *value)
> -{
> -  fprintf_filtered (file,
> -		    _("Use of shell to start subprocesses is %s.\n"),
> -		    value);
> -}
> -
> -/* Provide a prototype to silence -Wmissing-prototypes.  */
> -extern initialize_file_ftype _initialize_fork_child;
> -
> -void
> -_initialize_fork_child (void)
> -{
> -  add_setshow_filename_cmd ("exec-wrapper", class_run, &exec_wrapper, _("\
> -Set a wrapper for running programs.\n\
> -The wrapper prepares the system and environment for the new program."),
> -			    _("\
> -Show the wrapper for running programs."), NULL,
> -			    NULL, NULL,
> -			    &setlist, &showlist);
> -
> -  add_cmd ("exec-wrapper", class_run, unset_exec_wrapper_command,
> -           _("Disable use of an execution wrapper."),
> -           &unsetlist);
> -
> -  add_setshow_boolean_cmd ("startup-with-shell", class_support,
> -			   &startup_with_shell, _("\
> -Set use of shell to start subprocesses.  The default is on."), _("\
> -Show use of shell to start subprocesses."), NULL,
> -			   NULL,
> -			   show_startup_with_shell,
> -			   &setlist, &showlist);
> +  set_executing (resume_ptid, 0, last_waitstatus);
>  }
> diff --git a/gdb/common/common-inferior.h b/gdb/common/common-inferior.h
> new file mode 100644
> index 0000000..fb78109
> --- /dev/null
> +++ b/gdb/common/common-inferior.h
> @@ -0,0 +1,113 @@
> +/* Variables that describe the inferior process running under GDB:
> +   Where it is, why it stopped, and how to step it.

Common code that describes the inferior process under GDB/GDBserver ...?

I'd check the other files that were created in common/ to make sure 
their descriptions in the copyright block aren't unchanged from their 
original files.

> +
> +   Copyright (C) 1986-2016 Free Software Foundation, Inc.
> +
> +   This file is part of GDB.
> +
> +   This program is free software; you can redistribute it and/or modify
> +   it under the terms of the GNU General Public License as published by
> +   the Free Software Foundation; either version 3 of the License, or
> +   (at your option) any later version.
> +
> +   This program is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> +   GNU General Public License for more details.
> +
> +   You should have received a copy of the GNU General Public License
> +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef COMMON_INFERIOR_H
> +#define COMMON_INFERIOR_H
> +
> +/* Number of traps that happen between exec'ing the shell to run an
> +   inferior and when we finally get to the inferior code, not counting
> +   the exec for the shell.  This is 1 on all supported
> +   implementations.  */
> +
> +#define START_INFERIOR_TRAPS_EXPECTED 1
> +
> +struct inferior;
> +
> +/* Whether to start up the debuggee under a shell.
> +
> +   If startup-with-shell is set, GDB's "run" will attempt to start up
> +   the debuggee under a shell.
> +
> +   This is in order for argument-expansion to occur.  E.g.,
> +
> +   (gdb) run *
> +
> +   The "*" gets expanded by the shell into a list of files.
> +
> +   While this is a nice feature, it may be handy to bypass the shell
> +   in some cases.  To disable this feature, do "set startup-with-shell
> +   false".
> +
> +   The catch-exec traps expected during start-up will be one more if
> +   the target is started up with a shell.  */
> +
> +extern int startup_with_shell;
> +
> +/* Collected pid, tid, etc. of the debugged inferior.  When there's
> +   no inferior, ptid_get_pid (inferior_ptid) will be 0.  */
> +
> +extern ptid_t inferior_ptid;
> +
> +/* Accept NTRAPS traps from the inferior.  */
> +
> +extern void startup_inferior (int ntraps,
> +			      struct target_waitstatus *mystatus,
> +			      ptid_t *myptid);
> +
> +/* Start an inferior Unix child process and sets inferior_ptid to its
> +   pid.  EXEC_FILE is the file to run.  ALLARGS is a string containing
> +   the arguments to the program.  ENV is the environment vector to
> +   pass.  SHELL_FILE is the shell file, or NULL if we should pick
> +   one.  EXEC_FUN is the exec(2) function to use, or NULL for the default
> +   one.  */
> +
> +/* This function is NOT reentrant.  Some of the variables have been
> +   made static to ensure that they survive the vfork call.  */
> +
> +extern int fork_inferior (char *exec_file_arg, char *allargs, char **env,
> +	       void (*traceme_fun) (void), void (*init_trace_fun) (int),
> +	       void (*pre_trace_fun) (void), char *shell_file_arg,
> +               void (*exec_fun) (const char *file, char * const *argv,
> +				 char * const *env));
> +
> +/* Return the shell that must be used to startup the inferior.  The
> +   first attempt is the environment variable SHELL; if it is not set,
> +   then we default to SHELL_FILE.  */
> +
> +extern char *get_startup_shell (void);
> +
> +/* Set/get file name for default use for standard in/out in the inferior.  */
> +
> +extern void set_inferior_io_terminal (const char *terminal_name);
> +extern const char *get_inferior_io_terminal (void);
> +
> +/* Return the exec wrapper to be used when starting the inferior, or NULL
> +   otherwise.  */
> +
> +extern char *get_exec_wrapper (void);
> +
> +/* Return the name of the executable file as a string.
> +   ERR nonzero means get error if there is none specified;
> +   otherwise return 0 in that case.  */
> +
> +extern char *get_exec_file (int err);
> +
> +/* Returns true if the inferior list is not empty.  */
> +
> +extern int have_inferiors (void);
> +
> +extern void inferior_appeared (struct inferior *inf, int pid);
> +
> +/* Return a pointer to the current inferior.  It is an error to call
> +   this if there is no current inferior.  */
> +
> +extern struct inferior *current_inferior (void);
> +
> +#endif /* ! COMMON_INFERIOR_H */
> diff --git a/gdb/gdbserver/utils.h b/gdb/common/common-top.h
> similarity index 62%
> copy from gdb/gdbserver/utils.h
> copy to gdb/common/common-top.h
> index 5e0cead..e282116 100644
> --- a/gdb/gdbserver/utils.h
> +++ b/gdb/common/common-top.h
> @@ -1,5 +1,6 @@
> -/* General utility routines for the remote server for GDB.
> -   Copyright (C) 1993-2016 Free Software Foundation, Inc.
> +/* Top level stuff for GDB, the GNU debugger.
> +
> +   Copyright (C) 1986-2016 Free Software Foundation, Inc.
>
>     This file is part of GDB.
>
> @@ -16,10 +17,15 @@
>     You should have received a copy of the GNU General Public License
>     along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
>
> -#ifndef UTILS_H
> -#define UTILS_H
> +#ifndef COMMON_TOP_H
> +#define COMMON_TOP_H
> +
> +/* The main UI.  This is the UI that is bound to stdin/stdout/stderr.
> +   It always exists and is created automatically when GDB starts
> +   up.  */
> +extern struct ui *main_ui;
>
> -char *paddress (CORE_ADDR addr);
> -char *pfildes (gdb_fildes_t fd);
> +/* The current UI.  */
> +extern struct ui *current_ui;
>
> -#endif /* UTILS_H */
> +#endif /* ! COMMON_TOP_H */
> diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h
> index a9053ff..71a5a38 100644
> --- a/gdb/common/common-utils.h
> +++ b/gdb/common/common-utils.h
> @@ -103,4 +103,9 @@ extern const char *skip_spaces_const (const char *inp);
>
>  extern const char *skip_to_space_const (const char *inp);
>
> +/* Flush both stdout and stderr.  This function needs to be
> +   implemented differently on GDB and gdbserver.  */
> +
> +extern void gdb_flush_out_err (void);
> +
>  #endif
> diff --git a/gdb/corefile.c b/gdb/corefile.c
> index 64de931..694308f 100644
> --- a/gdb/corefile.c
> +++ b/gdb/corefile.c
> @@ -170,9 +170,7 @@ validate_files (void)
>      }
>  }
>
> -/* Return the name of the executable file as a string.
> -   ERR nonzero means get error if there is none specified;
> -   otherwise return 0 in that case.  */
> +/* See common/common-inferior.h.  */
>
>  char *
>  get_exec_file (int err)
> diff --git a/gdb/darwin-nat.c b/gdb/darwin-nat.c
> index 6ca659f4..61f634d 100644
> --- a/gdb/darwin-nat.c
> +++ b/gdb/darwin-nat.c
> @@ -1782,7 +1782,7 @@ darwin_ptrace_him (int pid)
>
>    darwin_init_thread_list (inf);
>
> -  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
> +  startup_inferior (START_INFERIOR_TRAPS_EXPECTED, NULL, NULL);
>  }
>
>  static void
> diff --git a/gdb/fork-child.c b/gdb/fork-child.c
> index 38fca60..d7d2f5e 100644
> --- a/gdb/fork-child.c
> +++ b/gdb/fork-child.c
> @@ -21,531 +21,19 @@
>
>  #include "defs.h"
>  #include "inferior.h"
> -#include "terminal.h"
> -#include "target.h"
> -#include "gdb_wait.h"
> -#include "gdb_vfork.h"
> -#include "gdbcore.h"
> -#include "gdbthread.h"
> -#include "command.h" /* for dont_repeat () */
>  #include "gdbcmd.h"
> -#include "solib.h"
> -#include "filestuff.h"
> -#include "top.h"
> -#include "signals-state-save-restore.h"
> -#include <signal.h>
>
> -/* This just gets used as a default if we can't find SHELL.  */
> -#define SHELL_FILE "/bin/sh"
> +/* The exec-wrapper, if any, that will be used when starting the
> +   inferior.  */
>
> -extern char **environ;
> +static char *exec_wrapper = NULL;
>
> -static char *exec_wrapper;
> +/* See common/common-inferior.h.  */
>
> -/* Break up SCRATCH into an argument vector suitable for passing to
> -   execvp and store it in ARGV.  E.g., on "run a b c d" this routine
> -   would get as input the string "a b c d", and as output it would
> -   fill in ARGV with the four arguments "a", "b", "c", "d".  */
> -
> -static void
> -breakup_args (char *scratch, char **argv)
> +char *
> +get_exec_wrapper (void)
>  {
> -  char *cp = scratch, *tmp;
> -
> -  for (;;)
> -    {
> -      /* Scan past leading separators */
> -      while (*cp == ' ' || *cp == '\t' || *cp == '\n')
> -	cp++;
> -
> -      /* Break if at end of string.  */
> -      if (*cp == '\0')
> -	break;
> -
> -      /* Take an arg.  */
> -      *argv++ = cp;
> -
> -      /* Scan for next arg separator.  */
> -      tmp = strchr (cp, ' ');
> -      if (tmp == NULL)
> -	tmp = strchr (cp, '\t');
> -      if (tmp == NULL)
> -	tmp = strchr (cp, '\n');
> -
> -      /* No separators => end of string => break.  */
> -      if (tmp == NULL)
> -	break;
> -      cp = tmp;
> -
> -      /* Replace the separator with a terminator.  */
> -      *cp++ = '\0';
> -    }
> -
> -  /* Null-terminate the vector.  */
> -  *argv = NULL;
> -}
> -
> -/* When executing a command under the given shell, return non-zero if
> -   the '!' character should be escaped when embedded in a quoted
> -   command-line argument.  */
> -
> -static int
> -escape_bang_in_quoted_argument (const char *shell_file)
> -{
> -  const int shell_file_len = strlen (shell_file);
> -
> -  /* Bang should be escaped only in C Shells.  For now, simply check
> -     that the shell name ends with 'csh', which covers at least csh
> -     and tcsh.  This should be good enough for now.  */
> -
> -  if (shell_file_len < 3)
> -    return 0;
> -
> -  if (shell_file[shell_file_len - 3] == 'c'
> -      && shell_file[shell_file_len - 2] == 's'
> -      && shell_file[shell_file_len - 1] == 'h')
> -    return 1;
> -
> -  return 0;
> -}
> -
> -/* Start an inferior Unix child process and sets inferior_ptid to its
> -   pid.  EXEC_FILE is the file to run.  ALLARGS is a string containing
> -   the arguments to the program.  ENV is the environment vector to
> -   pass.  SHELL_FILE is the shell file, or NULL if we should pick
> -   one.  EXEC_FUN is the exec(2) function to use, or NULL for the default
> -   one.  */
> -
> -/* This function is NOT reentrant.  Some of the variables have been
> -   made static to ensure that they survive the vfork call.  */
> -
> -int
> -fork_inferior (char *exec_file_arg, char *allargs, char **env,
> -	       void (*traceme_fun) (void), void (*init_trace_fun) (int),
> -	       void (*pre_trace_fun) (void), char *shell_file_arg,
> -               void (*exec_fun)(const char *file, char * const *argv,
> -                                char * const *env))
> -{
> -  int pid;
> -  static char default_shell_file[] = SHELL_FILE;
> -  /* Set debug_fork then attach to the child while it sleeps, to debug.  */
> -  static int debug_fork = 0;
> -  /* This is set to the result of setpgrp, which if vforked, will be visible
> -     to you in the parent process.  It's only used by humans for debugging.  */
> -  static int debug_setpgrp = 657473;
> -  static char *shell_file;
> -  static char *exec_file;
> -  char **save_our_env;
> -  int shell = 0;
> -  static char **argv;
> -  const char *inferior_io_terminal = get_inferior_io_terminal ();
> -  struct inferior *inf;
> -  int i;
> -  int save_errno;
> -  struct ui *save_ui;
> -
> -  /* If no exec file handed to us, get it from the exec-file command
> -     -- with a good, common error message if none is specified.  */
> -  exec_file = exec_file_arg;
> -  if (exec_file == 0)
> -    exec_file = get_exec_file (1);
> -
> -  /* 'startup_with_shell' is declared in inferior.h and bound to the
> -     "set startup-with-shell" option.  If 0, we'll just do a
> -     fork/exec, no shell, so don't bother figuring out what shell.  */
> -  shell_file = shell_file_arg;
> -  if (startup_with_shell)
> -    {
> -      /* Figure out what shell to start up the user program under.  */
> -      if (shell_file == NULL)
> -	shell_file = getenv ("SHELL");
> -      if (shell_file == NULL)
> -	shell_file = default_shell_file;
> -      shell = 1;
> -    }
> -
> -  if (!shell)
> -    {
> -      /* We're going to call execvp.  Create argument vector.
> -	 Calculate an upper bound on the length of the vector by
> -	 assuming that every other character is a separate
> -	 argument.  */
> -      int argc = (strlen (allargs) + 1) / 2 + 2;
> -
> -      argv = XALLOCAVEC (char *, argc);
> -      argv[0] = exec_file;
> -      breakup_args (allargs, &argv[1]);
> -    }
> -  else
> -    {
> -      /* We're going to call a shell.  */
> -      char *shell_command;
> -      int len;
> -      char *p;
> -      int need_to_quote;
> -      const int escape_bang = escape_bang_in_quoted_argument (shell_file);
> -
> -      /* Multiplying the length of exec_file by 4 is to account for the
> -         fact that it may expand when quoted; it is a worst-case number
> -         based on every character being '.  */
> -      len = 5 + 4 * strlen (exec_file) + 1 + strlen (allargs) + 1 + /*slop */ 12;
> -      if (exec_wrapper)
> -        len += strlen (exec_wrapper) + 1;
> -
> -      shell_command = (char *) alloca (len);
> -      shell_command[0] = '\0';
> -
> -      strcat (shell_command, "exec ");
> -
> -      /* Add any exec wrapper.  That may be a program name with arguments, so
> -	 the user must handle quoting.  */
> -      if (exec_wrapper)
> -	{
> -	  strcat (shell_command, exec_wrapper);
> -	  strcat (shell_command, " ");
> -	}
> -
> -      /* Now add exec_file, quoting as necessary.  */
> -
> -      /* Quoting in this style is said to work with all shells.  But
> -         csh on IRIX 4.0.1 can't deal with it.  So we only quote it if
> -         we need to.  */
> -      p = exec_file;
> -      while (1)
> -	{
> -	  switch (*p)
> -	    {
> -	    case '\'':
> -	    case '!':
> -	    case '"':
> -	    case '(':
> -	    case ')':
> -	    case '$':
> -	    case '&':
> -	    case ';':
> -	    case '<':
> -	    case '>':
> -	    case ' ':
> -	    case '\n':
> -	    case '\t':
> -	      need_to_quote = 1;
> -	      goto end_scan;
> -
> -	    case '\0':
> -	      need_to_quote = 0;
> -	      goto end_scan;
> -
> -	    default:
> -	      break;
> -	    }
> -	  ++p;
> -	}
> -    end_scan:
> -      if (need_to_quote)
> -	{
> -	  strcat (shell_command, "'");
> -	  for (p = exec_file; *p != '\0'; ++p)
> -	    {
> -	      if (*p == '\'')
> -		strcat (shell_command, "'\\''");
> -	      else if (*p == '!' && escape_bang)
> -		strcat (shell_command, "\\!");
> -	      else
> -		strncat (shell_command, p, 1);
> -	    }
> -	  strcat (shell_command, "'");
> -	}
> -      else
> -	strcat (shell_command, exec_file);
> -
> -      strcat (shell_command, " ");
> -      strcat (shell_command, allargs);
> -
> -      /* If we decided above to start up with a shell, we exec the
> -	 shell, "-c" says to interpret the next arg as a shell command
> -	 to execute, and this command is "exec <target-program>
> -	 <args>".  */
> -      argv = (char **) alloca (4 * sizeof (char *));
> -      argv[0] = shell_file;
> -      argv[1] = "-c";
> -      argv[2] = shell_command;
> -      argv[3] = (char *) 0;
> -    }
> -
> -  /* Retain a copy of our environment variables, since the child will
> -     replace the value of environ and if we're vforked, we have to
> -     restore it.  */
> -  save_our_env = environ;
> -
> -  /* Likewise the current UI.  */
> -  save_ui = current_ui;
> -
> -  /* Tell the terminal handling subsystem what tty we plan to run on;
> -     it will just record the information for later.  */
> -  new_tty_prefork (inferior_io_terminal);
> -
> -  /* It is generally good practice to flush any possible pending stdio
> -     output prior to doing a fork, to avoid the possibility of both
> -     the parent and child flushing the same data after the fork.  */
> -  gdb_flush (main_ui->m_gdb_stdout);
> -  gdb_flush (main_ui->m_gdb_stderr);
> -
> -  /* If there's any initialization of the target layers that must
> -     happen to prepare to handle the child we're about fork, do it
> -     now...  */
> -  if (pre_trace_fun != NULL)
> -    (*pre_trace_fun) ();
> -
> -  /* Create the child process.  Since the child process is going to
> -     exec(3) shortly afterwards, try to reduce the overhead by
> -     calling vfork(2).  However, if PRE_TRACE_FUN is non-null, it's
> -     likely that this optimization won't work since there's too much
> -     work to do between the vfork(2) and the exec(3).  This is known
> -     to be the case on ttrace(2)-based HP-UX, where some handshaking
> -     between parent and child needs to happen between fork(2) and
> -     exec(2).  However, since the parent is suspended in the vforked
> -     state, this doesn't work.  Also note that the vfork(2) call might
> -     actually be a call to fork(2) due to the fact that autoconf will
> -     ``#define vfork fork'' on certain platforms.  */
> -  if (pre_trace_fun || debug_fork)
> -    pid = fork ();
> -  else
> -    pid = vfork ();
> -
> -  if (pid < 0)
> -    perror_with_name (("vfork"));
> -
> -  if (pid == 0)
> -    {
> -      /* Switch to the main UI, so that gdb_std{in/out/err} in the
> -	 child are mapped to std{in/out/err}.  This makes it possible
> -	 to use fprintf_unfiltered/warning/error/etc. in the child
> -	 from here on.  */
> -      current_ui = main_ui;
> -
> -      /* Close all file descriptors except those that gdb inherited
> -	 (usually 0/1/2), so they don't leak to the inferior.  Note
> -	 that this closes the file descriptors of all secondary
> -	 UIs.  */
> -      close_most_fds ();
> -
> -      if (debug_fork)
> -	sleep (debug_fork);
> -
> -      /* Create a new session for the inferior process, if necessary.
> -         It will also place the inferior in a separate process group.  */
> -      if (create_tty_session () <= 0)
> -	{
> -	  /* No session was created, but we still want to run the inferior
> -	     in a separate process group.  */
> -	  debug_setpgrp = gdb_setpgid ();
> -	  if (debug_setpgrp == -1)
> -	    perror (_("setpgrp failed in child"));
> -	}
> -
> -      /* Ask the tty subsystem to switch to the one we specified
> -         earlier (or to share the current terminal, if none was
> -         specified).  */
> -      new_tty ();
> -
> -      /* Changing the signal handlers for the inferior after
> -         a vfork can also change them for the superior, so we don't mess
> -         with signals here.  See comments in
> -         initialize_signals for how we get the right signal handlers
> -         for the inferior.  */
> -
> -      /* "Trace me, Dr. Memory!"  */
> -      (*traceme_fun) ();
> -
> -      /* The call above set this process (the "child") as debuggable
> -        by the original gdb process (the "parent").  Since processes
> -        (unlike people) can have only one parent, if you are debugging
> -        gdb itself (and your debugger is thus _already_ the
> -        controller/parent for this child), code from here on out is
> -        undebuggable.  Indeed, you probably got an error message
> -        saying "not parent".  Sorry; you'll have to use print
> -        statements!  */
> -
> -      restore_original_signals_state ();
> -
> -      /* There is no execlpe call, so we have to set the environment
> -         for our child in the global variable.  If we've vforked, this
> -         clobbers the parent, but environ is restored a few lines down
> -         in the parent.  By the way, yes we do need to look down the
> -         path to find $SHELL.  Rich Pixley says so, and I agree.  */
> -      environ = env;
> -
> -      if (exec_fun != NULL)
> -        (*exec_fun) (argv[0], argv, env);
> -      else
> -        execvp (argv[0], argv);
> -
> -      /* If we get here, it's an error.  */
> -      save_errno = errno;
> -      fprintf_unfiltered (gdb_stderr, "Cannot exec %s", argv[0]);
> -      for (i = 1; argv[i] != NULL; i++)
> -	fprintf_unfiltered (gdb_stderr, " %s", argv[i]);
> -      fprintf_unfiltered (gdb_stderr, ".\n");
> -      fprintf_unfiltered (gdb_stderr, "Error: %s\n",
> -			  safe_strerror (save_errno));
> -      gdb_flush (gdb_stderr);
> -      _exit (0177);
> -    }
> -
> -  /* Restore our environment in case a vforked child clob'd it.  */
> -  environ = save_our_env;
> -
> -  /* Likewise the current UI.  */
> -  current_ui = save_ui;
> -
> -  if (!have_inferiors ())
> -    init_thread_list ();
> -
> -  inf = current_inferior ();
> -
> -  inferior_appeared (inf, pid);
> -
> -  /* Needed for wait_for_inferior stuff below.  */
> -  inferior_ptid = pid_to_ptid (pid);
> -
> -  new_tty_postfork ();
> -
> -  /* We have something that executes now.  We'll be running through
> -     the shell at this point, but the pid shouldn't change.  Targets
> -     supporting MT should fill this task's ptid with more data as soon
> -     as they can.  */
> -  add_thread_silent (inferior_ptid);
> -
> -  /* Now that we have a child process, make it our target, and
> -     initialize anything target-vector-specific that needs
> -     initializing.  */
> -  if (init_trace_fun)
> -    (*init_trace_fun) (pid);
> -
> -  /* We are now in the child process of interest, having exec'd the
> -     correct program, and are poised at the first instruction of the
> -     new program.  */
> -  return pid;
> -}
> -
> -/* Accept NTRAPS traps from the inferior.  */
> -
> -void
> -startup_inferior (int ntraps)
> -{
> -  int pending_execs = ntraps;
> -  int terminal_initted = 0;
> -  ptid_t resume_ptid;
> -
> -  if (startup_with_shell)
> -    {
> -      /* One trap extra for exec'ing the shell.  */
> -      pending_execs++;
> -    }
> -
> -  if (target_supports_multi_process ())
> -    resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
> -  else
> -    resume_ptid = minus_one_ptid;
> -
> -  /* The process was started by the fork that created it, but it will
> -     have stopped one instruction after execing the shell.  Here we
> -     must get it up to actual execution of the real program.  */
> -
> -  if (exec_wrapper)
> -    pending_execs++;
> -
> -  while (1)
> -    {
> -      enum gdb_signal resume_signal = GDB_SIGNAL_0;
> -      ptid_t event_ptid;
> -
> -      struct target_waitstatus ws;
> -      memset (&ws, 0, sizeof (ws));
> -      event_ptid = target_wait (resume_ptid, &ws, 0);
> -
> -      if (ws.kind == TARGET_WAITKIND_IGNORE)
> -	/* The inferior didn't really stop, keep waiting.  */
> -	continue;
> -
> -      switch (ws.kind)
> -	{
> -	  case TARGET_WAITKIND_SPURIOUS:
> -	  case TARGET_WAITKIND_LOADED:
> -	  case TARGET_WAITKIND_FORKED:
> -	  case TARGET_WAITKIND_VFORKED:
> -	  case TARGET_WAITKIND_SYSCALL_ENTRY:
> -	  case TARGET_WAITKIND_SYSCALL_RETURN:
> -	    /* Ignore gracefully during startup of the inferior.  */
> -	    switch_to_thread (event_ptid);
> -	    break;
> -
> -	  case TARGET_WAITKIND_SIGNALLED:
> -	    target_terminal_ours ();
> -	    target_mourn_inferior (event_ptid);
> -	    error (_("During startup program terminated with signal %s, %s."),
> -		   gdb_signal_to_name (ws.value.sig),
> -		   gdb_signal_to_string (ws.value.sig));
> -	    return;
> -
> -	  case TARGET_WAITKIND_EXITED:
> -	    target_terminal_ours ();
> -	    target_mourn_inferior (event_ptid);
> -	    if (ws.value.integer)
> -	      error (_("During startup program exited with code %d."),
> -		     ws.value.integer);
> -	    else
> -	      error (_("During startup program exited normally."));
> -	    return;
> -
> -	  case TARGET_WAITKIND_EXECD:
> -	    /* Handle EXEC signals as if they were SIGTRAP signals.  */
> -	    xfree (ws.value.execd_pathname);
> -	    resume_signal = GDB_SIGNAL_TRAP;
> -	    switch_to_thread (event_ptid);
> -	    break;
> -
> -	  case TARGET_WAITKIND_STOPPED:
> -	    resume_signal = ws.value.sig;
> -	    switch_to_thread (event_ptid);
> -	    break;
> -	}
> -
> -      if (resume_signal != GDB_SIGNAL_TRAP)
> -	{
> -	  /* Let shell child handle its own signals in its own way.  */
> -	  target_continue (resume_ptid, resume_signal);
> -	}
> -      else
> -	{
> -	  /* We handle SIGTRAP, however; it means child did an exec.  */
> -	  if (!terminal_initted)
> -	    {
> -	      /* Now that the child has exec'd we know it has already
> -	         set its process group.  On POSIX systems, tcsetpgrp
> -	         will fail with EPERM if we try it before the child's
> -	         setpgid.  */
> -
> -	      /* Set up the "saved terminal modes" of the inferior
> -	         based on what modes we are starting it with.  */
> -	      target_terminal_init ();
> -
> -	      /* Install inferior's terminal modes.  */
> -	      target_terminal_inferior ();
> -
> -	      terminal_initted = 1;
> -	    }
> -
> -	  if (--pending_execs == 0)
> -	    break;
> -
> -	  /* Just make it go on.  */
> -	  target_continue_no_signal (resume_ptid);
> -	}
> -    }
> -
> -  /* Mark all threads non-executing.  */
> -  set_executing (resume_ptid, 0, NULL);
> +  return exec_wrapper;
>  }
>
>  /* Implement the "unset exec-wrapper" command.  */
> @@ -586,7 +74,9 @@ Show the wrapper for running programs."), NULL,
>
>    add_setshow_boolean_cmd ("startup-with-shell", class_support,
>  			   &startup_with_shell, _("\
> -Set use of shell to start subprocesses.  The default is on."), _("\
> +Set use of shell to start subprocesses.  The default is on.\n\
> +This is also used to determine whether gdbserver will start the remote\n\
> +inferior using the shell."), _("\
>  Show use of shell to start subprocesses."), NULL,
>  			   NULL,
>  			   show_startup_with_shell,
> diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
> index 2add910..2ddcfd6 100644
> --- a/gdb/gdbserver/Makefile.in
> +++ b/gdb/gdbserver/Makefile.in
> @@ -185,6 +185,7 @@ SFILES = \
>  	$(srcdir)/target.c \
>  	$(srcdir)/thread-db.c \
>  	$(srcdir)/utils.c \
> +	$(srcdir)/terminal.c \
>  	$(srcdir)/win32-arm-low.c \
>  	$(srcdir)/win32-i386-low.c \
>  	$(srcdir)/win32-low.c \
> @@ -204,6 +205,7 @@ SFILES = \
>  	$(srcdir)/common/environ.c \
>  	$(srcdir)/common/fileio.c \
>  	$(srcdir)/common/filestuff.c \
> +	$(srcdir)/common/common-fork-child.c \
>  	$(srcdir)/common/common-inflow.c \
>  	$(srcdir)/common/gdb_vecs.c \
>  	$(srcdir)/common/new-op.c \
> @@ -235,6 +237,7 @@ OBS = \
>  	cleanups.o \
>  	common-debug.o \
>  	common-exceptions.o \
> +	common-fork-child.o \
>  	common-inflow.o \
>  	common-regcache.o \
>  	common-utils.o \
> @@ -269,6 +272,7 @@ OBS = \
>  	version.o \
>  	waitstatus.o \
>  	xml-utils.o \
> +	terminal.o \
>  	$(DEPFILES) \
>  	$(LIBOBJS) \
>  	$(XML_BUILTIN)
> @@ -772,6 +776,9 @@ format.o: ../common/format.c
>  filestuff.o: ../common/filestuff.c
>  	$(COMPILE) $<
>  	$(POSTCOMPILE)
> +common-fork-child.o: ../common/common-fork-child.c
> +	$(COMPILE) $<
> +	$(POSTCOMPILE)
>  common-inflow.o: ../common/common-inflow.c
>  	$(COMPILE) $<
>  	$(POSTCOMPILE)
> diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
> index 6b981d0..5f65e99 100644
> --- a/gdb/gdbserver/inferiors.c
> +++ b/gdb/gdbserver/inferiors.c
> @@ -29,6 +29,8 @@ struct thread_info *current_thread;
>
>  #define get_thread(inf) ((struct thread_info *)(inf))
>
> +ptid_t inferior_ptid;
> +
>  void
>  add_inferior_to_list (struct inferior_list *list,
>  		      struct inferior_list_entry *new_inferior)
> @@ -469,6 +471,23 @@ make_cleanup_restore_current_thread (void)
>    return make_cleanup (do_restore_current_thread_cleanup, current_thread);
>  }
>
> +/* See common/common-inferior.h.  */
> +
> +void
> +inferior_appeared (struct inferior *inf, int pid)
> +{
> +  /* To be implemented.  */
> +}
> +
> +/* See common/common-inferior.h.  */
> +
> +struct inferior *
> +current_inferior (void)
> +{
> +  /* To be implemented.  */
> +  return NULL;
> +}
> +
>  /* See common/common-gdbthread.h.  */
>
>  void
> @@ -510,3 +529,11 @@ add_thread_silent (ptid_t ptid)
>
>    return add_thread (ptid_build (pid, pid, 0), NULL);
>  }
> +
> +/* See common/common-inferior.h.  */
> +
> +int
> +have_inferiors (void)
> +{
> +  return get_first_process () != NULL;
> +}
> diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
> index e3e372c..ea35796 100644
> --- a/gdb/gdbserver/linux-low.c
> +++ b/gdb/gdbserver/linux-low.c
> @@ -47,6 +47,8 @@
>  #include "tracepoint.h"
>  #include "hostio.h"
>  #include <inttypes.h>
> +#include "common-inferior.h"
> +#include "environ.h"
>  #ifndef ELFMAG0
>  /* Don't include <linux/elf.h> here.  If it got included by gdb_proc_service.h
>     then ELFMAG0 will have been defined.  If it didn't get included by
> @@ -415,15 +417,14 @@ delete_lwp (struct lwp_info *lwp)
>    free (lwp);
>  }
>
> -/* Add a process to the common process list, and set its private
> -   data.  */
> +/* Update process represented by PID with necessary info.  */
>
>  static struct process_info *
> -linux_add_process (int pid, int attached)
> +linux_update_process (int pid)
>  {
> -  struct process_info *proc;
> +  struct process_info *proc = find_process_pid (pid);
>
> -  proc = add_process (pid, attached);
> +  gdb_assert (proc != NULL);
>    proc->priv = XCNEW (struct process_info_private);
>
>    if (the_low_target.new_process != NULL)
> @@ -432,6 +433,16 @@ linux_add_process (int pid, int attached)
>    return proc;
>  }
>
> +/* Add a process to the common process list, and set its private
> +   data.  */
> +
> +static struct process_info *
> +linux_add_process (int pid, int attached)
> +{
> +  add_process (pid, attached);
> +  return linux_update_process (pid);
> +}
> +
>  static CORE_ADDR get_pc (struct lwp_info *lwp);
>
>  /* Call the target arch_setup function on the current thread.  */
> @@ -929,6 +940,29 @@ save_stop_reason (struct lwp_info *lwp)
>    return 1;
>  }
>
> +/* Update the lwp associated to thread represented by PTID.  */
> +
> +static struct lwp_info *
> +update_thread_lwp (ptid_t ptid)
> +{
> +  struct lwp_info *lwp;
> +  struct thread_info *thread;
> +
> +  lwp = XCNEW (struct lwp_info);
> +
> +  lwp->waitstatus.kind = TARGET_WAITKIND_IGNORE;
> +
> +  if (the_low_target.new_thread != NULL)
> +    the_low_target.new_thread (lwp);
> +
> +  thread = find_thread_ptid (ptid);
> +  gdb_assert (thread != NULL);
> +  thread->target_data = lwp;
> +  lwp->thread = thread;
> +
> +  return lwp;
> +}
> +
>  static struct lwp_info *
>  add_lwp (ptid_t ptid)
>  {
> @@ -946,68 +980,62 @@ add_lwp (ptid_t ptid)
>    return lwp;
>  }
>
> +/* Callback to be used when calling fork_inferior, responsible for
> +   actually initiating the tracing of the inferior.  */
> +
> +static void
> +linux_ptrace_fun (void)
> +{
> +  ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
> +
> +  setpgid (0, 0);
> +
> +  /* If gdbserver is connected to gdb via stdio, redirect the inferior's
> +     stdout to stderr so that inferior i/o doesn't corrupt the connection.
> +     Also, redirect stdin to /dev/null.  */
> +  if (remote_connection_is_stdio ())
> +    {
> +      close (0);
> +      open ("/dev/null", O_RDONLY);
> +      dup2 (2, 1);
> +      if (write (2, "stdin/stdout redirected\n",
> +		 sizeof ("stdin/stdout redirected\n") - 1) < 0)
> +	{
> +	  /* Errors ignored.  */;
> +	}
> +    }
> +}
> +
>  /* Start an inferior process and returns its pid.
>     ALLARGS is a vector of program-name and args. */
>
>  static int
> -linux_create_inferior (char *program, char **allargs)
> +linux_create_inferior (std::vector<char *> &program_argv)
>  {
>    struct lwp_info *new_lwp;
>    int pid;
>    ptid_t ptid;
>    struct cleanup *restore_personality
>      = maybe_disable_address_space_randomization (disable_randomization);
> +  std::string program_args = stringify_argv (program_argv);
>
> -#if defined(__UCLIBC__) && defined(HAS_NOMMU)
> -  pid = vfork ();
> -#else
> -  pid = fork ();
> -#endif
> -  if (pid < 0)
> -    perror_with_name ("fork");
> +  pre_fork_inferior (program_argv);
>
> -  if (pid == 0)
> -    {
> -      close_most_fds ();
> -      ptrace (PTRACE_TRACEME, 0, (PTRACE_TYPE_ARG3) 0, (PTRACE_TYPE_ARG4) 0);
> -
> -      setpgid (0, 0);
> -
> -      /* If gdbserver is connected to gdb via stdio, redirect the inferior's
> -	 stdout to stderr so that inferior i/o doesn't corrupt the connection.
> -	 Also, redirect stdin to /dev/null.  */
> -      if (remote_connection_is_stdio ())
> -	{
> -	  close (0);
> -	  open ("/dev/null", O_RDONLY);
> -	  dup2 (2, 1);
> -	  if (write (2, "stdin/stdout redirected\n",
> -		     sizeof ("stdin/stdout redirected\n") - 1) < 0)
> -	    {
> -	      /* Errors ignored.  */;
> -	    }
> -	}
> -
> -      restore_original_signals_state ();
> -
> -      execv (program, allargs);
> -      if (errno == ENOENT)
> -	execvp (program, allargs);
> -
> -      fprintf (stderr, "Cannot exec %s: %s.\n", program,
> -	       strerror (errno));
> -      fflush (stderr);
> -      _exit (0177);
> -    }
> +  pid = fork_inferior (program_argv[0],
> +		       (char *) program_args.c_str (),
> +		       environ_vector (get_environ ()), linux_ptrace_fun,
> +		       NULL, NULL, startup_shell, NULL);
>
>    do_cleanups (restore_personality);
>
> -  linux_add_process (pid, 0);
> +  linux_update_process (pid);
>
>    ptid = ptid_build (pid, pid, 0);
> -  new_lwp = add_lwp (ptid);
> +  new_lwp = update_thread_lwp (ptid);
>    new_lwp->must_set_ptrace_flags = 1;
>
> +  post_fork_inferior (pid, program_argv);
> +
>    return pid;
>  }
>
> diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
> index 28a9757..1abf8e3 100644
> --- a/gdb/gdbserver/lynx-low.c
> +++ b/gdb/gdbserver/lynx-low.c
> @@ -208,15 +208,15 @@ lynx_ptrace (int request, ptid_t ptid, int addr, int data, int addr2)
>    return result;
>  }
>
> -/* Call add_process with the given parameters, and initializes
> -   the process' private data.  */
> +/* Update existing process represented by PID with necessary info.  */
>
>  static struct process_info *
> -lynx_add_process (int pid, int attached)
> +lynx_update_process (int pid)
>  {
> -  struct process_info *proc;
> +  struct process_info *proc = find_process_pid (pid);
> +
> +  gdb_assert (proc != NULL);
>
> -  proc = add_process (pid, attached);
>    proc->tdesc = lynx_tdesc;
>    proc->priv = XCNEW (struct process_info_private);
>    proc->priv->last_wait_event_ptid = null_ptid;
> @@ -224,41 +224,53 @@ lynx_add_process (int pid, int attached)
>    return proc;
>  }
>
> +/* Call add_process with the given parameters, and initializes
> +   the process' private data.  */
> +
> +static struct process_info *
> +lynx_add_process (int pid, int attached)
> +{
> +  add_process (pid, attached);
> +  return lynx_update_process (pid);
> +}
> +
> +static void
> +lynx_ptrace_fun (void)
> +{
> +  int pgrp;
> +
> +  /* Switch child to its own process group so that signals won't
> +     directly affect gdbserver. */
> +  pgrp = getpid();
> +  setpgid (0, pgrp);
> +  ioctl (0, TIOCSPGRP, &pgrp);
> +  lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0);
> +}
> +
>  /* Implement the create_inferior method of the target_ops vector.  */
>
>  static int
> -lynx_create_inferior (char *program, char **allargs)
> +lynx_create_inferior (std::vector<char *> &program_argv)
>  {
>    int pid;
>
>    lynx_debug ("lynx_create_inferior ()");
>
> -  pid = fork ();
> -  if (pid < 0)
> -    perror_with_name ("fork");
> +  pre_fork_inferior (program_argv);
>
> -  if (pid == 0)
> -    {
> -      int pgrp;
> -
> -      close_most_fds ();
> -
> -      /* Switch child to its own process group so that signals won't
> -         directly affect gdbserver. */
> -      pgrp = getpid();
> -      setpgid (0, pgrp);
> -      ioctl (0, TIOCSPGRP, &pgrp);
> -      lynx_ptrace (PTRACE_TRACEME, null_ptid, 0, 0, 0);
> -      execv (program, allargs);
> -      fprintf (stderr, "Cannot exec %s: %s.\n", program, strerror (errno));
> -      fflush (stderr);
> -      _exit (0177);
> -    }
> +  pid = fork_inferior (program_argv[0],
> +		       (char *) program_args.c_str (),
> +		       environ_vector (get_environ ()), lynx_ptrace_fun,
> +		       NULL, NULL, startup_shell, NULL);
>
> -  lynx_add_process (pid, 0);
> +  post_fork_inferior (pid, program_argv);
> +
> +  lynx_update_process (pid, 0);
>    /* Do not add the process thread just yet, as we do not know its tid.
>       We will add it later, during the wait for the STOP event corresponding
>       to the lynx_ptrace (PTRACE_TRACEME) call above.  */
> +  remove_thread (find_thread_ptid (ptid_build (pid, pid, 0)));
> +
>    return pid;
>  }
>
> diff --git a/gdb/gdbserver/nto-low.c b/gdb/gdbserver/nto-low.c
> index ce3b8e4..17d3dc9 100644
> --- a/gdb/gdbserver/nto-low.c
> +++ b/gdb/gdbserver/nto-low.c
> @@ -347,16 +347,17 @@ nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack,
>    return len_read;
>  }
>
> -/* Start inferior specified by PROGRAM passing arguments ALLARGS.  */
> +/* Start inferior specified by PROGRAM_ARGV.  */
>
>  static int
> -nto_create_inferior (char *program, char **allargs)
> +nto_create_inferior (std::vector<char *> &program_argv)
>  {
>    struct inheritance inherit;
>    pid_t pid;
>    sigset_t set;
> +  std::string program_args = stringify_argv (program_argv);
>
> -  TRACE ("%s %s\n", __func__, program);
> +  TRACE ("%s %s\n", __func__, program_argv[0]);
>    /* Clear any pending SIGUSR1's but keep the behavior the same.  */
>    signal (SIGUSR1, signal (SIGUSR1, SIG_IGN));
>
> @@ -367,7 +368,7 @@ nto_create_inferior (char *program, char **allargs)
>    memset (&inherit, 0, sizeof (inherit));
>    inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD;
>    inherit.pgroup = SPAWN_NEWPGROUP;
> -  pid = spawnp (program, 0, NULL, &inherit, allargs, 0);
> +  pid = spawnp (program, 0, NULL, &inherit, (char *) program_args.c_str (), 0);
>    sigprocmask (SIG_BLOCK, &set, NULL);
>
>    if (pid == -1)
> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
> index ef8dd03..55eebd9 100644
> --- a/gdb/gdbserver/server.c
> +++ b/gdb/gdbserver/server.c
> @@ -35,6 +35,31 @@
>  #include "tracepoint.h"
>  #include "dll.h"
>  #include "hostio.h"
> +#include "common-inferior.h"
> +#include "common-terminal.h"
> +#include "common-top.h"
> +#include "environ.h"
> +
> +/* We don't have a concept of a UI yet.  Therefore, we just set these
> +   to NULL.  */
> +
> +struct ui *main_ui = NULL;
> +struct ui *current_ui = NULL;
> +
> +/* The environment to pass to the inferior when creating it.  */
> +
> +struct gdb_environ *our_environ = NULL;
> +
> +/* Start the inferior using a shell.  */
> +
> +/* We always try to start the inferior using a shell.  */
> +
> +int startup_with_shell = 1;
> +
> +/* The shell that will be used to start the inferior will be
> +   determined later.  */
> +
> +char *startup_shell = NULL;
>
>  /* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
>     `vCont'.  Note the multi-process extensions made `vCont' a
> @@ -78,7 +103,8 @@ static int vCont_supported;
>     space randomization feature before starting an inferior.  */
>  int disable_randomization = 1;
>
> -static char **program_argv, **wrapper_argv;
> +static std::vector<char *> program_argv;
> +static std::vector<char *> wrapper_argv;
>
>  int pass_signals[GDB_SIGNAL_LAST];
>  int program_signals[GDB_SIGNAL_LAST];
> @@ -236,33 +262,64 @@ target_running (void)
>    return get_first_thread () != NULL;
>  }
>
> -static int
> -start_inferior (char **argv)
> +/* See common/common-inferior.h.  */
> +
> +char *
> +get_exec_wrapper (void)
>  {
> -  char **new_argv = argv;
> +  static std::string ret;
> +  static int initialized_p = 0;
> +
> +  if (wrapper_argv.empty ())
> +    return NULL;
>
> -  if (wrapper_argv != NULL)
> +  if (!initialized_p)
>      {
> -      int i, count = 1;
> -
> -      for (i = 0; wrapper_argv[i] != NULL; i++)
> -	count++;
> -      for (i = 0; argv[i] != NULL; i++)
> -	count++;
> -      new_argv = XALLOCAVEC (char *, count);
> -      count = 0;
> -      for (i = 0; wrapper_argv[i] != NULL; i++)
> -	new_argv[count++] = wrapper_argv[i];
> -      for (i = 0; argv[i] != NULL; i++)
> -	new_argv[count++] = argv[i];
> -      new_argv[count] = NULL;
> +      for (std::vector<char *>::iterator i = wrapper_argv.begin ();
> +	   i != wrapper_argv.end ();
> +	   ++i)
> +	ret += *i + std::string (" ");
> +
> +      /* Erasing the last whitespace.  */
> +      ret.erase (ret.end () - 1);
> +
> +      initialized_p = 1;
>      }
>
> +  return (char *) ret.c_str ();
> +}
> +
> +/* See common/common-inferior.h.  */
> +
> +char *
> +get_exec_file (int err)
> +{
> +  if (err && program_argv.empty ())
> +    error (_("Could not get the exec file."));
> +  return program_argv[0];
> +}
> +
> +/* See server.h.  */
> +
> +struct gdb_environ *
> +get_environ (void)
> +{
> +  return our_environ;
> +}
> +
> +/* See server.h.  */
> +
> +void
> +pre_fork_inferior (std::vector<char *> &argv)
> +{
>    if (debug_threads)
>      {
> -      int i;
> -      for (i = 0; new_argv[i]; ++i)
> -	debug_printf ("new_argv[%d] = \"%s\"\n", i, new_argv[i]);
> +      int idx = 0;
> +
> +      for (std::vector<char *>::iterator i = argv.begin ();
> +	   i != argv.end ();
> +	   ++i, ++idx)
> +	debug_printf ("new_argv[%d] = \"%s\"\n", idx, *i);
>        debug_flush ();
>      }
>
> @@ -271,67 +328,35 @@ start_inferior (char **argv)
>    signal (SIGTTIN, SIG_DFL);
>  #endif
>
> -  signal_pid = create_inferior (new_argv[0], new_argv);
> +  /* Clear this so the backend doesn't get confused, thinking
> +     CONT_THREAD died, and it needs to resume all threads.  */
> +  cont_thread = null_ptid;
> +}
>
> -  /* FIXME: we don't actually know at this point that the create
> -     actually succeeded.  We won't know that until we wait.  */
> -  fprintf (stderr, "Process %s created; pid = %ld\n", argv[0],
> -	   signal_pid);
> -  fflush (stderr);
> +/* See server.h.  */
> +
> +void
> +post_fork_inferior (int pid,
> +		    std::vector<char *> &argv)
> +{
> +  /* Number of traps to be expected by startup_inferior.  We always
> +     expect at least one trap for the main executable.  */
> +  int num_traps = START_INFERIOR_TRAPS_EXPECTED;
>
>  #ifdef SIGTTOU
>    signal (SIGTTOU, SIG_IGN);
>    signal (SIGTTIN, SIG_IGN);
>    terminal_fd = fileno (stderr);
>    old_foreground_pgrp = tcgetpgrp (terminal_fd);
> -  tcsetpgrp (terminal_fd, signal_pid);
> +  tcsetpgrp (terminal_fd, pid);
>    atexit (restore_old_foreground_pgrp);
>  #endif
>
> -  if (wrapper_argv != NULL)
> -    {
> -      ptid_t ptid = pid_to_ptid (signal_pid);
> -
> -      last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
> -
> -      if (last_status.kind == TARGET_WAITKIND_STOPPED)
> -	{
> -	  do
> -	    {
> -	      target_continue_no_signal (ptid);
> -
> -	      last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
> -	      if (last_status.kind != TARGET_WAITKIND_STOPPED)
> -		break;
> -
> -	      current_thread->last_resume_kind = resume_stop;
> -	      current_thread->last_status = last_status;
> -	    }
> -	  while (last_status.value.sig != GDB_SIGNAL_TRAP);
> -	}
> -      target_post_create_inferior ();
> -      return signal_pid;
> -    }
> -
> -  /* Wait till we are at 1st instruction in program, return new pid
> -     (assuming success).  */
> -  last_ptid = mywait (pid_to_ptid (signal_pid), &last_status, 0, 0);
> -
> -  /* At this point, the target process, if it exits, is stopped.  Do not call
> -     the function target_post_create_inferior if the process has already
> -     exited, as the target implementation of the routine may rely on the
> -     process being live. */
> -  if (last_status.kind != TARGET_WAITKIND_EXITED
> -      && last_status.kind != TARGET_WAITKIND_SIGNALLED)
> -    {
> -      target_post_create_inferior ();
> -      current_thread->last_resume_kind = resume_stop;
> -      current_thread->last_status = last_status;
> -    }
> -  else
> -    target_mourn_inferior (last_ptid);
> -
> -  return signal_pid;
> +  startup_inferior (num_traps, &last_status, &last_ptid);
> +  signal_pid = pid;
> +  target_post_create_inferior ();
> +  fprintf (stderr, "Process %s created; pid = %d\n", argv[0], pid);
> +  fflush (stderr);
>  }
>
>  static int
> @@ -2852,8 +2877,10 @@ handle_v_attach (char *own_buf)
>  static int
>  handle_v_run (char *own_buf)
>  {
> -  char *p, *next_p, **new_argv;
> -  int i, new_argc;
> +  char *p, *next_p;
> +  std::vector<char *> new_argv;
> +  int new_argc;
> +  int i;
>
>    new_argc = 0;
>    for (p = own_buf + strlen ("vRun;"); p && *p; p = strchr (p, ';'))
> @@ -2862,62 +2889,91 @@ handle_v_run (char *own_buf)
>        new_argc++;
>      }
>
> -  new_argv = (char **) calloc (new_argc + 2, sizeof (char *));
> -  if (new_argv == NULL)
> -    {
> -      write_enn (own_buf);
> -      return 0;
> -    }
> -
> -  i = 0;
> -  for (p = own_buf + strlen ("vRun;"); *p; p = next_p)
> +  for (i = 0, p = own_buf + strlen ("vRun;"); *p; p = next_p, ++i)
>      {
>        next_p = strchr (p, ';');
>        if (next_p == NULL)
>  	next_p = p + strlen (p);
>
> -      if (i == 0 && p == next_p)
> -	new_argv[i] = NULL;
> +      if (p == next_p)
> +	new_argv.push_back ("''");
>        else
>  	{
>  	  /* FIXME: Fail request if out of memory instead of dying.  */
> -	  new_argv[i] = (char *) xmalloc (1 + (next_p - p) / 2);
> -	  hex2bin (p, (gdb_byte *) new_argv[i], (next_p - p) / 2);
> -	  new_argv[i][(next_p - p) / 2] = '\0';
> +	  size_t len = 1 + (next_p - p) / 2;
> +	  char *s = (char *) xmalloc (len);
> +	  char *ss = (char *) xmalloc (len * 2);
> +	  char *tmp_s, *tmp_ss;
> +	  int need_quote;
> +
> +	  hex2bin (p, (gdb_byte *) s, (next_p - p) / 2);
> +	  s[(next_p - p) / 2] = '\0';
> +
> +	  tmp_s = s;
> +	  tmp_ss = ss;
> +	  need_quote = 0;
> +	  while (*tmp_s != '\0')
> +	    {
> +	      switch (*tmp_s)
> +		{
> +		case '\n':
> +		  *tmp_ss = '\'';
> +		  ++tmp_ss;
> +		  need_quote = 1;
> +		  break;
> +
> +		case '\'':
> +		  *tmp_ss = '\\';
> +		  ++tmp_ss;
> +		  break;
> +
> +		default:
> +		  break;
> +		}
> +
> +	      *tmp_ss = *tmp_s;
> +	      ++tmp_ss;
> +	      ++tmp_s;
> +	    }
> +
> +	  if (need_quote)
> +	    *tmp_ss++ = '\'';
> +
> +	  *tmp_ss = '\0';
> +	  new_argv.push_back (ss);
> +	  xfree (s);
>  	}
>
>        if (*next_p)
>  	next_p++;
> -      i++;
>      }
> -  new_argv[i] = NULL;
>
> -  if (new_argv[0] == NULL)
> +  if (new_argv.empty () || new_argv[0] == NULL)
>      {
>        /* GDB didn't specify a program to run.  Use the program from the
>  	 last run with the new argument list.  */
>
> -      if (program_argv == NULL)
> +      if (program_argv.empty ())
>  	{
>  	  write_enn (own_buf);
> -	  freeargv (new_argv);
> +	  free_vector_argv (new_argv);
>  	  return 0;
>  	}
>
> -      new_argv[0] = strdup (program_argv[0]);
> -      if (new_argv[0] == NULL)
> +      new_argv.push_back (strdup (program_argv[0]));
> +      if (new_argv.empty () || new_argv[0] == NULL)
>  	{
>  	  write_enn (own_buf);
> -	  freeargv (new_argv);
> +	  free_vector_argv (new_argv);
>  	  return 0;
>  	}
>      }
>
>    /* Free the old argv and install the new one.  */
> -  freeargv (program_argv);
> +  free_vector_argv (program_argv);
>    program_argv = new_argv;
>
> -  start_inferior (program_argv);
> +  create_inferior (program_argv);
>    if (last_status.kind == TARGET_WAITKIND_STOPPED)
>      {
>        prepare_resume_reply (own_buf, last_ptid, &last_status);
> @@ -3535,13 +3591,18 @@ captured_main (int argc, char *argv[])
>  	multi_mode = 1;
>        else if (strcmp (*next_arg, "--wrapper") == 0)
>  	{
> +	  char **tmp;
> +
>  	  next_arg++;
>
> -	  wrapper_argv = next_arg;
> +	  tmp = next_arg;
>  	  while (*next_arg != NULL && strcmp (*next_arg, "--") != 0)
> -	    next_arg++;
> +	    {
> +	      wrapper_argv.push_back (*next_arg);
> +	      next_arg++;
> +	    }
>
> -	  if (next_arg == wrapper_argv || *next_arg == NULL)
> +	  if (next_arg == tmp || *next_arg == NULL)
>  	    {
>  	      gdbserver_usage (stderr);
>  	      exit (1);
> @@ -3672,8 +3733,14 @@ captured_main (int argc, char *argv[])
>        exit (1);
>      }
>
> +  /* Gather information about the environment.  */
> +  our_environ = make_environ ();
> +  init_environ (our_environ);
> +
>    initialize_async_io ();
>    initialize_low ();
> +  /* This is called when initializing inflow on GDB.  */
> +  have_job_control ();
>    initialize_event_loop ();
>    if (target_supports_tracepoints ())
>      initialize_tracepoint ();
> @@ -3687,13 +3754,11 @@ captured_main (int argc, char *argv[])
>        int i, n;
>
>        n = argc - (next_arg - argv);
> -      program_argv = XNEWVEC (char *, n + 1);
>        for (i = 0; i < n; i++)
> -	program_argv[i] = xstrdup (next_arg[i]);
> -      program_argv[i] = NULL;
> +	program_argv.push_back (xstrdup (next_arg[i]));
>
>        /* Wait till we are at first instruction in program.  */
> -      start_inferior (program_argv);
> +      create_inferior (program_argv);
>
>        /* We are now (hopefully) stopped at the first instruction of
>  	 the target process.  This assumes that the target process was
> @@ -4308,9 +4373,9 @@ process_serial_event (void)
>  	  fprintf (stderr, "GDBserver restarting\n");
>
>  	  /* Wait till we are at 1st instruction in prog.  */
> -	  if (program_argv != NULL)
> +	  if (!program_argv.empty ())
>  	    {
> -	      start_inferior (program_argv);
> +	      create_inferior (program_argv);
>  	      if (last_status.kind == TARGET_WAITKIND_STOPPED)
>  		{
>  		  /* Stopped at the first instruction of the target
> diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
> index f56c0f5..6b3d668 100644
> --- a/gdb/gdbserver/server.h
> +++ b/gdb/gdbserver/server.h
> @@ -103,6 +103,8 @@ extern int swbreak_feature;
>     Only enabled if the target supports it.  */
>  extern int hwbreak_feature;
>
> +extern char *startup_shell;
> +
>  extern int disable_randomization;
>
>  #if USE_WIN32API
> @@ -132,6 +134,7 @@ extern int in_queued_stop_replies (ptid_t ptid);
>  #include "utils.h"
>  #include "debug.h"
>  #include "gdb_vecs.h"
> +#include <vector>
>
>  /* Maximum number of bytes to read/write at once.  The value here
>     is chosen to fill up a packet (the headers account for the 32).  */
> @@ -148,4 +151,20 @@ extern int in_queued_stop_replies (ptid_t ptid);
>  /* Definition for any syscall, used for unfiltered syscall reporting.  */
>  #define ANY_SYSCALL (-2)
>
> +/* Any pre-processing needed to be done before calling fork_inferior
> +   shall be implemented here.  ARGV is a vector containing the full
> +   argv of the inferior.  */
> +
> +extern void pre_fork_inferior (std::vector<char *> &argv);
> +
> +/* After fork_inferior has been called, we need to adjust a few
> +   signals and call startup_inferior.  This is done here.  PID is the
> +   pid of the new inferior, and ARGV is the vector containing the full
> +   argv of the inferior.  */
> +
> +extern void post_fork_inferior (int pid,
> +				std::vector<char *> &argv);
> +
> +extern struct gdb_environ *get_environ (void);
> +
>  #endif /* SERVER_H */
> diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
> index 32e7c72..ccf736f 100644
> --- a/gdb/gdbserver/spu-low.c
> +++ b/gdb/gdbserver/spu-low.c
> @@ -261,42 +261,39 @@ spu_proc_xfer_spu (const char *annex, unsigned char *readbuf,
>    return ret;
>  }
>
> +/* Callback to be used when calling fork_inferior, responsible for
> +   actually initiating the tracing of the inferior.  */
> +
> +static void
> +spu_ptrace_fun (void)
> +{
> +  ptrace (PTRACE_TRACEME, 0, 0, 0);
> +  setpgid (0, 0);
> +}
>
>  /* Start an inferior process and returns its pid.
> -   ALLARGS is a vector of program-name and args. */
> +   PROGRAM_ARGV is a vector of program-name and args. */
>  static int
> -spu_create_inferior (char *program, char **allargs)
> +spu_create_inferior (std::vector<char *> &program_argv)
>  {
>    int pid;
>    ptid_t ptid;
>    struct process_info *proc;
> +  std::string program_args = stringify_argv (program_argv);
>
> -  pid = fork ();
> -  if (pid < 0)
> -    perror_with_name ("fork");
> -
> -  if (pid == 0)
> -    {
> -      close_most_fds ();
> -      ptrace (PTRACE_TRACEME, 0, 0, 0);
> -
> -      setpgid (0, 0);
> +  pre_fork_inferior (program_argv);
>
> -      execv (program, allargs);
> -      if (errno == ENOENT)
> -	execvp (program, allargs);
> +  pid = fork_inferior (program_argv[0],
> +		       (char *) program_args.c_str (),
> +		       environ_vector (get_environ ()), spu_ptrace_fun,
> +		       NULL, NULL, startup_shell, NULL);
>
> -      fprintf (stderr, "Cannot exec %s: %s.\n", program,
> -	       strerror (errno));
> -      fflush (stderr);
> -      _exit (0177);
> -    }
> +  post_fork_inferior (pid, program_argv);
>
> -  proc = add_process (pid, 0);
> +  proc = find_process_pid (pid);
> +  gdb_assert (proc != NULL);
>    proc->tdesc = tdesc_spu;
>
> -  ptid = ptid_build (pid, pid, 0);
> -  add_thread (ptid, NULL);
>    return pid;
>  }
>
> diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c
> index 249a063..56c734c 100644
> --- a/gdb/gdbserver/target.c
> +++ b/gdb/gdbserver/target.c
> @@ -387,3 +387,27 @@ default_breakpoint_kind_from_pc (CORE_ADDR *pcptr)
>    (*the_target->sw_breakpoint_from_kind) (0, &size);
>    return size;
>  }
> +
> +/* See target/target.h.  */
> +
> +void
> +target_terminal_init (void)
> +{
> +  /* To be implemented.  */
> +}
> +
> +/* See target/target.h.  */
> +
> +void
> +target_terminal_inferior (void)
> +{
> +  /* To be implemented.  */
> +}
> +
> +/* See target/target.h.  */
> +
> +void
> +target_terminal_ours (void)
> +{
> +  /* To be implemented.  */
> +}

Same suggestion as the other patch regarding either putting something in 
place now or adding more documentation about what these need to do in 
the future.

> diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
> index d098a92..3e74b86 100644
> --- a/gdb/gdbserver/target.h
> +++ b/gdb/gdbserver/target.h
> @@ -28,6 +28,7 @@
>  #include "target/waitstatus.h"
>  #include "mem-break.h"
>  #include "btrace-common.h"
> +#include <vector>
>
>  struct emit_ops;
>  struct buffer;
> @@ -73,7 +74,7 @@ struct target_ops
>       Returns the new PID on success, -1 on failure.  Registers the new
>       process with the process list.  */
>
> -  int (*create_inferior) (char *program, char **args);
> +  int (*create_inferior) (std::vector<char *> &program_argv);
>
>    /* Do additional setup after a new process is created, including
>       exec-wrapper completion.  */
> @@ -480,8 +481,8 @@ extern struct target_ops *the_target;
>
>  void set_target_ops (struct target_ops *);
>
> -#define create_inferior(program, args) \
> -  (*the_target->create_inferior) (program, args)
> +#define create_inferior(program) \
> +  (*the_target->create_inferior) (program)
>
>  #define target_post_create_inferior()			 \
>    do							 \
> diff --git a/gdb/gdbserver/utils.c b/gdb/gdbserver/utils.c
> index 37b9c89..8fa3ce5 100644
> --- a/gdb/gdbserver/utils.c
> +++ b/gdb/gdbserver/utils.c
> @@ -137,3 +137,40 @@ pfildes (gdb_fildes_t fd)
>    return plongest (fd);
>  #endif
>  }
> +
> +/* See common/common-utils.h.  */
> +
> +void
> +gdb_flush_out_err (void)
> +{
> +  fflush (stdout);
> +  fflush (stderr);
> +}
> +
> +/* See common/common-utils.h.  */
> +
> +void
> +free_vector_argv (std::vector<char *> &v)
> +{
> +  for (std::vector<char *>::iterator i = v.begin ();
> +       i != v.end ();
> +       ++i)
> +    xfree (*i);
> +
> +  v.clear ();
> +}

Nothing wrong with the above, but with the decision to use C++ 11, maybe 
this could be further simplified with range for if you think it's worth it?

{
   for (char* arg : v)
     xfree (arg);

   v.clear ();
}

Or maybe it is a bit too fancy for our own good, though we will 
eventually need to get used to it.

Another thought is to make the elements std::string themselves, in which 
case std::vector::clear () will call each elements' destructor. Again, 
maybe too fancy.

> +
> +/* See common/common-utils.h.  */
> +
> +std::string
> +stringify_argv (std::vector<char *> &argv)
> +{
> +  std::string ret ("");
> +
> +  for (std::vector<char *>::iterator i = argv.begin () + 1;
> +       i != argv.end ();
> +       ++i)
> +    ret += *i + std::string (" ");
> +
> +  return ret;
> +}

Same suggestion as above for the range for.

{
   for (char* arg : argv)
     ret += arg + std::string (" ");

   return ret;
}

> diff --git a/gdb/gdbserver/utils.h b/gdb/gdbserver/utils.h
> index 5e0cead..20c8dcd 100644
> --- a/gdb/gdbserver/utils.h
> +++ b/gdb/gdbserver/utils.h
> @@ -19,7 +19,19 @@
>  #ifndef UTILS_H
>  #define UTILS_H
>
> +#include <vector>
> +
>  char *paddress (CORE_ADDR addr);
>  char *pfildes (gdb_fildes_t fd);
>
> +/* Works like FREEARGV, but with std::vector.  */
> +
> +extern void free_vector_argv (std::vector<char *> &v);
> +
> +/* Given a vector of arguments ARGV, return a string equivalent to
> +   joining all the arguments (starting from ARGV + 1) with a
> +   whitespace separating them.  */
> +
> +extern std::string stringify_argv (std::vector<char *> &argv);
> +
>  #endif /* UTILS_H */
> diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
> index 70abfcd..1f7f538 100644
> --- a/gdb/gdbserver/win32-low.c
> +++ b/gdb/gdbserver/win32-low.c
> @@ -608,13 +608,11 @@ create_process (const char *program, char *args,
>  }
>
>  /* Start a new process.
> -   PROGRAM is a path to the program to execute.
> -   ARGS is a standard NULL-terminated array of arguments,
> -   to be passed to the inferior as ``argv''.
> +   PROGRAM_ARGV is the vector containing the inferior's argv.
>     Returns the new PID on success, -1 on failure.  Registers the new
>     process with the process list.  */
>  static int
> -win32_create_inferior (char *program, char **program_args)
> +win32_create_inferior (std::vector<char *> &program_argv)
>  {
>  #ifndef USE_WIN32API
>    char real_path[PATH_MAX];
> @@ -627,6 +625,9 @@ win32_create_inferior (char *program, char **program_args)
>    int argc;
>    PROCESS_INFORMATION pi;
>    DWORD err;
> +  char *program = program_argv[0];
> +  std::string program_args = stringify_argv (program_argv);
> +  char *args = (char *) program_args.c_str ();
>
>    /* win32_wait needs to know we're not attaching.  */
>    attaching = 0;
> @@ -636,6 +637,8 @@ win32_create_inferior (char *program, char **program_args)
>
>    flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
>
> +  pre_fork_inferior (program, argv);
> +
>  #ifndef USE_WIN32API
>    orig_path = NULL;
>    path_ptr = getenv ("PATH");
> @@ -652,18 +655,6 @@ win32_create_inferior (char *program, char **program_args)
>    program = real_path;
>  #endif
>
> -  argslen = 1;
> -  for (argc = 1; program_args[argc]; argc++)
> -    argslen += strlen (program_args[argc]) + 1;
> -  args = (char *) alloca (argslen);
> -  args[0] = '\0';
> -  for (argc = 1; program_args[argc]; argc++)
> -    {
> -      /* FIXME: Can we do better about quoting?  How does Cygwin
> -	 handle this?  */
> -      strcat (args, " ");
> -      strcat (args, program_args[argc]);
> -    }
>    OUTMSG2 (("Command line is \"%s\"\n", args));
>
>  #ifdef CREATE_NEW_PROCESS_GROUP
> @@ -704,6 +695,8 @@ win32_create_inferior (char *program, char **program_args)
>
>    do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
>
> +  post_fork_inferior (current_process_id, program_argv);
> +
>    return current_process_id;
>  }
>
> diff --git a/gdb/gnu-nat.c b/gdb/gnu-nat.c
> index 85a53b8..3e2e226 100644
> --- a/gdb/gnu-nat.c
> +++ b/gdb/gnu-nat.c
> @@ -2161,7 +2161,7 @@ gnu_create_inferior (struct target_ops *ops,
>    thread_change_ptid (inferior_ptid,
>  		      ptid_build (inf->pid, inf_pick_first_thread (), 0));
>
> -  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
> +  startup_inferior (START_INFERIOR_TRAPS_EXPECTED, NULL, NULL);
>    inf->pending_execs = 0;
>    /* Get rid of the old shell threads.  */
>    prune_threads ();
> diff --git a/gdb/inf-ptrace.c b/gdb/inf-ptrace.c
> index 64aaabe..ceb1422 100644
> --- a/gdb/inf-ptrace.c
> +++ b/gdb/inf-ptrace.c
> @@ -111,7 +111,7 @@ inf_ptrace_create_inferior (struct target_ops *ops,
>
>    discard_cleanups (back_to);
>
> -  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
> +  startup_inferior (START_INFERIOR_TRAPS_EXPECTED, NULL, NULL);
>
>    /* On some targets, there must be some explicit actions taken after
>       the inferior has been started up.  */
> diff --git a/gdb/inferior.h b/gdb/inferior.h
> index 403c096..6dae6b2 100644
> --- a/gdb/inferior.h
> +++ b/gdb/inferior.h
> @@ -42,6 +42,7 @@ struct target_desc_info;
>
>  #include "progspace.h"
>  #include "registry.h"
> +#include "common-inferior.h"
>
>  #include "symfile-add-flags.h"
>
> @@ -130,17 +131,6 @@ extern void child_terminal_init (struct target_ops *self);
>
>  extern void child_terminal_init_with_pgrp (int pgrp);
>
> -/* From fork-child.c */
> -
> -extern int fork_inferior (char *, char *, char **,
> -			  void (*)(void),
> -			  void (*)(int), void (*)(void), char *,
> -                          void (*)(const char *,
> -                                   char * const *, char * const *));
> -
> -
> -extern void startup_inferior (int);
> -
>  extern char *construct_inferior_arguments (int, char **);
>
>  /* From infcmd.c */
> diff --git a/gdb/procfs.c b/gdb/procfs.c
> index ff814ba..5b64618 100644
> --- a/gdb/procfs.c
> +++ b/gdb/procfs.c
> @@ -4380,7 +4380,7 @@ procfs_init_inferior (struct target_ops *ops, int pid)
>    thread_change_ptid (pid_to_ptid (pid),
>  		      ptid_build (pid, lwpid, 0));
>
> -  startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
> +  startup_inferior (START_INFERIOR_TRAPS_EXPECTED, NULL, NULL);
>
>  #ifdef SYS_syssgi
>    /* On mips-irix, we need to stop the inferior early enough during
> diff --git a/gdb/target.h b/gdb/target.h
> index a54b3db..adec5f2 100644
> --- a/gdb/target.h
> +++ b/gdb/target.h
> @@ -1529,17 +1529,6 @@ extern int target_terminal_is_inferior (void);
>
>  extern int target_terminal_is_ours (void);
>
> -/* Initialize the terminal settings we record for the inferior,
> -   before we actually run the inferior.  */
> -
> -extern void target_terminal_init (void);
> -
> -/* Put the inferior's terminal settings into effect.  This is
> -   preparation for starting or resuming the inferior.  This is a no-op
> -   unless called with the main UI as current UI.  */
> -
> -extern void target_terminal_inferior (void);
> -
>  /* Put some of our terminal settings into effect, enough to get proper
>     results from our output, but do not change into or out of RAW mode
>     so that no input is discarded.  This is a no-op if terminal_ours
> @@ -1548,12 +1537,6 @@ extern void target_terminal_inferior (void);
>
>  extern void target_terminal_ours_for_output (void);
>
> -/* Put our terminal settings into effect.  First record the inferior's
> -   terminal settings so they can be restored properly later.  This is
> -   a no-op unless called with the main UI as current UI.  */
> -
> -extern void target_terminal_ours (void);
> -
>  /* Return true if the target stack has a non-default
>    "to_terminal_ours" method.  */
>
> diff --git a/gdb/target/target.h b/gdb/target/target.h
> index 2f4c716..2f0d8ba 100644
> --- a/gdb/target/target.h
> +++ b/gdb/target/target.h
> @@ -95,4 +95,21 @@ extern void target_mourn_inferior (ptid_t ptid);
>
>  extern int target_supports_multi_process (void);
>
> +/* Initialize the terminal settings we record for the inferior,
> +   before we actually run the inferior.  */
> +

Spurious newline due to the following?

 
https://sourceware.org/gdb/wiki/Internals%20GDB-C-Coding-Standards#Empty_line_between_subprogram_description_and_the_subprogram_implementation

   "Note that this only applies to the case where the comment is placed
   besides the subprogram implementation (typically in a .c file). In the
   case of the documentation being placed next to the subprogram
   declaration, then the comment should be placed immediately before the
   declaration."

> +extern void target_terminal_init (void);
> +
> +/* Put the inferior's terminal settings into effect.  This is
> +   preparation for starting or resuming the inferior.  This is a no-op
> +   unless called with the main UI as current UI.  */
> +
> +extern void target_terminal_inferior (void);
> +
> +/* Put our terminal settings into effect.  First record the inferior's
> +   terminal settings so they can be restored properly later.  This is
> +   a no-op unless called with the main UI as current UI.  */
> +
> +extern void target_terminal_ours (void);
> +
>  #endif /* TARGET_COMMON_H */
> diff --git a/gdb/testsuite/gdb.server/non-existing-program.exp b/gdb/testsuite/gdb.server/non-existing-program.exp
> index f68029d..efdfb58 100644
> --- a/gdb/testsuite/gdb.server/non-existing-program.exp
> +++ b/gdb/testsuite/gdb.server/non-existing-program.exp
> @@ -39,8 +39,14 @@ set spawn_id [remote_spawn target "$gdbserver stdio non-existing-program"]
>  set msg "gdbserver exits cleanly"
>  set saw_exiting 0
>  expect {
> -    # This is what we get on ptrace-based targets.
> -    -re "stdin/stdout redirected.*No program to debug\r\nExiting\r\n$" {
> +    # This is what we get on ptrace-based targets with
> +    # startup-with-shell disabled.
> +    -re "stdin/stdout redirected.*gdbserver: Cannot exec non-existing-program\r\ngdbserver: Error: No such file or directory\r\n\r\nDuring startup program exited with code 127\.\r\nExiting\r\n$" {
> +	set saw_exiting 1
> +	exp_continue
> +    }
> +    # Likewise, but with startup-with-shell enabled.
> +    -re "stdin/stdout redirected.*exec: non-existing-program: not found\r\nDuring startup program exited with code 127\.\r\nExiting\r\n$" {
>  	set saw_exiting 1
>  	exp_continue
>      }
> diff --git a/gdb/top.h b/gdb/top.h
> index 482ed3e..0c057d7 100644
> --- a/gdb/top.h
> +++ b/gdb/top.h
> @@ -22,6 +22,7 @@
>
>  #include "buffer.h"
>  #include "event-loop.h"
> +#include "common-top.h"
>
>  struct tl_interp_info;
>
> @@ -144,14 +145,6 @@ struct ui
>    struct ui_out *m_current_uiout;
>  };
>
> -/* The main UI.  This is the UI that is bound to stdin/stdout/stderr.
> -   It always exists and is created automatically when GDB starts
> -   up.  */
> -extern struct ui *main_ui;
> -
> -/* The current UI.  */
> -extern struct ui *current_ui;
> -
>  /* The list of all UIs.  */
>  extern struct ui *ui_list;
>
> diff --git a/gdb/utils.c b/gdb/utils.c
> index 6bf3716..026e9d7 100644
> --- a/gdb/utils.c
> +++ b/gdb/utils.c
> @@ -3435,6 +3435,15 @@ strip_leading_path_elements (const char *path, int n)
>    return p;
>  }
>
> +/* See common/common-utils.h.  */
> +
> +void
> +gdb_flush_out_err (void)
> +{
> +  gdb_flush (main_ui->m_gdb_stdout);
> +  gdb_flush (main_ui->m_gdb_stderr);
> +}
> +
>  /* Provide a prototype to silence -Wmissing-prototypes.  */
>  extern initialize_file_ftype _initialize_utils;
>
>

The patch looks reasonable to me, though it would be nice to do a second 
pass on a version without the git-copy in place. That way we can see the 
real changes for the code that was moved.

Thanks,
Luis



More information about the Gdb-patches mailing list