public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [RFC][PATCH] Consolidate gdbserver global variables
@ 2017-11-07 22:03 Stan Cox
  2018-01-31  3:41 ` Stan Cox
  0 siblings, 1 reply; 15+ messages in thread
From: Stan Cox @ 2017-11-07 22:03 UTC (permalink / raw)
  To: gdb-patches

Josh Stone, with later help from myself, added a gdb remote protocol 
backend to strace, which is slowly percolating through the strace 
approval process.  The patch allows strace to operate normally, by using 
a gdbserver that has syscall support.  Additionally there is a set of 
patches that allows gdbserver to work with a remote gdb and 
simultaneously with an strace client.  Part of that effort involves 
consolidating the global variables in gdbserver into one of two 
structures: client_state and server_state.  Client_state are those items 
that have, or potentially could have, per client values, whereas 
server_state are those items that have a per process value, i.e. will 
have the same value for all clients.  This patch, although large, 
primarily moves global data into one of the two structures and adds 
convenience access macros.  The access macros provide a getter 
functionality; somewhat akin to gcc's macro usage.  This avoids having 
to change variable references to struct->variable references, no change 
is needed as the convenience macro handles the underlying details. There 
are a couple of frequent cases where a local variable name clashed with 
a global variable.  This is handled by changing either the local or 
global variable name, whichever had the smallest impact.

  gdbserver.h::thread_info.last_status becomes last_waitstatus
   (many "mechanical" changes for this one)
  linux-low.c::linux_create_inferior::program_args becomes p_program_args
  remote-utils.c::look_up_one_symbol::mem_buf becomes mem_buffer
  server.h::client_state.own_buf becomes own_buffer
   (many "mechanical" changes for this one; own_buf is a frequent local var)

struct multi_client_states is a map from an fd to a struct client_state
plus a pointer to the current client_state, a client_state cursor if you
will.  client_state flow:

captured_main initially calls set_client_state(fd=-1)
  creates a multi_client_states mapping for -1 -> client_state
remote_prepare calls get_client_state
  returns client_state entry for -1, the current client_state
handle_accept_event calls get_client_states which returns 
multi_client_states
handle_accept_event calls set_client_state(fd=4)
  creates a multi_client_states mapping for 4 -> client_state
handle_accept_event calls get_client_state which returns client_state for 4
readchar calls get_client_state  which returns client_state for 4
...
... when the client completes
remote_close calls delete_file_handler calls delete_client_state(fd=4)
  This sets the current client_state to be -1 -> client_state
handle_accept_event calls set_client_state(fd=4)
  assuming extended_remote then the cycle repeats

The patch below is present in the branch:
  ssh://sourceware.org/git/archer.git::scox/gdbserver-multi-client

gdbserver/ChangeLog
2017-11-03  Stan Cox  <scox@redhat.com>

	* server.h (client_breakpoints):  Use a set. Change all users.
	(multi_client_states.cs):  Use a map.  Change all users.
	* mem-break.c (has_client_breakpoint_at): Move from here..
	* server.c (multi_client_states::has_client_breakpoint_at): ..to here
	(client_state::client_state):  New constructor.
	(multi_client_states::set_client_state): Use it.  Use client
	states map.
	(multi_client_states::add_client_breakpoint):  Use client breaks
	set.

diff --git a/gdb/gdbserver/event-loop.c b/gdb/gdbserver/event-loop.c
index b391e2e..b9bd166 100644
--- a/gdb/gdbserver/event-loop.c
+++ b/gdb/gdbserver/event-loop.c
@@ -385,6 +385,9 @@ delete_file_handler (gdb_fildes_t fd)
  	;
        prev_ptr->next_file = file_ptr->next_file;
      }
+
+  struct multi_client_states *client_states = get_client_states();
+  client_states->delete_client_state (fd);
    free (file_ptr);
  }

diff --git a/gdb/gdbserver/fork-child.c b/gdb/gdbserver/fork-child.c
index 1002620..aaf01e4 100644
--- a/gdb/gdbserver/fork-child.c
+++ b/gdb/gdbserver/fork-child.c
@@ -108,7 +108,7 @@ post_fork_inferior (int pid, const char *program)
    startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED,
  		    &last_status, &last_ptid);
    current_thread->last_resume_kind = resume_stop;
-  current_thread->last_status = last_status;
+  current_thread->last_waitstatus = last_status;
    signal_pid = pid;
    target_post_create_inferior ();
    fprintf (stderr, "Process %s created; pid = %d\n", program, pid);
diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
index b82d5b0..4ff2a69 100644
--- a/gdb/gdbserver/gdbthread.h
+++ b/gdb/gdbserver/gdbthread.h
@@ -39,7 +39,7 @@ struct thread_info
    enum resume_kind last_resume_kind;

    /* The last wait status reported for this thread.  */
-  struct target_waitstatus last_status;
+  struct target_waitstatus last_waitstatus;

    /* True if LAST_STATUS hasn't been reported to GDB yet.  */
    int status_pending_p;
@@ -73,8 +73,6 @@ struct thread_info
    struct btrace_target_info *btrace;
  };

-extern std::list<thread_info *> all_threads;
-
  void remove_thread (struct thread_info *thread);
  struct thread_info *add_thread (ptid_t ptid, void *target_data);

diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
index cd40e28..6638623 100644
--- a/gdb/gdbserver/hostio.c
+++ b/gdb/gdbserver/hostio.c
@@ -29,8 +29,6 @@
  #include <sys/stat.h>
  #include "fileio.h"

-extern int remote_debug;
-
  struct fd_list
  {
    int fd;
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index a0ece4d..1518ac0 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -22,10 +22,6 @@
  #include "gdbthread.h"
  #include "dll.h"

-std::list<process_info *> all_processes;
-std::list<thread_info *> all_threads;
-
-struct thread_info *current_thread;

  /* The current working directory used to start the inferior.  */
  static const char *current_inferior_cwd = NULL;
@@ -94,7 +90,7 @@ add_thread (ptid_t thread_id, void *target_data)

    new_thread->id = thread_id;
    new_thread->last_resume_kind = resume_continue;
-  new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;
+  new_thread->last_waitstatus.kind = TARGET_WAITKIND_IGNORE;

    all_threads.push_back (new_thread);

diff --git a/gdb/gdbserver/inferiors.h b/gdb/gdbserver/inferiors.h
index fb0e2fd..6a64df7 100644
--- a/gdb/gdbserver/inferiors.h
+++ b/gdb/gdbserver/inferiors.h
@@ -81,8 +81,6 @@ pid_of (const process_info *proc)
  struct process_info *current_process (void);
  struct process_info *get_thread_process (const struct thread_info *);

-extern std::list<process_info *> all_processes;
-
  /* Invoke FUNC for each process.  */

  template <typename Func>
@@ -123,8 +121,6 @@ find_process (Func func)
    return NULL;
  }

-extern struct thread_info *current_thread;
-
  /* Return the first process in the processes list.  */
  struct process_info *get_first_process (void);

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index b367e53..d068cc6 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -545,7 +545,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
  	  child_lwp->status_pending_p = 0;
  	  child_thr = get_lwp_thread (child_lwp);
  	  child_thr->last_resume_kind = resume_stop;
-	  child_thr->last_status.kind = TARGET_WAITKIND_STOPPED;
+	  child_thr->last_waitstatus.kind = TARGET_WAITKIND_STOPPED;

  	  /* If we're suspending all threads, leave this one suspended
  	     too.  If the fork/clone parent is stepping over a breakpoint,
@@ -723,7 +723,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
        event_lwp->status_pending_p = 1;
        event_lwp->status_pending = wstat;
        event_thr->last_resume_kind = resume_continue;
-      event_thr->last_status.kind = TARGET_WAITKIND_IGNORE;
+      event_thr->last_waitstatus.kind = TARGET_WAITKIND_IGNORE;

        /* Update syscall state in the new lwp, effectively mid-syscall 
too.  */
        event_lwp->syscall_state = TARGET_WAITKIND_SYSCALL_ENTRY;
@@ -994,14 +994,14 @@ linux_ptrace_fun ()

  static int
  linux_create_inferior (const char *program,
-		       const std::vector<char *> &program_args)
+		       const std::vector<char *> &p_program_args)
  {
    struct lwp_info *new_lwp;
    int pid;
    ptid_t ptid;
    struct cleanup *restore_personality
      = maybe_disable_address_space_randomization (disable_randomization);
-  std::string str_program_args = stringify_argv (program_args);
+  std::string str_program_args = stringify_argv (p_program_args);

    pid = fork_inferior (program,
  		       str_program_args.c_str (),
@@ -1441,13 +1441,13 @@ get_detach_signal (struct thread_info *thread)
        /* If the thread had been suspended by gdbserver, and it stopped
  	 cleanly, then it'll have stopped with SIGSTOP.  But we don't
  	 want to deliver that SIGSTOP.  */
-      if (thread->last_status.kind != TARGET_WAITKIND_STOPPED
-	  || thread->last_status.value.sig == GDB_SIGNAL_0)
+      if (thread->last_waitstatus.kind != TARGET_WAITKIND_STOPPED
+	  || thread->last_waitstatus.value.sig == GDB_SIGNAL_0)
  	return 0;

        /* Otherwise, we may need to deliver the signal we
  	 intercepted.  */
-      status = lp->last_status;
+      status = lp->last_waitstatus;
      }

    if (!WIFSTOPPED (status))
@@ -1741,7 +1741,7 @@ thread_still_has_status_pending_p (struct 
thread_info *thread)
        CORE_ADDR pc;
        int discard = 0;

-      gdb_assert (lp->last_status != 0);
+      gdb_assert (lp->last_waitstatus != 0);

        pc = get_pc (lp);

@@ -1803,7 +1803,7 @@ lwp_resumed (struct lwp_info *lwp)
       corresponding stop to gdb yet?  If so, the thread is still
       resumed/running from gdb's perspective.  */
    if (thread->last_resume_kind == resume_stop
-      && thread->last_status.kind == TARGET_WAITKIND_IGNORE)
+      && thread->last_waitstatus.kind == TARGET_WAITKIND_IGNORE)
      return 1;

    return 0;
@@ -2478,7 +2478,7 @@ linux_low_filter_event (int lwpid, int wstat)

    child->stopped = 1;

-  child->last_status = wstat;
+  child->last_waitstatus = wstat;

    /* Check if the thread has exited.  */
    if ((WIFEXITED (wstat) || WIFSIGNALED (wstat)))
@@ -2657,7 +2657,7 @@ resume_stopped_resumed_lwps (thread_info *thread)
    if (lp->stopped
        && !lp->suspended
        && !lp->status_pending_p
-      && thread->last_status.kind == TARGET_WAITKIND_IGNORE)
+      && thread->last_waitstatus.kind == TARGET_WAITKIND_IGNORE)
      {
        int step = 0;

@@ -2899,7 +2899,7 @@ count_events_callback (thread_info *thread, void 
*data)
    gdb_assert (count != NULL);

    /* Count only resumed LWPs that have an event pending. */
-  if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
+  if (thread->last_waitstatus.kind == TARGET_WAITKIND_IGNORE
        && lp->status_pending_p)
      (*count)++;

@@ -2913,7 +2913,7 @@ select_singlestep_lwp_callback (thread_info 
*thread, void *data)
  {
    struct lwp_info *lp = get_thread_lwp (thread);

-  if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
+  if (thread->last_waitstatus.kind == TARGET_WAITKIND_IGNORE
        && thread->last_resume_kind == resume_step
        && lp->status_pending_p)
      return 1;
@@ -2932,7 +2932,7 @@ select_event_lwp_callback (thread_info *thread, 
void *data)
    gdb_assert (selector != NULL);

    /* Select only resumed LWPs that have an event pending. */
-  if (thread->last_status.kind == TARGET_WAITKIND_IGNORE
+  if (thread->last_waitstatus.kind == TARGET_WAITKIND_IGNORE
        && lp->status_pending_p)
      if ((*selector)-- == 0)
        return 1;
@@ -4661,7 +4661,7 @@ linux_set_resume_request (thread_info *thread, 
void *arg)
  	    {
  	      if (debug_threads)
  		debug_printf ("already %s LWP %ld at GDB's request\n",
-			      (thread->last_status.kind
+			      (thread->last_waitstatus.kind
  			       == TARGET_WAITKIND_STOPPED)
  			      ? "stopped"
  			      : "stopping",
@@ -5101,7 +5101,7 @@ linux_resume_one_thread (thread_info *thread, void 
*arg)

        /* For stop requests, we're done.  */
        lwp->resume = NULL;
-      thread->last_status.kind = TARGET_WAITKIND_IGNORE;
+      thread->last_waitstatus.kind = TARGET_WAITKIND_IGNORE;
        return 0;
      }

@@ -5124,8 +5124,8 @@ linux_resume_one_thread (thread_info *thread, void 
*arg)

        /* If this is the same signal we were previously stopped by,
  	 make sure to queue its siginfo.  */
-      if (WIFSTOPPED (lwp->last_status)
-	  && WSTOPSIG (lwp->last_status) == lwp->resume->sig
+      if (WIFSTOPPED (lwp->last_waitstatus)
+	  && WSTOPSIG (lwp->last_waitstatus) == lwp->resume->sig
  	  && ptrace (PTRACE_GETSIGINFO, lwpid_of (thread),
  		     (PTRACE_TYPE_ARG3) 0, &info) == 0)
  	info_p = &info;
@@ -5148,7 +5148,7 @@ linux_resume_one_thread (thread_info *thread, void 
*arg)
  	debug_printf ("leaving LWP %ld stopped\n", lwpid_of (thread));
      }

-  thread->last_status.kind = TARGET_WAITKIND_IGNORE;
+  thread->last_waitstatus.kind = TARGET_WAITKIND_IGNORE;
    lwp->resume = NULL;
    return 0;
  }
@@ -5251,7 +5251,7 @@ proceed_one_lwp (thread_info *thread, void *except)
      }

    if (thread->last_resume_kind == resume_stop
-      && thread->last_status.kind != TARGET_WAITKIND_IGNORE)
+      && thread->last_waitstatus.kind != TARGET_WAITKIND_IGNORE)
      {
        if (debug_threads)
  	debug_printf ("   client wants LWP to remain %ld stopped\n",
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index eda452f..f2381f3 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -302,7 +302,7 @@ struct lwp_info
    enum target_waitkind syscall_state;

    /* When stopped is set, the last wait status recorded for this lwp.  */
-  int last_status;
+  int last_waitstatus;

    /* If WAITSTATUS->KIND != TARGET_WAITKIND_IGNORE, the waitstatus for
       this LWP's last event, to pass to GDB without any further
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 54f27f4..0b060f3 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -103,7 +103,6 @@ struct sym_cache
    struct sym_cache *next;
  };

-int remote_debug = 0;
  struct ui_file *gdb_stdlog;

  static int remote_is_stdio = 0;
@@ -115,17 +114,19 @@ static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
  extern int using_threads;
  extern int debug_threads;

-/* If true, then GDB has requested noack mode.  */
-int noack_mode = 0;
-/* If true, then we tell GDB to use noack mode by default.  */
-int transport_is_reliable = 0;
-
  #ifdef USE_WIN32API
  # define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)
  #endif

  int
+get_remote_desc (void)
+{
+  return remote_desc;
+}
+
+
+int
  gdb_connected (void)
  {
    return remote_desc != INVALID_DESCRIPTOR;
@@ -167,6 +168,9 @@ handle_accept_event (int err, gdb_client_data 
client_data)
    if (remote_desc == -1)
      perror_with_name ("Accept failed");

+  struct multi_client_states *client_states = get_client_states();
+  client_states->set_client_state (remote_desc);
+
    /* Enable TCP keep alive process. */
    tmp = 1;
    setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE,
@@ -841,14 +845,6 @@ initialize_async_io (void)
  #endif
  }

-/* Internal buffer used by readchar.
-   These are global to readchar because reschedule_remote needs to be
-   able to tell whether the buffer is empty.  */
-
-static unsigned char readchar_buf[BUFSIZ];
-static int readchar_bufcnt = 0;
-static unsigned char *readchar_bufp;
-
  /* Returns next char from remote GDB.  -1 if error.  */

  static int
@@ -1459,14 +1455,14 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
      return 0;

    /* Send the request.  */
-  strcpy (own_buf, "qSymbol:");
-  bin2hex ((const gdb_byte *) name, own_buf + strlen ("qSymbol:"),
+  strcpy (own_buffer, "qSymbol:");
+  bin2hex ((const gdb_byte *) name, own_buffer + strlen ("qSymbol:"),
  	  strlen (name));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (own_buffer) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (own_buffer);
    if (len < 0)
      return -1;

@@ -1477,45 +1473,45 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
       while it figures out the address of the symbol.  */
    while (1)
      {
-      if (own_buf[0] == 'm')
+      if (own_buffer[0] == 'm')
  	{
  	  CORE_ADDR mem_addr;
-	  unsigned char *mem_buf;
+	  unsigned char *mem_buffer;
  	  unsigned int mem_len;

-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
-	  mem_buf = (unsigned char *) xmalloc (mem_len);
-	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	  decode_m_packet (&own_buffer[1], &mem_addr, &mem_len);
+	  mem_buffer = (unsigned char *) xmalloc (mem_len);
+	  if (read_inferior_memory (mem_addr, mem_buffer, mem_len) == 0)
+	    bin2hex (mem_buffer, own_buffer, mem_len);
  	  else
-	    write_enn (own_buf);
-	  free (mem_buf);
-	  if (putpkt (own_buf) < 0)
+	    write_enn (own_buffer);
+	  free (mem_buffer);
+	  if (putpkt (own_buffer) < 0)
  	    return -1;
  	}
-      else if (own_buf[0] == 'v')
+      else if (own_buffer[0] == 'v')
  	{
  	  int new_len = -1;
-	  handle_v_requests (own_buf, len, &new_len);
+	  handle_v_requests (own_buffer, len, &new_len);
  	  if (new_len != -1)
-	    putpkt_binary (own_buf, new_len);
+	    putpkt_binary (own_buffer, new_len);
  	  else
-	    putpkt (own_buf);
+	    putpkt (own_buffer);
  	}
        else
  	break;
-      len = getpkt (own_buf);
+      len = getpkt (own_buffer);
        if (len < 0)
  	return -1;
      }

-  if (!startswith (own_buf, "qSymbol:"))
+  if (!startswith (own_buffer, "qSymbol:"))
      {
-      warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf);
+      warning ("Malformed response to qSymbol, ignoring: %s\n", 
own_buffer);
        return -1;
      }

-  p = own_buf + strlen ("qSymbol:");
+  p = own_buffer + strlen ("qSymbol:");
    q = p;
    while (*q && *q != ':')
      q++;
@@ -1555,13 +1551,13 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR 
oldloc)
    ULONGEST written = 0;

    /* Send the request.  */
-  sprintf (own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
+  sprintf (own_buffer, "qRelocInsn:%s;%s", paddress (oldloc),
  	   paddress (*to));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (own_buffer) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (own_buffer);
    if (len < 0)
      return -1;

@@ -1569,61 +1565,61 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR 
oldloc)
       wait for the qRelocInsn "response".  That requires re-entering
       the main loop.  For now, this is an adequate approximation; allow
       GDB to access memory.  */
-  while (own_buf[0] == 'm' || own_buf[0] == 'M' || own_buf[0] == 'X')
+  while (own_buffer[0] == 'm' || own_buffer[0] == 'M' || own_buffer[0] 
== 'X')
      {
        CORE_ADDR mem_addr;
-      unsigned char *mem_buf = NULL;
+      unsigned char *mem_buffer = NULL;
        unsigned int mem_len;

-      if (own_buf[0] == 'm')
+      if (own_buffer[0] == 'm')
  	{
-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
-	  mem_buf = (unsigned char *) xmalloc (mem_len);
-	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	  decode_m_packet (&own_buffer[1], &mem_addr, &mem_len);
+	  mem_buffer = (unsigned char *) xmalloc (mem_len);
+	  if (read_inferior_memory (mem_addr, mem_buffer, mem_len) == 0)
+	    bin2hex (mem_buffer, own_buffer, mem_len);
  	  else
-	    write_enn (own_buf);
+	    write_enn (own_buffer);
  	}
-      else if (own_buf[0] == 'X')
+      else if (own_buffer[0] == 'X')
  	{
-	  if (decode_X_packet (&own_buf[1], len - 1, &mem_addr,
-			       &mem_len, &mem_buf) < 0
-	      || write_inferior_memory (mem_addr, mem_buf, mem_len) != 0)
-	    write_enn (own_buf);
+	  if (decode_X_packet (&own_buffer[1], len - 1, &mem_addr,
+			       &mem_len, &mem_buffer) < 0
+	      || write_inferior_memory (mem_addr, mem_buffer, mem_len) != 0)
+	    write_enn (own_buffer);
  	  else
-	    write_ok (own_buf);
+	    write_ok (own_buffer);
  	}
        else
  	{
-	  decode_M_packet (&own_buf[1], &mem_addr, &mem_len, &mem_buf);
-	  if (write_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    write_ok (own_buf);
+	  decode_M_packet (&own_buffer[1], &mem_addr, &mem_len, &mem_buffer);
+	  if (write_inferior_memory (mem_addr, mem_buffer, mem_len) == 0)
+	    write_ok (own_buffer);
  	  else
-	    write_enn (own_buf);
+	    write_enn (own_buffer);
  	}
-      free (mem_buf);
-      if (putpkt (own_buf) < 0)
+      free (mem_buffer);
+      if (putpkt (own_buffer) < 0)
  	return -1;
-      len = getpkt (own_buf);
+      len = getpkt (own_buffer);
        if (len < 0)
  	return -1;
      }

-  if (own_buf[0] == 'E')
+  if (own_buffer[0] == 'E')
      {
        warning ("An error occurred while relocating an instruction: %s\n",
-	       own_buf);
+	       own_buffer);
        return -1;
      }

-  if (!startswith (own_buf, "qRelocInsn:"))
+  if (!startswith (own_buffer, "qRelocInsn:"))
      {
        warning ("Malformed response to qRelocInsn, ignoring: %s\n",
-	       own_buf);
+	       own_buffer);
        return -1;
      }

-  unpack_varlen_hex (own_buf + strlen ("qRelocInsn:"), &written);
+  unpack_varlen_hex (own_buffer + strlen ("qRelocInsn:"), &written);

    *to += written;
    return 0;
diff --git a/gdb/gdbserver/remote-utils.h b/gdb/gdbserver/remote-utils.h
index b45a725..9ae355c 100644
--- a/gdb/gdbserver/remote-utils.h
+++ b/gdb/gdbserver/remote-utils.h
@@ -19,10 +19,7 @@
  #ifndef REMOTE_UTILS_H
  #define REMOTE_UTILS_H

-extern int remote_debug;
-extern int noack_mode;
-extern int transport_is_reliable;
-
+int get_remote_desc (void);
  int gdb_connected (void);

  #define STDIO_CONNECTION_NAME "stdio"
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index e827b9c..57bb253 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -66,63 +66,6 @@ static gdb_environ our_environ;

  int startup_with_shell = 1;

-/* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
-   `vCont'.  Note the multi-process extensions made `vCont' a
-   requirement, so `Hc pPID.TID' is pretty much undefined.  So
-   CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
-   resuming all threads of the process (again, `Hc' isn't used for
-   multi-process), or a specific thread ptid_t.  */
-ptid_t cont_thread;
-
-/* The thread set with an `Hg' packet.  */
-ptid_t general_thread;
-
-int server_waiting;
-
-static int extended_protocol;
-static int response_needed;
-static int exit_requested;
-
-/* --once: Exit after the first connection has closed.  */
-int run_once;
-
-int multi_process;
-int report_fork_events;
-int report_vfork_events;
-int report_exec_events;
-int report_thread_events;
-
-/* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
-static int report_no_resumed;
-
-int non_stop;
-int swbreak_feature;
-int hwbreak_feature;
-
-/* True if the "vContSupported" feature is active.  In that case, GDB
-   wants us to report whether single step is supported in the reply to
-   "vCont?" packet.  */
-static int vCont_supported;
-
-/* Whether we should attempt to disable the operating system's address
-   space randomization feature before starting an inferior.  */
-int disable_randomization = 1;
-
-static char *program_name = NULL;
-static std::vector<char *> program_args;
-static std::string wrapper_argv;
-
-int pass_signals[GDB_SIGNAL_LAST];
-int program_signals[GDB_SIGNAL_LAST];
-int program_signals_p;
-
-/* The PID of the originally created or attached inferior.  Used to
-   send signals to the process when GDB sends us an asynchronous interrupt
-   (user hitting Control-C in the client), and to wait for the child to 
exit
-   when no longer debugging it.  */
-
-unsigned long signal_pid;
-
  /* Set if you want to disable optional thread related packets support
     in gdbserver, for the sake of testing GDB against stubs that don't
     support them.  */
@@ -131,13 +74,6 @@ int disable_packet_Tthread;
  int disable_packet_qC;
  int disable_packet_qfThreadInfo;

-/* Last status reported to GDB.  */
-struct target_waitstatus last_status;
-ptid_t last_ptid;
-
-char *own_buf;
-static unsigned char *mem_buf;
-
  /* A sub-class of 'struct notif_event' for stop, holding information
     relative to a single stop reply.  We keep a queue of these to
     push to GDB in non-stop mode.  */
@@ -159,6 +95,159 @@ static struct btrace_config current_btrace_conf;

  DEFINE_QUEUE_P (notif_event_p);

+static struct multi_client_states client_states;
+
+
+multi_client_states*
+get_client_states (void)
+{
+  return &client_states;
+}
+
+
+client_state*
+get_client_state (void)
+{
+  return client_states.get_client_state();
+}
+
+
+client_state::client_state (gdb_fildes_t fd, client_state *csidx)
+{
+  file_desc = fd;
+  attached_to_client = csidx->attached_to_client;
+  //   nonstop_pending = csidx->nonstop_pending;
+  catch_syscalls = csidx->catch_syscalls;
+  extended_protocol_ = csidx->extended_protocol_;
+  response_needed_ = csidx->response_needed_;
+  exit_requested_ = csidx->exit_requested_;
+  run_once_ = csidx->run_once_;
+  multi_process_ = csidx->multi_process_;
+  report_fork_events_ = csidx->report_fork_events_;
+  report_vfork_events_ = csidx->report_vfork_events_;
+  report_exec_events_ = csidx->report_exec_events_;
+  report_thread_events_ = csidx->report_thread_events_;
+  report_no_resumed_ = csidx->report_no_resumed_;
+  non_stop_ = csidx->non_stop_;
+  swbreak_feature_ = csidx->swbreak_feature_;
+  hwbreak_feature_ = csidx->hwbreak_feature_;
+  vCont_supported_ = csidx->vCont_supported_;
+  disable_randomization_ = csidx->disable_randomization_;
+  program_name_ = csidx->program_name_;
+  program_args_ = csidx->program_args_;
+  wrapper_argv_ = csidx->wrapper_argv_;
+  remote_debug_ = csidx->remote_debug_;
+  noack_mode_ = csidx->noack_mode_;
+  transport_is_reliable_ = csidx->transport_is_reliable_;
+  ss = new (server_state);
+  ss->mem_buf_ = csidx->ss->mem_buf_;
+  ss->readchar_bufcnt_ = 0;
+  packet_type = other_packet;
+  last_packet_type = other_packet;
+  //   pending = none_pending;
+  notify_buffer_ = NULL;
+  own_buffer_ = (char*) xmalloc (PBUFSIZ + 1);
+  ss->attach_count_ = 0;
+  ss->cont_thread_ = null_ptid;
+  ss->general_thread_ = null_ptid;
+  ss->signal_pid_ = 0;
+  ss->last_ptid_ = null_ptid;
+  ss->last_status_.kind = TARGET_WAITKIND_IGNORE;
+  if (csidx->file_desc < 0)
+    {
+      ss->all_processes_ = all_processes;
+      ss->all_threads_ = all_threads;
+      ss->current_thread_ = current_thread;
+    }
+  else
+    ss->current_thread_ = NULL;
+}
+
+
+/* Add a new client state for FD or return if found */
+
+client_state *
+multi_client_states::set_client_state (gdb_fildes_t fd)
+{
+/* States:
+ * fd = -1 add initial client state
+ * fd =  F add client state for fd F
+ */
+
+  client_state *csidx, *cs;
+
+  /* add/return initial client state */
+  if (fd == -1)
+    {
+      if (client_states.cs.empty())
+	{
+	  client_states.cs[fd] = new (client_state);
+	  client_states.cs[fd]->ss = new (server_state);
+	  client_states.cs[fd]->file_desc = fd;
+	}
+      client_states.current_cs = client_states.cs[fd];
+      return client_states.cs[fd];
+    }
+
+  /* add/return client state for fd F */
+
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+  it = client_states.cs.find(fd);
+  if (it != client_states.cs.end())
+    {
+      client_states.current_cs = it->second;
+      return it->second;
+    }
+  else
+    csidx = client_states.cs.rbegin()->second;
+
+  /* add client state S for fd F */
+  client_states.cs[fd] = cs = new client_state (fd, csidx);
+  cs->file_desc = fd;
+  client_states.set_current_client (cs);
+  return cs;
+}
+
+
+/* Remove the client state corresponding to fd */
+
+void
+multi_client_states::delete_client_state (gdb_fildes_t fd)
+{
+  client_state *cs, *previous_cs = NULL;
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      server_state *ss= NULL;
+
+      cs = it->second;
+
+      if (it->first == fd)
+	{
+	  client_states.current_cs = previous_cs;
+	  extended_protocol = cs->extended_protocol_;
+	  run_once = cs->run_once_;
+	  non_stop = cs->non_stop_;
+	  if (cs->notify_buffer_)
+	    xfree (cs->notify_buffer_);
+	  free (cs->own_buffer_);
+	  delete (cs->ss);
+	  delete (cs);
+	  client_states.cs.erase (fd);
+	}
+      previous_cs = cs;
+    }
+}
+
+
+#if 0
+static int
+queue_stop_reply_callback (thread_info *thread, void *arg);
+#endif
+
+/**********************************/
+
  /* Put a stop reply to the stop reply queue.  */

  static void
@@ -308,14 +397,12 @@ attach_inferior (int pid)
  	last_status.value.sig = GDB_SIGNAL_TRAP;

        current_thread->last_resume_kind = resume_stop;
-      current_thread->last_status = last_status;
+      current_thread->last_waitstatus = last_status;
      }

    return 0;
  }

-extern int remote_debug;
-
  /* Decode a qXfer read request.  Return 0 if everything looks OK,
     or -1 otherwise.  */

@@ -639,6 +726,7 @@ handle_general_set (char *own_buf)
  	    }
  	  else
  	    VEC_safe_push (int, process->syscalls_to_catch, ANY_SYSCALL);
+	  client_states.current_cs->catch_syscalls = 1;
  	}

        write_ok (own_buf);
@@ -1831,20 +1919,20 @@ handle_qxfer_btrace (const char *annex,
    if (ptid_equal (general_thread, null_ptid)
        || ptid_equal (general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (own_buffer, "E.Must select a single thread.");
        return -3;
      }

    thread = find_thread_ptid (general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (own_buffer, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (own_buffer, "E.Btrace not enabled.");
        return -3;
      }

@@ -1856,7 +1944,7 @@ handle_qxfer_btrace (const char *annex,
      type = BTRACE_READ_DELTA;
    else
      {
-      strcpy (own_buf, "E.Bad annex.");
+      strcpy (own_buffer, "E.Bad annex.");
        return -3;
      }

@@ -1867,7 +1955,7 @@ handle_qxfer_btrace (const char *annex,
        result = target_read_btrace (thread->btrace, &cache, type);
        if (result != 0)
  	{
-	  memcpy (own_buf, cache.buffer, cache.used_size);
+	  memcpy (own_buffer, cache.buffer, cache.used_size);
  	  return -3;
  	}
      }
@@ -1905,20 +1993,20 @@ handle_qxfer_btrace_conf (const char *annex,
    if (ptid_equal (general_thread, null_ptid)
        || ptid_equal (general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (own_buffer, "E.Must select a single thread.");
        return -3;
      }

    thread = find_thread_ptid (general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (own_buffer, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (own_buffer, "E.Btrace not enabled.");
        return -3;
      }

@@ -1929,7 +2017,7 @@ handle_qxfer_btrace_conf (const char *annex,
        result = target_read_btrace_conf (thread->btrace, &cache);
        if (result != 0)
  	{
-	  memcpy (own_buf, cache.buffer, cache.used_size);
+	  memcpy (own_buffer, cache.buffer, cache.used_size);
  	  return -3;
  	}
      }
@@ -2717,9 +2805,9 @@ handle_pending_status (const struct thread_resume 
*resumption,
      {
        thread->status_pending_p = 0;

-      last_status = thread->last_status;
+      last_status = thread->last_waitstatus;
        last_ptid = thread->id;
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (own_buffer, last_ptid, &last_status);
        return 1;
      }
    return 0;
@@ -2861,7 +2949,7 @@ resume (struct thread_resume *actions, size_t 
num_actions)
    (*the_target->resume) (actions, num_actions);

    if (non_stop)
-    write_ok (own_buf);
+    write_ok (own_buffer);
    else
      {
        last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
@@ -2871,7 +2959,7 @@ resume (struct thread_resume *actions, size_t 
num_actions)
  	{
  	  /* The client does not support this stop reply.  At least
  	     return error.  */
-	  sprintf (own_buf, "E.No unwaited-for children left.");
+	  sprintf (own_buffer, "E.No unwaited-for children left.");
  	  disable_async_io ();
  	  return;
  	}
@@ -2879,14 +2967,14 @@ resume (struct thread_resume *actions, size_t 
num_actions)
        if (last_status.kind != TARGET_WAITKIND_EXITED
            && last_status.kind != TARGET_WAITKIND_SIGNALLED
  	  && last_status.kind != TARGET_WAITKIND_NO_RESUMED)
-	current_thread->last_status = last_status;
+	current_thread->last_waitstatus = last_status;

        /* From the client's perspective, all-stop mode always stops all
  	 threads implicitly (and the target backend has already done
  	 so by now).  Tag all threads as "want-stopped", so we don't
  	 resume them implicitly without the client telling us to.  */
        gdb_wants_all_threads_stopped ();
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (own_buffer, last_ptid, &last_status);
        disable_async_io ();

        if (last_status.kind == TARGET_WAITKIND_EXITED
@@ -3229,7 +3317,7 @@ queue_stop_reply_callback (thread_info *thread)
        struct vstop_notif *new_notif = XNEW (struct vstop_notif);

        new_notif->ptid = thread->id;
-      new_notif->status = thread->last_status;
+      new_notif->status = thread->last_waitstatus;
        /* Pass the last stop reply back to GDB, but don't notify
  	 yet.  */
        notif_event_enque (&notif_stop,
@@ -3241,19 +3329,19 @@ queue_stop_reply_callback (thread_info *thread)
  	{
  	  if (debug_threads)
  	    {
-	      std::string status_string
-		= target_waitstatus_to_string (&thread->last_status);
+		std::string status_string
+		= target_waitstatus_to_string (&thread->last_waitstatus);

  	      debug_printf ("Reporting thread %s as already stopped with %s\n",
  			    target_pid_to_str (thread->id),
  			    status_string.c_str ());
  	    }

-	  gdb_assert (thread->last_status.kind != TARGET_WAITKIND_IGNORE);
+	  gdb_assert (thread->last_waitstatus.kind != TARGET_WAITKIND_IGNORE);

  	  /* Pass the last stop reply back to GDB, but don't notify
  	     yet.  */
-	  queue_stop_reply (thread->id, &thread->last_status);
+	  queue_stop_reply (thread->id, &thread->last_waitstatus);
  	}
      }
  }
@@ -3267,12 +3355,12 @@ gdb_wants_thread_stopped (thread_info *thread)
  {
    thread->last_resume_kind = resume_stop;

-  if (thread->last_status.kind == TARGET_WAITKIND_IGNORE)
+  if (thread->last_waitstatus.kind == TARGET_WAITKIND_IGNORE)
      {
        /* Most threads are stopped implicitly (all-stop); tag that with
  	 signal 0.  */
-      thread->last_status.kind = TARGET_WAITKIND_STOPPED;
-      thread->last_status.value.sig = GDB_SIGNAL_0;
+      thread->last_waitstatus.kind = TARGET_WAITKIND_STOPPED;
+      thread->last_waitstatus.value.sig = GDB_SIGNAL_0;
      }
  }

@@ -3299,15 +3387,15 @@ clear_pending_status_callback (thread_info *thread)
  static void
  set_pending_status_callback (thread_info *thread)
  {
-  if (thread->last_status.kind != TARGET_WAITKIND_STOPPED
-      || (thread->last_status.value.sig != GDB_SIGNAL_0
+  if (thread->last_waitstatus.kind != TARGET_WAITKIND_STOPPED
+      || (thread->last_waitstatus.value.sig != GDB_SIGNAL_0
  	  /* A breakpoint, watchpoint or finished step from a previous
  	     GDB run isn't considered interesting for a new GDB run.
  	     If we left those pending, the new GDB could consider them
  	     random SIGTRAPs.  This leaves out real async traps.  We'd
  	     have to peek into the (target-specific) siginfo to
  	     distinguish those.  */
-	  && thread->last_status.value.sig != GDB_SIGNAL_TRAP))
+	  && thread->last_waitstatus.value.sig != GDB_SIGNAL_TRAP))
      thread->status_pending_p = 1;
  }

@@ -3329,8 +3417,8 @@ handle_status (char *own_buf)
      {
        for_each_thread (queue_stop_reply_callback);

-      /* The first is sent immediatly.  OK is sent if there is no
-	 stopped thread, which is the same handling of the vStopped
+      /* The first is sent immediately.  OK is sent if there is no
+	 stopped thread, which is the same handling as the vStopped
  	 packet (by design).  */
        notif_write_event (&notif_stop, own_buf);
      }
@@ -3383,8 +3471,8 @@ handle_status (char *own_buf)
  	  general_thread = thread->id;
  	  set_desired_thread ();

-	  gdb_assert (tp->last_status.kind != TARGET_WAITKIND_IGNORE);
-	  prepare_resume_reply (own_buf, tp->id, &tp->last_status);
+	  gdb_assert (tp->last_waitstatus.kind != TARGET_WAITKIND_IGNORE);
+	  prepare_resume_reply (own_buf, tp->id, &tp->last_waitstatus);
  	}
        else
  	strcpy (own_buf, "W00");
@@ -3567,6 +3655,11 @@ captured_main (int argc, char *argv[])
    volatile int multi_mode = 0;
    volatile int attach = 0;
    int was_running;
+  int run_once_arg = 0;
+  int disable_randomization_arg = 1;
+
+  int remote_desc = get_remote_desc();
+  client_states.set_client_state (remote_desc);
    bool selftest = false;
    const char *selftest_filter = NULL;

@@ -3678,15 +3771,15 @@ captured_main (int argc, char *argv[])
  	  break;
  	}
        else if (strcmp (*next_arg, "--disable-randomization") == 0)
-	disable_randomization = 1;
+	disable_randomization_arg = 1;
        else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
-	disable_randomization = 0;
+	disable_randomization_arg = 0;
        else if (strcmp (*next_arg, "--startup-with-shell") == 0)
  	startup_with_shell = true;
        else if (strcmp (*next_arg, "--no-startup-with-shell") == 0)
  	startup_with_shell = false;
        else if (strcmp (*next_arg, "--once") == 0)
-	run_once = 1;
+	run_once_arg = 1;
        else if (strcmp (*next_arg, "--selftest") == 0)
  	selftest = true;
        else if (startswith (*next_arg, "--selftest="))
@@ -3704,6 +3797,9 @@ captured_main (int argc, char *argv[])
        continue;
      }

+  run_once = run_once_arg;
+  disable_randomization = disable_randomization_arg;
+
    if (port == NULL)
      {
        port = *next_arg;
@@ -3765,7 +3861,7 @@ captured_main (int argc, char *argv[])
      initialize_tracepoint ();
    initialize_notif ();

-  own_buf = (char *) xmalloc (PBUFSIZ + 1);
+  own_buffer = (char *) xmalloc (PBUFSIZ + 1);
    mem_buf = (unsigned char *) xmalloc (PBUFSIZ);

    if (selftest)
@@ -3824,10 +3920,6 @@ captured_main (int argc, char *argv[])
      {

        noack_mode = 0;
-      multi_process = 0;
-      report_fork_events = 0;
-      report_vfork_events = 0;
-      report_exec_events = 0;
        /* Be sure we're out of tfind mode.  */
        current_traceframe = -1;
        cont_thread = null_ptid;
@@ -3907,8 +3999,8 @@ captured_main (int argc, char *argv[])

  	  if (response_needed)
  	    {
-	      write_enn (own_buf);
-	      putpkt (own_buf);
+	      write_enn (own_buffer);
+	      putpkt (own_buffer);
  	    }

  	  if (run_once)
@@ -4010,12 +4102,13 @@ process_serial_event (void)
    unsigned char sig;
    int packet_len;
    int new_packet_len = -1;
+  client_state *cs = get_client_state();

    disable_async_io ();

    response_needed = 0;
-  packet_len = getpkt (own_buf);
-  if (packet_len <= 0)
+  packet_length = getpkt (own_buffer);
+  if (packet_length <= 0)
      {
        remote_close ();
        /* Force an event loop break.  */
@@ -4023,31 +4116,31 @@ process_serial_event (void)
      }
    response_needed = 1;

-  char ch = own_buf[0];
+  char ch = own_buffer[0];
    switch (ch)
      {
      case 'q':
-      handle_query (own_buf, packet_len, &new_packet_len);
+      handle_query (own_buffer, packet_length, &new_packet_len);
        break;
      case 'Q':
-      handle_general_set (own_buf);
+      handle_general_set (own_buffer);
        break;
      case 'D':
-      handle_detach (own_buf);
+      handle_detach (own_buffer);
        break;
      case '!':
        extended_protocol = 1;
-      write_ok (own_buf);
+      write_ok (own_buffer);
        break;
      case '?':
-      handle_status (own_buf);
+      handle_status (own_buffer);
        break;
      case 'H':
-      if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
+      if (own_buffer[1] == 'c' || own_buffer[1] == 'g' || own_buffer[1] 
== 's')
  	{
-	  require_running_or_break (own_buf);
+	  require_running_or_break (own_buffer);

-	  ptid_t thread_id = read_ptid (&own_buf[2], NULL);
+	  ptid_t thread_id = read_ptid (&own_buffer[2], NULL);

  	  if (thread_id == null_ptid || thread_id == minus_one_ptid)
  	    thread_id = null_ptid;
@@ -4058,7 +4151,7 @@ process_serial_event (void)

  	      if (thread == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (own_buffer);
  		  break;
  		}

@@ -4069,12 +4162,12 @@ process_serial_event (void)
  	      /* The ptid represents a lwp/tid.  */
  	      if (find_thread_ptid (thread_id) == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (own_buffer);
  		  break;
  		}
  	    }

-	  if (own_buf[1] == 'g')
+	  if (own_buffer[1] == 'g')
  	    {
  	      if (ptid_equal (thread_id, null_ptid))
  		{
@@ -4093,20 +4186,20 @@ process_serial_event (void)
  	      set_desired_thread ();
  	      gdb_assert (current_thread != NULL);
  	    }
-	  else if (own_buf[1] == 'c')
+	  else if (own_buffer[1] == 'c')
  	    cont_thread = thread_id;

-	  write_ok (own_buf);
+	  write_ok (own_buffer);
  	}
        else
  	{
  	  /* Silently ignore it so that gdb can extend the protocol
  	     without compatibility headaches.  */
-	  own_buf[0] = '\0';
+	  own_buffer[0] = '\0';
  	}
        break;
      case 'g':
-      require_running_or_break (own_buf);
+      require_running_or_break (own_buffer);
        if (current_traceframe >= 0)
  	{
  	  struct regcache *regcache
@@ -4114,9 +4207,9 @@ process_serial_event (void)

  	  if (fetch_traceframe_registers (current_traceframe,
  					  regcache, -1) == 0)
-	    registers_to_string (regcache, own_buf);
+	    registers_to_string (regcache, own_buffer);
  	  else
-	    write_enn (own_buf);
+	    write_enn (own_buffer);
  	  free_register_cache (regcache);
  	}
        else
@@ -4124,85 +4217,85 @@ process_serial_event (void)
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (own_buffer);
  	  else
  	    {
  	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_to_string (regcache, own_buf);
+	      registers_to_string (regcache, own_buffer);
  	    }
  	}
        break;
      case 'G':
-      require_running_or_break (own_buf);
+      require_running_or_break (own_buffer);
        if (current_traceframe >= 0)
-	write_enn (own_buf);
+	write_enn (own_buffer);
        else
  	{
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (own_buffer);
  	  else
  	    {
  	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_from_string (regcache, &own_buf[1]);
-	      write_ok (own_buf);
+	      registers_from_string (regcache, &own_buffer[1]);
+	      write_ok (own_buffer);
  	    }
  	}
        break;
      case 'm':
-      require_running_or_break (own_buf);
-      decode_m_packet (&own_buf[1], &mem_addr, &len);
+      require_running_or_break (own_buffer);
+      decode_m_packet (&own_buffer[1], &mem_addr, &len);
        res = gdb_read_memory (mem_addr, mem_buf, len);
        if (res < 0)
-	write_enn (own_buf);
+	write_enn (own_buffer);
        else
-	bin2hex (mem_buf, own_buf, res);
+	bin2hex (mem_buf, own_buffer, res);
        break;
      case 'M':
-      require_running_or_break (own_buf);
-      decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf);
+      require_running_or_break (own_buffer);
+      decode_M_packet (&own_buffer[1], &mem_addr, &len, &mem_buf);
        if (gdb_write_memory (mem_addr, mem_buf, len) == 0)
-	write_ok (own_buf);
+	write_ok (own_buffer);
        else
-	write_enn (own_buf);
+	write_enn (own_buffer);
        break;
      case 'X':
-      require_running_or_break (own_buf);
-      if (decode_X_packet (&own_buf[1], packet_len - 1,
+      require_running_or_break (own_buffer);
+      if (decode_X_packet (&own_buffer[1], packet_length - 1,
  			   &mem_addr, &len, &mem_buf) < 0
  	  || gdb_write_memory (mem_addr, mem_buf, len) != 0)
-	write_enn (own_buf);
+	write_enn (own_buffer);
        else
-	write_ok (own_buf);
+	write_ok (own_buffer);
        break;
      case 'C':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (own_buffer);
+      hex2bin (own_buffer + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (own_buffer, 0, signal);
        break;
      case 'S':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (own_buffer);
+      hex2bin (own_buffer + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (own_buffer, 1, signal);
        break;
      case 'c':
-      require_running_or_break (own_buf);
+      require_running_or_break (own_buffer);
        signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (own_buffer, 0, signal);
        break;
      case 's':
-      require_running_or_break (own_buf);
+      require_running_or_break (own_buffer);
        signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (own_buffer, 1, signal);
        break;
      case 'Z':  /* insert_ ... */
        /* Fallthrough.  */
@@ -4211,12 +4304,12 @@ process_serial_event (void)
  	char *dataptr;
  	ULONGEST addr;
  	int kind;
-	char type = own_buf[1];
+	char type = own_buffer[1];
  	int res;
  	const int insert = ch == 'Z';
-	const char *p = &own_buf[3];
+	char *p = &own_buffer[3];

-	p = unpack_varlen_hex (p, &addr);
+	p = (char*)unpack_varlen_hex (p, &addr);
  	kind = strtol (p + 1, &dataptr, 16);

  	if (insert)
@@ -4242,12 +4335,12 @@ process_serial_event (void)
  	  res = delete_gdb_breakpoint (type, addr, kind);

  	if (res == 0)
-	  write_ok (own_buf);
+	  write_ok (own_buffer);
  	else if (res == 1)
  	  /* Unsupported.  */
-	  own_buf[0] = '\0';
+	  own_buffer[0] = '\0';
  	else
-	  write_enn (own_buf);
+	  write_enn (own_buffer);
  	break;
        }
      case 'k':
@@ -4274,19 +4367,19 @@ process_serial_event (void)

      case 'T':
        {
-	require_running_or_break (own_buf);
+	require_running_or_break (own_buffer);

-	ptid_t thread_id = read_ptid (&own_buf[1], NULL);
+	ptid_t thread_id = read_ptid (&own_buffer[1], NULL);
  	if (find_thread_ptid (thread_id) == NULL)
  	  {
-	    write_enn (own_buf);
+	    write_enn (own_buffer);
  	    break;
  	  }

  	if (mythread_alive (thread_id))
-	  write_ok (own_buf);
+	  write_ok (own_buffer);
  	else
-	  write_enn (own_buf);
+	  write_enn (own_buffer);
        }
        break;
      case 'R':
@@ -4330,26 +4423,26 @@ process_serial_event (void)
  	  /* It is a request we don't understand.  Respond with an
  	     empty packet so that gdb knows that we don't support this
  	     request.  */
-	  own_buf[0] = '\0';
+	  own_buffer[0] = '\0';
  	  break;
  	}
      case 'v':
        /* Extended (long) request.  */
-      handle_v_requests (own_buf, packet_len, &new_packet_len);
+      handle_v_requests (own_buffer, packet_length, &new_packet_len);
        break;

      default:
        /* It is a request we don't understand.  Respond with an empty
  	 packet so that gdb knows that we don't support this
  	 request.  */
-      own_buf[0] = '\0';
+      own_buffer[0] = '\0';
        break;
      }

    if (new_packet_len != -1)
-    putpkt_binary (own_buf, new_packet_len);
+    putpkt_binary (own_buffer, new_packet_len);
    else
-    putpkt (own_buf);
+    putpkt (own_buffer);

    response_needed = 0;

@@ -4427,7 +4520,7 @@ handle_target_event (int err, gdb_client_data 
client_data)
  	     "want-stopped" state to what the client wants, until it
  	     gets a new resume action.  */
  	  current_thread->last_resume_kind = resume_stop;
-	  current_thread->last_status = last_status;
+	  current_thread->last_waitstatus = last_status;
  	}

        if (forward_event)
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 46b614c..db4ed97 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -60,52 +60,19 @@ int vsnprintf(char *str, size_t size, const char 
*format, va_list ap);
  #include "gdb_signals.h"
  #include "target.h"
  #include "mem-break.h"
-#include "gdbthread.h"
-#include "inferiors.h"
  #include "environ.h"
+#include <list>
+#include <map>

  /* Target-specific functions */

  void initialize_low ();

-/* Public variables in server.c */
-
-extern ptid_t cont_thread;
-extern ptid_t general_thread;
-
-extern int server_waiting;
-extern int pass_signals[];
-extern int program_signals[];
-extern int program_signals_p;
-
  extern int disable_packet_vCont;
  extern int disable_packet_Tthread;
  extern int disable_packet_qC;
  extern int disable_packet_qfThreadInfo;

-extern char *own_buf;
-
-extern int run_once;
-extern int multi_process;
-extern int report_fork_events;
-extern int report_vfork_events;
-extern int report_exec_events;
-extern int report_thread_events;
-extern int non_stop;
-
-/* True if the "swbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a software breakpoint
-   and for the server to handle PC adjustment if necessary on this
-   target.  Only enabled if the target supports it.  */
-extern int swbreak_feature;
-
-/* True if the "hwbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a hardware breakpoint.
-   Only enabled if the target supports it.  */
-extern int hwbreak_feature;
-
-extern int disable_randomization;
-
  #if USE_WIN32API
  #include <winsock2.h>
  typedef SOCKET gdb_fildes_t;
@@ -158,8 +125,204 @@ extern void post_fork_inferior (int pid, const 
char *program);
  /* Get the gdb_environ being used in the current session.  */
  extern gdb_environ *get_environ ();

-extern target_waitstatus last_status;
  extern ptid_t last_ptid;
  extern unsigned long signal_pid;

  #endif /* SERVER_H */
+
+/* Description of the remote protocol state for the currently
+   connected target.  This is per-target state, and independent of the
+   selected architecture. */
+
+struct server_state
+{
+  int attach_count_;
+  /* From server.c */
+  /* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
+     `vCont'.  Note the multi-process extensions made `vCont' a
+     requirement, so `Hc pPID.TID' is pretty much undefined.  So
+     CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
+     resuming all threads of the process (again, `Hc' isn't used for
+     multi-process), or a specific thread ptid_t.  */
+  ptid_t cont_thread_;
+  /* The thread set with an `Hg' packet.  */
+  ptid_t general_thread_;
+  /* The PID of the originally created or attached inferior.  Used to
+     send signals to the process when GDB sends us an asynchronous 
interrupt
+     (user hitting Control-C in the client), and to wait for the child 
to exit
+     when no longer debugging it.  */
+
+  unsigned long signal_pid_;
+  /* Last status reported to GDB.  */
+  struct target_waitstatus last_status_;
+  /* Was last status an exit status? (sticky if yes) */
+  int last_status_exited;
+  ptid_t last_ptid_;
+  unsigned char *mem_buf_;
+
+  /* from remote-utils.c */
+  /* Internal buffer used by readchar.
+     These are global to readchar because reschedule_remote needs to be
+     able to tell whether the buffer is empty.  */
+  unsigned char readchar_buf_[BUFSIZ];
+  int readchar_bufcnt_;
+  unsigned char *readchar_bufp_;
+  /* from inferiors.c */
+  std::list<process_info *> all_processes_;
+  std::list<thread_info *> all_threads_;
+
+  struct thread_info *current_thread_;
+};
+
+typedef struct server_state server_state;
+
+
+enum packet_types { other_packet, vContc, vConts, vContt, vRun, 
vAttach, Hg, g_or_m, vStopped };
+typedef enum packet_types packet_types;
+
+enum exit_types { no_exit, have_exit, sent_exit };
+typedef enum exit_types exit_types;
+
+
+struct client_state
+{
+  gdb_fildes_t file_desc;
+  int attached_to_client;
+  int packet_type;
+  int last_packet_type;
+  int pending;
+  int nonstop_pending;
+  int catch_syscalls;
+  ptid_t last_cont_ptid;
+  ptid_t new_general_thread;
+  struct target_waitstatus last_cont_waitstatus;
+
+  /* From server.c */
+  int server_waiting_;
+
+  int extended_protocol_;
+  int response_needed_;
+  int exit_requested_;
+
+  /* --once: Exit after the first connection has closed.  */
+  int run_once_;
+
+  int multi_process_;
+  int report_fork_events_;
+  int report_vfork_events_;
+  int report_exec_events_;
+  int report_thread_events_;
+  /* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
+  int report_no_resumed_;
+  int non_stop_;
+  /* True if the "swbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a software breakpoint
+     and for the server to handle PC adjustment if necessary on this
+     target.  Only enabled if the target supports it.  */
+  int swbreak_feature_;
+  /* True if the "hwbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a hardware breakpoint.
+     Only enabled if the target supports it.  */
+  int hwbreak_feature_;
+
+  /* True if the "vContSupported" feature is active.  In that case, GDB
+     wants us to report whether single step is supported in the reply to
+     "vCont?" packet.  */
+  int vCont_supported_;
+
+  /* Whether we should attempt to disable the operating system's address
+     space randomization feature before starting an inferior.  */
+  int disable_randomization_;
+
+  char *program_name_ = NULL;
+  std::vector<char *> program_args_;
+  std::string wrapper_argv_;
+
+  int packet_length_;
+
+  int pass_signals_[GDB_SIGNAL_LAST];
+  int program_signals_[GDB_SIGNAL_LAST];
+  int program_signals_p_;
+
+  char *notify_buffer_;
+  /* Renamed from own_buf to avoid macro name conflict with a common 
local variable name */
+  char *own_buffer_;
+
+  /* from remote-utils.c */
+  int remote_debug_;
+  /* If true, then GDB has requested noack mode.  */
+  int noack_mode_;
+  /* If true, then we tell GDB to use noack mode by default.  */
+  int transport_is_reliable_;
+
+  server_state *ss;
+
+  client_state () {};
+  client_state (gdb_fildes_t, client_state*);
+};
+
+typedef struct client_state client_state;
+
+
+struct multi_client_states
+{
+public:
+  std::map<gdb_fildes_t,client_state*> cs;
+  client_state *current_cs;
+
+  client_state* get_client_state (void) { return current_cs; }
+  void set_current_client (client_state* p_cs) { current_cs = p_cs; }
+
+  client_state * set_client_state (gdb_fildes_t);
+  void free_client_state (client_state *cs);
+  void delete_client_state (gdb_fildes_t fd);
+};
+
+client_state* get_client_state (void);
+struct multi_client_states * get_client_states (void);
+
+
+#define attach_count	(get_client_state()->ss->attach_count_)
+#define cont_thread	(get_client_state()->ss->cont_thread_)
+#define general_thread	(get_client_state()->ss->general_thread_)
+#define signal_pid	(get_client_state()->ss->signal_pid_)
+#define last_status	(get_client_state()->ss->last_status_)
+#define last_ptid	(get_client_state()->ss->last_ptid_)
+#define mem_buf		(get_client_state()->ss->mem_buf_)
+#define readchar_buf	(get_client_state()->ss->readchar_buf_)
+#define readchar_bufcnt	(get_client_state()->ss->readchar_bufcnt_)
+#define readchar_bufp	(get_client_state()->ss->readchar_bufp_)
+#define all_processes  	(get_client_state()->ss->all_processes_)
+#define all_threads	(get_client_state()->ss->all_threads_)
+#define current_thread   (get_client_state()->ss->current_thread_)
+#define server_waiting	(get_client_state()->server_waiting_)
+#define extended_protocol	(get_client_state()->extended_protocol_)
+#define response_needed	(get_client_state()->response_needed_)
+#define exit_requested	(get_client_state()->exit_requested_)
+#define run_once	(get_client_state()->run_once_)
+#define multi_process	(get_client_state()->multi_process_)
+#define report_fork_events	(get_client_state()->report_fork_events_)
+#define report_vfork_events	(get_client_state()->report_vfork_events_)
+#define report_exec_events     (get_client_state()->report_exec_events_)
+#define report_thread_events   (get_client_state()->report_thread_events_)
+#define report_no_resumed      (get_client_state()->report_no_resumed_)
+#define non_stop	(get_client_state()->non_stop_)
+#define swbreak_feature	(get_client_state()->swbreak_feature_)
+#define hwbreak_feature	(get_client_state()->hwbreak_feature_)
+#define vCont_supported        (get_client_state()->vCont_supported_)
+#define disable_randomization	(get_client_state()->disable_randomization_)
+#define wrapper_argv	(get_client_state()->wrapper_argv_)
+#define program_name	(get_client_state()->program_name_)
+#define program_args	(get_client_state()->program_args_)
+#define packet_length	(get_client_state()->packet_length_)
+#define pass_signals	(get_client_state()->pass_signals_)
+#define program_signals	(get_client_state()->program_signals_)
+#define program_signals_p	(get_client_state()->program_signals_p_)
+#define notify_buffer	(get_client_state()->notify_buffer_)
+#define own_buffer	(get_client_state()->own_buffer_)
+#define remote_debug	(get_client_state()->remote_debug_)
+#define noack_mode	(get_client_state()->noack_mode_)
+#define transport_is_reliable (get_client_state()->transport_is_reliable_)
+
+#include "gdbthread.h"
+#include "inferiors.h"
diff --git a/gdb/nat/linux-personality.h b/gdb/nat/linux-personality.h
index 687086e..bc81f87 100644
--- a/gdb/nat/linux-personality.h
+++ b/gdb/nat/linux-personality.h
@@ -26,6 +26,6 @@
     re-enable the inferior's address space randomization.  */

  extern struct cleanup *maybe_disable_address_space_randomization
-  (int disable_randomization);
+  (int disable_randomization_p);

  #endif /* ! NAT_LINUX_PERSONALITY_H */

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH] Consolidate gdbserver global variables
  2017-11-07 22:03 [RFC][PATCH] Consolidate gdbserver global variables Stan Cox
@ 2018-01-31  3:41 ` Stan Cox
  2018-04-23 17:58   ` Pedro Alves
  0 siblings, 1 reply; 15+ messages in thread
From: Stan Cox @ 2018-01-31  3:41 UTC (permalink / raw)
  To: gdb-patches

 > consolidating the global variables in gdbserver into one of two
 > structures: client_state and server_state.  Client_state are those items
 > that have, or potentially could have, per client values, whereas
 > server_state are those items that have a per process value, i.e. will
 > have the same value for all clients.  This patch, although large,
 > primarily moves global data into one of the two structures
This is the same patch but with one major difference.  No use is made of 
access macros; instead the actual accesses are used.  For example, 
instead of a macro
  #define current_thread    (get_client_state()->ss->current_thread_)
through which all current_thread accesses are made
instead:
    client_state *cs = get_client_state();
    ...
    cs->ss->current_thread
(Another possibility to make the patch smaller would be an additional
  struct thread_info *current_thread = cs->ss->current_thread;
  ... )
Distribution of global variables with more than 10 accesses:
program_name 11
last_ptid 11
program_args 14
remote_debug 22
non_stop 23
general_thread 23
last_status 47
own_buf 106
current_thread 248

The patch below is present in the branch:
  ssh://sourceware.org/git/archer.git::scox/gdbserver-multi-client
(it is large, sorry about that, but much of it is mechanical)

diff --git a/gdb/gdbserver/event-loop.c b/gdb/gdbserver/event-loop.c
index eec0bcf3af6..382d9b3efa7 100644
--- a/gdb/gdbserver/event-loop.c
+++ b/gdb/gdbserver/event-loop.c
@@ -385,6 +385,9 @@ delete_file_handler (gdb_fildes_t fd)
  	;
        prev_ptr->next_file = file_ptr->next_file;
      }
+
+  struct multi_client_states *client_states = get_client_states();
+  client_states->delete_client_state (fd);
    free (file_ptr);
  }

diff --git a/gdb/gdbserver/fork-child.c b/gdb/gdbserver/fork-child.c
index 831e7e13100..74fa5e424c7 100644
--- a/gdb/gdbserver/fork-child.c
+++ b/gdb/gdbserver/fork-child.c
@@ -44,6 +44,8 @@ restore_old_foreground_pgrp (void)
  void
  prefork_hook (const char *args)
  {
+  client_state *cs = get_client_state();
+
    if (debug_threads)
      {
        debug_printf ("args: %s\n", args);
@@ -57,7 +59,7 @@ prefork_hook (const char *args)

    /* Clear this so the backend doesn't get confused, thinking
       CONT_THREAD died, and it needs to resume all threads.  */
-  cont_thread = null_ptid;
+  cs->ss->cont_thread = null_ptid;
  }

  /* See nat/fork-inferior.h.  */
@@ -97,6 +99,7 @@ void
  post_fork_inferior (int pid, const char *program)
  {
  #ifdef SIGTTOU
+  client_state *cs = get_client_state();
    signal (SIGTTOU, SIG_IGN);
    signal (SIGTTIN, SIG_IGN);
    terminal_fd = fileno (stderr);
@@ -106,10 +109,10 @@ post_fork_inferior (int pid, const char *program)
  #endif

    startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED,
-		    &last_status, &last_ptid);
-  current_thread->last_resume_kind = resume_stop;
-  current_thread->last_status = last_status;
-  signal_pid = pid;
+		    &cs->ss->last_status, &cs->ss->last_ptid);
+  cs->ss->current_thread->last_resume_kind = resume_stop;
+  cs->ss->current_thread->last_status = cs->ss->last_status;
+  cs->ss->signal_pid = pid;
    target_post_create_inferior ();
    fprintf (stderr, "Process %s created; pid = %d\n", program, pid);
    fflush (stderr);
diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
index 9a8c72e780e..c5bd1175f22 100644
--- a/gdb/gdbserver/gdbthread.h
+++ b/gdb/gdbserver/gdbthread.h
@@ -73,8 +73,6 @@ struct thread_info
    struct btrace_target_info *btrace;
  };

-extern std::list<thread_info *> all_threads;
-
  void remove_thread (struct thread_info *thread);
  struct thread_info *add_thread (ptid_t ptid, void *target_data);

@@ -95,9 +93,9 @@ template <typename Func>
  static thread_info *
  find_thread (Func func)
  {
-  std::list<thread_info *>::iterator next, cur = all_threads.begin ();
+  std::list<thread_info *>::iterator next, cur = 
get_client_state()->ss->all_threads.begin ();

-  while (cur != all_threads.end ())
+  while (cur != get_client_state()->ss->all_threads.end ())
      {
        next = cur;
        next++;
@@ -141,9 +139,9 @@ template <typename Func>
  static void
  for_each_thread (Func func)
  {
-  std::list<thread_info *>::iterator next, cur = all_threads.begin ();
+  std::list<thread_info *>::iterator next, cur = 
get_client_state()->ss->all_threads.begin ();

-  while (cur != all_threads.end ())
+  while (cur != get_client_state()->ss->all_threads.end ())
      {
        next = cur;
        next++;
@@ -198,7 +196,7 @@ find_thread_in_random (Func func)
  }

  /* Get current thread ID (Linux task ID).  */
-#define current_ptid (current_thread->id)
+#define current_ptid (get_client_state()->ss->current_thread->id)

  /* Get the ptid of THREAD.  */

diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
index d2b5a71bade..4e388a85dc8 100644
--- a/gdb/gdbserver/hostio.c
+++ b/gdb/gdbserver/hostio.c
@@ -29,8 +29,6 @@
  #include <sys/stat.h>
  #include "fileio.h"

-extern int remote_debug;
-
  struct fd_list
  {
    int fd;
diff --git a/gdb/gdbserver/inferiors.c b/gdb/gdbserver/inferiors.c
index 600bf201bff..c63f2026d08 100644
--- a/gdb/gdbserver/inferiors.c
+++ b/gdb/gdbserver/inferiors.c
@@ -22,10 +22,6 @@
  #include "gdbthread.h"
  #include "dll.h"

-std::list<process_info *> all_processes;
-std::list<thread_info *> all_threads;
-
-struct thread_info *current_thread;

  /* The current working directory used to start the inferior.  */
  static const char *current_inferior_cwd = NULL;
@@ -33,16 +29,17 @@ static const char *current_inferior_cwd = NULL;
  struct thread_info *
  add_thread (ptid_t thread_id, void *target_data)
  {
+  client_state *cs = get_client_state();
    struct thread_info *new_thread = XCNEW (struct thread_info);

    new_thread->id = thread_id;
    new_thread->last_resume_kind = resume_continue;
    new_thread->last_status.kind = TARGET_WAITKIND_IGNORE;

-  all_threads.push_back (new_thread);
+  cs->ss->all_threads.push_back (new_thread);

-  if (current_thread == NULL)
-    current_thread = new_thread;
+  if (cs->ss->current_thread == NULL)
+    cs->ss->current_thread = new_thread;

    new_thread->target_data = target_data;

@@ -54,8 +51,10 @@ add_thread (ptid_t thread_id, void *target_data)
  struct thread_info *
  get_first_thread (void)
  {
-  if (!all_threads.empty ())
-    return all_threads.front ();
+  client_state *cs = get_client_state();
+
+  if (!cs->ss->all_threads.empty ())
+    return cs->ss->all_threads.front ();
    else
      return NULL;
  }
@@ -97,14 +96,16 @@ free_one_thread (thread_info *thread)
  void
  remove_thread (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
+
    if (thread->btrace != NULL)
      target_disable_btrace (thread->btrace);

    discard_queued_stop_replies (ptid_of (thread));
-  all_threads.remove (thread);
+  cs->ss->all_threads.remove (thread);
    free_one_thread (thread);
-  if (current_thread == thread)
-    current_thread = NULL;
+  if (cs->ss->current_thread == thread)
+    cs->ss->current_thread = NULL;
  }

  void *
@@ -128,20 +129,24 @@ set_thread_regcache_data (struct thread_info 
*thread, struct regcache *data)
  void
  clear_inferiors (void)
  {
+  client_state *cs = get_client_state();
+
    for_each_thread (free_one_thread);
-  all_threads.clear ();
+  cs->ss->all_threads.clear ();

    clear_dlls ();

-  current_thread = NULL;
+  cs->ss->current_thread = NULL;
  }

  struct process_info *
  add_process (int pid, int attached)
  {
+  client_state *cs = get_client_state();
+
    process_info *process = new process_info (pid, attached);

-  all_processes.push_back (process);
+  cs->ss->all_processes.push_back (process);

    return process;
  }
@@ -153,10 +158,12 @@ add_process (int pid, int attached)
  void
  remove_process (struct process_info *process)
  {
+  client_state *cs = get_client_state();
+
    clear_symbol_cache (&process->symbol_cache);
    free_all_breakpoints (process);
    gdb_assert (find_thread_process (process) == NULL);
-  all_processes.remove (process);
+  cs->ss->all_processes.remove (process);
    delete process;
  }

@@ -173,8 +180,10 @@ find_process_pid (int pid)
  process_info *
  get_first_process (void)
  {
-  if (!all_processes.empty ())
-    return all_processes.front ();
+  client_state *cs = get_client_state();
+
+  if (!cs->ss->all_processes.empty ())
+    return cs->ss->all_processes.front ();
    else
      return NULL;
  }
@@ -209,20 +218,26 @@ get_thread_process (const struct thread_info *thread)
  struct process_info *
  current_process (void)
  {
-  gdb_assert (current_thread != NULL);
-  return get_thread_process (current_thread);
+  client_state *cs = get_client_state();
+
+  gdb_assert (cs->ss->current_thread != NULL);
+  return get_thread_process (cs->ss->current_thread);
  }

  static void
  do_restore_current_thread_cleanup (void *arg)
  {
-  current_thread = (struct thread_info *) arg;
+  client_state *cs = get_client_state();
+
+  cs->ss->current_thread = (struct thread_info *) arg;
  }

  struct cleanup *
  make_cleanup_restore_current_thread (void)
  {
-  return make_cleanup (do_restore_current_thread_cleanup, current_thread);
+  client_state *cs = get_client_state();
+
+  return make_cleanup (do_restore_current_thread_cleanup, 
cs->ss->current_thread);
  }

  /* See common/common-gdbthread.h.  */
@@ -230,8 +245,10 @@ make_cleanup_restore_current_thread (void)
  void
  switch_to_thread (ptid_t ptid)
  {
+  client_state *cs = get_client_state();
+
    gdb_assert (ptid != minus_one_ptid);
-  current_thread = find_thread_ptid (ptid);
+  cs->ss->current_thread = find_thread_ptid (ptid);
  }

  /* See common/common-inferior.h.  */
diff --git a/gdb/gdbserver/inferiors.h b/gdb/gdbserver/inferiors.h
index ccd42df9da4..7f149f53a48 100644
--- a/gdb/gdbserver/inferiors.h
+++ b/gdb/gdbserver/inferiors.h
@@ -85,17 +85,15 @@ pid_of (const process_info *proc)
  struct process_info *current_process (void);
  struct process_info *get_thread_process (const struct thread_info *);

-extern std::list<process_info *> all_processes;
-
  /* Invoke FUNC for each process.  */

  template <typename Func>
  static void
  for_each_process (Func func)
  {
-  std::list<process_info *>::iterator next, cur = all_processes.begin ();
+  std::list<process_info *>::iterator next, cur = 
get_client_state()->ss->all_processes.begin ();

-  while (cur != all_processes.end ())
+  while (cur != get_client_state()->ss->all_processes.end ())
      {
        next = cur;
        next++;
@@ -111,9 +109,9 @@ template <typename Func>
  static process_info *
  find_process (Func func)
  {
-  std::list<process_info *>::iterator next, cur = all_processes.begin ();
+  std::list<process_info *>::iterator next, cur = 
get_client_state()->ss->all_processes.begin ();

-  while (cur != all_processes.end ())
+  while (cur != get_client_state()->ss->all_processes.end ())
      {
        next = cur;
        next++;
@@ -127,8 +125,6 @@ find_process (Func func)
    return NULL;
  }

-extern struct thread_info *current_thread;
-
  /* Return the first process in the processes list.  */
  struct process_info *get_first_process (void);

diff --git a/gdb/gdbserver/linux-aarch32-low.c 
b/gdb/gdbserver/linux-aarch32-low.c
index 12c11a4252b..85b2d0d63b4 100644
--- a/gdb/gdbserver/linux-aarch32-low.c
+++ b/gdb/gdbserver/linux-aarch32-low.c
@@ -171,7 +171,7 @@ struct regs_info regs_info_aarch32 =
  int
  arm_is_thumb_mode (void)
  {
-  struct regcache *regcache = get_thread_regcache (current_thread, 1);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 1);
    unsigned long cpsr;

    collect_register_by_name (regcache, "cpsr", &cpsr);
diff --git a/gdb/gdbserver/linux-aarch64-low.c 
b/gdb/gdbserver/linux-aarch64-low.c
index eccac4da138..b382f4e97d1 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -67,7 +67,7 @@ struct arch_process_info
  static int
  is_64bit_tdesc (void)
  {
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);

    return register_size (regcache->tdesc, 0) == 8;
  }
@@ -253,7 +253,7 @@ aarch64_insert_point (enum raw_bkpt_type type, 
CORE_ADDR addr,
    int ret;
    enum target_hw_bp_type targ_type;
    struct aarch64_debug_reg_state *state
-    = aarch64_get_debug_reg_state (pid_of (current_thread));
+    = aarch64_get_debug_reg_state (pid_of (cs->ss->current_thread));

    if (show_debug_regs)
      fprintf (stderr, "insert_point on entry (addr=0x%08lx, len=%d)\n",
@@ -302,7 +302,7 @@ aarch64_remove_point (enum raw_bkpt_type type, 
CORE_ADDR addr,
    int ret;
    enum target_hw_bp_type targ_type;
    struct aarch64_debug_reg_state *state
-    = aarch64_get_debug_reg_state (pid_of (current_thread));
+    = aarch64_get_debug_reg_state (pid_of (cs->ss->current_thread));

    if (show_debug_regs)
      fprintf (stderr, "remove_point on entry (addr=0x%08lx, len=%d)\n",
@@ -345,7 +345,7 @@ aarch64_stopped_data_address (void)
    int pid, i;
    struct aarch64_debug_reg_state *state;

-  pid = lwpid_of (current_thread);
+  pid = lwpid_of (cs->ss->current_thread);

    /* Get the siginfo.  */
    if (ptrace (PTRACE_GETSIGINFO, pid, NULL, &siginfo) != 0)
@@ -357,7 +357,7 @@ aarch64_stopped_data_address (void)
      return (CORE_ADDR) 0;

    /* Check if the address matches any watched address.  */
-  state = aarch64_get_debug_reg_state (pid_of (current_thread));
+  state = aarch64_get_debug_reg_state (pid_of (cs->ss->current_thread));
    for (i = aarch64_num_wp_regs - 1; i >= 0; --i)
      {
        const unsigned int len = aarch64_watchpoint_length 
(state->dr_ctrl_wp[i]);
@@ -473,7 +473,7 @@ aarch64_arch_setup (void)
    int is_elf64;
    int tid;

-  tid = lwpid_of (current_thread);
+  tid = lwpid_of (cs->ss->current_thread);

    is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);

@@ -482,7 +482,7 @@ aarch64_arch_setup (void)
    else
      current_process ()->tdesc = tdesc_arm_with_neon;

-  aarch64_linux_get_debug_reg_capacity (lwpid_of (current_thread));
+  aarch64_linux_get_debug_reg_capacity (lwpid_of (cs->ss->current_thread));
  }

  static struct regset_info aarch64_regsets[] =
@@ -527,7 +527,7 @@ aarch64_regs_info (void)
  static int
  aarch64_supports_tracepoints (void)
  {
-  if (current_thread == NULL)
+  if (cs->ss->current_thread == NULL)
      return 1;
    else
      {
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index 6c2dcead03d..2bf687b773b 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -528,7 +528,7 @@ arm_insert_point (enum raw_bkpt_type type, CORE_ADDR 
addr,
  	pts[i] = p;

  	/* Only update the threads of the current process.  */
-	for_each_thread (current_thread->id.pid (), [&] (thread_info *thread)
+	for_each_thread (cs->ss->current_thread->id.pid (), [&] (thread_info 
*thread)
  	  {
  	    update_registers_callback (thread, watch, i);
  	  });
@@ -573,7 +573,7 @@ arm_remove_point (enum raw_bkpt_type type, CORE_ADDR 
addr,
  	pts[i].control = arm_hwbp_control_disable (pts[i].control);

  	/* Only update the threads of the current process.  */
-	for_each_thread (current_thread->id.pid (), [&] (thread_info *thread)
+	for_each_thread (cs->ss->current_thread->id.pid (), [&] (thread_info 
*thread)
  	  {
  	    update_registers_callback (thread, watch, i);
  	  });
@@ -589,7 +589,7 @@ arm_remove_point (enum raw_bkpt_type type, CORE_ADDR 
addr,
  static int
  arm_stopped_by_watchpoint (void)
  {
-  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  struct lwp_info *lwp = get_thread_lwp (cs->ss->current_thread);
    siginfo_t siginfo;

    /* We must be able to set hardware watchpoints.  */
@@ -598,7 +598,7 @@ arm_stopped_by_watchpoint (void)

    /* Retrieve siginfo.  */
    errno = 0;
-  ptrace (PTRACE_GETSIGINFO, lwpid_of (current_thread), 0, &siginfo);
+  ptrace (PTRACE_GETSIGINFO, lwpid_of (cs->ss->current_thread), 0, 
&siginfo);
    if (errno != 0)
      return 0;

@@ -624,7 +624,7 @@ arm_stopped_by_watchpoint (void)
  static CORE_ADDR
  arm_stopped_data_address (void)
  {
-  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  struct lwp_info *lwp = get_thread_lwp (cs->ss->current_thread);
    return lwp->arch_private->stopped_data_address;
  }

@@ -872,7 +872,7 @@ arm_get_hwcap (unsigned long *valp)
  static const struct target_desc *
  arm_read_description (void)
  {
-  int pid = lwpid_of (current_thread);
+  int pid = lwpid_of (cs->ss->current_thread);
    unsigned long arm_hwcap = 0;

    /* Query hardware watchpoint/breakpoint capabilities.  */
@@ -919,7 +919,7 @@ arm_read_description (void)
  static void
  arm_arch_setup (void)
  {
-  int tid = lwpid_of (current_thread);
+  int tid = lwpid_of (cs->ss->current_thread);
    int gpregs[18];
    struct iovec iov;

diff --git a/gdb/gdbserver/linux-crisv32-low.c 
b/gdb/gdbserver/linux-crisv32-low.c
index 6eb82175bce..415826072fc 100644
--- a/gdb/gdbserver/linux-crisv32-low.c
+++ b/gdb/gdbserver/linux-crisv32-low.c
@@ -139,7 +139,7 @@ cris_insert_point (enum raw_bkpt_type type, 
CORE_ADDR addr,
    unsigned long ccs;
    struct regcache *regcache;

-  regcache = get_thread_regcache (current_thread, 1);
+  regcache = get_thread_regcache (cs->ss->current_thread, 1);

    /* Read watchpoints are set as access watchpoints, because of GDB's
       inability to deal with pure read watchpoints.  */
@@ -212,7 +212,7 @@ cris_remove_point (enum raw_bkpt_type type, 
CORE_ADDR addr, int len,
    struct regcache *regcache;
    unsigned long bp_d_regs[12];

-  regcache = get_thread_regcache (current_thread, 1);
+  regcache = get_thread_regcache (cs->ss->current_thread, 1);

    /* Read watchpoints are set as access watchpoints, because of GDB's
       inability to deal with pure read watchpoints.  */
@@ -289,7 +289,7 @@ static int
  cris_stopped_by_watchpoint (void)
  {
    unsigned long exs;
-  struct regcache *regcache = get_thread_regcache (current_thread, 1);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 1);

    collect_register_by_name (regcache, "exs", &exs);

@@ -300,7 +300,7 @@ static CORE_ADDR
  cris_stopped_data_address (void)
  {
    unsigned long eda;
-  struct regcache *regcache = get_thread_regcache (current_thread, 1);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 1);

    collect_register_by_name (regcache, "eda", &eda);

diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index 38142bba03d..3359ce7136f 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -455,14 +455,15 @@ linux_arch_setup (void)
  static void
  linux_arch_setup_thread (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct thread_info *saved_thread;

-  saved_thread = current_thread;
-  current_thread = thread;
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = thread;

    linux_arch_setup ();

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
  }

  /* Handle a GNU/Linux extended wait response.  If we see a clone,
@@ -474,6 +475,7 @@ linux_arch_setup_thread (struct thread_info *thread)
  static int
  handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
  {
+  client_state *cs = get_client_state();
    struct lwp_info *event_lwp = *orig_event_lwp;
    int event = linux_ptrace_get_extended_event (wstat);
    struct thread_info *event_thr = get_lwp_thread (event_lwp);
@@ -654,7 +656,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
  	  new_lwp->status_pending_p = 1;
  	  new_lwp->status_pending = status;
  	}
-      else if (report_thread_events)
+      else if (cs->report_thread_events)
  	{
  	  new_lwp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED;
  	  new_lwp->status_pending_p = 1;
@@ -682,7 +684,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
        /* Report the event.  */
        return 0;
      }
-  else if (event == PTRACE_EVENT_EXEC && report_exec_events)
+  else if (event == PTRACE_EVENT_EXEC && cs->report_exec_events)
      {
        struct process_info *proc;
        std::vector<int> syscalls_to_catch;
@@ -705,13 +707,13 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)

        /* Delete the execing process and all its threads.  */
        linux_mourn (proc);
-      current_thread = NULL;
+      cs->ss->current_thread = NULL;

        /* Create a new process/lwp/thread.  */
        proc = linux_add_process (event_pid, 0);
        event_lwp = add_lwp (event_ptid);
        event_thr = get_lwp_thread (event_lwp);
-      gdb_assert (current_thread == event_thr);
+      gdb_assert (cs->ss->current_thread == event_thr);
        linux_arch_setup_thread (event_thr);

        /* Set the event status.  */
@@ -748,6 +750,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
  static CORE_ADDR
  get_pc (struct lwp_info *lwp)
  {
+  client_state *cs = get_client_state();
    struct thread_info *saved_thread;
    struct regcache *regcache;
    CORE_ADDR pc;
@@ -755,16 +758,16 @@ get_pc (struct lwp_info *lwp)
    if (the_low_target.get_pc == NULL)
      return 0;

-  saved_thread = current_thread;
-  current_thread = get_lwp_thread (lwp);
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = get_lwp_thread (lwp);

-  regcache = get_thread_regcache (current_thread, 1);
+  regcache = get_thread_regcache (cs->ss->current_thread, 1);
    pc = (*the_low_target.get_pc) (regcache);

    if (debug_threads)
      debug_printf ("pc is 0x%lx\n", (long) pc);

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
    return pc;
  }

@@ -774,6 +777,7 @@ get_pc (struct lwp_info *lwp)
  static void
  get_syscall_trapinfo (struct lwp_info *lwp, int *sysno)
  {
+  client_state *cs = get_client_state();
    struct thread_info *saved_thread;
    struct regcache *regcache;

@@ -785,16 +789,16 @@ get_syscall_trapinfo (struct lwp_info *lwp, int 
*sysno)
        return;
      }

-  saved_thread = current_thread;
-  current_thread = get_lwp_thread (lwp);
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = get_lwp_thread (lwp);

-  regcache = get_thread_regcache (current_thread, 1);
+  regcache = get_thread_regcache (cs->ss->current_thread, 1);
    (*the_low_target.get_syscall_trapinfo) (regcache, sysno);

    if (debug_threads)
      debug_printf ("get_syscall_trapinfo sysno %d\n", *sysno);

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
  }

  static int check_stopped_by_watchpoint (struct lwp_info *child);
@@ -808,6 +812,7 @@ static int check_stopped_by_watchpoint (struct 
lwp_info *child);
  static int
  save_stop_reason (struct lwp_info *lwp)
  {
+  client_state *cs = get_client_state();
    CORE_ADDR pc;
    CORE_ADDR sw_breakpoint_pc;
    struct thread_info *saved_thread;
@@ -822,11 +827,11 @@ save_stop_reason (struct lwp_info *lwp)
    sw_breakpoint_pc = pc - the_low_target.decr_pc_after_break;

    /* breakpoint_at reads from the current thread.  */
-  saved_thread = current_thread;
-  current_thread = get_lwp_thread (lwp);
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = get_lwp_thread (lwp);

  #if USE_SIGTRAP_SIGINFO
-  if (ptrace (PTRACE_GETSIGINFO, lwpid_of (current_thread),
+  if (ptrace (PTRACE_GETSIGINFO, lwpid_of (cs->ss->current_thread),
  	      (PTRACE_TYPE_ARG3) 0, &siginfo) == 0)
      {
        if (siginfo.si_signo == SIGTRAP)
@@ -897,7 +902,7 @@ save_stop_reason (struct lwp_info *lwp)
        if (pc != sw_breakpoint_pc)
  	{
  	  struct regcache *regcache
-	    = get_thread_regcache (current_thread, 1);
+	    = get_thread_regcache (cs->ss->current_thread, 1);
  	  (*the_low_target.set_pc) (regcache, sw_breakpoint_pc);
  	}

@@ -936,7 +941,7 @@ save_stop_reason (struct lwp_info *lwp)
      }

    lwp->stop_pc = pc;
-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
    return 1;
  }

@@ -997,13 +1002,14 @@ static int
  linux_create_inferior (const char *program,
  		       const std::vector<char *> &program_args)
  {
+  client_state *cs = get_client_state();
    struct lwp_info *new_lwp;
    int pid;
    ptid_t ptid;

    {
      maybe_disable_address_space_randomization restore_personality
-      (disable_randomization);
+      (cs->disable_randomization);
      std::string str_program_args = stringify_argv (program_args);

      pid = fork_inferior (program,
@@ -1028,7 +1034,8 @@ linux_create_inferior (const char *program,
  static void
  linux_post_create_inferior (void)
  {
-  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  client_state *cs = get_client_state();
+  struct lwp_info *lwp = get_thread_lwp (cs->ss->current_thread);

    linux_arch_setup ();

@@ -1037,7 +1044,7 @@ linux_post_create_inferior (void)
        struct process_info *proc = current_process ();
        int options = linux_low_ptrace_options (proc->attached);

-      linux_enable_event_reporting (lwpid_of (current_thread), options);
+      linux_enable_event_reporting (lwpid_of (cs->ss->current_thread), 
options);
        lwp->must_set_ptrace_flags = 0;
      }
  }
@@ -1180,6 +1187,7 @@ static void async_file_mark (void);
  static int
  linux_attach (unsigned long pid)
  {
+  client_state *cs = get_client_state();
    struct process_info *proc;
    struct thread_info *initial_thread;
    ptid_t ptid = ptid_build (pid, pid, 0);
@@ -1219,7 +1227,7 @@ linux_attach (unsigned long pid)
       the thread group reports its initial PTRACE_ATTACH SIGSTOP.  Do
       that now, otherwise, if GDB is fast enough, it could read the
       target description _before_ that initial stop.  */
-  if (non_stop)
+  if (cs->non_stop)
      {
        struct lwp_info *lwp;
        int wstat, lwpid;
@@ -1428,6 +1436,7 @@ linux_kill (int pid)
  static int
  get_detach_signal (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
    enum gdb_signal signo = GDB_SIGNAL_0;
    int status;
    struct lwp_info *lp = get_thread_lwp (thread);
@@ -1468,7 +1477,7 @@ get_detach_signal (struct thread_info *thread)

    signo = gdb_signal_from_host (WSTOPSIG (status));

-  if (program_signals_p && !program_signals[signo])
+  if (cs->program_signals_p && !cs->program_signals[signo])
      {
        if (debug_threads)
  	debug_printf ("GPS: lwp %s had signal %s, but it is in nopass state\n",
@@ -1476,7 +1485,7 @@ get_detach_signal (struct thread_info *thread)
  		      gdb_signal_to_string (signo));
        return 0;
      }
-  else if (!program_signals_p
+  else if (!cs->program_signals_p
  	   /* If we have no way to know which signals GDB does not
  	      want to have passed to the program, assume
  	      SIGTRAP/SIGINT, which is GDB's default.  */
@@ -1709,6 +1718,7 @@ linux_thread_alive (ptid_t ptid)
  static int
  thread_still_has_status_pending_p (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct lwp_info *lp = get_thread_lwp (thread);

    if (!lp->status_pending_p)
@@ -1726,8 +1736,8 @@ thread_still_has_status_pending_p (struct 
thread_info *thread)

        pc = get_pc (lp);

-      saved_thread = current_thread;
-      current_thread = thread;
+      saved_thread = cs->ss->current_thread;
+      cs->ss->current_thread = thread;

        if (pc != lp->stop_pc)
  	{
@@ -1756,7 +1766,7 @@ thread_still_has_status_pending_p (struct 
thread_info *thread)
  	}
  #endif

-      current_thread = saved_thread;
+      cs->ss->current_thread = saved_thread;

        if (discard)
  	{
@@ -2054,10 +2064,11 @@ linux_fast_tracepoint_collecting (struct 
lwp_info *lwp,
  static int
  maybe_move_out_of_jump_pad (struct lwp_info *lwp, int *wstat)
  {
+  client_state *cs = get_client_state();
    struct thread_info *saved_thread;

-  saved_thread = current_thread;
-  current_thread = get_lwp_thread (lwp);
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = get_lwp_thread (lwp);

    if ((wstat == NULL
         || (WIFSTOPPED (*wstat) && WSTOPSIG (*wstat) != SIGTRAP))
@@ -2069,7 +2080,7 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, 
int *wstat)
        if (debug_threads)
  	debug_printf ("Checking whether LWP %ld needs to move out of the "
  		      "jump pad.\n",
-		      lwpid_of (current_thread));
+		      lwpid_of (cs->ss->current_thread));

        fast_tpoint_collect_result r
  	= linux_fast_tracepoint_collecting (lwp, &status);
@@ -2097,8 +2108,8 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, 
int *wstat)
  	      if (debug_threads)
  		debug_printf ("Checking whether LWP %ld needs to move out of "
  			      "the jump pad...it does\n",
-			      lwpid_of (current_thread));
-	      current_thread = saved_thread;
+			      lwpid_of (cs->ss->current_thread));
+	      cs->ss->current_thread = saved_thread;

  	      return 1;
  	    }
@@ -2128,18 +2139,18 @@ maybe_move_out_of_jump_pad (struct lwp_info 
*lwp, int *wstat)
  		   || WSTOPSIG (*wstat) == SIGFPE
  		   || WSTOPSIG (*wstat) == SIGBUS
  		   || WSTOPSIG (*wstat) == SIGSEGV)
-		  && ptrace (PTRACE_GETSIGINFO, lwpid_of (current_thread),
+		  && ptrace (PTRACE_GETSIGINFO, lwpid_of (cs->ss->current_thread),
  			     (PTRACE_TYPE_ARG3) 0, &info) == 0
  		  /* Final check just to make sure we don't clobber
  		     the siginfo of non-kernel-sent signals.  */
  		  && (uintptr_t) info.si_addr == lwp->stop_pc)
  		{
  		  info.si_addr = (void *) (uintptr_t) status.tpoint_addr;
-		  ptrace (PTRACE_SETSIGINFO, lwpid_of (current_thread),
+		  ptrace (PTRACE_SETSIGINFO, lwpid_of (cs->ss->current_thread),
  			  (PTRACE_TYPE_ARG3) 0, &info);
  		}

-	      regcache = get_thread_regcache (current_thread, 1);
+	      regcache = get_thread_regcache (cs->ss->current_thread, 1);
  	      (*the_low_target.set_pc) (regcache, status.tpoint_addr);
  	      lwp->stop_pc = status.tpoint_addr;

@@ -2169,9 +2180,9 @@ maybe_move_out_of_jump_pad (struct lwp_info *lwp, 
int *wstat)
    if (debug_threads)
      debug_printf ("Checking whether LWP %ld needs to move out of the "
  		  "jump pad...no\n",
-		  lwpid_of (current_thread));
+		  lwpid_of (cs->ss->current_thread));

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
    return 0;
  }

@@ -2298,12 +2309,14 @@ dequeue_one_deferred_signal (struct lwp_info 
*lwp, int *wstat)
  static int
  check_stopped_by_watchpoint (struct lwp_info *child)
  {
+  client_state *cs = get_client_state();
+
    if (the_low_target.stopped_by_watchpoint != NULL)
      {
        struct thread_info *saved_thread;

-      saved_thread = current_thread;
-      current_thread = get_lwp_thread (child);
+      saved_thread = cs->ss->current_thread;
+      cs->ss->current_thread = get_lwp_thread (child);

        if (the_low_target.stopped_by_watchpoint ())
  	{
@@ -2316,7 +2329,7 @@ check_stopped_by_watchpoint (struct lwp_info *child)
  	    child->stopped_data_address = 0;
  	}

-      current_thread = saved_thread;
+      cs->ss->current_thread = saved_thread;
      }

    return child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
@@ -2327,18 +2340,19 @@ check_stopped_by_watchpoint (struct lwp_info *child)
  static int
  linux_low_ptrace_options (int attached)
  {
+  client_state *cs = get_client_state();
    int options = 0;

    if (!attached)
      options |= PTRACE_O_EXITKILL;

-  if (report_fork_events)
+  if (cs->report_fork_events)
      options |= PTRACE_O_TRACEFORK;

-  if (report_vfork_events)
+  if (cs->report_vfork_events)
      options |= (PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE);

-  if (report_exec_events)
+  if (cs->report_exec_events)
      options |= PTRACE_O_TRACEEXEC;

    options |= PTRACE_O_TRACESYSGOOD;
@@ -2353,6 +2367,7 @@ linux_low_ptrace_options (int attached)
  static struct lwp_info *
  linux_low_filter_event (int lwpid, int wstat)
  {
+  client_state *cs = get_client_state();
    struct lwp_info *child;
    struct thread_info *thread;
    int have_stop_pc = 0;
@@ -2388,7 +2403,7 @@ linux_low_filter_event (int lwpid, int wstat)
        child_ptid = ptid_build (lwpid, lwpid, 0);
        child = add_lwp (child_ptid);
        child->stopped = 1;
-      current_thread = child->thread;
+      cs->ss->current_thread = child->thread;
      }

    /* If we didn't find a process, one of two things presumably happened:
@@ -2424,7 +2439,7 @@ linux_low_filter_event (int lwpid, int wstat)
        /* If there is at least one more LWP, then the exit signal was
  	 not the end of the debugged application and should be
  	 ignored, unless GDB wants to hear about thread exits.  */
-      if (report_thread_events
+      if (cs->report_thread_events
  	  || last_thread_of_process_p (pid_of (thread)))
  	{
  	  /* Since events are serialized to GDB core, and we can't
@@ -2616,6 +2631,7 @@ static int
  linux_wait_for_event_filtered (ptid_t wait_ptid, ptid_t filter_ptid,
  			       int *wstatp, int options)
  {
+  client_state *cs = get_client_state();
    struct thread_info *event_thread;
    struct lwp_info *event_child, *requested_child;
    sigset_t block_mask, prev_mask;
@@ -2680,7 +2696,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, 
ptid_t filter_ptid,
        *wstatp = event_child->status_pending;
        event_child->status_pending_p = 0;
        event_child->status_pending = 0;
-      current_thread = event_thread;
+      cs->ss->current_thread = event_thread;
        return lwpid_of (event_thread);
      }

@@ -2805,7 +2821,7 @@ linux_wait_for_event_filtered (ptid_t wait_ptid, 
ptid_t filter_ptid,

    sigprocmask (SIG_SETMASK, &prev_mask, NULL);

-  current_thread = event_thread;
+  cs->ss->current_thread = event_thread;

    return lwpid_of (event_thread);
  }
@@ -2829,6 +2845,7 @@ linux_wait_for_event (ptid_t ptid, int *wstatp, 
int options)
  static void
  select_event_lwp (struct lwp_info **orig_lp)
  {
+  client_state *cs = get_client_state();
    int random_selector;
    struct thread_info *event_thread = NULL;

@@ -2840,7 +2857,7 @@ select_event_lwp (struct lwp_info **orig_lp)
       report the pending SIGTRAP, and the core, not having stepped the
       thread, wouldn't understand what the trap was for, and therefore
       would report it to the user as a random signal.  */
-  if (!non_stop)
+  if (!cs->non_stop)
      {
        event_thread = find_thread ([] (thread_info *thread)
  	{
@@ -2963,6 +2980,8 @@ static ptid_t linux_wait_1 (ptid_t ptid,
  static void
  linux_stabilize_threads (void)
  {
+  client_state *cs = get_client_state();
+
    thread_info *thread_stuck = find_thread (stuck_in_jump_pad_callback);

    if (thread_stuck != NULL)
@@ -2973,7 +2992,7 @@ linux_stabilize_threads (void)
        return;
      }

-  thread_info *saved_thread = current_thread;
+  thread_info *saved_thread = cs->ss->current_thread;

    stabilizing_threads = 1;

@@ -2994,13 +3013,13 @@ linux_stabilize_threads (void)

        if (ourstatus.kind == TARGET_WAITKIND_STOPPED)
  	{
-	  lwp = get_thread_lwp (current_thread);
+	  lwp = get_thread_lwp (cs->ss->current_thread);

  	  /* Lock it.  */
  	  lwp_suspended_inc (lwp);

  	  if (ourstatus.value.sig != GDB_SIGNAL_0
-	      || current_thread->last_resume_kind == resume_stop)
+	      || cs->ss->current_thread->last_resume_kind == resume_stop)
  	    {
  	      wstat = W_STOPCODE (gdb_signal_to_host (ourstatus.value.sig));
  	      enqueue_one_deferred_signal (lwp, &wstat);
@@ -3012,7 +3031,7 @@ linux_stabilize_threads (void)

    stabilizing_threads = 0;

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;

    if (debug_threads)
      {
@@ -3048,12 +3067,13 @@ static ptid_t
  filter_exit_event (struct lwp_info *event_child,
  		   struct target_waitstatus *ourstatus)
  {
+  client_state *cs = get_client_state();
    struct thread_info *thread = get_lwp_thread (event_child);
    ptid_t ptid = ptid_of (thread);

    if (!last_thread_of_process_p (pid_of (thread)))
      {
-      if (report_thread_events)
+      if (cs->report_thread_events)
  	ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
        else
  	ourstatus->kind = TARGET_WAITKIND_IGNORE;
@@ -3105,6 +3125,7 @@ static ptid_t
  linux_wait_1 (ptid_t ptid,
  	      struct target_waitstatus *ourstatus, int target_options)
  {
+  client_state *cs = get_client_state();
    int w;
    struct lwp_info *event_child;
    int options;
@@ -3188,7 +3209,7 @@ linux_wait_1 (ptid_t ptid,
        return null_ptid;
      }

-  event_child = get_thread_lwp (current_thread);
+  event_child = get_thread_lwp (cs->ss->current_thread);

    /* linux_wait_for_event only returns an exit status for the last
       child of a process.  Report it.  */
@@ -3203,7 +3224,7 @@ linux_wait_1 (ptid_t ptid,
  	    {
  	      debug_printf ("linux_wait_1 ret = %s, exited with "
  			    "retcode %d\n",
-			    target_pid_to_str (ptid_of (current_thread)),
+			    target_pid_to_str (ptid_of (cs->ss->current_thread)),
  			    WEXITSTATUS (w));
  	      debug_exit ();
  	    }
@@ -3217,7 +3238,7 @@ linux_wait_1 (ptid_t ptid,
  	    {
  	      debug_printf ("linux_wait_1 ret = %s, terminated with "
  			    "signal %d\n",
-			    target_pid_to_str (ptid_of (current_thread)),
+			    target_pid_to_str (ptid_of (cs->ss->current_thread)),
  			    WTERMSIG (w));
  	      debug_exit ();
  	    }
@@ -3226,7 +3247,7 @@ linux_wait_1 (ptid_t ptid,
        if (ourstatus->kind == TARGET_WAITKIND_EXITED)
  	return filter_exit_event (event_child, ourstatus);

-      return ptid_of (current_thread);
+      return ptid_of (cs->ss->current_thread);
      }

    /* If step-over executes a breakpoint instruction, in the case of a
@@ -3256,13 +3277,13 @@ linux_wait_1 (ptid_t ptid,
        if (debug_threads)
  	{
  	  debug_printf ("step-over for %s executed software breakpoint\n",
-			target_pid_to_str (ptid_of (current_thread)));
+			target_pid_to_str (ptid_of (cs->ss->current_thread)));
  	}

        if (increment_pc != 0)
  	{
  	  struct regcache *regcache
-	    = get_thread_regcache (current_thread, 1);
+	    = get_thread_regcache (cs->ss->current_thread, 1);

  	  event_child->stop_pc += increment_pc;
  	  (*the_low_target.set_pc) (regcache, event_child->stop_pc);
@@ -3337,17 +3358,17 @@ linux_wait_1 (ptid_t ptid,
        if (debug_threads)
  	debug_printf ("Got signal %d for LWP %ld.  Check if we need "
  		      "to defer or adjust it.\n",
-		      WSTOPSIG (w), lwpid_of (current_thread));
+		      WSTOPSIG (w), lwpid_of (cs->ss->current_thread));

        /* Allow debugging the jump pad itself.  */
-      if (current_thread->last_resume_kind != resume_step
+      if (cs->ss->current_thread->last_resume_kind != resume_step
  	  && maybe_move_out_of_jump_pad (event_child, &w))
  	{
  	  enqueue_one_deferred_signal (event_child, &w);

  	  if (debug_threads)
  	    debug_printf ("Signal %d for LWP %ld deferred (in jump pad)\n",
-			  WSTOPSIG (w), lwpid_of (current_thread));
+			  WSTOPSIG (w), lwpid_of (cs->ss->current_thread));

  	  linux_resume_one_lwp (event_child, 0, 0, NULL);

@@ -3363,7 +3384,7 @@ linux_wait_1 (ptid_t ptid,
        if (debug_threads)
  	debug_printf ("LWP %ld was trying to move out of the jump pad (%d). "
  		      "Check if we're already there.\n",
-		      lwpid_of (current_thread),
+		      lwpid_of (cs->ss->current_thread),
  		      (int) event_child->collecting_fast_tracepoint);

        trace_event = 1;
@@ -3426,11 +3447,11 @@ linux_wait_1 (ptid_t ptid,
  		    {
  		      debug_printf ("linux_wait_1 ret = %s, stopped "
  				    "while stabilizing threads\n",
-				    target_pid_to_str (ptid_of (current_thread)));
+				    target_pid_to_str (ptid_of (cs->ss->current_thread)));
  		      debug_exit ();
  		    }

-		  return ptid_of (current_thread);
+		  return ptid_of (cs->ss->current_thread);
  		}
  	    }
  	}
@@ -3446,7 +3467,7 @@ linux_wait_1 (ptid_t ptid,
        if (debug_threads)
  	{
  	  debug_printf ("Ignored syscall for LWP %ld.\n",
-			lwpid_of (current_thread));
+			lwpid_of (cs->ss->current_thread));
  	}

        linux_resume_one_lwp (event_child, event_child->stepping,
@@ -3466,7 +3487,7 @@ linux_wait_1 (ptid_t ptid,
       handler. Also never ignore signals that could be caused by a
       breakpoint.  */
    if (WIFSTOPPED (w)
-      && current_thread->last_resume_kind != resume_step
+      && cs->ss->current_thread->last_resume_kind != resume_step
        && (
  #if defined (USE_THREAD_DB) && !defined (__ANDROID__)
  	  (current_process ()->priv->thread_db != NULL
@@ -3474,18 +3495,18 @@ linux_wait_1 (ptid_t ptid,
  	       || WSTOPSIG (w) == __SIGRTMIN + 1))
  	  ||
  #endif
-	  (pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
+	  (cs->pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
  	   && !(WSTOPSIG (w) == SIGSTOP
-		&& current_thread->last_resume_kind == resume_stop)
+		&& cs->ss->current_thread->last_resume_kind == resume_stop)
  	   && !linux_wstatus_maybe_breakpoint (w))))
      {
        siginfo_t info, *info_p;

        if (debug_threads)
  	debug_printf ("Ignored signal %d for LWP %ld.\n",
-		      WSTOPSIG (w), lwpid_of (current_thread));
+		      WSTOPSIG (w), lwpid_of (cs->ss->current_thread));

-      if (ptrace (PTRACE_GETSIGINFO, lwpid_of (current_thread),
+      if (ptrace (PTRACE_GETSIGINFO, lwpid_of (cs->ss->current_thread),
  		  (PTRACE_TYPE_ARG3) 0, &info) == 0)
  	info_p = &info;
        else
@@ -3534,14 +3555,14 @@ linux_wait_1 (ptid_t ptid,
       left the single-step pending -- see
       complete_ongoing_step_over.  */
    report_to_gdb = (!maybe_internal_trap
-		   || (current_thread->last_resume_kind == resume_step
+		   || (cs->ss->current_thread->last_resume_kind == resume_step
  		       && !in_step_range)
  		   || event_child->stop_reason == TARGET_STOPPED_BY_WATCHPOINT
  		   || (!in_step_range
  		       && !bp_explains_trap
  		       && !trace_event
  		       && !step_over_finished
-		       && !(current_thread->last_resume_kind == resume_continue
+		       && !(cs->ss->current_thread->last_resume_kind == resume_continue
  			    && event_child->stop_reason == TARGET_STOPPED_BY_SINGLE_STEP))
  		   || (gdb_breakpoint_here (event_child->stop_pc)
  		       && gdb_condition_true_at_breakpoint (event_child->stop_pc)
@@ -3577,7 +3598,7 @@ linux_wait_1 (ptid_t ptid,
        if (the_low_target.set_pc != NULL)
  	{
  	  struct regcache *regcache
-	    = get_thread_regcache (current_thread, 1);
+	    = get_thread_regcache (cs->ss->current_thread, 1);
  	  (*the_low_target.set_pc) (regcache, event_child->stop_pc);
  	}

@@ -3596,10 +3617,10 @@ linux_wait_1 (ptid_t ptid,
  	     there isn't single-step breakpoint if we finished stepping
  	     over.  */
  	  if (can_software_single_step ()
-	      && has_single_step_breakpoints (current_thread))
+	      && has_single_step_breakpoints (cs->ss->current_thread))
  	    {
  	      stop_all_lwps (0, event_child);
-	      delete_single_step_breakpoints (current_thread);
+	      delete_single_step_breakpoints (cs->ss->current_thread);
  	      unstop_all_lwps (0, event_child);
  	    }
  	}
@@ -3624,7 +3645,7 @@ linux_wait_1 (ptid_t ptid,
  	  debug_printf ("LWP %ld: extended event with waitstatus %s\n",
  			lwpid_of (get_lwp_thread (event_child)), str.c_str ());
  	}
-      if (current_thread->last_resume_kind == resume_step)
+      if (cs->ss->current_thread->last_resume_kind == resume_step)
  	{
  	  if (event_child->step_range_start == event_child->step_range_end)
  	    debug_printf ("GDB wanted to single-step, reporting event.\n");
@@ -3649,10 +3670,10 @@ linux_wait_1 (ptid_t ptid,
  	 staled memory.  */
        int remove_single_step_breakpoints_p = 0;

-      if (non_stop)
+      if (cs->non_stop)
  	{
  	  remove_single_step_breakpoints_p
-	    = has_single_step_breakpoints (current_thread);
+	    = has_single_step_breakpoints (cs->ss->current_thread);
  	}
        else
  	{
@@ -3677,10 +3698,10 @@ linux_wait_1 (ptid_t ptid,
  	     memory.  */
  	  stop_all_lwps (0, event_child);

-	  if (non_stop)
+	  if (cs->non_stop)
  	    {
-	      gdb_assert (has_single_step_breakpoints (current_thread));
-	      delete_single_step_breakpoints (current_thread);
+	      gdb_assert (has_single_step_breakpoints (cs->ss->current_thread));
+	      delete_single_step_breakpoints (cs->ss->current_thread);
  	    }
  	  else
  	    {
@@ -3697,12 +3718,12 @@ linux_wait_1 (ptid_t ptid,
    if (!stabilizing_threads)
      {
        /* In all-stop, stop all threads.  */
-      if (!non_stop)
+      if (!cs->non_stop)
  	stop_all_lwps (0, NULL);

        if (step_over_finished)
  	{
-	  if (!non_stop)
+	  if (!cs->non_stop)
  	    {
  	      /* If we were doing a step-over, all other threads but
  		 the stepping one had been paused in start_step_over,
@@ -3736,7 +3757,7 @@ linux_wait_1 (ptid_t ptid,
  	  select_event_lwp (&event_child);

  	  /* current_thread and event_child must stay in sync.  */
-	  current_thread = get_lwp_thread (event_child);
+	  cs->ss->current_thread = get_lwp_thread (event_child);

  	  event_child->status_pending_p = 0;
  	  w = event_child->status_pending;
@@ -3744,7 +3765,7 @@ linux_wait_1 (ptid_t ptid,


        /* Stabilize threads (move out of jump pads).  */
-      if (!non_stop)
+      if (!cs->non_stop)
  	stabilize_threads ();
      }
    else
@@ -3781,14 +3802,14 @@ linux_wait_1 (ptid_t ptid,
       it was a software breakpoint, and the client doesn't know we can
       adjust the breakpoint ourselves.  */
    if (event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
-      && !swbreak_feature)
+      && !cs->swbreak_feature)
      {
        int decr_pc = the_low_target.decr_pc_after_break;

        if (decr_pc != 0)
  	{
  	  struct regcache *regcache
-	    = get_thread_regcache (current_thread, 1);
+	    = get_thread_regcache (cs->ss->current_thread, 1);
  	  (*the_low_target.set_pc) (regcache, event_child->stop_pc + decr_pc);
  	}
      }
@@ -3799,7 +3820,7 @@ linux_wait_1 (ptid_t ptid,
  			    &ourstatus->value.syscall_number);
        ourstatus->kind = event_child->syscall_state;
      }
-  else if (current_thread->last_resume_kind == resume_stop
+  else if (cs->ss->current_thread->last_resume_kind == resume_stop
  	   && WSTOPSIG (w) == SIGSTOP)
      {
        /* A thread that has been requested to stop by GDB with vCont;t,
@@ -3807,7 +3828,7 @@ linux_wait_1 (ptid_t ptid,
  	 SIGSTOP is an implementation detail.  */
        ourstatus->value.sig = GDB_SIGNAL_0;
      }
-  else if (current_thread->last_resume_kind == resume_stop
+  else if (cs->ss->current_thread->last_resume_kind == resume_stop
  	   && WSTOPSIG (w) != SIGSTOP)
      {
        /* A thread that has been requested to stop by GDB with vCont;t,
@@ -3824,7 +3845,7 @@ linux_wait_1 (ptid_t ptid,
    if (debug_threads)
      {
        debug_printf ("linux_wait_1 ret = %s, %d, %d\n",
-		    target_pid_to_str (ptid_of (current_thread)),
+		    target_pid_to_str (ptid_of (cs->ss->current_thread)),
  		    ourstatus->kind, ourstatus->value.sig);
        debug_exit ();
      }
@@ -3832,7 +3853,7 @@ linux_wait_1 (ptid_t ptid,
    if (ourstatus->kind == TARGET_WAITKIND_EXITED)
      return filter_exit_event (event_child, ourstatus);

-  return ptid_of (current_thread);
+  return ptid_of (cs->ss->current_thread);
  }

  /* Get rid of any pending event in the pipe.  */
@@ -4013,12 +4034,13 @@ lwp_is_marked_dead (struct lwp_info *lwp)
  static void
  wait_for_sigstop (void)
  {
+  client_state *cs = get_client_state();
    struct thread_info *saved_thread;
    ptid_t saved_tid;
    int wstat;
    int ret;

-  saved_thread = current_thread;
+  saved_thread = cs->ss->current_thread;
    if (saved_thread != NULL)
      saved_tid = saved_thread->id;
    else
@@ -4035,7 +4057,7 @@ wait_for_sigstop (void)
    gdb_assert (ret == -1);

    if (saved_thread == NULL || linux_thread_alive (saved_tid))
-    current_thread = saved_thread;
+    cs->ss->current_thread = saved_thread;
    else
      {
        if (debug_threads)
@@ -4044,7 +4066,7 @@ wait_for_sigstop (void)
        /* We can't change the current inferior behind GDB's back,
  	 otherwise, a subsequent command may apply to the wrong
  	 process.  */
-      current_thread = NULL;
+      cs->ss->current_thread = NULL;
      }
  }

@@ -4079,6 +4101,7 @@ stuck_in_jump_pad_callback (thread_info *thread)
  static void
  move_out_of_jump_pad_callback (thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct thread_info *saved_thread;
    struct lwp_info *lwp = get_thread_lwp (thread);
    int *wstat;
@@ -4092,8 +4115,8 @@ move_out_of_jump_pad_callback (thread_info *thread)
    gdb_assert (lwp->stopped);

    /* For gdb_breakpoint_here.  */
-  saved_thread = current_thread;
-  current_thread = thread;
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = thread;

    wstat = lwp->status_pending_p ? &lwp->status_pending : NULL;

@@ -4123,7 +4146,7 @@ move_out_of_jump_pad_callback (thread_info *thread)
    else
      lwp_suspended_inc (lwp);

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
  }

  static bool
@@ -4205,11 +4228,12 @@ enqueue_pending_signal (struct lwp_info *lwp, 
int signal, siginfo_t *info)
  static void
  install_software_single_step_breakpoints (struct lwp_info *lwp)
  {
+  client_state *cs = get_client_state();
    struct thread_info *thread = get_lwp_thread (lwp);
    struct regcache *regcache = get_thread_regcache (thread, 1);
    struct cleanup *old_chain = make_cleanup_restore_current_thread ();

-  current_thread = thread;
+  cs->ss->current_thread = thread;
    std::vector<CORE_ADDR> next_pcs = the_low_target.get_next_pcs 
(regcache);

    for (CORE_ADDR pc : next_pcs)
@@ -4265,6 +4289,7 @@ static void
  linux_resume_one_lwp_throw (struct lwp_info *lwp,
  			    int step, int signal, siginfo_t *info)
  {
+  client_state *cs = get_client_state();
    struct thread_info *thread = get_lwp_thread (lwp);
    struct thread_info *saved_thread;
    int ptrace_request;
@@ -4322,8 +4347,8 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
        return;
      }

-  saved_thread = current_thread;
-  current_thread = thread;
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = thread;

    /* This bit needs some thinking about.  If we get a signal that
       we must report while a single-step reinsert is still pending,
@@ -4399,7 +4424,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,

    if (proc->tdesc != NULL && the_low_target.get_pc != NULL)
      {
-      struct regcache *regcache = get_thread_regcache (current_thread, 1);
+      struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 1);

        lwp->stop_pc = (*the_low_target.get_pc) (regcache);

@@ -4453,7 +4478,7 @@ linux_resume_one_lwp_throw (struct lwp_info *lwp,
  	     of coercing an 8 byte integer to a 4 byte pointer.  */
  	  (PTRACE_TYPE_ARG4) (uintptr_t) signal);

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
    if (errno)
      perror_with_name ("resuming thread");

@@ -4655,6 +4680,7 @@ resume_status_pending_p (thread_info *thread)
  static bool
  need_step_over_p (thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct lwp_info *lwp = get_thread_lwp (thread);
    struct thread_info *saved_thread;
    CORE_ADDR pc;
@@ -4737,8 +4763,8 @@ need_step_over_p (thread_info *thread)
        return false;
      }

-  saved_thread = current_thread;
-  current_thread = thread;
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = thread;

    /* We can only step over breakpoints we know about.  */
    if (breakpoint_here (pc) || fast_tracepoint_jump_here (pc))
@@ -4755,7 +4781,7 @@ need_step_over_p (thread_info *thread)
  			  " GDB breakpoint at 0x%s; skipping step over\n",
  			  lwpid_of (thread), paddress (pc));

-	  current_thread = saved_thread;
+	  cs->ss->current_thread = saved_thread;
  	  return false;
  	}
        else
@@ -4767,13 +4793,13 @@ need_step_over_p (thread_info *thread)

  	  /* We've found an lwp that needs stepping over --- return 1 so
  	     that find_thread stops looking.  */
-	  current_thread = saved_thread;
+	  cs->ss->current_thread = saved_thread;

  	  return true;
  	}
      }

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;

    if (debug_threads)
      debug_printf ("Need step over [LWP %ld]? No, no breakpoint found"
@@ -4796,6 +4822,7 @@ need_step_over_p (thread_info *thread)
  static int
  start_step_over (struct lwp_info *lwp)
  {
+  client_state *cs = get_client_state();
    struct thread_info *thread = get_lwp_thread (lwp);
    struct thread_info *saved_thread;
    CORE_ADDR pc;
@@ -4823,8 +4850,8 @@ start_step_over (struct lwp_info *lwp)
       shouldn't care about.  */
    pc = get_pc (lwp);

-  saved_thread = current_thread;
-  current_thread = thread;
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = thread;

    lwp->bp_reinsert = pc;
    uninsert_breakpoints_at (pc);
@@ -4832,7 +4859,7 @@ start_step_over (struct lwp_info *lwp)

    step = single_step (lwp);

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;

    linux_resume_one_lwp (lwp, step, 0, NULL);

@@ -4848,14 +4875,16 @@ start_step_over (struct lwp_info *lwp)
  static int
  finish_step_over (struct lwp_info *lwp)
  {
+  client_state *cs = get_client_state();
+
    if (lwp->bp_reinsert != 0)
      {
-      struct thread_info *saved_thread = current_thread;
+      struct thread_info *saved_thread = cs->ss->current_thread;

        if (debug_threads)
  	debug_printf ("Finished step over.\n");

-      current_thread = get_lwp_thread (lwp);
+      cs->ss->current_thread = get_lwp_thread (lwp);

        /* Reinsert any breakpoint at LWP->BP_REINSERT.  Note that there
  	 may be no breakpoint to reinsert there by now.  */
@@ -4871,12 +4900,12 @@ finish_step_over (struct lwp_info *lwp)
  	 LWP stopped while doing that.  */
        if (!can_hardware_single_step ())
  	{
-	  gdb_assert (has_single_step_breakpoints (current_thread));
-	  delete_single_step_breakpoints (current_thread);
+	  gdb_assert (has_single_step_breakpoints (cs->ss->current_thread));
+	  delete_single_step_breakpoints (cs->ss->current_thread);
  	}

        step_over_bkpt = null_ptid;
-      current_thread = saved_thread;
+      cs->ss->current_thread = saved_thread;
        return 1;
      }
    else
@@ -5036,6 +5065,7 @@ linux_resume_one_thread (thread_info *thread, bool 
leave_all_stopped)
  static void
  linux_resume (struct thread_resume *resume_info, size_t n)
  {
+  client_state *cs = get_client_state();
    struct thread_info *need_step_over = NULL;

    if (debug_threads)
@@ -5056,7 +5086,7 @@ linux_resume (struct thread_resume *resume_info, 
size_t n)
       logic to each thread individually.  We consume all pending events
       before considering to start a step-over (in all-stop).  */
    bool any_pending = false;
-  if (!non_stop)
+  if (!cs->non_stop)
      any_pending = find_thread (resume_status_pending_p) != NULL;

    /* If there is a thread which would otherwise be resumed, which is
@@ -5327,12 +5357,13 @@ static int
  regsets_fetch_inferior_registers (struct regsets_info *regsets_info,
  				  struct regcache *regcache)
  {
+  client_state *cs = get_client_state();
    struct regset_info *regset;
    int saw_general_regs = 0;
    int pid;
    struct iovec iov;

-  pid = lwpid_of (current_thread);
+  pid = lwpid_of (cs->ss->current_thread);
    for (regset = regsets_info->regsets; regset->size >= 0; regset++)
      {
        void *buf, *data;
@@ -5405,12 +5436,13 @@ static int
  regsets_store_inferior_registers (struct regsets_info *regsets_info,
  				  struct regcache *regcache)
  {
+  client_state *cs = get_client_state();
    struct regset_info *regset;
    int saw_general_regs = 0;
    int pid;
    struct iovec iov;

-  pid = lwpid_of (current_thread);
+  pid = lwpid_of (cs->ss->current_thread);
    for (regset = regsets_info->regsets; regset->size >= 0; regset++)
      {
        void *buf, *data;
@@ -5531,6 +5563,7 @@ static void
  fetch_register (const struct usrregs_info *usrregs,
  		struct regcache *regcache, int regno)
  {
+  client_state *cs = get_client_state();
    CORE_ADDR regaddr;
    int i, size;
    char *buf;
@@ -5550,7 +5583,7 @@ fetch_register (const struct usrregs_info *usrregs,
  	  & -sizeof (PTRACE_XFER_TYPE));
    buf = (char *) alloca (size);

-  pid = lwpid_of (current_thread);
+  pid = lwpid_of (cs->ss->current_thread);
    for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
      {
        errno = 0;
@@ -5579,6 +5612,7 @@ static void
  store_register (const struct usrregs_info *usrregs,
  		struct regcache *regcache, int regno)
  {
+  client_state *cs = get_client_state();
    CORE_ADDR regaddr;
    int i, size;
    char *buf;
@@ -5604,7 +5638,7 @@ store_register (const struct usrregs_info *usrregs,
    else
      collect_register (regcache, regno, buf);

-  pid = lwpid_of (current_thread);
+  pid = lwpid_of (cs->ss->current_thread);
    for (i = 0; i < size; i += sizeof (PTRACE_XFER_TYPE))
      {
        errno = 0;
@@ -5744,7 +5778,8 @@ linux_store_registers (struct regcache *regcache, 
int regno)
  static int
  linux_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
  {
-  int pid = lwpid_of (current_thread);
+  client_state *cs = get_client_state();
+  int pid = lwpid_of (cs->ss->current_thread);
    PTRACE_XFER_TYPE *buffer;
    CORE_ADDR addr;
    int count;
@@ -5833,6 +5868,7 @@ linux_read_memory (CORE_ADDR memaddr, unsigned 
char *myaddr, int len)
  static int
  linux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, 
int len)
  {
+  client_state *cs = get_client_state();
    int i;
    /* Round starting address down to longword boundary.  */
    CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
@@ -5844,7 +5880,7 @@ linux_write_memory (CORE_ADDR memaddr, const 
unsigned char *myaddr, int len)
    /* Allocate buffer of that many longwords.  */
    PTRACE_XFER_TYPE *buffer = XALLOCAVEC (PTRACE_XFER_TYPE, count);

-  int pid = lwpid_of (current_thread);
+  int pid = lwpid_of (cs->ss->current_thread);

    if (len == 0)
      {
@@ -5933,9 +5969,11 @@ linux_look_up_symbols (void)
  static void
  linux_request_interrupt (void)
  {
+  client_state *cs = get_client_state();
+
    /* Send a SIGINT to the process group.  This acts just like the user
       typed a ^C on the controlling terminal.  */
-  kill (-signal_pid, SIGINT);
+  kill (-cs->ss->signal_pid, SIGINT);
  }

  /* Copy LEN bytes from inferior's auxiliary vector starting at OFFSET
@@ -5944,9 +5982,11 @@ linux_request_interrupt (void)
  static int
  linux_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int 
len)
  {
+  client_state *cs = get_client_state();
+
    char filename[PATH_MAX];
    int fd, n;
-  int pid = lwpid_of (current_thread);
+  int pid = lwpid_of (cs->ss->current_thread);

    xsnprintf (filename, sizeof filename, "/proc/%d/auxv", pid);

@@ -6008,7 +6048,8 @@ linux_remove_point (enum raw_bkpt_type type, 
CORE_ADDR addr,
  static int
  linux_stopped_by_sw_breakpoint (void)
  {
-  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  client_state *cs = get_client_state();
+  struct lwp_info *lwp = get_thread_lwp (cs->ss->current_thread);

    return (lwp->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT);
  }
@@ -6028,7 +6069,8 @@ linux_supports_stopped_by_sw_breakpoint (void)
  static int
  linux_stopped_by_hw_breakpoint (void)
  {
-  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  client_state *cs = get_client_state();
+  struct lwp_info *lwp = get_thread_lwp (cs->ss->current_thread);

    return (lwp->stop_reason == TARGET_STOPPED_BY_HW_BREAKPOINT);
  }
@@ -6059,7 +6101,8 @@ linux_supports_software_single_step (void)
  static int
  linux_stopped_by_watchpoint (void)
  {
-  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  client_state *cs = get_client_state();
+  struct lwp_info *lwp = get_thread_lwp (cs->ss->current_thread);

    return lwp->stop_reason == TARGET_STOPPED_BY_WATCHPOINT;
  }
@@ -6067,7 +6110,8 @@ linux_stopped_by_watchpoint (void)
  static CORE_ADDR
  linux_stopped_data_address (void)
  {
-  struct lwp_info *lwp = get_thread_lwp (current_thread);
+  client_state *cs = get_client_state();
+  struct lwp_info *lwp = get_thread_lwp (cs->ss->current_thread);

    return lwp->stopped_data_address;
  }
@@ -6088,7 +6132,7 @@ static int
  linux_read_offsets (CORE_ADDR *text_p, CORE_ADDR *data_p)
  {
    unsigned long text, text_end, data;
-  int pid = lwpid_of (current_thread);
+  int pid = lwpid_of (cs->ss->current_thread);

    errno = 0;

@@ -6133,6 +6177,7 @@ linux_qxfer_osdata (const char *annex,
  static void
  siginfo_fixup (siginfo_t *siginfo, gdb_byte *inf_siginfo, int direction)
  {
+  client_state *cs = get_client_state();
    int done = 0;

    if (the_low_target.siginfo_fixup != NULL)
@@ -6153,14 +6198,15 @@ static int
  linux_xfer_siginfo (const char *annex, unsigned char *readbuf,
  		    unsigned const char *writebuf, CORE_ADDR offset, int len)
  {
+  client_state *cs = get_client_state();
    int pid;
    siginfo_t siginfo;
    gdb_byte inf_siginfo[sizeof (siginfo_t)];

-  if (current_thread == NULL)
+  if (cs->ss->current_thread == NULL)
      return -1;

-  pid = lwpid_of (current_thread);
+  pid = lwpid_of (cs->ss->current_thread);

    if (debug_threads)
      debug_printf ("%s siginfo for lwp %d.\n",
@@ -6441,7 +6487,8 @@ linux_qxfer_spu (const char *annex, unsigned char 
*readbuf,
  		 unsigned const char *writebuf,
  		 CORE_ADDR offset, int len)
  {
-  long pid = lwpid_of (current_thread);
+  client_state *cs = get_client_state();
+  long pid = lwpid_of (cs->ss->current_thread);
    char buf[128];
    int fd = 0;
    int ret = 0;
@@ -6524,7 +6571,7 @@ static int
  linux_read_loadmap (const char *annex, CORE_ADDR offset,
  		    unsigned char *myaddr, unsigned int len)
  {
-  int pid = lwpid_of (current_thread);
+  int pid = lwpid_of (cs->ss->current_thread);
    int addr = -1;
    struct target_loadmap *data = NULL;
    unsigned int actual_length, copy_length;
@@ -6631,9 +6678,11 @@ linux_unpause_all (int unfreeze)
  static int
  linux_prepare_to_access_memory (void)
  {
+  client_state *cs = get_client_state();
+
    /* Neither ptrace nor /proc/PID/mem allow accessing memory through a
       running LWP.  */
-  if (non_stop)
+  if (cs->non_stop)
      linux_pause_all (1);
    return 0;
  }
@@ -6641,9 +6690,11 @@ linux_prepare_to_access_memory (void)
  static void
  linux_done_accessing_memory (void)
  {
+  client_state *cs = get_client_state();
+
    /* Neither ptrace nor /proc/PID/mem allow accessing memory through a
       running LWP.  */
-  if (non_stop)
+  if (cs->non_stop)
      linux_unpause_all (1);
  }

@@ -6988,6 +7039,7 @@ linux_qxfer_libraries_svr4 (const char *annex, 
unsigned char *readbuf,
  			    unsigned const char *writebuf,
  			    CORE_ADDR offset, int len)
  {
+  client_state *cs = get_client_state();
    char *document;
    unsigned document_len;
    struct process_info_private *const priv = current_process ()->priv;
@@ -7029,7 +7081,7 @@ linux_qxfer_libraries_svr4 (const char *annex, 
unsigned char *readbuf,
    if (readbuf == NULL)
      return -1;

-  pid = lwpid_of (current_thread);
+  pid = lwpid_of (cs->ss->current_thread);
    xsnprintf (filename, sizeof filename, "/proc/%d/exe", pid);
    is_elf64 = elf_64_file_p (filename, &machine);
    lmo = is_elf64 ? &lmo_64bit_offsets : &lmo_32bit_offsets;
@@ -7367,7 +7419,9 @@ linux_low_btrace_conf (const struct 
btrace_target_info *tinfo,
  ptid_t
  current_lwp_ptid (void)
  {
-  return ptid_of (current_thread);
+  client_state *cs = get_client_state();
+
+  return ptid_of (cs->ss->current_thread);
  }

  /* Implementation of the target_ops method "breakpoint_kind_from_pc".  */
diff --git a/gdb/gdbserver/linux-mips-low.c b/gdb/gdbserver/linux-mips-low.c
index d423633747a..9054d560157 100644
--- a/gdb/gdbserver/linux-mips-low.c
+++ b/gdb/gdbserver/linux-mips-low.c
@@ -126,7 +126,7 @@ mips_read_description (void)
  {
    if (have_dsp < 0)
      {
-      int pid = lwpid_of (current_thread);
+      int pid = lwpid_of (cs->ss->current_thread);

        errno = 0;
        ptrace (PTRACE_PEEKUSER, pid, DSP_CONTROL, 0);
@@ -467,7 +467,7 @@ mips_insert_point (enum raw_bkpt_type type, 
CORE_ADDR addr,
    enum target_hw_bp_type watch_type;
    uint32_t irw;

-  lwpid = lwpid_of (current_thread);
+  lwpid = lwpid_of (cs->ss->current_thread);
    if (!mips_linux_read_watch_registers (lwpid,
  					&priv->watch_readback,
  					&priv->watch_readback_valid,
@@ -558,7 +558,7 @@ mips_stopped_by_watchpoint (void)
    struct arch_process_info *priv = proc->priv->arch_private;
    int n;
    int num_valid;
-  long lwpid = lwpid_of (current_thread);
+  long lwpid = lwpid_of (cs->ss->current_thread);

    if (!mips_linux_read_watch_registers (lwpid,
  					&priv->watch_readback,
@@ -586,7 +586,7 @@ mips_stopped_data_address (void)
    struct arch_process_info *priv = proc->priv->arch_private;
    int n;
    int num_valid;
-  long lwpid = lwpid_of (current_thread);
+  long lwpid = lwpid_of (cs->ss->current_thread);

    /* On MIPS we don't know the low order 3 bits of the data address.
       GDB does not support remote targets that can't report the
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 36bd373c885..35557ab582c 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -1272,7 +1272,7 @@ ppc_install_fast_tracepoint_jump_pad (CORE_ADDR 
tpoint, CORE_ADDR tpaddr,
    const CORE_ADDR entryaddr = *jump_entry;
    int rsz, min_frame, frame_size, tp_reg;
  #ifdef __powerpc64__
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);
    int is_64 = register_size (regcache->tdesc, 0) == 8;
    int is_opd = is_64 && !is_elfv2_inferior ();
  #else
@@ -3044,7 +3044,7 @@ static struct emit_ops *
  ppc_emit_ops (void)
  {
  #ifdef __powerpc64__
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);

    if (register_size (regcache->tdesc, 0) == 8)
      {
@@ -3062,7 +3062,7 @@ ppc_emit_ops (void)
  static int
  ppc_get_ipa_tdesc_idx (void)
  {
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);
    const struct target_desc *tdesc = regcache->tdesc;

  #ifdef __powerpc64__
diff --git a/gdb/gdbserver/linux-s390-low.c b/gdb/gdbserver/linux-s390-low.c
index 451f42c7c99..d5828549620 100644
--- a/gdb/gdbserver/linux-s390-low.c
+++ b/gdb/gdbserver/linux-s390-low.c
@@ -541,7 +541,7 @@ s390_arch_setup (void)
    struct regset_info *regset;

    /* Check whether the kernel supports extra register sets.  */
-  int pid = pid_of (current_thread);
+  int pid = pid_of (cs->ss->current_thread);
    int have_regset_last_break
      = s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
    int have_regset_system_call
@@ -770,7 +770,7 @@ s390_get_thread_area (int lwpid, CORE_ADDR *addrp)
  {
    CORE_ADDR res = ptrace (PTRACE_PEEKUSER, lwpid, (long) PT_ACR0, 
(long) 0);
  #ifdef __s390x__
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);

    if (register_size (regcache->tdesc, 0) == 4)
      res &= 0xffffffffull;
@@ -1260,7 +1260,7 @@ s390_install_fast_tracepoint_jump_pad (CORE_ADDR 
tpoint,
    unsigned char jbuf[6] = { 0xc0, 0xf4, 0, 0, 0, 0 };	/* jg ... */
    CORE_ADDR buildaddr = *jump_entry;
  #ifdef __s390x__
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);
    int is_64 = register_size (regcache->tdesc, 0) == 8;
    int is_zarch = is_64 || have_hwcap_s390_high_gprs;
    int has_vx = have_hwcap_s390_vx;
@@ -1425,7 +1425,7 @@ s390_get_min_fast_tracepoint_insn_len (void)
  static int
  s390_get_ipa_tdesc_idx (void)
  {
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);
    const struct target_desc *tdesc = regcache->tdesc;

  #ifdef __s390x__
@@ -2798,7 +2798,7 @@ static struct emit_ops *
  s390_emit_ops (void)
  {
  #ifdef __s390x__
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);

    if (register_size (regcache->tdesc, 0) == 8)
      return &s390x_emit_ops;
diff --git a/gdb/gdbserver/linux-tile-low.c b/gdb/gdbserver/linux-tile-low.c
index 620f61d1707..dafbab674ef 100644
--- a/gdb/gdbserver/linux-tile-low.c
+++ b/gdb/gdbserver/linux-tile-low.c
@@ -150,7 +150,7 @@ tile_regs_info (void)
  static void
  tile_arch_setup (void)
  {
-  int pid = pid_of (current_thread);
+  int pid = pid_of (cs->ss->current_thread);
    unsigned int machine;
    int is_elf64 = linux_pid_exe_is_elf_64_file (pid, &machine);

diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 408b54f2577..2fa464e889e 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -181,7 +181,8 @@ static /*const*/ int i386_regmap[] =
  static int
  is_64bit_tdesc (void)
  {
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  client_state *cs = get_client_state();
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);

    return register_size (regcache->tdesc, 0) == 8;
  }
@@ -304,6 +305,7 @@ x86_cannot_fetch_register (int regno)
  static void
  x86_fill_gregset (struct regcache *regcache, void *buf)
  {
+  client_state *cs = get_client_state();
    int i;

  #ifdef __x86_64__
@@ -316,7 +318,7 @@ x86_fill_gregset (struct regcache *regcache, void *buf)
  #ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
        {
          unsigned long base;
-        int lwpid = lwpid_of (current_thread);
+        int lwpid = lwpid_of (cs->ss->current_thread);

          collect_register_by_name (regcache, "fs_base", &base);
          ptrace (PTRACE_ARCH_PRCTL, lwpid, &base, ARCH_SET_FS);
@@ -344,6 +346,7 @@ x86_fill_gregset (struct regcache *regcache, void *buf)
  static void
  x86_store_gregset (struct regcache *regcache, const void *buf)
  {
+  client_state *cs = get_client_state();
    int i;

  #ifdef __x86_64__
@@ -356,7 +359,7 @@ x86_store_gregset (struct regcache *regcache, const 
void *buf)
  #ifndef HAVE_STRUCT_USER_REGS_STRUCT_FS_BASE
        {
          unsigned long base;
-        int lwpid = lwpid_of (current_thread);
+        int lwpid = lwpid_of (cs->ss->current_thread);

          if (ptrace (PTRACE_ARCH_PRCTL, lwpid, &base, ARCH_GET_FS) == 0)
            supply_register_by_name (regcache, "fs_base", &base);
@@ -679,8 +682,9 @@ static int
  x86_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction)
  {
  #ifdef __x86_64__
+  client_state *cs = get_client_state();
    unsigned int machine;
-  int tid = lwpid_of (current_thread);
+  int tid = lwpid_of (cs->ss->current_thread);
    int is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);

    /* Is the inferior 32-bit?  If so, then fixup the siginfo object.  */
@@ -735,6 +739,7 @@ int have_ptrace_getfpxregs =
  static const struct target_desc *
  x86_linux_read_description (void)
  {
+  client_state *cs = get_client_state();
    unsigned int machine;
    int is_elf64;
    int xcr0_features;
@@ -742,7 +747,7 @@ x86_linux_read_description (void)
    static uint64_t xcr0;
    struct regset_info *regset;

-  tid = lwpid_of (current_thread);
+  tid = lwpid_of (cs->ss->current_thread);

    is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);

@@ -860,7 +865,8 @@ x86_linux_read_description (void)
  static void
  x86_linux_update_xmltarget (void)
  {
-  struct thread_info *saved_thread = current_thread;
+  client_state *cs = get_client_state();
+  struct thread_info *saved_thread = cs->ss->current_thread;

    /* Before changing the register cache's internal layout, flush the
       contents of the current valid caches back to the threads, and
@@ -868,15 +874,16 @@ x86_linux_update_xmltarget (void)
    regcache_release ();

    for_each_process ([] (process_info *proc) {
+    client_state *cs = get_client_state();
      int pid = proc->pid;

      /* Look up any thread of this process.  */
-    current_thread = find_any_thread_of_pid (pid);
+    cs->ss->current_thread = find_any_thread_of_pid (pid);

      the_low_target.arch_setup ();
    });

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
  }

  /* Process qSupported query, "xmlRegisters=".  Update the buffer size for
@@ -2824,7 +2831,8 @@ x86_supports_hardware_single_step (void)
  static int
  x86_get_ipa_tdesc_idx (void)
  {
-  struct regcache *regcache = get_thread_regcache (current_thread, 0);
+  client_state *cs = get_client_state();
+  struct regcache *regcache = get_thread_regcache 
(cs->ss->current_thread, 0);
    const struct target_desc *tdesc = regcache->tdesc;

  #ifdef __x86_64__
diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c
index a0b98177296..4e72721498b 100644
--- a/gdb/gdbserver/lynx-low.c
+++ b/gdb/gdbserver/lynx-low.c
@@ -250,10 +250,10 @@ lynx_ptrace_fun ()

  static int
  lynx_create_inferior (const char *program,
-		      const std::vector<char *> &program_args)
+		      const std::vector<char *> &cs->program_args)
  {
    int pid;
-  std::string str_program_args = stringify_argv (program_args);
+  std::string str_program_args = stringify_argv (cs->program_args);

    lynx_debug ("lynx_create_inferior ()");

@@ -350,7 +350,7 @@ lynx_resume (struct thread_resume *resume_info, 
size_t n)
       the moment we resume its execution for the first time.  It is
       fine to use the current_thread's ptid in those cases.  */
    if (ptid_equal (ptid, minus_one_ptid))
-    ptid = ptid_of (current_thread);
+    ptid = ptid_of (cs->ss->current_thread);

    regcache_invalidate_pid (ptid_get_pid (ptid));

@@ -423,7 +423,7 @@ lynx_wait_1 (ptid_t ptid, struct target_waitstatus 
*status, int options)
    ptid_t new_ptid;

    if (ptid_equal (ptid, minus_one_ptid))
-    pid = lynx_ptid_get_pid (ptid_of (current_thread));
+    pid = lynx_ptid_get_pid (ptid_of (cs->ss->current_thread));
    else
      pid = BUILDPID (lynx_ptid_get_pid (ptid), lynx_ptid_get_tid (ptid));

@@ -594,7 +594,7 @@ static void
  lynx_fetch_registers (struct regcache *regcache, int regno)
  {
    struct lynx_regset_info *regset = lynx_target_regsets;
-  ptid_t inferior_ptid = ptid_of (current_thread);
+  ptid_t inferior_ptid = ptid_of (cs->ss->current_thread);

    lynx_debug ("lynx_fetch_registers (regno = %d)", regno);

@@ -619,7 +619,7 @@ static void
  lynx_store_registers (struct regcache *regcache, int regno)
  {
    struct lynx_regset_info *regset = lynx_target_regsets;
-  ptid_t inferior_ptid = ptid_of (current_thread);
+  ptid_t inferior_ptid = ptid_of (cs->ss->current_thread);

    lynx_debug ("lynx_store_registers (regno = %d)", regno);

@@ -655,7 +655,7 @@ lynx_read_memory (CORE_ADDR memaddr, unsigned char 
*myaddr, int len)
    int buf;
    const int xfer_size = sizeof (buf);
    CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
-  ptid_t inferior_ptid = ptid_of (current_thread);
+  ptid_t inferior_ptid = ptid_of (cs->ss->current_thread);

    while (addr < memaddr + len)
      {
@@ -688,7 +688,7 @@ lynx_write_memory (CORE_ADDR memaddr, const unsigned 
char *myaddr, int len)
    int buf;
    const int xfer_size = sizeof (buf);
    CORE_ADDR addr = memaddr & -(CORE_ADDR) xfer_size;
-  ptid_t inferior_ptid = ptid_of (current_thread);
+  ptid_t inferior_ptid = ptid_of (cs->ss->current_thread);

    while (addr < memaddr + len)
      {
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index bb385733fe4..dca4756bacd 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -1301,6 +1301,8 @@ add_breakpoint_condition (struct gdb_breakpoint 
*bp, const char **condition)
  static int
  gdb_condition_true_at_breakpoint_z_type (char z_type, CORE_ADDR addr)
  {
+  client_state *cs = get_client_state();
+
    /* Fetch registers for the current inferior.  */
    struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1);
    ULONGEST value = 0;
@@ -1316,7 +1318,7 @@ gdb_condition_true_at_breakpoint_z_type (char 
z_type, CORE_ADDR addr)
    if (bp->cond_list == NULL)
      return 1;

-  ctx.regcache = get_thread_regcache (current_thread, 1);
+  ctx.regcache = get_thread_regcache (cs->ss->current_thread, 1);
    ctx.tframe = NULL;
    ctx.tpoint = NULL;

@@ -1429,6 +1431,8 @@ gdb_no_commands_at_breakpoint (CORE_ADDR where)
  static int
  run_breakpoint_commands_z_type (char z_type, CORE_ADDR addr)
  {
+  client_state *cs = get_client_state();
+
    /* Fetch registers for the current inferior.  */
    struct gdb_breakpoint *bp = find_gdb_breakpoint (z_type, addr, -1);
    ULONGEST value = 0;
@@ -1439,7 +1443,7 @@ run_breakpoint_commands_z_type (char z_type, 
CORE_ADDR addr)
    if (bp == NULL)
      return 1;

-  ctx.regcache = get_thread_regcache (current_thread, 1);
+  ctx.regcache = get_thread_regcache (cs->ss->current_thread, 1);
    ctx.tframe = NULL;
    ctx.tpoint = NULL;

@@ -1479,6 +1483,7 @@ gdb_breakpoint_here (CORE_ADDR where)
  void
  set_single_step_breakpoint (CORE_ADDR stop_at, ptid_t ptid)
  {
+  client_state *cs = get_client_state();
    struct single_step_breakpoint *bp;

    gdb_assert (ptid_get_pid (current_ptid) == ptid_get_pid (ptid));
@@ -1491,6 +1496,7 @@ set_single_step_breakpoint (CORE_ADDR stop_at, 
ptid_t ptid)
  void
  delete_single_step_breakpoints (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct process_info *proc = get_thread_process (thread);
    struct breakpoint *bp, **bp_link;

@@ -1503,13 +1509,13 @@ delete_single_step_breakpoints (struct 
thread_info *thread)
  	  && ptid_equal (((struct single_step_breakpoint *) bp)->ptid,
  			 ptid_of (thread)))
  	{
-	  struct thread_info *saved_thread = current_thread;
+	  struct thread_info *saved_thread = cs->ss->current_thread;

-	  current_thread = thread;
+	  cs->ss->current_thread = thread;
  	  *bp_link = bp->next;
  	  release_breakpoint (proc, bp);
  	  bp = *bp_link;
-	  current_thread = saved_thread;
+	  cs->ss->current_thread = saved_thread;
  	}
        else
  	{
@@ -1591,6 +1597,7 @@ uninsert_all_breakpoints (void)
  void
  uninsert_single_step_breakpoints (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct process_info *proc = get_thread_process (thread);
    struct breakpoint *bp;

@@ -1606,11 +1613,11 @@ uninsert_single_step_breakpoints (struct 
thread_info *thread)
  	   reinsert breakpoint.  */
  	if (bp->raw->refcount == 1)
  	  {
-	    struct thread_info *saved_thread = current_thread;
+	    struct thread_info *saved_thread = cs->ss->current_thread;

-	    current_thread = thread;
+	    cs->ss->current_thread = thread;
  	    uninsert_raw_breakpoint (bp->raw);
-	    current_thread = saved_thread;
+	    cs->ss->current_thread = saved_thread;
  	  }
        }
      }
@@ -1701,6 +1708,7 @@ reinsert_all_breakpoints (void)
  void
  reinsert_single_step_breakpoints (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct process_info *proc = get_thread_process (thread);
    struct breakpoint *bp;

@@ -1714,11 +1722,11 @@ reinsert_single_step_breakpoints (struct 
thread_info *thread)

  	  if (bp->raw->refcount == 1)
  	    {
-	      struct thread_info *saved_thread = current_thread;
+	      struct thread_info *saved_thread = cs->ss->current_thread;

-	      current_thread = thread;
+	      cs->ss->current_thread = thread;
  	      reinsert_raw_breakpoint (bp->raw);
-	      current_thread = saved_thread;
+	      cs->ss->current_thread = saved_thread;
  	    }
  	}
      }
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 5ff7079123f..b2ca4b50207 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -79,6 +79,7 @@ notif_write_event (struct notif_server *notif, char 
*own_buf)
  int
  handle_notif_ack (char *own_buf, int packet_len)
  {
+  client_state *cs = get_client_state();
    size_t i;
    struct notif_server *np;

@@ -103,7 +104,7 @@ handle_notif_ack (char *own_buf, int packet_len)
        struct notif_event *head
  	= QUEUE_deque (notif_event_p, np->queue);

-      if (remote_debug)
+      if (cs->remote_debug)
  	debug_printf ("%s: acking %d\n", np->ack_name,
  		      QUEUE_length (notif_event_p, np->queue));

@@ -121,9 +122,11 @@ void
  notif_event_enque (struct notif_server *notif,
  		   struct notif_event *event)
  {
+  client_state *cs = get_client_state();
+
    QUEUE_enque (notif_event_p, notif->queue, event);

-  if (remote_debug)
+  if (cs->remote_debug)
      debug_printf ("pending events: %s %d\n", notif->notif_name,
  		  QUEUE_length (notif_event_p, notif->queue));

diff --git a/gdb/gdbserver/nto-low.c b/gdb/gdbserver/nto-low.c
index a570ca9991c..02c5ece47d2 100644
--- a/gdb/gdbserver/nto-low.c
+++ b/gdb/gdbserver/nto-low.c
@@ -352,12 +352,12 @@ nto_read_auxv_from_initial_stack (CORE_ADDR 
initial_stack,

  static int
  nto_create_inferior (const char *program,
-		     const std::vector<char *> &program_args)
+		     const std::vector<char *> &cs->program_args)
  {
    struct inheritance inherit;
    pid_t pid;
    sigset_t set;
-  std::string str_program_args = stringify_argv (program_args);
+  std::string str_program_args = stringify_argv (cs->program_args);

    TRACE ("%s %s\n", __func__, program);
    /* Clear any pending SIGUSR1's but keep the behavior the same.  */
@@ -625,12 +625,12 @@ nto_fetch_registers (struct regcache *regcache, 
int regno)
    if (regno >= the_low_target.num_regs)
      return;

-  if (current_thread == NULL)
+  if (cs->ss->current_thread == NULL)
      {
        TRACE ("current_thread is NULL\n");
        return;
      }
-  ptid_t ptid = ptid_of (current_thread);
+  ptid_t ptid = ptid_of (cs->ss->current_thread);
    if (!nto_set_thread (ptid))
      return;

@@ -671,12 +671,12 @@ nto_store_registers (struct regcache *regcache, 
int regno)

    TRACE ("%s (regno:%d)\n", __func__, regno);

-  if (current_thread == NULL)
+  if (cs->ss->current_thread == NULL)
      {
        TRACE ("current_thread is NULL\n");
        return;
      }
-  ptid_t ptid = ptid_of (current_thread);
+  ptid_t ptid = ptid_of (cs->ss->current_thread);
    if (!nto_set_thread (ptid))
      return;

@@ -863,9 +863,9 @@ nto_stopped_by_watchpoint (void)
    int ret = 0;

    TRACE ("%s\n", __func__);
-  if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
+  if (nto_inferior.ctl_fd != -1 && cs->ss->current_thread != NULL)
      {
-      ptid_t ptid = ptid_of (current_thread);
+      ptid_t ptid = ptid_of (cs->ss->current_thread);
        if (nto_set_thread (ptid))
  	{
  	  const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR
@@ -893,9 +893,9 @@ nto_stopped_data_address (void)
    CORE_ADDR ret = (CORE_ADDR)0;

    TRACE ("%s\n", __func__);
-  if (nto_inferior.ctl_fd != -1 && current_thread != NULL)
+  if (nto_inferior.ctl_fd != -1 && cs->ss->current_thread != NULL)
      {
-      ptid_t ptid = ptid_of (current_thread);
+      ptid_t ptid = ptid_of (cs->ss->current_thread);

        if (nto_set_thread (ptid))
  	{
diff --git a/gdb/gdbserver/proc-service.c b/gdb/gdbserver/proc-service.c
index f7912b884c5..01a9371465a 100644
--- a/gdb/gdbserver/proc-service.c
+++ b/gdb/gdbserver/proc-service.c
@@ -104,6 +104,7 @@ ps_err_e
  ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
  {
  #ifdef HAVE_REGSETS
+  client_state *cs = get_client_state();
    struct lwp_info *lwp;
    struct thread_info *reg_thread, *saved_thread;
    struct regcache *regcache;
@@ -113,12 +114,12 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t 
lwpid, prgregset_t gregset)
      return PS_ERR;

    reg_thread = get_lwp_thread (lwp);
-  saved_thread = current_thread;
-  current_thread = reg_thread;
-  regcache = get_thread_regcache (current_thread, 1);
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = reg_thread;
+  regcache = get_thread_regcache (cs->ss->current_thread, 1);
    gregset_info ()->fill_function (regcache, gregset);

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
    return PS_OK;
  #else
    return PS_ERR;
@@ -161,5 +162,7 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t 
lwpid, const prfpregset_t *fpregs
  pid_t
  ps_getpid (gdb_ps_prochandle_t ph)
  {
-  return pid_of (current_thread);
+  client_state *cs = get_client_state();
+
+  return pid_of (cs->ss->current_thread);
  }
diff --git a/gdb/gdbserver/regcache.c b/gdb/gdbserver/regcache.c
index 1bb15900dd2..0ae73fb78e8 100644
--- a/gdb/gdbserver/regcache.c
+++ b/gdb/gdbserver/regcache.c
@@ -26,6 +26,7 @@
  struct regcache *
  get_thread_regcache (struct thread_info *thread, int fetch)
  {
+  client_state *cs = get_client_state();
    struct regcache *regcache;

    regcache = thread_regcache_data (thread);
@@ -49,14 +50,14 @@ get_thread_regcache (struct thread_info *thread, int 
fetch)

    if (fetch && regcache->registers_valid == 0)
      {
-      struct thread_info *saved_thread = current_thread;
+      struct thread_info *saved_thread = cs->ss->current_thread;

-      current_thread = thread;
+      cs->ss->current_thread = thread;
        /* Invalidate all registers, to prevent stale left-overs.  */
        memset (regcache->register_status, REG_UNAVAILABLE,
  	      regcache->tdesc->reg_defs.size ());
        fetch_inferior_registers (regcache, -1);
-      current_thread = saved_thread;
+      cs->ss->current_thread = saved_thread;
        regcache->registers_valid = 1;
      }

@@ -74,6 +75,7 @@ get_thread_regcache_for_ptid (ptid_t ptid)
  void
  regcache_invalidate_thread (struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
    struct regcache *regcache;

    regcache = thread_regcache_data (thread);
@@ -83,11 +85,11 @@ regcache_invalidate_thread (struct thread_info *thread)

    if (regcache->registers_valid)
      {
-      struct thread_info *saved_thread = current_thread;
+      struct thread_info *saved_thread = cs->ss->current_thread;

-      current_thread = thread;
+      cs->ss->current_thread = thread;
        store_inferior_registers (regcache, -1);
-      current_thread = saved_thread;
+      cs->ss->current_thread = saved_thread;
      }

    regcache->registers_valid = 0;
@@ -107,8 +109,10 @@ regcache_invalidate_pid (int pid)
  void
  regcache_invalidate (void)
  {
+  client_state *cs = get_client_state();
+
    /* Only update the threads of the current process.  */
-  int pid = current_thread->id.pid ();
+  int pid = cs->ss->current_thread->id.pid ();

    regcache_invalidate_pid (pid);
  }
diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 3b5a459ae4c..99ba97c02ca 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -103,7 +103,6 @@ struct sym_cache
    struct sym_cache *next;
  };

-int remote_debug = 0;
  struct ui_file *gdb_stdlog;

  static int remote_is_stdio = 0;
@@ -115,16 +114,18 @@ static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
  extern int using_threads;
  extern int debug_threads;

-/* If true, then GDB has requested noack mode.  */
-int noack_mode = 0;
-/* If true, then we tell GDB to use noack mode by default.  */
-int transport_is_reliable = 0;
-
  #ifdef USE_WIN32API
  # define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)
  #endif

+int
+get_remote_desc (void)
+{
+  return remote_desc;
+}
+
+
  int
  gdb_connected (void)
  {
@@ -156,6 +157,7 @@ enable_async_notification (int fd)
  static int
  handle_accept_event (int err, gdb_client_data client_data)
  {
+  client_state *cs = get_client_state();
    struct sockaddr_in sockaddr;
    socklen_t tmp;

@@ -167,6 +169,9 @@ handle_accept_event (int err, gdb_client_data 
client_data)
    if (remote_desc == -1)
      perror_with_name ("Accept failed");

+  struct multi_client_states *client_states = get_client_states();
+  client_states->set_client_state (remote_desc);
+
    /* Enable TCP keep alive process. */
    tmp = 1;
    setsockopt (remote_desc, SOL_SOCKET, SO_KEEPALIVE,
@@ -183,7 +188,7 @@ handle_accept_event (int err, gdb_client_data 
client_data)
  				   exits when the remote side dies.  */
  #endif

-  if (run_once)
+  if (cs->run_once)
      {
  #ifndef USE_WIN32API
        close (listen_desc);		/* No longer need this */
@@ -222,6 +227,7 @@ handle_accept_event (int err, gdb_client_data 
client_data)
  void
  remote_prepare (const char *name)
  {
+  client_state *cs = get_client_state();
    const char *port_str;
  #ifdef USE_WIN32API
    static int winsock_initialized;
@@ -238,14 +244,14 @@ remote_prepare (const char *name)
  	 call to remote_open so start_inferior knows the connection is
  	 via stdio.  */
        remote_is_stdio = 1;
-      transport_is_reliable = 1;
+      cs->transport_is_reliable = 1;
        return;
      }

    port_str = strchr (name, ':');
    if (port_str == NULL)
      {
-      transport_is_reliable = 0;
+      cs->transport_is_reliable = 0;
        return;
      }

@@ -280,7 +286,7 @@ remote_prepare (const char *name)
        || listen (listen_desc, 1))
      perror_with_name ("Can't bind address");

-  transport_is_reliable = 1;
+  cs->transport_is_reliable = 1;
  }

  /* Open a connection to a remote debugger.
@@ -485,9 +491,10 @@ try_rle (char *buf, int remaining, unsigned char 
*csum, char **p)
  char *
  write_ptid (char *buf, ptid_t ptid)
  {
+  client_state *cs = get_client_state();
    int pid, tid;

-  if (multi_process)
+  if (cs->multi_process)
      {
        pid = ptid_get_pid (ptid);
        if (pid < 0)
@@ -594,6 +601,7 @@ read_prim (void *buf, int count)
  static int
  putpkt_binary_1 (char *buf, int cnt, int is_notif)
  {
+  client_state *cs = get_client_state();
    int i;
    unsigned char csum = 0;
    char *buf2;
@@ -631,10 +639,10 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  return -1;
  	}

-      if (noack_mode || is_notif)
+      if (cs->noack_mode || is_notif)
  	{
  	  /* Don't expect an ack then.  */
-	  if (remote_debug)
+	  if (cs->remote_debug)
  	    {
  	      if (is_notif)
  		debug_printf ("putpkt (\"%s\"); [notif]\n", buf2);
@@ -645,7 +653,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  break;
  	}

-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf ("putpkt (\"%s\"); [looking for ack]\n", buf2);
  	  debug_flush ();
@@ -659,14 +667,14 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  return -1;
  	}

-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf ("[received '%c' (0x%x)]\n", cc, cc);
  	  debug_flush ();
  	}

        /* Check for an input interrupt while we're here.  */
-      if (cc == '\003' && current_thread != NULL)
+      if (cc == '\003' && cs->ss->current_thread != NULL)
  	(*the_target->request_interrupt) ();
      }
    while (cc != '+');
@@ -838,30 +846,23 @@ initialize_async_io (void)
  #endif
  }

-/* Internal buffer used by readchar.
-   These are global to readchar because reschedule_remote needs to be
-   able to tell whether the buffer is empty.  */
-
-static unsigned char readchar_buf[BUFSIZ];
-static int readchar_bufcnt = 0;
-static unsigned char *readchar_bufp;
-
  /* Returns next char from remote GDB.  -1 if error.  */

  static int
  readchar (void)
  {
+  client_state *cs = get_client_state();
    int ch;

-  if (readchar_bufcnt == 0)
+  if (cs->ss->readchar_bufcnt == 0)
      {
-      readchar_bufcnt = read_prim (readchar_buf, sizeof (readchar_buf));
+      cs->ss->readchar_bufcnt = read_prim (cs->ss->readchar_buf, sizeof 
(cs->ss->readchar_buf));

-      if (readchar_bufcnt <= 0)
+      if (cs->ss->readchar_bufcnt <= 0)
  	{
-	  if (readchar_bufcnt == 0)
+	  if (cs->ss->readchar_bufcnt == 0)
  	    {
-	      if (remote_debug)
+	      if (cs->remote_debug)
  		debug_printf ("readchar: Got EOF\n");
  	    }
  	  else
@@ -870,11 +871,11 @@ readchar (void)
  	  return -1;
  	}

-      readchar_bufp = readchar_buf;
+      cs->ss->readchar_bufp = cs->ss->readchar_buf;
      }

-  readchar_bufcnt--;
-  ch = *readchar_bufp++;
+  cs->ss->readchar_bufcnt--;
+  ch = *cs->ss->readchar_bufp++;
    reschedule ();
    return ch;
  }
@@ -884,7 +885,9 @@ readchar (void)
  static void
  reset_readchar (void)
  {
-  readchar_bufcnt = 0;
+  client_state *cs = get_client_state();
+
+  cs->ss->readchar_bufcnt = 0;
    if (readchar_callback != NOT_SCHEDULED)
      {
        delete_callback_event (readchar_callback);
@@ -897,12 +900,13 @@ reset_readchar (void)
  static int
  process_remaining (void *context)
  {
+  client_state *cs = get_client_state();
    int res;

    /* This is a one-shot event.  */
    readchar_callback = NOT_SCHEDULED;

-  if (readchar_bufcnt > 0)
+  if (cs->ss->readchar_bufcnt > 0)
      res = handle_serial_event (0, NULL);
    else
      res = 0;
@@ -916,7 +920,9 @@ process_remaining (void *context)
  static void
  reschedule (void)
  {
-  if (readchar_bufcnt > 0 && readchar_callback == NOT_SCHEDULED)
+  client_state *cs = get_client_state();
+
+  if (cs->ss->readchar_bufcnt > 0 && readchar_callback == NOT_SCHEDULED)
      readchar_callback = append_callback_event (process_remaining, NULL);
  }

@@ -926,6 +932,7 @@ reschedule (void)
  int
  getpkt (char *buf)
  {
+  client_state *cs = get_client_state();
    char *bp;
    unsigned char csum, c1, c2;
    int c;
@@ -948,7 +955,7 @@ getpkt (char *buf)

  	  if (c == '$')
  	    break;
-	  if (remote_debug)
+	  if (cs->remote_debug)
  	    {
  	      debug_printf ("[getpkt: discarding char '%c']\n", c);
  	      debug_flush ();
@@ -977,7 +984,7 @@ getpkt (char *buf)
        if (csum == (c1 << 4) + c2)
  	break;

-      if (noack_mode)
+      if (cs->noack_mode)
  	{
  	  fprintf (stderr,
  		   "Bad checksum, sentsum=0x%x, csum=0x%x, "
@@ -993,9 +1000,9 @@ getpkt (char *buf)
  	return -1;
      }

-  if (!noack_mode)
+  if (!cs->noack_mode)
      {
-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf ("getpkt (\"%s\");  [sending ack] \n", buf);
  	  debug_flush ();
@@ -1004,7 +1011,7 @@ getpkt (char *buf)
        if (write_prim ("+", 1) != 1)
  	return -1;

-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf ("[sent ack]\n");
  	  debug_flush ();
@@ -1012,7 +1019,7 @@ getpkt (char *buf)
      }
    else
      {
-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf ("getpkt (\"%s\");  [no ack sent] \n", buf);
  	  debug_flush ();
@@ -1028,7 +1035,7 @@ getpkt (char *buf)
       check for interrupt after the vCont;c packet, the interrupt character
       would stay in the buffer unattended until after the next (unrelated)
       stop.  */
-  while (readchar_bufcnt > 0 && *readchar_bufp == '\003')
+  while (cs->ss->readchar_bufcnt > 0 && *cs->ss->readchar_bufp == '\003')
      {
        /* Consume the interrupt character in the buffer.  */
        readchar ();
@@ -1081,6 +1088,8 @@ void
  prepare_resume_reply (char *buf, ptid_t ptid,
  		      struct target_waitstatus *status)
  {
+  client_state *cs = get_client_state();
+
    if (debug_threads)
      debug_printf ("Writing resume reply for %s:%d\n",
  		  target_pid_to_str (ptid), status->kind);
@@ -1100,8 +1109,8 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	const char **regp;
  	struct regcache *regcache;

-	if ((status->kind == TARGET_WAITKIND_FORKED && report_fork_events)
-	    || (status->kind == TARGET_WAITKIND_VFORKED && report_vfork_events))
+	if ((status->kind == TARGET_WAITKIND_FORKED && cs->report_fork_events)
+	    || (status->kind == TARGET_WAITKIND_VFORKED && 
cs->report_vfork_events))
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;
  	    const char *event = (status->kind == TARGET_WAITKIND_FORKED
@@ -1112,13 +1121,13 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	    buf = write_ptid (buf, status->value.related_pid);
  	    strcat (buf, ";");
  	  }
-	else if (status->kind == TARGET_WAITKIND_VFORK_DONE && 
report_vfork_events)
+	else if (status->kind == TARGET_WAITKIND_VFORK_DONE && 
cs->report_vfork_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;

  	    sprintf (buf, "T%02xvforkdone:;", signal);
  	  }
-	else if (status->kind == TARGET_WAITKIND_EXECD && report_exec_events)
+	else if (status->kind == TARGET_WAITKIND_EXECD && cs->report_exec_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;
  	    const char *event = "exec";
@@ -1138,7 +1147,7 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	    buf += strlen (buf);
  	  }
  	else if (status->kind == TARGET_WAITKIND_THREAD_CREATED
-		 && report_thread_events)
+		 && cs->report_thread_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;

@@ -1159,13 +1168,13 @@ prepare_resume_reply (char *buf, ptid_t ptid,

  	buf += strlen (buf);

-	saved_thread = current_thread;
+	saved_thread = cs->ss->current_thread;

  	switch_to_thread (ptid);

  	regp = current_target_desc ()->expedite_regs;

-	regcache = get_thread_regcache (current_thread, 1);
+	regcache = get_thread_regcache (cs->ss->current_thread, 1);

  	if (the_target->stopped_by_watchpoint != NULL
  	    && (*the_target->stopped_by_watchpoint) ())
@@ -1186,12 +1195,12 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	      *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
  	    *buf++ = ';';
  	  }
-	else if (swbreak_feature && target_stopped_by_sw_breakpoint ())
+	else if (cs->swbreak_feature && target_stopped_by_sw_breakpoint ())
  	  {
  	    sprintf (buf, "swbreak:;");
  	    buf += strlen (buf);
  	  }
-	else if (hwbreak_feature && target_stopped_by_hw_breakpoint ())
+	else if (cs->hwbreak_feature && target_stopped_by_hw_breakpoint ())
  	  {
  	    sprintf (buf, "hwbreak:;");
  	    buf += strlen (buf);
@@ -1219,13 +1228,13 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	       in GDB will claim this event belongs to inferior_ptid
  	       if we do not specify a thread, and there's no way for
  	       gdbserver to know what inferior_ptid is.  */
-	    if (1 || !ptid_equal (general_thread, ptid))
+	    if (1 || !ptid_equal (cs->ss->general_thread, ptid))
  	      {
  		int core = -1;
  		/* In non-stop, don't change the general thread behind
  		   GDB's back.  */
-		if (!non_stop)
-		  general_thread = ptid;
+		if (!cs->non_stop)
+		  cs->ss->general_thread = ptid;
  		sprintf (buf, "thread:");
  		buf += strlen (buf);
  		buf = write_ptid (buf, ptid);
@@ -1252,18 +1261,18 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	    dlls_changed = 0;
  	  }

-	current_thread = saved_thread;
+	cs->ss->current_thread = saved_thread;
        }
        break;
      case TARGET_WAITKIND_EXITED:
-      if (multi_process)
+      if (cs->multi_process)
  	sprintf (buf, "W%x;process:%x",
  		 status->value.integer, ptid_get_pid (ptid));
        else
  	sprintf (buf, "W%02x", status->value.integer);
        break;
      case TARGET_WAITKIND_SIGNALLED:
-      if (multi_process)
+      if (cs->multi_process)
  	sprintf (buf, "X%x;process:%x",
  		 status->value.sig, ptid_get_pid (ptid));
        else
@@ -1435,6 +1444,7 @@ clear_symbol_cache (struct sym_cache **symcache_p)
  int
  look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb)
  {
+  client_state *cs = get_client_state();
    char *p, *q;
    int len;
    struct sym_cache *sym;
@@ -1456,14 +1466,14 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
      return 0;

    /* Send the request.  */
-  strcpy (own_buf, "qSymbol:");
-  bin2hex ((const gdb_byte *) name, own_buf + strlen ("qSymbol:"),
+  strcpy (cs->own_buf, "qSymbol:");
+  bin2hex ((const gdb_byte *) name, cs->own_buf + strlen ("qSymbol:"),
  	  strlen (name));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (cs->own_buf) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (cs->own_buf);
    if (len < 0)
      return -1;

@@ -1474,45 +1484,45 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
       while it figures out the address of the symbol.  */
    while (1)
      {
-      if (own_buf[0] == 'm')
+      if (cs->own_buf[0] == 'm')
  	{
  	  CORE_ADDR mem_addr;
-	  unsigned char *mem_buf;
+	  unsigned char *mem_buffer;
  	  unsigned int mem_len;

-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
-	  mem_buf = (unsigned char *) xmalloc (mem_len);
-	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	  decode_m_packet (&cs->own_buf[1], &mem_addr, &mem_len);
+	  mem_buffer = (unsigned char *) xmalloc (mem_len);
+	  if (read_inferior_memory (mem_addr, mem_buffer, mem_len) == 0)
+	    bin2hex (mem_buffer, cs->own_buf, mem_len);
  	  else
-	    write_enn (own_buf);
-	  free (mem_buf);
-	  if (putpkt (own_buf) < 0)
+	    write_enn (cs->own_buf);
+	  free (mem_buffer);
+	  if (putpkt (cs->own_buf) < 0)
  	    return -1;
  	}
-      else if (own_buf[0] == 'v')
+      else if (cs->own_buf[0] == 'v')
  	{
  	  int new_len = -1;
-	  handle_v_requests (own_buf, len, &new_len);
+	  handle_v_requests (cs->own_buf, len, &new_len);
  	  if (new_len != -1)
-	    putpkt_binary (own_buf, new_len);
+	    putpkt_binary (cs->own_buf, new_len);
  	  else
-	    putpkt (own_buf);
+	    putpkt (cs->own_buf);
  	}
        else
  	break;
-      len = getpkt (own_buf);
+      len = getpkt (cs->own_buf);
        if (len < 0)
  	return -1;
      }

-  if (!startswith (own_buf, "qSymbol:"))
+  if (!startswith (cs->own_buf, "qSymbol:"))
      {
-      warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf);
+      warning ("Malformed response to qSymbol, ignoring: %s\n", 
cs->own_buf);
        return -1;
      }

-  p = own_buf + strlen ("qSymbol:");
+  p = cs->own_buf + strlen ("qSymbol:");
    q = p;
    while (*q && *q != ':')
      q++;
@@ -1548,17 +1558,18 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
  int
  relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
  {
+  client_state *cs = get_client_state();
    int len;
    ULONGEST written = 0;

    /* Send the request.  */
-  sprintf (own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
+  sprintf (cs->own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
  	   paddress (*to));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (cs->own_buf) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (cs->own_buf);
    if (len < 0)
      return -1;

@@ -1566,61 +1577,61 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR 
oldloc)
       wait for the qRelocInsn "response".  That requires re-entering
       the main loop.  For now, this is an adequate approximation; allow
       GDB to access memory.  */
-  while (own_buf[0] == 'm' || own_buf[0] == 'M' || own_buf[0] == 'X')
+  while (cs->own_buf[0] == 'm' || cs->own_buf[0] == 'M' || 
cs->own_buf[0] == 'X')
      {
        CORE_ADDR mem_addr;
-      unsigned char *mem_buf = NULL;
+      unsigned char *mem_buffer = NULL;
        unsigned int mem_len;

-      if (own_buf[0] == 'm')
+      if (cs->own_buf[0] == 'm')
  	{
-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
-	  mem_buf = (unsigned char *) xmalloc (mem_len);
-	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	  decode_m_packet (&cs->own_buf[1], &mem_addr, &mem_len);
+	  mem_buffer = (unsigned char *) xmalloc (mem_len);
+	  if (read_inferior_memory (mem_addr, mem_buffer, mem_len) == 0)
+	    bin2hex (mem_buffer, cs->own_buf, mem_len);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs->own_buf);
  	}
-      else if (own_buf[0] == 'X')
+      else if (cs->own_buf[0] == 'X')
  	{
-	  if (decode_X_packet (&own_buf[1], len - 1, &mem_addr,
-			       &mem_len, &mem_buf) < 0
-	      || write_inferior_memory (mem_addr, mem_buf, mem_len) != 0)
-	    write_enn (own_buf);
+	  if (decode_X_packet (&cs->own_buf[1], len - 1, &mem_addr,
+			       &mem_len, &mem_buffer) < 0
+	      || write_inferior_memory (mem_addr, mem_buffer, mem_len) != 0)
+	    write_enn (cs->own_buf);
  	  else
-	    write_ok (own_buf);
+	    write_ok (cs->own_buf);
  	}
        else
  	{
-	  decode_M_packet (&own_buf[1], &mem_addr, &mem_len, &mem_buf);
-	  if (write_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    write_ok (own_buf);
+	  decode_M_packet (&cs->own_buf[1], &mem_addr, &mem_len, &mem_buffer);
+	  if (write_inferior_memory (mem_addr, mem_buffer, mem_len) == 0)
+	    write_ok (cs->own_buf);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs->own_buf);
  	}
-      free (mem_buf);
-      if (putpkt (own_buf) < 0)
+      free (mem_buffer);
+      if (putpkt (cs->own_buf) < 0)
  	return -1;
-      len = getpkt (own_buf);
+      len = getpkt (cs->own_buf);
        if (len < 0)
  	return -1;
      }

-  if (own_buf[0] == 'E')
+  if (cs->own_buf[0] == 'E')
      {
        warning ("An error occurred while relocating an instruction: %s\n",
-	       own_buf);
+	       cs->own_buf);
        return -1;
      }

-  if (!startswith (own_buf, "qRelocInsn:"))
+  if (!startswith (cs->own_buf, "qRelocInsn:"))
      {
        warning ("Malformed response to qRelocInsn, ignoring: %s\n",
-	       own_buf);
+	       cs->own_buf);
        return -1;
      }

-  unpack_varlen_hex (own_buf + strlen ("qRelocInsn:"), &written);
+  unpack_varlen_hex (cs->own_buf + strlen ("qRelocInsn:"), &written);

    *to += written;
    return 0;
diff --git a/gdb/gdbserver/remote-utils.h b/gdb/gdbserver/remote-utils.h
index c64807f406e..8714791e605 100644
--- a/gdb/gdbserver/remote-utils.h
+++ b/gdb/gdbserver/remote-utils.h
@@ -19,10 +19,7 @@
  #ifndef REMOTE_UTILS_H
  #define REMOTE_UTILS_H

-extern int remote_debug;
-extern int noack_mode;
-extern int transport_is_reliable;
-
+int get_remote_desc (void);
  int gdb_connected (void);

  #define STDIO_CONNECTION_NAME "stdio"
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 9d12ce6f706..261d28a5271 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -66,63 +66,6 @@ static gdb_environ our_environ;

  int startup_with_shell = 1;

-/* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
-   `vCont'.  Note the multi-process extensions made `vCont' a
-   requirement, so `Hc pPID.TID' is pretty much undefined.  So
-   CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
-   resuming all threads of the process (again, `Hc' isn't used for
-   multi-process), or a specific thread ptid_t.  */
-ptid_t cont_thread;
-
-/* The thread set with an `Hg' packet.  */
-ptid_t general_thread;
-
-int server_waiting;
-
-static int extended_protocol;
-static int response_needed;
-static int exit_requested;
-
-/* --once: Exit after the first connection has closed.  */
-int run_once;
-
-int multi_process;
-int report_fork_events;
-int report_vfork_events;
-int report_exec_events;
-int report_thread_events;
-
-/* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
-static int report_no_resumed;
-
-int non_stop;
-int swbreak_feature;
-int hwbreak_feature;
-
-/* True if the "vContSupported" feature is active.  In that case, GDB
-   wants us to report whether single step is supported in the reply to
-   "vCont?" packet.  */
-static int vCont_supported;
-
-/* Whether we should attempt to disable the operating system's address
-   space randomization feature before starting an inferior.  */
-int disable_randomization = 1;
-
-static char *program_name = NULL;
-static std::vector<char *> program_args;
-static std::string wrapper_argv;
-
-int pass_signals[GDB_SIGNAL_LAST];
-int program_signals[GDB_SIGNAL_LAST];
-int program_signals_p;
-
-/* The PID of the originally created or attached inferior.  Used to
-   send signals to the process when GDB sends us an asynchronous interrupt
-   (user hitting Control-C in the client), and to wait for the child to 
exit
-   when no longer debugging it.  */
-
-unsigned long signal_pid;
-
  /* Set if you want to disable optional thread related packets support
     in gdbserver, for the sake of testing GDB against stubs that don't
     support them.  */
@@ -131,13 +74,6 @@ int disable_packet_Tthread;
  int disable_packet_qC;
  int disable_packet_qfThreadInfo;

-/* Last status reported to GDB.  */
-struct target_waitstatus last_status;
-ptid_t last_ptid;
-
-char *own_buf;
-static unsigned char *mem_buf;
-
  /* A sub-class of 'struct notif_event' for stop, holding information
     relative to a single stop reply.  We keep a queue of these to
     push to GDB in non-stop mode.  */
@@ -159,6 +95,167 @@ static struct btrace_config current_btrace_conf;

  DEFINE_QUEUE_P (notif_event_p);

+static struct multi_client_states client_states;
+
+
+void dump_client_states (void) {
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+  it = client_states.cs.begin();
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); it++)
+    {
+      gdb_fildes_t cfd = it->first;
+      client_state *cs = it->second;
+      printf ("%d %#lx %ld %d %d\n", cfd, (unsigned long) cs, 
(long)cs->ss->signal_pid, cs->ss->last_status.kind, 
cs->ss->last_status.value.sig);
+    }
+}
+
+
+multi_client_states*
+get_client_states (void)
+{
+  return &client_states;
+}
+
+
+client_state*
+get_client_state (void)
+{
+  return client_states.get_client_state();
+}
+
+
+client_state::client_state (gdb_fildes_t fd, client_state *csidx)
+{
+  client_state *cs = get_client_state();
+  file_desc = fd;
+  attached_to_client = csidx->attached_to_client;
+  catch_syscalls = csidx->catch_syscalls;
+  extended_protocol = csidx->extended_protocol;
+  response_needed = csidx->response_needed;
+  exit_requested = csidx->exit_requested;
+  run_once = csidx->run_once;
+  multi_process = csidx->multi_process;
+  report_fork_events = csidx->report_fork_events;
+  report_vfork_events = csidx->report_vfork_events;
+  report_exec_events = csidx->report_exec_events;
+  report_thread_events = csidx->report_thread_events;
+  report_no_resumed = csidx->report_no_resumed;
+  non_stop = csidx->non_stop;
+  swbreak_feature = csidx->swbreak_feature;
+  hwbreak_feature = csidx->hwbreak_feature;
+  vCont_supported = csidx->vCont_supported;
+  disable_randomization = csidx->disable_randomization;
+  program_name = csidx->program_name;
+  program_args = csidx->program_args;
+  wrapper_argv = csidx->wrapper_argv;
+  remote_debug = csidx->remote_debug;
+  noack_mode = csidx->noack_mode;
+  transport_is_reliable = csidx->transport_is_reliable;
+  ss = new (server_state);
+  ss->mem_buf = csidx->ss->mem_buf;
+  ss->readchar_bufcnt = 0;
+  packet_type = other_packet;
+  last_packet_type = other_packet;
+  notify_buffer = NULL;
+  own_buf = (char*) xmalloc (PBUFSIZ + 1);
+  ss->attach_count = 0;
+  ss->cont_thread = null_ptid;
+  ss->general_thread = null_ptid;
+  ss->signal_pid = csidx->ss->signal_pid;
+  ss->last_ptid = null_ptid;
+  ss->last_status = csidx->ss->last_status;
+  if (csidx->file_desc < 0)
+    {
+      ss->all_processes = cs->ss->all_processes;
+      ss->all_threads = cs->ss->all_threads;
+      ss->current_thread = cs->ss->current_thread;
+    }
+  else
+    ss->current_thread = NULL;
+}
+
+
+/* Add a new client state for FD or return if found */
+
+client_state *
+multi_client_states::set_client_state (gdb_fildes_t fd)
+{
+/* States:
+ * fd = -1 add initial client state
+ * fd =  F add client state for fd F
+ */
+
+  client_state *csidx, *cs;
+
+  /* add/return initial client state */
+  if (fd == -1)
+    {
+      if (client_states.cs.empty())
+	{
+	  client_states.cs[fd] = new (client_state);
+	  client_states.cs[fd]->ss = new (server_state);
+	  client_states.cs[fd]->file_desc = fd;
+	}
+      client_states.current_cs = client_states.cs[fd];
+      return client_states.cs[fd];
+    }
+
+  /* add/return client state for fd F */
+
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+  it = client_states.cs.find(fd);
+  if (it != client_states.cs.end())
+    {
+      client_states.current_cs = it->second;
+      return it->second;
+    }
+  else
+    csidx = client_states.cs.rbegin()->second;
+
+  /* add client state S for fd F */
+  client_states.cs[fd] = cs = new client_state (fd, csidx);
+  cs->file_desc = fd;
+  client_states.set_current_client (cs);
+  return cs;
+}
+
+
+/* Remove the client state corresponding to fd */
+
+void
+multi_client_states::delete_client_state (gdb_fildes_t fd)
+{
+  client_state *cs, *previous_cs = NULL;
+  std::map<gdb_fildes_t,client_state*>::iterator it;
+
+  for (it = client_states.cs.begin(); it != client_states.cs.end(); ++it)
+    {
+      server_state *ss= NULL;
+
+      cs = it->second;
+
+      if (it->first == fd)
+	{
+	  client_states.current_cs = previous_cs;
+	  if (cs->notify_buffer)
+	    xfree (cs->notify_buffer);
+	  free (cs->own_buf);
+	  delete (cs->ss);
+	  delete (cs);
+	  client_states.cs.erase (fd);
+	}
+      previous_cs = cs;
+    }
+}
+
+
+#if 0
+static int
+queue_stop_reply_callback (thread_info *thread, void *arg);
+#endif
+
+/**********************************/
+
  /* Put a stop reply to the stop reply queue.  */

  static void
@@ -257,7 +354,9 @@ target_running (void)
  const char *
  get_exec_wrapper ()
  {
-  return !wrapper_argv.empty () ? wrapper_argv.c_str () : NULL;
+  client_state *cs = get_client_state();
+
+  return !cs->wrapper_argv.empty () ? cs->wrapper_argv.c_str () : NULL;
  }

  /* See common/common-inferior.h.  */
@@ -265,10 +364,12 @@ get_exec_wrapper ()
  char *
  get_exec_file (int err)
  {
-  if (err && program_name == NULL)
+  client_state *cs = get_client_state();
+
+  if (err && cs->program_name == NULL)
      error (_("No executable file specified."));

-  return program_name;
+  return cs->program_name;
  }

  /* See server.h.  */
@@ -282,6 +383,8 @@ get_environ ()
  static int
  attach_inferior (int pid)
  {
+  client_state *cs = get_client_state();
+
    /* myattach should return -1 if attaching is unsupported,
       0 if it succeeded, and call error() otherwise.  */

@@ -294,28 +397,26 @@ attach_inferior (int pid)
    /* FIXME - It may be that we should get the SIGNAL_PID from the
       attach function, so that it can be the main thread instead of
       whichever we were told to attach to.  */
-  signal_pid = pid;
+  cs->ss->signal_pid = pid;

-  if (!non_stop)
+  if (!cs->non_stop)
      {
-      last_ptid = mywait (pid_to_ptid (pid), &last_status, 0, 0);
+      cs->ss->last_ptid = mywait (pid_to_ptid (pid), 
&cs->ss->last_status, 0, 0);

        /* GDB knows to ignore the first SIGSTOP after attaching to a 
running
  	 process using the "attach" command, but this is different; it's
  	 just using "target remote".  Pretend it's just starting up.  */
-      if (last_status.kind == TARGET_WAITKIND_STOPPED
-	  && last_status.value.sig == GDB_SIGNAL_STOP)
-	last_status.value.sig = GDB_SIGNAL_TRAP;
+      if (cs->ss->last_status.kind == TARGET_WAITKIND_STOPPED
+	  && cs->ss->last_status.value.sig == GDB_SIGNAL_STOP)
+	cs->ss->last_status.value.sig = GDB_SIGNAL_TRAP;

-      current_thread->last_resume_kind = resume_stop;
-      current_thread->last_status = last_status;
+      cs->ss->current_thread->last_resume_kind = resume_stop;
+      cs->ss->current_thread->last_status = cs->ss->last_status;
      }

    return 0;
  }

-extern int remote_debug;
-
  /* Decode a qXfer read request.  Return 0 if everything looks OK,
     or -1 otherwise.  */

@@ -431,6 +532,7 @@ handle_btrace_disable (struct thread_info *thread)
  static int
  handle_btrace_general_set (char *own_buf)
  {
+  client_state *cs = get_client_state();
    struct thread_info *thread;
    const char *err;
    char *op;
@@ -440,14 +542,14 @@ handle_btrace_general_set (char *own_buf)

    op = own_buf + strlen ("Qbtrace:");

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs->ss->general_thread, null_ptid)
+      || ptid_equal (cs->ss->general_thread, minus_one_ptid))
      {
        strcpy (own_buf, "E.Must select a single thread.");
        return -1;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs->ss->general_thread);
    if (thread == NULL)
      {
        strcpy (own_buf, "E.No such thread.");
@@ -478,6 +580,7 @@ handle_btrace_general_set (char *own_buf)
  static int
  handle_btrace_conf_general_set (char *own_buf)
  {
+  client_state *cs = get_client_state();
    struct thread_info *thread;
    char *op;

@@ -486,14 +589,14 @@ handle_btrace_conf_general_set (char *own_buf)

    op = own_buf + strlen ("Qbtrace-conf:");

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs->ss->general_thread, null_ptid)
+      || ptid_equal (cs->ss->general_thread, minus_one_ptid))
      {
        strcpy (own_buf, "E.Must select a single thread.");
        return -1;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs->ss->general_thread);
    if (thread == NULL)
      {
        strcpy (own_buf, "E.No such thread.");
@@ -545,6 +648,8 @@ handle_btrace_conf_general_set (char *own_buf)
  static void
  handle_general_set (char *own_buf)
  {
+  client_state *cs = get_client_state();
+
    if (startswith (own_buf, "QPassSignals:"))
      {
        int numsigs = (int) GDB_SIGNAL_LAST, i;
@@ -556,7 +661,7 @@ handle_general_set (char *own_buf)
  	{
  	  if (i == cursig)
  	    {
-	      pass_signals[i] = 1;
+	      cs->pass_signals[i] = 1;
  	      if (*p == '\0')
  		/* Keep looping, to clear the remaining signals.  */
  		cursig = -1;
@@ -564,7 +669,7 @@ handle_general_set (char *own_buf)
  		p = decode_address_to_semicolon (&cursig, p);
  	    }
  	  else
-	    pass_signals[i] = 0;
+	    cs->pass_signals[i] = 0;
  	}
        strcpy (own_buf, "OK");
        return;
@@ -576,14 +681,14 @@ handle_general_set (char *own_buf)
        const char *p = own_buf + strlen ("QProgramSignals:");
        CORE_ADDR cursig;

-      program_signals_p = 1;
+      cs->program_signals_p = 1;

        p = decode_address_to_semicolon (&cursig, p);
        for (i = 0; i < numsigs; i++)
  	{
  	  if (i == cursig)
  	    {
-	      program_signals[i] = 1;
+	      cs->program_signals[i] = 1;
  	      if (*p == '\0')
  		/* Keep looping, to clear the remaining signals.  */
  		cursig = -1;
@@ -591,7 +696,7 @@ handle_general_set (char *own_buf)
  		p = decode_address_to_semicolon (&cursig, p);
  	    }
  	  else
-	    program_signals[i] = 0;
+	    cs->program_signals[i] = 0;
  	}
        strcpy (own_buf, "OK");
        return;
@@ -661,7 +766,7 @@ handle_general_set (char *own_buf)
        std::string final_var = hex2str (p);
        std::string var_name, var_value;

-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf (_("[QEnvironmentHexEncoded received '%s']\n"), p);
  	  debug_printf (_("[Environment variable to be set: '%s']\n"),
@@ -692,7 +797,7 @@ handle_general_set (char *own_buf)
        const char *p = own_buf + sizeof ("QEnvironmentUnset:") - 1;
        std::string varname = hex2str (p);

-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf (_("[QEnvironmentUnset received '%s']\n"), p);
  	  debug_printf (_("[Environment variable to be unset: '%s']\n"),
@@ -708,13 +813,13 @@ handle_general_set (char *own_buf)

    if (strcmp (own_buf, "QStartNoAckMode") == 0)
      {
-      if (remote_debug)
+      if (cs->remote_debug)
  	{
  	  debug_printf ("[noack mode enabled]\n");
  	  debug_flush ();
  	}

-      noack_mode = 1;
+      cs->noack_mode = 1;
        write_ok (own_buf);
        return;
      }
@@ -747,9 +852,9 @@ handle_general_set (char *own_buf)
  	  return;
  	}

-      non_stop = req;
+      cs->non_stop = req;

-      if (remote_debug)
+      if (cs->remote_debug)
  	debug_printf ("[%s mode enabled]\n", req_str);

        write_ok (own_buf);
@@ -762,11 +867,11 @@ handle_general_set (char *own_buf)
        ULONGEST setting;

        unpack_varlen_hex (packet, &setting);
-      disable_randomization = setting;
+      cs->disable_randomization = setting;

-      if (remote_debug)
+      if (cs->remote_debug)
  	{
-	  debug_printf (disable_randomization
+	  debug_printf (cs->disable_randomization
  			? "[address space randomization disabled]\n"
  			: "[address space randomization enabled]\n");
  	}
@@ -797,7 +902,7 @@ handle_general_set (char *own_buf)

        /* Update the flag.  */
        use_agent = req;
-      if (remote_debug)
+      if (cs->remote_debug)
  	debug_printf ("[%s agent]\n", req ? "Enable" : "Disable");
        write_ok (own_buf);
        return;
@@ -829,11 +934,11 @@ handle_general_set (char *own_buf)
  	  return;
  	}

-      report_thread_events = (req == TRIBOOL_TRUE);
+      cs->report_thread_events = (req == TRIBOOL_TRUE);

-      if (remote_debug)
+      if (cs->remote_debug)
  	{
-	  const char *req_str = report_thread_events ? "enabled" : "disabled";
+	  const char *req_str = cs->report_thread_events ? "enabled" : "disabled";

  	  debug_printf ("[thread events are now %s]\n", req_str);
  	}
@@ -859,7 +964,7 @@ handle_general_set (char *own_buf)
  	  return;
  	}

-      if (remote_debug)
+      if (cs->remote_debug)
  	debug_printf (_("[Inferior will %s started with shell]"),
  		      startup_with_shell ? "be" : "not be");

@@ -877,7 +982,7 @@ handle_general_set (char *own_buf)

  	  set_inferior_cwd (path.c_str ());

-	  if (remote_debug)
+	  if (cs->remote_debug)
  	    debug_printf (_("[Set the inferior's current directory to %s]\n"),
  			  path.c_str ());
  	}
@@ -887,7 +992,7 @@ handle_general_set (char *own_buf)
  	     previously set cwd for the inferior.  */
  	  set_inferior_cwd (NULL);

-	  if (remote_debug)
+	  if (cs->remote_debug)
  	    debug_printf (_("\
  [Unset the inferior's current directory; will use gdbserver's cwd]\n"));
  	}
@@ -1189,11 +1294,12 @@ handle_search_memory (char *own_buf, int packet_len)
  static void
  handle_detach (char *own_buf)
  {
+  client_state *cs = get_client_state();
    require_running_or_return (own_buf);

    int pid;

-  if (multi_process)
+  if (cs->multi_process)
      {
        /* skip 'D;' */
        pid = strtol (&own_buf[2], NULL, 16);
@@ -1226,12 +1332,12 @@ handle_detach (char *own_buf)
  	 events simultaneously.  There's also no point either in
  	 having the target stop all threads, when we're going to
  	 pass signals down without informing GDB.  */
-      if (!non_stop)
+      if (!cs->non_stop)
  	{
  	  if (debug_threads)
  	    debug_printf ("Forcing non-stop mode\n");

-	  non_stop = 1;
+	  cs->non_stop = 1;
  	  start_non_stop (1);
  	}

@@ -1253,16 +1359,16 @@ handle_detach (char *own_buf)
        discard_queued_stop_replies (pid_to_ptid (pid));
        write_ok (own_buf);

-      if (extended_protocol || target_running ())
+      if (cs->extended_protocol || target_running ())
  	{
  	  /* There is still at least one inferior remaining or
  	     we are in extended mode, so don't terminate gdbserver,
  	     and instead treat this like a normal program exit.  */
-	  last_status.kind = TARGET_WAITKIND_EXITED;
-	  last_status.value.integer = 0;
-	  last_ptid = pid_to_ptid (pid);
+	  cs->ss->last_status.kind = TARGET_WAITKIND_EXITED;
+	  cs->ss->last_status.value.integer = 0;
+	  cs->ss->last_ptid = pid_to_ptid (pid);

-	  current_thread = NULL;
+	  cs->ss->current_thread = NULL;
  	}
        else
  	{
@@ -1355,6 +1461,8 @@ parse_debug_format_options (const char *arg, int 
is_monitor)
  static void
  handle_monitor_command (char *mon, char *own_buf)
  {
+  client_state *cs = get_client_state();
+
    if (strcmp (mon, "set debug 1") == 0)
      {
        debug_threads = 1;
@@ -1377,12 +1485,12 @@ handle_monitor_command (char *mon, char *own_buf)
      }
    else if (strcmp (mon, "set remote-debug 1") == 0)
      {
-      remote_debug = 1;
+      cs->remote_debug = 1;
        monitor_output ("Protocol debug output enabled.\n");
      }
    else if (strcmp (mon, "set remote-debug 0") == 0)
      {
-      remote_debug = 0;
+      cs->remote_debug = 0;
        monitor_output ("Protocol debug output disabled.\n");
      }
    else if (startswith (mon, "set debug-format "))
@@ -1401,7 +1509,7 @@ handle_monitor_command (char *mon, char *own_buf)
    else if (strcmp (mon, "help") == 0)
      monitor_show_help ();
    else if (strcmp (mon, "exit") == 0)
-    exit_requested = 1;
+    cs->exit_requested = 1;
    else
      {
        monitor_output ("Unknown monitor command.\n\n");
@@ -1441,10 +1549,12 @@ handle_qxfer_auxv (const char *annex,
  		   gdb_byte *readbuf, const gdb_byte *writebuf,
  		   ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
+
    if (the_target->read_auxv == NULL || writebuf != NULL)
      return -2;

-  if (annex[0] != '\0' || current_thread == NULL)
+  if (annex[0] != '\0' || cs->ss->current_thread == NULL)
      return -1;

    return (*the_target->read_auxv) (offset, readbuf, len);
@@ -1457,6 +1567,7 @@ handle_qxfer_exec_file (const char *annex,
  			gdb_byte *readbuf, const gdb_byte *writebuf,
  			ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
    char *file;
    ULONGEST pid;
    int total_len;
@@ -1466,10 +1577,10 @@ handle_qxfer_exec_file (const char *annex,

    if (annex[0] == '\0')
      {
-      if (current_thread == NULL)
+      if (cs->ss->current_thread == NULL)
  	return -1;

-      pid = pid_of (current_thread);
+      pid = pid_of (cs->ss->current_thread);
      }
    else
      {
@@ -1537,10 +1648,12 @@ handle_qxfer_libraries (const char *annex,
  			gdb_byte *readbuf, const gdb_byte *writebuf,
  			ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
+
    if (writebuf != NULL)
      return -2;

-  if (annex[0] != '\0' || current_thread == NULL)
+  if (annex[0] != '\0' || cs->ss->current_thread == NULL)
      return -1;

    std::string document = "<library-list version=\"1.0\">\n";
@@ -1570,10 +1683,12 @@ handle_qxfer_libraries_svr4 (const char *annex,
  			     gdb_byte *readbuf, const gdb_byte *writebuf,
  			     ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
+
    if (writebuf != NULL)
      return -2;

-  if (current_thread == NULL || the_target->qxfer_libraries_svr4 == NULL)
+  if (cs->ss->current_thread == NULL || 
the_target->qxfer_libraries_svr4 == NULL)
      return -1;

    return the_target->qxfer_libraries_svr4 (annex, readbuf, writebuf, 
offset, len);
@@ -1599,10 +1714,12 @@ handle_qxfer_siginfo (const char *annex,
  		      gdb_byte *readbuf, const gdb_byte *writebuf,
  		      ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
+
    if (the_target->qxfer_siginfo == NULL)
      return -2;

-  if (annex[0] != '\0' || current_thread == NULL)
+  if (annex[0] != '\0' || cs->ss->current_thread == NULL)
      return -1;

    return (*the_target->qxfer_siginfo) (annex, readbuf, writebuf, 
offset, len);
@@ -1615,10 +1732,12 @@ handle_qxfer_spu (const char *annex,
  		  gdb_byte *readbuf, const gdb_byte *writebuf,
  		  ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
+
    if (the_target->qxfer_spu == NULL)
      return -2;

-  if (current_thread == NULL)
+  if (cs->ss->current_thread == NULL)
      return -1;

    return (*the_target->qxfer_spu) (annex, readbuf, writebuf, offset, len);
@@ -1631,12 +1750,13 @@ handle_qxfer_statictrace (const char *annex,
  			  gdb_byte *readbuf, const gdb_byte *writebuf,
  			  ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
    ULONGEST nbytes;

    if (writebuf != NULL)
      return -2;

-  if (annex[0] != '\0' || current_thread == NULL || current_traceframe 
== -1)
+  if (annex[0] != '\0' || cs->ss->current_thread == NULL || 
current_traceframe == -1)
      return -1;

    if (traceframe_read_sdata (current_traceframe, offset,
@@ -1804,10 +1924,12 @@ static int
  handle_qxfer_fdpic (const char *annex, gdb_byte *readbuf,
  		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
+
    if (the_target->read_loadmap == NULL)
      return -2;

-  if (current_thread == NULL)
+  if (cs->ss->current_thread == NULL)
      return -1;

    return (*the_target->read_loadmap) (annex, offset, readbuf, len);
@@ -1820,6 +1942,7 @@ handle_qxfer_btrace (const char *annex,
  		     gdb_byte *readbuf, const gdb_byte *writebuf,
  		     ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
    static struct buffer cache;
    struct thread_info *thread;
    enum btrace_read_type type;
@@ -1828,23 +1951,23 @@ handle_qxfer_btrace (const char *annex,
    if (the_target->read_btrace == NULL || writebuf != NULL)
      return -2;

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs->ss->general_thread, null_ptid)
+      || ptid_equal (cs->ss->general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (cs->own_buf, "E.Must select a single thread.");
        return -3;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs->ss->general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (cs->own_buf, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (cs->own_buf, "E.Btrace not enabled.");
        return -3;
      }

@@ -1856,7 +1979,7 @@ handle_qxfer_btrace (const char *annex,
      type = BTRACE_READ_DELTA;
    else
      {
-      strcpy (own_buf, "E.Bad annex.");
+      strcpy (cs->own_buf, "E.Bad annex.");
        return -3;
      }

@@ -1867,7 +1990,7 @@ handle_qxfer_btrace (const char *annex,
        result = target_read_btrace (thread->btrace, &cache, type);
        if (result != 0)
  	{
-	  memcpy (own_buf, cache.buffer, cache.used_size);
+	  memcpy (cs->own_buf, cache.buffer, cache.used_size);
  	  return -3;
  	}
      }
@@ -1892,6 +2015,7 @@ handle_qxfer_btrace_conf (const char *annex,
  			  gdb_byte *readbuf, const gdb_byte *writebuf,
  			  ULONGEST offset, LONGEST len)
  {
+  client_state *cs = get_client_state();
    static struct buffer cache;
    struct thread_info *thread;
    int result;
@@ -1902,23 +2026,23 @@ handle_qxfer_btrace_conf (const char *annex,
    if (annex[0] != '\0')
      return -1;

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs->ss->general_thread, null_ptid)
+      || ptid_equal (cs->ss->general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (cs->own_buf, "E.Must select a single thread.");
        return -3;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs->ss->general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (cs->own_buf, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (cs->own_buf, "E.Btrace not enabled.");
        return -3;
      }

@@ -1929,7 +2053,7 @@ handle_qxfer_btrace_conf (const char *annex,
        result = target_read_btrace_conf (thread->btrace, &cache);
        if (result != 0)
  	{
-	  memcpy (own_buf, cache.buffer, cache.used_size);
+	  memcpy (cs->own_buf, cache.buffer, cache.used_size);
  	  return -3;
  	}
      }
@@ -2142,6 +2266,7 @@ supported_btrace_packets (char *buf)
  static void
  handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
  {
+  client_state *cs = get_client_state();
    static std::list<thread_info *>::const_iterator thread_iter;

    /* Reply the current thread id.  */
@@ -2150,11 +2275,11 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
        ptid_t ptid;
        require_running_or_return (own_buf);

-      if (general_thread != null_ptid && general_thread != minus_one_ptid)
-	ptid = general_thread;
+      if (cs->ss->general_thread != null_ptid && cs->ss->general_thread 
!= minus_one_ptid)
+	ptid = cs->ss->general_thread;
        else
  	{
-	  thread_iter = all_threads.begin ();
+	  thread_iter = cs->ss->all_threads.begin ();
  	  ptid = (*thread_iter)->id;
  	}

@@ -2166,24 +2291,24 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)

    if (strcmp ("qSymbol::", own_buf) == 0)
      {
-      struct thread_info *save_thread = current_thread;
+      struct thread_info *save_thread = cs->ss->current_thread;

        /* For qSymbol, GDB only changes the current thread if the
  	 previous current thread was of a different process.  So if
  	 the previous thread is gone, we need to pick another one of
  	 the same process.  This can happen e.g., if we followed an
  	 exec in a non-leader thread.  */
-      if (current_thread == NULL)
+      if (cs->ss->current_thread == NULL)
  	{
-	  current_thread
-	    = find_any_thread_of_pid (ptid_get_pid (general_thread));
+	  cs->ss->current_thread
+	    = find_any_thread_of_pid (ptid_get_pid (cs->ss->general_thread));

  	  /* Just in case, if we didn't find a thread, then bail out
  	     instead of crashing.  */
-	  if (current_thread == NULL)
+	  if (cs->ss->current_thread == NULL)
  	    {
  	      write_enn (own_buf);
-	      current_thread = save_thread;
+	      cs->ss->current_thread = save_thread;
  	      return;
  	    }
  	}
@@ -2203,10 +2328,10 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
        if (target_supports_tracepoints ())
  	tracepoint_look_up_symbols ();

-      if (current_thread != NULL && the_target->look_up_symbols != NULL)
+      if (cs->ss->current_thread != NULL && the_target->look_up_symbols 
!= NULL)
  	(*the_target->look_up_symbols) ();

-      current_thread = save_thread;
+      cs->ss->current_thread = save_thread;

        strcpy (own_buf, "OK");
        return;
@@ -2217,7 +2342,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
        if (strcmp ("qfThreadInfo", own_buf) == 0)
  	{
  	  require_running_or_return (own_buf);
-	  thread_iter = all_threads.begin ();
+	  thread_iter = cs->ss->all_threads.begin ();

  	  *own_buf++ = 'm';
  	  ptid_t ptid = (*thread_iter)->id;
@@ -2229,7 +2354,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
        if (strcmp ("qsThreadInfo", own_buf) == 0)
  	{
  	  require_running_or_return (own_buf);
-	  if (thread_iter != all_threads.end ())
+	  if (thread_iter != cs->ss->all_threads.end ())
  	    {
  	      *own_buf++ = 'm';
  	      ptid_t ptid = (*thread_iter)->id;
@@ -2296,7 +2421,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  		  /* GDB supports and wants multi-process support if
  		     possible.  */
  		  if (target_supports_multi_process ())
-		    multi_process = 1;
+		    cs->multi_process = 1;
  		}
  	      else if (strcmp (p, "qRelocInsn+") == 0)
  		{
@@ -2309,42 +2434,42 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  		     by a software breakpoint and for us to handle PC
  		     adjustment if necessary on this target.  */
  		  if (target_supports_stopped_by_sw_breakpoint ())
-		    swbreak_feature = 1;
+		    cs->swbreak_feature = 1;
  		}
  	      else if (strcmp (p, "hwbreak+") == 0)
  		{
  		  /* GDB wants us to report whether a trap is caused
  		     by a hardware breakpoint.  */
  		  if (target_supports_stopped_by_hw_breakpoint ())
-		    hwbreak_feature = 1;
+		    cs->hwbreak_feature = 1;
  		}
  	      else if (strcmp (p, "fork-events+") == 0)
  		{
  		  /* GDB supports and wants fork events if possible.  */
  		  if (target_supports_fork_events ())
-		    report_fork_events = 1;
+		    cs->report_fork_events = 1;
  		}
  	      else if (strcmp (p, "vfork-events+") == 0)
  		{
  		  /* GDB supports and wants vfork events if possible.  */
  		  if (target_supports_vfork_events ())
-		    report_vfork_events = 1;
+		    cs->report_vfork_events = 1;
  		}
  	      else if (strcmp (p, "exec-events+") == 0)
  		{
  		  /* GDB supports and wants exec events if possible.  */
  		  if (target_supports_exec_events ())
-		    report_exec_events = 1;
+		    cs->report_exec_events = 1;
  		}
  	      else if (strcmp (p, "vContSupported+") == 0)
-		vCont_supported = 1;
+		cs->vCont_supported = 1;
  	      else if (strcmp (p, "QThreadEvents+") == 0)
  		;
  	      else if (strcmp (p, "no-resumed+") == 0)
  		{
  		  /* GDB supports and wants TARGET_WAITKIND_NO_RESUMED
  		     events.  */
-		  report_no_resumed = 1;
+		  cs->report_no_resumed = 1;
  		}
  	      else
  		{
@@ -2402,7 +2527,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  	 qXfer:feature:read at all, we will never be re-queried.  */
        strcat (own_buf, ";qXfer:features:read+");

-      if (transport_is_reliable)
+      if (cs->transport_is_reliable)
  	strcat (own_buf, ";QStartNoAckMode+");

        if (the_target->qxfer_osdata != NULL)
@@ -2713,13 +2838,15 @@ static int
  handle_pending_status (const struct thread_resume *resumption,
  		       struct thread_info *thread)
  {
+  client_state *cs = get_client_state();
+
    if (thread->status_pending_p)
      {
        thread->status_pending_p = 0;

-      last_status = thread->last_status;
-      last_ptid = thread->id;
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      cs->ss->last_status = thread->last_status;
+      cs->ss->last_ptid = thread->id;
+      prepare_resume_reply (cs->own_buf, cs->ss->last_ptid, 
&cs->ss->last_status);
        return 1;
      }
    return 0;
@@ -2839,7 +2966,9 @@ err:
  static void
  resume (struct thread_resume *actions, size_t num_actions)
  {
-  if (!non_stop)
+  client_state *cs = get_client_state();
+
+  if (!cs->non_stop)
      {
        /* Check if among the threads that GDB wants actioned, there's
  	 one with a pending status to report.  If so, skip actually
@@ -2860,38 +2989,38 @@ resume (struct thread_resume *actions, size_t 
num_actions)

    (*the_target->resume) (actions, num_actions);

-  if (non_stop)
-    write_ok (own_buf);
+  if (cs->non_stop)
+    write_ok (cs->own_buf);
    else
      {
-      last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
+      cs->ss->last_ptid = mywait (minus_one_ptid, &cs->ss->last_status, 
0, 1);

-      if (last_status.kind == TARGET_WAITKIND_NO_RESUMED
-	  && !report_no_resumed)
+      if (cs->ss->last_status.kind == TARGET_WAITKIND_NO_RESUMED
+	  && !cs->report_no_resumed)
  	{
  	  /* The client does not support this stop reply.  At least
  	     return error.  */
-	  sprintf (own_buf, "E.No unwaited-for children left.");
+	  sprintf (cs->own_buf, "E.No unwaited-for children left.");
  	  disable_async_io ();
  	  return;
  	}

-      if (last_status.kind != TARGET_WAITKIND_EXITED
-          && last_status.kind != TARGET_WAITKIND_SIGNALLED
-	  && last_status.kind != TARGET_WAITKIND_NO_RESUMED)
-	current_thread->last_status = last_status;
+      if (cs->ss->last_status.kind != TARGET_WAITKIND_EXITED
+          && cs->ss->last_status.kind != TARGET_WAITKIND_SIGNALLED
+	  && cs->ss->last_status.kind != TARGET_WAITKIND_NO_RESUMED)
+	cs->ss->current_thread->last_status = cs->ss->last_status;

        /* From the client's perspective, all-stop mode always stops all
  	 threads implicitly (and the target backend has already done
  	 so by now).  Tag all threads as "want-stopped", so we don't
  	 resume them implicitly without the client telling us to.  */
        gdb_wants_all_threads_stopped ();
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (cs->own_buf, cs->ss->last_ptid, 
&cs->ss->last_status);
        disable_async_io ();

-      if (last_status.kind == TARGET_WAITKIND_EXITED
-          || last_status.kind == TARGET_WAITKIND_SIGNALLED)
-        target_mourn_inferior (last_ptid);
+      if (cs->ss->last_status.kind == TARGET_WAITKIND_EXITED
+          || cs->ss->last_status.kind == TARGET_WAITKIND_SIGNALLED)
+        target_mourn_inferior (cs->ss->last_ptid);
      }
  }

@@ -2899,6 +3028,7 @@ resume (struct thread_resume *actions, size_t 
num_actions)
  static int
  handle_v_attach (char *own_buf)
  {
+  client_state *cs = get_client_state();
    int pid;

    pid = strtol (own_buf + 8, NULL, 16);
@@ -2910,7 +3040,7 @@ handle_v_attach (char *own_buf)
  	 notice on the GDB side.  */
        dlls_changed = 0;

-      if (non_stop)
+      if (cs->non_stop)
  	{
  	  /* In non-stop, we don't send a resume reply.  Stop events
  	     will follow up using the normal notification
@@ -2918,7 +3048,7 @@ handle_v_attach (char *own_buf)
  	  write_ok (own_buf);
  	}
        else
-	prepare_resume_reply (own_buf, last_ptid, &last_status);
+	prepare_resume_reply (own_buf, cs->ss->last_ptid, &cs->ss->last_status);

        return 1;
      }
@@ -2933,6 +3063,7 @@ handle_v_attach (char *own_buf)
  static int
  handle_v_run (char *own_buf)
  {
+  client_state *cs = get_client_state();
    char *p, *next_p;
    std::vector<char *> new_argv;
    char *new_program_name = NULL;
@@ -3023,7 +3154,7 @@ handle_v_run (char *own_buf)
      {
        /* GDB didn't specify a program to run.  Use the program from the
  	 last run with the new argument list.  */
-      if (program_name == NULL)
+      if (cs->program_name == NULL)
  	{
  	  write_enn (own_buf);
  	  free_vector_argv (new_argv);
@@ -3032,25 +3163,25 @@ handle_v_run (char *own_buf)
      }
    else
      {
-      xfree (program_name);
-      program_name = new_program_name;
+      xfree (cs->program_name);
+      cs->program_name = new_program_name;
      }

    /* Free the old argv and install the new one.  */
-  free_vector_argv (program_args);
-  program_args = new_argv;
+  free_vector_argv (cs->program_args);
+  cs->program_args = new_argv;

-  create_inferior (program_name, program_args);
+  create_inferior (cs->program_name, cs->program_args);

-  if (last_status.kind == TARGET_WAITKIND_STOPPED)
+  if (cs->ss->last_status.kind == TARGET_WAITKIND_STOPPED)
      {
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (own_buf, cs->ss->last_ptid, 
&cs->ss->last_status);

        /* In non-stop, sending a resume reply doesn't set the general
  	 thread, but GDB assumes a vRun sets it (this is so GDB can
  	 query which is the main thread of the new inferior.  */
-      if (non_stop)
-	general_thread = last_ptid;
+      if (cs->non_stop)
+	cs->ss->general_thread = cs->ss->last_ptid;

        return 1;
      }
@@ -3065,18 +3196,19 @@ handle_v_run (char *own_buf)
  static int
  handle_v_kill (char *own_buf)
  {
+  client_state *cs = get_client_state();
    int pid;
    char *p = &own_buf[6];
-  if (multi_process)
+  if (cs->multi_process)
      pid = strtol (p, NULL, 16);
    else
-    pid = signal_pid;
+    pid = cs->ss->signal_pid;
    if (pid != 0 && kill_inferior (pid) == 0)
      {
-      last_status.kind = TARGET_WAITKIND_SIGNALLED;
-      last_status.value.sig = GDB_SIGNAL_KILL;
-      last_ptid = pid_to_ptid (pid);
-      discard_queued_stop_replies (last_ptid);
+      cs->ss->last_status.kind = TARGET_WAITKIND_SIGNALLED;
+      cs->ss->last_status.value.sig = GDB_SIGNAL_KILL;
+      cs->ss->last_ptid = pid_to_ptid (pid);
+      discard_queued_stop_replies (cs->ss->last_ptid);
        write_ok (own_buf);
        return 1;
      }
@@ -3091,6 +3223,8 @@ handle_v_kill (char *own_buf)
  void
  handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
  {
+  client_state *cs = get_client_state();
+
    if (!disable_packet_vCont)
      {
        if (strcmp (own_buf, "vCtrlC") == 0)
@@ -3112,7 +3246,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

  	  if (target_supports_hardware_single_step ()
  	      || target_supports_software_single_step ()
-	      || !vCont_supported)
+	      || !cs->vCont_supported)
  	    {
  	      /* If target supports single step either by hardware or by
  		 software, add actions s and S to the list of supported
@@ -3138,7 +3272,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

    if (startswith (own_buf, "vAttach;"))
      {
-      if ((!extended_protocol || !multi_process) && target_running ())
+      if ((!cs->extended_protocol || !cs->multi_process) && 
target_running ())
  	{
  	  fprintf (stderr, "Already debugging a process\n");
  	  write_enn (own_buf);
@@ -3150,7 +3284,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

    if (startswith (own_buf, "vRun;"))
      {
-      if ((!extended_protocol || !multi_process) && target_running ())
+      if ((!cs->extended_protocol || !cs->multi_process) && 
target_running ())
  	{
  	  fprintf (stderr, "Already debugging a process\n");
  	  write_enn (own_buf);
@@ -3187,12 +3321,13 @@ handle_v_requests (char *own_buf, int 
packet_len, int *new_packet_len)
  static void
  myresume (char *own_buf, int step, int sig)
  {
+  client_state *cs = get_client_state();
    struct thread_resume resume_info[2];
    int n = 0;
    int valid_cont_thread;

-  valid_cont_thread = (!ptid_equal (cont_thread, null_ptid)
-			 && !ptid_equal (cont_thread, minus_one_ptid));
+  valid_cont_thread = (!ptid_equal (cs->ss->cont_thread, null_ptid)
+			 && !ptid_equal (cs->ss->cont_thread, minus_one_ptid));

    if (step || sig || valid_cont_thread)
      {
@@ -3241,7 +3376,7 @@ queue_stop_reply_callback (thread_info *thread)
  	{
  	  if (debug_threads)
  	    {
-	      std::string status_string
+		std::string status_string
  		= target_waitstatus_to_string (&thread->last_status);

  	      debug_printf ("Reporting thread %s as already stopped with %s\n",
@@ -3307,6 +3442,8 @@ set_pending_status_callback (thread_info *thread)
  static void
  handle_status (char *own_buf)
  {
+  client_state *cs = get_client_state();
+
    /* GDB is connected, don't forward events to the target anymore.  */
    for_each_process ([] (process_info *process) {
      process->gdb_detached = 0;
@@ -3316,12 +3453,12 @@ handle_status (char *own_buf)
       thread.  In all-stop mode, just send one for the first stopped
       thread we find.  */

-  if (non_stop)
+  if (cs->non_stop)
      {
        for_each_thread (queue_stop_reply_callback);

-      /* The first is sent immediatly.  OK is sent if there is no
-	 stopped thread, which is the same handling of the vStopped
+      /* The first is sent immediately.  OK is sent if there is no
+	 stopped thread, which is the same handling as the vStopped
  	 packet (by design).  */
        notif_write_event (&notif_stop, own_buf);
      }
@@ -3343,10 +3480,10 @@ handle_status (char *own_buf)

        /* Prefer the last thread that reported an event to GDB (even if
  	 that was a GDB_SIGNAL_TRAP).  */
-      if (last_status.kind != TARGET_WAITKIND_IGNORE
-	  && last_status.kind != TARGET_WAITKIND_EXITED
-	  && last_status.kind != TARGET_WAITKIND_SIGNALLED)
-	thread = find_thread_ptid (last_ptid);
+      if (cs->ss->last_status.kind != TARGET_WAITKIND_IGNORE
+	  && cs->ss->last_status.kind != TARGET_WAITKIND_EXITED
+	  && cs->ss->last_status.kind != TARGET_WAITKIND_SIGNALLED)
+	thread = find_thread_ptid (cs->ss->last_ptid);

        /* If the last event thread is not found for some reason, look
  	 for some other thread that might have an event to report.  */
@@ -3371,7 +3508,7 @@ handle_status (char *own_buf)

  	  /* GDB assumes the current thread is the thread we're
  	     reporting the status for.  */
-	  general_thread = thread->id;
+	  cs->ss->general_thread = thread->id;
  	  set_desired_thread ();

  	  gdb_assert (tp->last_status.kind != TARGET_WAITKIND_IGNORE);
@@ -3558,6 +3695,12 @@ captured_main (int argc, char *argv[])
    volatile int multi_mode = 0;
    volatile int attach = 0;
    int was_running;
+  int run_once_arg = 0;
+  int disable_randomization_arg = 1;
+
+  int remote_desc = get_remote_desc();
+  client_states.set_client_state (remote_desc);
+  client_state *cs = get_client_state();
    bool selftest = false;
  #if GDB_SELF_TEST
    const char *selftest_filter = NULL;
@@ -3588,15 +3731,15 @@ captured_main (int argc, char *argv[])
  	  tmp = next_arg;
  	  while (*next_arg != NULL && strcmp (*next_arg, "--") != 0)
  	    {
-	      wrapper_argv += *next_arg;
-	      wrapper_argv += ' ';
+	      cs->wrapper_argv += *next_arg;
+	      cs->wrapper_argv += ' ';
  	      next_arg++;
  	    }

-	  if (!wrapper_argv.empty ())
+	  if (!cs->wrapper_argv.empty ())
  	    {
  	      /* Erase the last whitespace.  */
-	      wrapper_argv.erase (wrapper_argv.end () - 1);
+	      cs->wrapper_argv.erase (cs->wrapper_argv.end () - 1);
  	    }

  	  if (next_arg == tmp || *next_arg == NULL)
@@ -3623,7 +3766,7 @@ captured_main (int argc, char *argv[])
  	    }
  	}
        else if (strcmp (*next_arg, "--remote-debug") == 0)
-	remote_debug = 1;
+	cs->remote_debug = 1;
        else if (strcmp (*next_arg, "--disable-packet") == 0)
  	{
  	  gdbserver_show_disableable (stdout);
@@ -3671,15 +3814,15 @@ captured_main (int argc, char *argv[])
  	  break;
  	}
        else if (strcmp (*next_arg, "--disable-randomization") == 0)
-	disable_randomization = 1;
+	disable_randomization_arg = 1;
        else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
-	disable_randomization = 0;
+	disable_randomization_arg = 0;
        else if (strcmp (*next_arg, "--startup-with-shell") == 0)
  	startup_with_shell = true;
        else if (strcmp (*next_arg, "--no-startup-with-shell") == 0)
  	startup_with_shell = false;
        else if (strcmp (*next_arg, "--once") == 0)
-	run_once = 1;
+	run_once_arg = 1;
        else if (strcmp (*next_arg, "--selftest") == 0)
  	selftest = true;
        else if (startswith (*next_arg, "--selftest="))
@@ -3699,6 +3842,9 @@ captured_main (int argc, char *argv[])
        continue;
      }

+  cs->run_once = run_once_arg;
+  cs->disable_randomization = disable_randomization_arg;
+
    if (port == NULL)
      {
        port = *next_arg;
@@ -3760,8 +3906,8 @@ captured_main (int argc, char *argv[])
      initialize_tracepoint ();
    initialize_notif ();

-  own_buf = (char *) xmalloc (PBUFSIZ + 1);
-  mem_buf = (unsigned char *) xmalloc (PBUFSIZ);
+  cs->own_buf = (char *) xmalloc (PBUFSIZ + 1);
+  cs->ss->mem_buf = (unsigned char *) xmalloc (PBUFSIZ);

    if (selftest)
      {
@@ -3778,13 +3924,13 @@ captured_main (int argc, char *argv[])
        int i, n;

        n = argc - (next_arg - argv);
-      program_name = xstrdup (next_arg[0]);
+      cs->program_name = xstrdup (next_arg[0]);
        for (i = 1; i < n; i++)
-	program_args.push_back (xstrdup (next_arg[i]));
-      program_args.push_back (NULL);
+	cs->program_args.push_back (xstrdup (next_arg[i]));
+      cs->program_args.push_back (NULL);

        /* Wait till we are at first instruction in program.  */
-      create_inferior (program_name, program_args);
+      create_inferior (cs->program_name, cs->program_args);

        /* We are now (hopefully) stopped at the first instruction of
  	 the target process.  This assumes that the target process was
@@ -3799,9 +3945,9 @@ captured_main (int argc, char *argv[])
      }
    else
      {
-      last_status.kind = TARGET_WAITKIND_EXITED;
-      last_status.value.integer = 0;
-      last_ptid = minus_one_ptid;
+      cs->ss->last_status.kind = TARGET_WAITKIND_EXITED;
+      cs->ss->last_status.value.integer = 0;
+      cs->ss->last_ptid = minus_one_ptid;
      }
    make_cleanup (detach_or_kill_for_exit_cleanup, NULL);

@@ -3810,8 +3956,8 @@ captured_main (int argc, char *argv[])
       shared library event" notice on gdb side.  */
    dlls_changed = 0;

-  if (last_status.kind == TARGET_WAITKIND_EXITED
-      || last_status.kind == TARGET_WAITKIND_SIGNALLED)
+  if (cs->ss->last_status.kind == TARGET_WAITKIND_EXITED
+      || cs->ss->last_status.kind == TARGET_WAITKIND_SIGNALLED)
      was_running = 0;
    else
      was_running = 1;
@@ -3822,17 +3968,13 @@ captured_main (int argc, char *argv[])
    while (1)
      {

-      noack_mode = 0;
-      multi_process = 0;
-      report_fork_events = 0;
-      report_vfork_events = 0;
-      report_exec_events = 0;
+      cs->noack_mode = 0;
        /* Be sure we're out of tfind mode.  */
        current_traceframe = -1;
-      cont_thread = null_ptid;
-      swbreak_feature = 0;
-      hwbreak_feature = 0;
-      vCont_supported = 0;
+      cs->ss->cont_thread = null_ptid;
+      cs->swbreak_feature = 0;
+      cs->hwbreak_feature = 0;
+      cs->vCont_supported = 0;

        remote_open (port);

@@ -3844,7 +3986,7 @@ captured_main (int argc, char *argv[])

  	  /* If an exit was requested (using the "monitor exit"
  	     command), terminate now.  */
-	  if (exit_requested)
+	  if (cs->exit_requested)
  	    throw_quit ("Quit");

  	  /* The only other way to get here is for getpkt to fail:
@@ -3857,7 +3999,7 @@ captured_main (int argc, char *argv[])

  	      - Otherwise, close the connection and reopen it at the
  	        top of the loop.  */
-	  if (run_once || (!extended_protocol && !target_running ()))
+	  if (cs->run_once || (!cs->extended_protocol && !target_running ()))
  	    throw_quit ("Quit");

  	  fprintf (stderr,
@@ -3883,10 +4025,10 @@ captured_main (int argc, char *argv[])
  		     no point either in having the target always stop
  		     all threads, when we're going to pass signals
  		     down without informing GDB.  */
-		  if (!non_stop)
+		  if (!cs->non_stop)
  		    {
  		      if (start_non_stop (1))
-			non_stop = 1;
+			cs->non_stop = 1;

  		      /* Detaching implicitly resumes all threads;
  			 simply disconnecting does not.  */
@@ -3906,13 +4048,13 @@ captured_main (int argc, char *argv[])
  	  fflush (stdout);
  	  fprintf (stderr, "gdbserver: %s\n", exception.message);

-	  if (response_needed)
+	  if (cs->response_needed)
  	    {
-	      write_enn (own_buf);
-	      putpkt (own_buf);
+	      write_enn (cs->own_buf);
+	      putpkt (cs->own_buf);
  	    }

-	  if (run_once)
+	  if (cs->run_once)
  	    throw_quit ("Quit");
  	}
        END_CATCH
@@ -4004,6 +4146,7 @@ process_point_options (struct gdb_breakpoint *bp, 
const char **packet)
  static int
  process_serial_event (void)
  {
+  client_state *cs = get_client_state();
    int signal;
    unsigned int len;
    int res;
@@ -4014,41 +4157,41 @@ process_serial_event (void)

    disable_async_io ();

-  response_needed = 0;
-  packet_len = getpkt (own_buf);
-  if (packet_len <= 0)
+  cs->response_needed = 0;
+  cs->packet_length = getpkt (cs->own_buf);
+  if (cs->packet_length <= 0)
      {
        remote_close ();
        /* Force an event loop break.  */
        return -1;
      }
-  response_needed = 1;
+  cs->response_needed = 1;

-  char ch = own_buf[0];
+  char ch = cs->own_buf[0];
    switch (ch)
      {
      case 'q':
-      handle_query (own_buf, packet_len, &new_packet_len);
+      handle_query (cs->own_buf, cs->packet_length, &new_packet_len);
        break;
      case 'Q':
-      handle_general_set (own_buf);
+      handle_general_set (cs->own_buf);
        break;
      case 'D':
-      handle_detach (own_buf);
+      handle_detach (cs->own_buf);
        break;
      case '!':
-      extended_protocol = 1;
-      write_ok (own_buf);
+      cs->extended_protocol = 1;
+      write_ok (cs->own_buf);
        break;
      case '?':
-      handle_status (own_buf);
+      handle_status (cs->own_buf);
        break;
      case 'H':
-      if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
+      if (cs->own_buf[1] == 'c' || cs->own_buf[1] == 'g' || 
cs->own_buf[1] == 's')
  	{
-	  require_running_or_break (own_buf);
+	  require_running_or_break (cs->own_buf);

-	  ptid_t thread_id = read_ptid (&own_buf[2], NULL);
+	  ptid_t thread_id = read_ptid (&cs->own_buf[2], NULL);

  	  if (thread_id == null_ptid || thread_id == minus_one_ptid)
  	    thread_id = null_ptid;
@@ -4059,7 +4202,7 @@ process_serial_event (void)

  	      if (thread == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (cs->own_buf);
  		  break;
  		}

@@ -4070,42 +4213,42 @@ process_serial_event (void)
  	      /* The ptid represents a lwp/tid.  */
  	      if (find_thread_ptid (thread_id) == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (cs->own_buf);
  		  break;
  		}
  	    }

-	  if (own_buf[1] == 'g')
+	  if (cs->own_buf[1] == 'g')
  	    {
  	      if (ptid_equal (thread_id, null_ptid))
  		{
  		  /* GDB is telling us to choose any thread.  Check if
  		     the currently selected thread is still valid. If
  		     it is not, select the first available.  */
-		  thread_info *thread = find_thread_ptid (general_thread);
+		  thread_info *thread = find_thread_ptid (cs->ss->general_thread);
  		  if (thread == NULL)
  		    thread = get_first_thread ();
  		  thread_id = thread->id;
  		}

-	      general_thread = thread_id;
+	      cs->ss->general_thread = thread_id;
  	      set_desired_thread ();
-	      gdb_assert (current_thread != NULL);
+	      gdb_assert (cs->ss->current_thread != NULL);
  	    }
-	  else if (own_buf[1] == 'c')
-	    cont_thread = thread_id;
+	  else if (cs->own_buf[1] == 'c')
+	    cs->ss->cont_thread = thread_id;

-	  write_ok (own_buf);
+	  write_ok (cs->own_buf);
  	}
        else
  	{
  	  /* Silently ignore it so that gdb can extend the protocol
  	     without compatibility headaches.  */
-	  own_buf[0] = '\0';
+	  cs->own_buf[0] = '\0';
  	}
        break;
      case 'g':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs->own_buf);
        if (current_traceframe >= 0)
  	{
  	  struct regcache *regcache
@@ -4113,9 +4256,9 @@ process_serial_event (void)

  	  if (fetch_traceframe_registers (current_traceframe,
  					  regcache, -1) == 0)
-	    registers_to_string (regcache, own_buf);
+	    registers_to_string (regcache, cs->own_buf);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs->own_buf);
  	  free_register_cache (regcache);
  	}
        else
@@ -4123,85 +4266,85 @@ process_serial_event (void)
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (cs->own_buf);
  	  else
  	    {
-	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_to_string (regcache, own_buf);
+	      regcache = get_thread_regcache (cs->ss->current_thread, 1);
+	      registers_to_string (regcache, cs->own_buf);
  	    }
  	}
        break;
      case 'G':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs->own_buf);
        if (current_traceframe >= 0)
-	write_enn (own_buf);
+	write_enn (cs->own_buf);
        else
  	{
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (cs->own_buf);
  	  else
  	    {
-	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_from_string (regcache, &own_buf[1]);
-	      write_ok (own_buf);
+	      regcache = get_thread_regcache (cs->ss->current_thread, 1);
+	      registers_from_string (regcache, &cs->own_buf[1]);
+	      write_ok (cs->own_buf);
  	    }
  	}
        break;
      case 'm':
-      require_running_or_break (own_buf);
-      decode_m_packet (&own_buf[1], &mem_addr, &len);
-      res = gdb_read_memory (mem_addr, mem_buf, len);
+      require_running_or_break (cs->own_buf);
+      decode_m_packet (&cs->own_buf[1], &mem_addr, &len);
+      res = gdb_read_memory (mem_addr, cs->ss->mem_buf, len);
        if (res < 0)
-	write_enn (own_buf);
+	write_enn (cs->own_buf);
        else
-	bin2hex (mem_buf, own_buf, res);
+	bin2hex (cs->ss->mem_buf, cs->own_buf, res);
        break;
      case 'M':
-      require_running_or_break (own_buf);
-      decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf);
-      if (gdb_write_memory (mem_addr, mem_buf, len) == 0)
-	write_ok (own_buf);
+      require_running_or_break (cs->own_buf);
+      decode_M_packet (&cs->own_buf[1], &mem_addr, &len, &cs->ss->mem_buf);
+      if (gdb_write_memory (mem_addr, cs->ss->mem_buf, len) == 0)
+	write_ok (cs->own_buf);
        else
-	write_enn (own_buf);
+	write_enn (cs->own_buf);
        break;
      case 'X':
-      require_running_or_break (own_buf);
-      if (decode_X_packet (&own_buf[1], packet_len - 1,
-			   &mem_addr, &len, &mem_buf) < 0
-	  || gdb_write_memory (mem_addr, mem_buf, len) != 0)
-	write_enn (own_buf);
+      require_running_or_break (cs->own_buf);
+      if (decode_X_packet (&cs->own_buf[1], cs->packet_length - 1,
+			   &mem_addr, &len, &cs->ss->mem_buf) < 0
+	  || gdb_write_memory (mem_addr, cs->ss->mem_buf, len) != 0)
+	write_enn (cs->own_buf);
        else
-	write_ok (own_buf);
+	write_ok (cs->own_buf);
        break;
      case 'C':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (cs->own_buf);
+      hex2bin (cs->own_buf + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (cs->own_buf, 0, signal);
        break;
      case 'S':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (cs->own_buf);
+      hex2bin (cs->own_buf + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (cs->own_buf, 1, signal);
        break;
      case 'c':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs->own_buf);
        signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (cs->own_buf, 0, signal);
        break;
      case 's':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs->own_buf);
        signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (cs->own_buf, 1, signal);
        break;
      case 'Z':  /* insert_ ... */
        /* Fallthrough.  */
@@ -4210,12 +4353,12 @@ process_serial_event (void)
  	char *dataptr;
  	ULONGEST addr;
  	int kind;
-	char type = own_buf[1];
+	char type = cs->own_buf[1];
  	int res;
  	const int insert = ch == 'Z';
-	const char *p = &own_buf[3];
+	char *p = &cs->own_buf[3];

-	p = unpack_varlen_hex (p, &addr);
+	p = (char*)unpack_varlen_hex (p, &addr);
  	kind = strtol (p + 1, &dataptr, 16);

  	if (insert)
@@ -4241,16 +4384,16 @@ process_serial_event (void)
  	  res = delete_gdb_breakpoint (type, addr, kind);

  	if (res == 0)
-	  write_ok (own_buf);
+	  write_ok (cs->own_buf);
  	else if (res == 1)
  	  /* Unsupported.  */
-	  own_buf[0] = '\0';
+	  cs->own_buf[0] = '\0';
  	else
-	  write_enn (own_buf);
+	  write_enn (cs->own_buf);
  	break;
        }
      case 'k':
-      response_needed = 0;
+      cs->response_needed = 0;
        if (!target_running ())
  	/* The packet we received doesn't make sense - but we can't
  	   reply to it, either.  */
@@ -4262,10 +4405,10 @@ process_serial_event (void)

        /* When using the extended protocol, we wait with no program
  	 running.  The traditional protocol will exit instead.  */
-      if (extended_protocol)
+      if (cs->extended_protocol)
  	{
-	  last_status.kind = TARGET_WAITKIND_EXITED;
-	  last_status.value.sig = GDB_SIGNAL_KILL;
+	  cs->ss->last_status.kind = TARGET_WAITKIND_EXITED;
+	  cs->ss->last_status.value.sig = GDB_SIGNAL_KILL;
  	  return 0;
  	}
        else
@@ -4273,27 +4416,27 @@ process_serial_event (void)

      case 'T':
        {
-	require_running_or_break (own_buf);
+	require_running_or_break (cs->own_buf);

-	ptid_t thread_id = read_ptid (&own_buf[1], NULL);
+	ptid_t thread_id = read_ptid (&cs->own_buf[1], NULL);
  	if (find_thread_ptid (thread_id) == NULL)
  	  {
-	    write_enn (own_buf);
+	    write_enn (cs->own_buf);
  	    break;
  	  }

  	if (mythread_alive (thread_id))
-	  write_ok (own_buf);
+	  write_ok (cs->own_buf);
  	else
-	  write_enn (own_buf);
+	  write_enn (cs->own_buf);
        }
        break;
      case 'R':
-      response_needed = 0;
+      cs->response_needed = 0;

        /* Restarting the inferior is only supported in the extended
  	 protocol.  */
-      if (extended_protocol)
+      if (cs->extended_protocol)
  	{
  	  if (target_running ())
  	    for_each_process (kill_inferior_callback);
@@ -4301,26 +4444,26 @@ process_serial_event (void)
  	  fprintf (stderr, "GDBserver restarting\n");

  	  /* Wait till we are at 1st instruction in prog.  */
-	  if (program_name != NULL)
+	  if (cs->program_name != NULL)
  	    {
-	      create_inferior (program_name, program_args);
+	      create_inferior (cs->program_name, cs->program_args);

-	      if (last_status.kind == TARGET_WAITKIND_STOPPED)
+	      if (cs->ss->last_status.kind == TARGET_WAITKIND_STOPPED)
  		{
  		  /* Stopped at the first instruction of the target
  		     process.  */
-		  general_thread = last_ptid;
+		  cs->ss->general_thread = cs->ss->last_ptid;
  		}
  	      else
  		{
  		  /* Something went wrong.  */
-		  general_thread = null_ptid;
+		  cs->ss->general_thread = null_ptid;
  		}
  	    }
  	  else
  	    {
-	      last_status.kind = TARGET_WAITKIND_EXITED;
-	      last_status.value.sig = GDB_SIGNAL_KILL;
+	      cs->ss->last_status.kind = TARGET_WAITKIND_EXITED;
+	      cs->ss->last_status.value.sig = GDB_SIGNAL_KILL;
  	    }
  	  return 0;
  	}
@@ -4329,30 +4472,30 @@ process_serial_event (void)
  	  /* It is a request we don't understand.  Respond with an
  	     empty packet so that gdb knows that we don't support this
  	     request.  */
-	  own_buf[0] = '\0';
+	  cs->own_buf[0] = '\0';
  	  break;
  	}
      case 'v':
        /* Extended (long) request.  */
-      handle_v_requests (own_buf, packet_len, &new_packet_len);
+      handle_v_requests (cs->own_buf, cs->packet_length, &new_packet_len);
        break;

      default:
        /* It is a request we don't understand.  Respond with an empty
  	 packet so that gdb knows that we don't support this
  	 request.  */
-      own_buf[0] = '\0';
+      cs->own_buf[0] = '\0';
        break;
      }

    if (new_packet_len != -1)
-    putpkt_binary (own_buf, new_packet_len);
+    putpkt_binary (cs->own_buf, new_packet_len);
    else
-    putpkt (own_buf);
+    putpkt (cs->own_buf);

-  response_needed = 0;
+  cs->response_needed = 0;

-  if (exit_requested)
+  if (cs->exit_requested)
      return -1;

    return 0;
@@ -4395,38 +4538,40 @@ push_stop_notification (ptid_t ptid, struct 
target_waitstatus *status)
  int
  handle_target_event (int err, gdb_client_data client_data)
  {
+  client_state *cs = get_client_state();
+
    if (debug_threads)
      debug_printf ("handling possible target event\n");

-  last_ptid = mywait (minus_one_ptid, &last_status,
+  cs->ss->last_ptid = mywait (minus_one_ptid, &cs->ss->last_status,
  		      TARGET_WNOHANG, 1);

-  if (last_status.kind == TARGET_WAITKIND_NO_RESUMED)
+  if (cs->ss->last_status.kind == TARGET_WAITKIND_NO_RESUMED)
      {
-      if (gdb_connected () && report_no_resumed)
-	push_stop_notification (null_ptid, &last_status);
+      if (gdb_connected () && cs->report_no_resumed)
+	push_stop_notification (null_ptid, &cs->ss->last_status);
      }
-  else if (last_status.kind != TARGET_WAITKIND_IGNORE)
+  else if (cs->ss->last_status.kind != TARGET_WAITKIND_IGNORE)
      {
-      int pid = ptid_get_pid (last_ptid);
+      int pid = ptid_get_pid (cs->ss->last_ptid);
        struct process_info *process = find_process_pid (pid);
        int forward_event = !gdb_connected () || process->gdb_detached;

-      if (last_status.kind == TARGET_WAITKIND_EXITED
-	  || last_status.kind == TARGET_WAITKIND_SIGNALLED)
+      if (cs->ss->last_status.kind == TARGET_WAITKIND_EXITED
+	  || cs->ss->last_status.kind == TARGET_WAITKIND_SIGNALLED)
  	{
  	  mark_breakpoints_out (process);
-	  target_mourn_inferior (last_ptid);
+	  target_mourn_inferior (cs->ss->last_ptid);
  	}
-      else if (last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+      else if (cs->ss->last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
  	;
        else
  	{
  	  /* We're reporting this thread as stopped.  Update its
  	     "want-stopped" state to what the client wants, until it
  	     gets a new resume action.  */
-	  current_thread->last_resume_kind = resume_stop;
-	  current_thread->last_status = last_status;
+	  cs->ss->current_thread->last_resume_kind = resume_stop;
+	  cs->ss->current_thread->last_status = cs->ss->last_status;
  	}

        if (forward_event)
@@ -4437,9 +4582,9 @@ handle_target_event (int err, gdb_client_data 
client_data)
  	      exit (0);
  	    }

-	  if (last_status.kind == TARGET_WAITKIND_EXITED
-	      || last_status.kind == TARGET_WAITKIND_SIGNALLED
-	      || last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+	  if (cs->ss->last_status.kind == TARGET_WAITKIND_EXITED
+	      || cs->ss->last_status.kind == TARGET_WAITKIND_SIGNALLED
+	      || cs->ss->last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
  	    ;
  	  else
  	    {
@@ -4451,18 +4596,18 @@ handle_target_event (int err, gdb_client_data 
client_data)
  	      if (debug_threads)
  		debug_printf ("GDB not connected; forwarding event %d for"
  			      " [%s]\n",
-			      (int) last_status.kind,
-			      target_pid_to_str (last_ptid));
+			      (int) cs->ss->last_status.kind,
+			      target_pid_to_str (cs->ss->last_ptid));

-	      if (last_status.kind == TARGET_WAITKIND_STOPPED)
-		signal = last_status.value.sig;
+	      if (cs->ss->last_status.kind == TARGET_WAITKIND_STOPPED)
+		signal = cs->ss->last_status.value.sig;
  	      else
  		signal = GDB_SIGNAL_0;
-	      target_continue (last_ptid, signal);
+	      target_continue (cs->ss->last_ptid, signal);
  	    }
  	}
        else
-	push_stop_notification (last_ptid, &last_status);
+	push_stop_notification (cs->ss->last_ptid, &cs->ss->last_status);
      }

    /* Be sure to not change the selected thread behind GDB's back.
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 5970431d8ed..8e1459f74e2 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -60,52 +60,19 @@ int vsnprintf(char *str, size_t size, const char 
*format, va_list ap);
  #include "gdb_signals.h"
  #include "target.h"
  #include "mem-break.h"
-#include "gdbthread.h"
-#include "inferiors.h"
  #include "environ.h"
+#include <list>
+#include <map>

  /* Target-specific functions */

  void initialize_low ();

-/* Public variables in server.c */
-
-extern ptid_t cont_thread;
-extern ptid_t general_thread;
-
-extern int server_waiting;
-extern int pass_signals[];
-extern int program_signals[];
-extern int program_signals_p;
-
  extern int disable_packet_vCont;
  extern int disable_packet_Tthread;
  extern int disable_packet_qC;
  extern int disable_packet_qfThreadInfo;

-extern char *own_buf;
-
-extern int run_once;
-extern int multi_process;
-extern int report_fork_events;
-extern int report_vfork_events;
-extern int report_exec_events;
-extern int report_thread_events;
-extern int non_stop;
-
-/* True if the "swbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a software breakpoint
-   and for the server to handle PC adjustment if necessary on this
-   target.  Only enabled if the target supports it.  */
-extern int swbreak_feature;
-
-/* True if the "hwbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a hardware breakpoint.
-   Only enabled if the target supports it.  */
-extern int hwbreak_feature;
-
-extern int disable_randomization;
-
  #if USE_WIN32API
  #include <winsock2.h>
  typedef SOCKET gdb_fildes_t;
@@ -158,8 +125,161 @@ extern void post_fork_inferior (int pid, const 
char *program);
  /* Get the gdb_environ being used in the current session.  */
  extern gdb_environ *get_environ ();

-extern target_waitstatus last_status;
-extern ptid_t last_ptid;
-extern unsigned long signal_pid;
+// extern ptid_t cs->ss->last_ptid;
+// extern unsigned long cs->ss->signal_pid;

  #endif /* SERVER_H */
+
+/* Description of the remote protocol state for the currently
+   connected target.  This is per-target state, and independent of the
+   selected architecture. */
+
+struct server_state
+{
+  int attach_count;
+  /* From server.c */
+  /* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
+     `vCont'.  Note the multi-process extensions made `vCont' a
+     requirement, so `Hc pPID.TID' is pretty much undefined.  So
+     CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
+     resuming all threads of the process (again, `Hc' isn't used for
+     multi-process), or a specific thread ptid_t.  */
+  ptid_t cont_thread;
+  /* The thread set with an `Hg' packet.  */
+  ptid_t general_thread;
+  /* The PID of the originally created or attached inferior.  Used to
+     send signals to the process when GDB sends us an asynchronous 
interrupt
+     (user hitting Control-C in the client), and to wait for the child 
to exit
+     when no longer debugging it.  */
+
+  unsigned long signal_pid;
+  /* Last status reported to GDB.  */
+  struct target_waitstatus last_status;
+  /* Was last status an exit status? (sticky if yes) */
+  int last_status_exited;
+  ptid_t last_ptid;
+  unsigned char *mem_buf;
+
+  /* from remote-utils.c */
+  /* Internal buffer used by readchar.
+     These are global to readchar because reschedule_remote needs to be
+     able to tell whether the buffer is empty.  */
+  unsigned char readchar_buf[BUFSIZ];
+  int readchar_bufcnt;
+  unsigned char *readchar_bufp;
+  /* from inferiors.c */
+  std::list<process_info *> all_processes;
+  std::list<thread_info *> all_threads;
+
+  struct thread_info *current_thread;
+};
+
+typedef struct server_state server_state;
+
+
+enum packet_types { other_packet, vContc, vConts, vContt, vRun, 
vAttach, Hg, g_or_m, vStopped };
+typedef enum packet_types packet_types;
+
+enum exit_types { no_exit, have_exit, sent_exit };
+typedef enum exit_types exit_types;
+
+
+struct client_state
+{
+  gdb_fildes_t file_desc;
+  int attached_to_client;
+  int packet_type;
+  int last_packet_type;
+  int pending;
+  int nonstop_pending;
+  int catch_syscalls;
+  ptid_t last_cont_ptid;
+  ptid_t new_general_thread;
+
+  /* From server.c */
+  int server_waiting;
+
+  int extended_protocol;
+  int response_needed;
+  int exit_requested;
+
+  /* --once: Exit after the first connection has closed.  */
+  int run_once;
+
+  int multi_process;
+  int report_fork_events;
+  int report_vfork_events;
+  int report_exec_events;
+  int report_thread_events;
+  /* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
+  int report_no_resumed;
+  int non_stop;
+  /* True if the "swbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a software breakpoint
+     and for the server to handle PC adjustment if necessary on this
+     target.  Only enabled if the target supports it.  */
+  int swbreak_feature;
+  /* True if the "hwbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a hardware breakpoint.
+     Only enabled if the target supports it.  */
+  int hwbreak_feature;
+
+  /* True if the "vContSupported" feature is active.  In that case, GDB
+     wants us to report whether single step is supported in the reply to
+     "vCont?" packet.  */
+  int vCont_supported;
+
+  /* Whether we should attempt to disable the operating system's address
+     space randomization feature before starting an inferior.  */
+  int disable_randomization;
+
+  char *program_name = NULL;
+  std::vector<char *> program_args;
+  std::string wrapper_argv;
+
+  int packet_length;
+
+  int pass_signals[GDB_SIGNAL_LAST];
+  int program_signals[GDB_SIGNAL_LAST];
+  int program_signals_p;
+
+  char *notify_buffer;
+  /* Renamed from own_buf to avoid macro name conflict with a common 
local variable name */
+  char *own_buf;
+
+  /* from remote-utils.c */
+  int remote_debug;
+  /* If true, then GDB has requested noack mode.  */
+  int noack_mode;
+  /* If true, then we tell GDB to use noack mode by default.  */
+  int transport_is_reliable;
+
+  server_state *ss;
+
+  client_state () {};
+  client_state (gdb_fildes_t, client_state*);
+};
+
+typedef struct client_state client_state;
+
+
+struct multi_client_states
+{
+public:
+  std::map<gdb_fildes_t,client_state*> cs;
+  client_state *current_cs;
+
+  client_state* get_client_state (void) { return current_cs; }
+  void set_current_client (client_state* p_cs) { current_cs = p_cs; }
+
+  client_state * set_client_state (gdb_fildes_t);
+  void free_client_state (client_state *cs);
+  void delete_client_state (gdb_fildes_t fd);
+};
+
+client_state* get_client_state (void);
+struct multi_client_states * get_client_states (void);
+
+
+#include "gdbthread.h"
+#include "inferiors.h"
diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
index fd1f8d652c6..5d51a420586 100644
--- a/gdb/gdbserver/spu-low.c
+++ b/gdb/gdbserver/spu-low.c
@@ -280,12 +280,12 @@ spu_ptrace_fun ()

  static int
  spu_create_inferior (const char *program,
-		     const std::vector<char *> &program_args)
+		     const std::vector<char *> &cs->program_args)
  {
    int pid;
    ptid_t ptid;
    struct process_info *proc;
-  std::string str_program_args = stringify_argv (program_args);
+  std::string str_program_args = stringify_argv (cs->program_args);

    pid = fork_inferior (program,
  		       str_program_args.c_str (),
@@ -439,7 +439,7 @@ spu_wait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options)

    /* On the first wait, continue running the inferior until we are
       blocked inside an spu_run system call.  */
-  if (!server_waiting)
+  if (!cs->server_waiting)
      {
        int fd;
        CORE_ADDR addr;
@@ -470,7 +470,7 @@ spu_wait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options)

    /* After attach, we may have received a SIGSTOP.  Do not return this
       as signal to GDB, or else it will try to continue with SIGSTOP 
...  */
-  if (!server_waiting)
+  if (!cs->server_waiting)
      {
        ourstatus->kind = TARGET_WAITKIND_STOPPED;
        ourstatus->value.sig = GDB_SIGNAL_0;
diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c
index 019f9748346..38ad8b3341f 100644
--- a/gdb/gdbserver/target.c
+++ b/gdb/gdbserver/target.c
@@ -26,10 +26,11 @@ struct target_ops *the_target;
  int
  set_desired_thread ()
  {
-  thread_info *found = find_thread_ptid (general_thread);
+  client_state *cs = get_client_state();
+  thread_info *found = find_thread_ptid (cs->ss->general_thread);

-  current_thread = found;
-  return (current_thread != NULL);
+  cs->ss->current_thread = found;
+  return (cs->ss->current_thread != NULL);
  }

  /* The thread that was current before prepare_to_access_memory was
@@ -42,6 +43,8 @@ static ptid_t prev_general_thread;
  int
  prepare_to_access_memory (void)
  {
+  client_state *cs = get_client_state();
+
    /* The first thread found.  */
    struct thread_info *first = NULL;
    /* The first stopped thread found.  */
@@ -51,7 +54,7 @@ prepare_to_access_memory (void)

    /* Save the general thread value, since prepare_to_access_memory 
could change
       it.  */
-  prev_general_thread = general_thread;
+  prev_general_thread = cs->ss->general_thread;

    if (the_target->prepare_to_access_memory != NULL)
      {
@@ -97,8 +100,8 @@ prepare_to_access_memory (void)
        return 1;
      }

-  current_thread = thread;
-  general_thread = ptid_of (thread);
+  cs->ss->current_thread = thread;
+  cs->ss->general_thread = ptid_of (thread);

    return 0;
  }
@@ -108,12 +111,14 @@ prepare_to_access_memory (void)
  void
  done_accessing_memory (void)
  {
+  client_state *cs = get_client_state();
+
    if (the_target->done_accessing_memory != NULL)
      the_target->done_accessing_memory ();

    /* Restore the previous selected thread.  */
-  general_thread = prev_general_thread;
-  switch_to_thread (general_thread);
+  cs->ss->general_thread = prev_general_thread;
+  switch_to_thread (cs->ss->general_thread);
  }

  int
@@ -176,10 +181,11 @@ ptid_t
  mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
  	int connected_wait)
  {
+  client_state *cs = get_client_state();
    ptid_t ret;

    if (connected_wait)
-    server_waiting = 1;
+    cs->server_waiting = 1;

    ret = target_wait (ptid, ourstatus, options);

@@ -206,7 +212,7 @@ mywait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options,
      }

    if (connected_wait)
-    server_waiting = 0;
+    cs->server_waiting = 0;

    return ret;
  }
@@ -216,8 +222,9 @@ mywait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options,
  void
  target_stop_and_wait (ptid_t ptid)
  {
+  client_state *cs = get_client_state();
    struct target_waitstatus status;
-  int was_non_stop = non_stop;
+  int was_non_stop = cs->non_stop;
    struct thread_resume resume_info;

    resume_info.thread = ptid;
@@ -225,9 +232,9 @@ target_stop_and_wait (ptid_t ptid)
    resume_info.sig = GDB_SIGNAL_0;
    (*the_target->resume) (&resume_info, 1);

-  non_stop = 1;
+  cs->non_stop = 1;
    mywait (ptid, &status, 0, 0);
-  non_stop = was_non_stop;
+  cs->non_stop = was_non_stop;
  }

  /* See target/target.h.  */
diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c
index c39b5e7d27e..9b1c398e53a 100644
--- a/gdb/gdbserver/tdesc.c
+++ b/gdb/gdbserver/tdesc.c
@@ -60,7 +60,9 @@ copy_target_description (struct target_desc *dest,
  const struct target_desc *
  current_target_desc (void)
  {
-  if (current_thread == NULL)
+  client_state *cs = get_client_state();
+
+  if (cs->ss->current_thread == NULL)
      return &default_description;

    return current_process ()->tdesc;
diff --git a/gdb/gdbserver/thread-db.c b/gdb/gdbserver/thread-db.c
index 812aa0f61f1..f9f31c6878a 100644
--- a/gdb/gdbserver/thread-db.c
+++ b/gdb/gdbserver/thread-db.c
@@ -308,6 +308,7 @@ find_new_threads_callback (const td_thrhandle_t 
*th_p, void *data)
  static void
  thread_db_find_new_threads (void)
  {
+  client_state *cs = get_client_state();
    td_err_e err;
    ptid_t ptid = current_ptid;
    struct thread_db *thread_db = current_process ()->priv->thread_db;
@@ -386,6 +387,7 @@ int
  thread_db_get_tls_address (struct thread_info *thread, CORE_ADDR offset,
  			   CORE_ADDR load_module, CORE_ADDR *address)
  {
+  client_state *cs = get_client_state();
    psaddr_t addr;
    td_err_e err;
    struct lwp_info *lwp;
@@ -412,8 +414,8 @@ thread_db_get_tls_address (struct thread_info 
*thread, CORE_ADDR offset,
    if (!lwp->thread_known)
      return TD_NOTHR;

-  saved_thread = current_thread;
-  current_thread = thread;
+  saved_thread = cs->ss->current_thread;
+  cs->ss->current_thread = thread;

    if (load_module != 0)
      {
@@ -436,7 +438,7 @@ thread_db_get_tls_address (struct thread_info 
*thread, CORE_ADDR offset,
        addr = (char *) addr + offset;
      }

-  current_thread = saved_thread;
+  cs->ss->current_thread = saved_thread;
    if (err == TD_OK)
      {
        *address = (CORE_ADDR) (uintptr_t) addr;
@@ -772,9 +774,10 @@ thread_db_init (void)
  static void
  switch_to_process (struct process_info *proc)
  {
+  client_state *cs = get_client_state();
    int pid = pid_of (proc);

-  current_thread = find_any_thread_of_pid (pid);
+  cs->ss->current_thread = find_any_thread_of_pid (pid);
  }

  /* Disconnect from libthread_db and free resources.  */
@@ -782,6 +785,7 @@ switch_to_process (struct process_info *proc)
  static void
  disable_thread_event_reporting (struct process_info *proc)
  {
+  client_state *cs = get_client_state();
    struct thread_db *thread_db = proc->priv->thread_db;
    if (thread_db)
      {
@@ -798,7 +802,7 @@ disable_thread_event_reporting (struct process_info 
*proc)

        if (td_ta_clear_event_p != NULL)
  	{
-	  struct thread_info *saved_thread = current_thread;
+	  struct thread_info *saved_thread = cs->ss->current_thread;
  	  td_thr_events_t events;

  	  switch_to_process (proc);
@@ -808,7 +812,7 @@ disable_thread_event_reporting (struct process_info 
*proc)
  	  td_event_fillset (&events);
  	  (*td_ta_clear_event_p) (thread_db->thread_agent, &events);

-	  current_thread = saved_thread;
+	  cs->ss->current_thread = saved_thread;
  	}
      }
  }
@@ -893,6 +897,7 @@ thread_db_handle_monitor_command (char *mon)
  void
  thread_db_notice_clone (struct thread_info *parent_thr, ptid_t child_ptid)
  {
+  client_state *cs = get_client_state();
    process_info *parent_proc = get_thread_process (parent_thr);
    struct thread_db *thread_db = parent_proc->priv->thread_db;

@@ -905,7 +910,7 @@ thread_db_notice_clone (struct thread_info 
*parent_thr, ptid_t child_ptid)
       the current thread.  Temporarily switch to a thread we know is
       stopped.  */
    scoped_restore restore_current_thread
-    = make_scoped_restore (&current_thread, parent_thr);
+    = make_scoped_restore (&cs->ss->current_thread, parent_thr);

    if (!find_one_thread (child_ptid))
      warning ("Cannot find thread after clone.\n");
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 41727561925..4873ecf8b44 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -2343,10 +2343,11 @@ find_next_traceframe_by_tracepoint (int num, int 
*tfnump)
  static void
  cmd_qtinit (char *packet)
  {
+  client_state *cs = get_client_state();
    struct trace_state_variable *tsv, *prev, *next;

    /* Can't do this command without a pid attached.  */
-  if (current_thread == NULL)
+  if (cs->ss->current_thread == NULL)
      {
        write_enn (packet);
        return;
@@ -3959,22 +3960,23 @@ cmd_qtstmat (char *packet)
  void
  gdb_agent_about_to_close (int pid)
  {
+  client_state *cs = get_client_state();
    char buf[IPA_CMD_BUF_SIZE];

    if (!maybe_write_ipa_not_loaded (buf))
      {
        struct thread_info *saved_thread;

-      saved_thread = current_thread;
+      saved_thread = cs->ss->current_thread;

        /* Find any thread which belongs to process PID.  */
-      current_thread = find_any_thread_of_pid (pid);
+      cs->ss->current_thread = find_any_thread_of_pid (pid);

        strcpy (buf, "close");

        run_inferior_command (buf, strlen (buf) + 1);

-      current_thread = saved_thread;
+      cs->ss->current_thread = saved_thread;
      }
  }

@@ -3984,7 +3986,9 @@ gdb_agent_about_to_close (int pid)
  static void
  cmd_qtminftpilen (char *packet)
  {
-  if (current_thread == NULL)
+  client_state *cs = get_client_state();
+
+  if (cs->ss->current_thread == NULL)
      {
        /* Indicate that the minimum length is currently unknown.  */
        strcpy (packet, "0");
@@ -6833,6 +6837,7 @@ static struct ltt_available_probe gdb_ust_probe =
  static int
  run_inferior_command (char *cmd, int len)
  {
+  client_state *cs = get_client_state();
    int err = -1;
    int pid = ptid_get_pid (current_ptid);

diff --git a/gdb/gdbserver/win32-i386-low.c b/gdb/gdbserver/win32-i386-low.c
index a242f7258af..04e8b13c66f 100644
--- a/gdb/gdbserver/win32-i386-low.c
+++ b/gdb/gdbserver/win32-i386-low.c
@@ -54,7 +54,7 @@ x86_dr_low_set_addr (int regnum, CORE_ADDR addr)
    gdb_assert (DR_FIRSTADDR <= regnum && regnum <= DR_LASTADDR);

    /* Only update the threads of this process.  */
-  for_each_thread (current_thread->id.pid (), update_debug_registers);
+  for_each_thread (cs->ss->current_thread->id.pid (), 
update_debug_registers);
  }

  /* Update the inferior's DR7 debug control register from STATE.  */
@@ -63,7 +63,7 @@ static void
  x86_dr_low_set_control (unsigned long control)
  {
    /* Only update the threads of this process.  */
-  for_each_thread (current_thread->id.pid (), update_debug_registers);
+  for_each_thread (cs->ss->current_thread->id.pid (), 
update_debug_registers);
  }

  /* Return the current value of a DR register of the current thread's
@@ -73,7 +73,7 @@ static DWORD64
  win32_get_current_dr (int dr)
  {
    win32_thread_info *th
-    = (win32_thread_info *) thread_target_data (current_thread);
+    = (win32_thread_info *) thread_target_data (cs->ss->current_thread);

    win32_require_context (th);

diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index b1d9b51e533..9ae5829d546 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -242,7 +242,7 @@ static void
  child_delete_thread (DWORD pid, DWORD tid)
  {
    /* If the last thread is exiting, just return.  */
-  if (all_threads.size () == 1)
+  if (cs->ss->all_threads.size () == 1)
      return;

    thread_info *thread = find_thread_ptid (ptid_t (pid, tid));
@@ -622,7 +622,7 @@ Could not convert the expanded inferior cwd to 
wide-char."));
     process with the process list.  */
  static int
  win32_create_inferior (const char *program,
-		       const std::vector<char *> &program_args)
+		       const std::vector<char *> &cs->program_args)
  {
  #ifndef USE_WIN32API
    char real_path[PATH_MAX];
@@ -634,7 +634,7 @@ win32_create_inferior (const char *program,
    int argc;
    PROCESS_INFORMATION pi;
    DWORD err;
-  std::string str_program_args = stringify_argv (program_args);
+  std::string str_program_args = stringify_argv (cs->program_args);
    char *args = (char *) str_program_args.c_str ();

    /* win32_wait needs to know we're not attaching.  */
@@ -776,7 +776,7 @@ handle_output_debug_string (void)

    if (!startswith (s, "cYg"))
      {
-      if (!server_waiting)
+      if (!cs->server_waiting)
  	{
  	  OUTMSG2(("%s", s));
  	  return;
@@ -1472,7 +1472,7 @@ get_child_debug_event (struct target_waitstatus 
*ourstatus)
        child_delete_thread (current_event.dwProcessId,
  			   current_event.dwThreadId);

-      current_thread = get_first_thread ();
+      cs->ss->current_thread = get_first_thread ();
        return 1;

      case CREATE_PROCESS_DEBUG_EVENT:
@@ -1570,7 +1570,7 @@ get_child_debug_event (struct target_waitstatus 
*ourstatus)
      }

    ptid = debug_event_ptid (&current_event);
-  current_thread = find_thread_ptid (ptid);
+  cs->ss->current_thread = find_thread_ptid (ptid);
    return 1;
  }

@@ -1610,7 +1610,7 @@ win32_wait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options)
  	  OUTMSG2 (("Child Stopped with signal = %d \n",
  		    ourstatus->value.sig));

-	  regcache = get_thread_regcache (current_thread, 1);
+	  regcache = get_thread_regcache (cs->ss->current_thread, 1);
  	  child_fetch_inferior_registers (regcache, -1);
  	  return debug_event_ptid (&current_event);
  	default:
diff --git a/gdb/gnulib/import/error.c b/gdb/gnulib/import/error.c
index b3b1286a350..1d151112ca5 100644
--- a/gdb/gnulib/import/error.c
+++ b/gdb/gnulib/import/error.c
@@ -65,7 +65,7 @@ unsigned int error_message_count;
  #ifdef _LIBC
  /* In the GNU C library, there is a predefined variable for this.  */

-# define program_name program_invocation_name
+# define cs->program_name program_invocation_name
  # include <errno.h>
  # include <limits.h>
  # include <libio/libioP.h>
@@ -115,7 +115,7 @@ int strerror_r ();
  #  endif
  # endif

-#define program_name getprogname ()
+#define cs->program_name getprogname ()

  # if HAVE_STRERROR_R || defined strerror_r
  #  define __strerror_r strerror_r
@@ -310,9 +310,9 @@ error (int status, int errnum, const char *message, ...)
    else
      {
  #if _LIBC
-      __fxprintf (NULL, "%s: ", program_name);
+      __fxprintf (NULL, "%s: ", cs->program_name);
  #else
-      fprintf (stderr, "%s: ", program_name);
+      fprintf (stderr, "%s: ", cs->program_name);
  #endif
      }

@@ -372,9 +372,9 @@ error_at_line (int status, int errnum, const char 
*file_name,
    else
      {
  #if _LIBC
-      __fxprintf (NULL, "%s:", program_name);
+      __fxprintf (NULL, "%s:", cs->program_name);
  #else
-      fprintf (stderr, "%s:", program_name);
+      fprintf (stderr, "%s:", cs->program_name);
  #endif
      }

diff --git a/gdb/nat/linux-personality.h b/gdb/nat/linux-personality.h
index 229cc3ef1c9..3f2e0724c49 100644
--- a/gdb/nat/linux-personality.h
+++ b/gdb/nat/linux-personality.h
@@ -27,7 +27,7 @@ public:
    /* Disable the inferior's address space randomization if
       DISABLE_RANDOMIZATION is not zero and if we have
       <sys/personality.h>. */
-  maybe_disable_address_space_randomization (int disable_randomization);
+  maybe_disable_address_space_randomization (int p_disable_randomization);

    /* On destruction, re-enable address space randomization.  */
    ~maybe_disable_address_space_randomization ();


^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH] Consolidate gdbserver global variables
  2018-01-31  3:41 ` Stan Cox
@ 2018-04-23 17:58   ` Pedro Alves
  2018-05-03 15:06     ` [RFC][PATCH v2] " Stan Cox
  0 siblings, 1 reply; 15+ messages in thread
From: Pedro Alves @ 2018-04-23 17:58 UTC (permalink / raw)
  To: Stan Cox, gdb-patches

Hi Stan,

On 01/31/2018 03:41 AM, Stan Cox wrote:
>> consolidating the global variables in gdbserver into one of two
>> structures: client_state and server_state.  Client_state are those items
>> that have, or potentially could have, per client values, whereas
>> server_state are those items that have a per process value, i.e. will
>> have the same value for all clients.  

I've tried to take another fresh look at this today.
Sorry for the delay...

I'm afraid I am still confused about the client vs server states.
Why do we need server_state, if the value is the same for
all clients?

The structures in the code itself should have leading describing
comments, explaining their relations.

+/* Description of the remote protocol state for the currently
+   connected target.  This is per-target state, and independent of the
+   selected architecture. */
+
+struct server_state
+{

What is a "connected target" in this context?

I did not see description for client_state in the code.

I think the parts about multiple client states and the fd mapping
should be split to a separate patch.  The first patch would
only move the globals to structures, and start with a single
global instance of such structures.  Uses of map/set and other
data structure changes would be another patch.  Code to support
multiple connections would likely be another patch, etc.

 +enum packet_types { other_packet, vContc, vConts, vContt, vRun, vAttach, Hg, g_or_m, vStopped };
 +typedef enum packet_types packet_types;
 +
 +enum exit_types { no_exit, have_exit, sent_exit };
 +typedef enum exit_types exit_types;

These look like things that are not used yet and thus
should be split to a separate patch.

This patch, although large,
>> primarily moves global data into one of the two structures
> This is the same patch but with one major difference.  No use is made of access macros; instead the actual accesses are used.  For example, instead of a macro
>  #define current_thread    (get_client_state()->ss->current_thread_)
> through which all current_thread accesses are made
> instead:
>    client_state *cs = get_client_state();
>    ...
>    cs->ss->current_thread

Thanks.  I like the over-avoidance of macros.

I'm not super thrilled about the long "cs->ss->" chains though.

There is _always_ a client_state, right?  I.e., get_client_state()
never returns NULL?  If so, sounds like get_client_state()
could return a reference instead of a pointer?

> (Another possibility to make the patch smaller would be an additional
>  struct thread_info *current_thread = cs->ss->current_thread;

Yeah.  Since that would just be decomposing expressions, we could
make use of "auto &&" too, like:

   auto &&current_thread = client_state ()->ss->current_thread;
   auto &&all_threads = client_state ()->ss->all_threads;

Another option would be to add some convenient wrapper functions
for the most common cases.  Like

thread_info *current_thread ()
{
  return client_state ()->ss->current_thread;
}

>  ... )
> Distribution of global variables with more than 10 accesses:
> program_name 11
> last_ptid 11
> program_args 14
> remote_debug 22
> non_stop 23
> general_thread 23
> last_status 47
> own_buf 106
> current_thread 248



> 
> The patch below is present in the branch:
>  ssh://sourceware.org/git/archer.git::scox/gdbserver-multi-client
> (it is large, sorry about that, but much of it is mechanical)
> 
> diff --git a/gdb/gdbserver/event-loop.c b/gdb/gdbserver/event-loop.c
> index eec0bcf3af6..382d9b3efa7 100644
> --- a/gdb/gdbserver/event-loop.c
> +++ b/gdb/gdbserver/event-loop.c
> @@ -385,6 +385,9 @@ delete_file_handler (gdb_fildes_t fd)
>      ;
>        prev_ptr->next_file = file_ptr->next_file;
>      }
> +
> +  struct multi_client_states *client_states = get_client_states();
> +  client_states->delete_client_state (fd);
>    free (file_ptr);

Formatting nit: there should be a space before "(" in 
"get_client_states()" (and all function calls).

Note the patch has clear signs of global sed'ing. :-)
E.g., obviously this is incorrect:

 @@ -628,7 +628,7 @@ Could not convert the expanded inferior cwd to wide-char."));
     process with the process list.  */
  static int
  win32_create_inferior (const char *program,
 -                      const std::vector<char *> &program_args)
 +                      const std::vector<char *> &cs->program_args)
  {
 
Here too:

 --- a/gdb/gnulib/import/error.c
 +++ b/gdb/gnulib/import/error.c
 @@ -65,7 +65,7 @@ unsigned int error_message_count;
  #ifdef _LIBC
  /* In the GNU C library, there is a predefined variable for this.  */
  
 -# define program_name program_invocation_name
 +# define cs->program_name program_invocation_name
  # include <errno.h>
  # include <limits.h>
  # include <libio/libioP.h>
 @@ -115,7 +115,7 @@ int strerror_r ();
  #  endif
  # endif
  
 -#define program_name getprogname ()
 +#define cs->program_name getprogname ()

The patch should not be changing anything under gnulib/ at all.

There may be more cases.



> +  client_state () {};

Spurious ;.  

What is initializing all the fields in the structure?
Can we use in-class initialization?

> +  client_state (gdb_fildes_t, client_state*);
> +};

This needs a comment/description.  What is this ctor for?

> 
> 
> struct multi_client_states
> {
> public:
>   std::map<gdb_fildes_t,client_state*> cs;
>   client_state *current_cs;
> 
>   client_state* get_client_state (void) { return current_cs; }
>   void set_current_client (client_state* p_cs) { current_cs = p_cs; }
> 
>   client_state * set_client_state (gdb_fildes_t);
>   void free_client_state (client_state *cs);
>   void delete_client_state (gdb_fildes_t fd);
> };

Should this structure be part of this patch?
free_client_state does not look to be defined anywhere,
for instance.

>  }
> 
> diff --git a/gdb/gdbserver/fork-child.c b/gdb/gdbserver/fork-child.c
> index 831e7e13100..74fa5e424c7 100644
> --- a/gdb/gdbserver/fork-child.c
> +++ b/gdb/gdbserver/fork-child.c
> @@ -44,6 +44,8 @@ restore_old_foreground_pgrp (void)
>  void
>  prefork_hook (const char *args)
>  {
> +  client_state *cs = get_client_state();
> +
>    if (debug_threads)
>      {
>        debug_printf ("args: %s\n", args);
> @@ -57,7 +59,7 @@ prefork_hook (const char *args)
> 
>    /* Clear this so the backend doesn't get confused, thinking
>       CONT_THREAD died, and it needs to resume all threads.  */
> -  cont_thread = null_ptid;
> +  cs->ss->cont_thread = null_ptid;
>  }
> 
>  /* See nat/fork-inferior.h.  */
> @@ -97,6 +99,7 @@ void
>  post_fork_inferior (int pid, const char *program)
>  {
>  #ifdef SIGTTOU
> +  client_state *cs = get_client_state();
>    signal (SIGTTOU, SIG_IGN);
>    signal (SIGTTIN, SIG_IGN);
>    terminal_fd = fileno (stderr);
> @@ -106,10 +109,10 @@ post_fork_inferior (int pid, const char *program)
>  #endif
> 
>    startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED,
> -            &last_status, &last_ptid);
> -  current_thread->last_resume_kind = resume_stop;
> -  current_thread->last_status = last_status;
> -  signal_pid = pid;
> +            &cs->ss->last_status, &cs->ss->last_ptid);
> +  cs->ss->current_thread->last_resume_kind = resume_stop;
> +  cs->ss->current_thread->last_status = cs->ss->last_status;
> +  cs->ss->signal_pid = pid;
>    target_post_create_inferior ();
>    fprintf (stderr, "Process %s created; pid = %d\n", program, pid);
>    fflush (stderr);
> diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
> index 9a8c72e780e..c5bd1175f22 100644
> --- a/gdb/gdbserver/gdbthread.h
> +++ b/gdb/gdbserver/gdbthread.h
> @@ -73,8 +73,6 @@ struct thread_info
>    struct btrace_target_info *btrace;
>  };
> 
> -extern std::list<thread_info *> all_threads;
> -
>  void remove_thread (struct thread_info *thread);
>  struct thread_info *add_thread (ptid_t ptid, void *target_data);
> 
> @@ -95,9 +93,9 @@ template <typename Func>
>  static thread_info *
>  find_thread (Func func)
>  {
> -  std::list<thread_info *>::iterator next, cur = all_threads.begin ();
> +  std::list<thread_info *>::iterator next, cur = get_client_state()->ss->all_threads.begin ();

Please watch out for too-long lines.  The hard limit is 80 cols.

This would be case where doing instead:

 auto &&all_threads = get_client_state()->ss->all_threads;

would avoid the formatting issues, as well as ...

> 
> -  while (cur != all_threads.end ())
> +  while (cur != get_client_state()->ss->all_threads.end ())

... all this indirection for each iteration.

>      {
>        next = cur;
>        next++;
> @@ -141,9 +139,9 @@ template <typename Func>
>  static void
>  for_each_thread (Func func)
>  {
> -  std::list<thread_info *>::iterator next, cur = all_threads.begin ();
> +  std::list<thread_info *>::iterator next, cur = get_client_state()->ss->all_threads.begin ();
> 
> -  while (cur != all_threads.end ())
> +  while (cur != get_client_state()->ss->all_threads.end ())

Ditto.  Etc.

> +int
> +get_remote_desc (void)
> +{
> +  return remote_desc;
> +}

Is "remote_desc" a global?  If so, why do we need the wrapper function?

> @@ -1474,45 +1484,45 @@ look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb)
>       while it figures out the address of the symbol.  */
>    while (1)
>      {
> -      if (own_buf[0] == 'm')
> +      if (cs->own_buf[0] == 'm')
>      {
>        CORE_ADDR mem_addr;
> -      unsigned char *mem_buf;
> +      unsigned char *mem_buffer;

Renames that were necessary because of the macros
conflicts can/should be reverted.



> diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
> index 5970431d8ed..8e1459f74e2 100644
> --- a/gdb/gdbserver/server.h
> +++ b/gdb/gdbserver/server.h
> @@ -60,52 +60,19 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap);
>  #include "gdb_signals.h"
>  #include "target.h"
>  #include "mem-break.h"
> -#include "gdbthread.h"
> -#include "inferiors.h"
>  #include "environ.h"
> +#include <list>
> +#include <map>
> 
>  /* Target-specific functions */
> 
>  void initialize_low ();
> 
> -/* Public variables in server.c */
> -
> -extern ptid_t cont_thread;
> -extern ptid_t general_thread;
> -
> -extern int server_waiting;
> -extern int pass_signals[];
> -extern int program_signals[];
> -extern int program_signals_p;
> -
>  extern int disable_packet_vCont;
>  extern int disable_packet_Tthread;
>  extern int disable_packet_qC;
>  extern int disable_packet_qfThreadInfo;
> 
> -extern char *own_buf;
> -
> -extern int run_once;
> -extern int multi_process;
> -extern int report_fork_events;
> -extern int report_vfork_events;
> -extern int report_exec_events;
> -extern int report_thread_events;
> -extern int non_stop;
> -
> -/* True if the "swbreak+" feature is active.  In that case, GDB wants
> -   us to report whether a trap is explained by a software breakpoint
> -   and for the server to handle PC adjustment if necessary on this
> -   target.  Only enabled if the target supports it.  */
> -extern int swbreak_feature;
> -
> -/* True if the "hwbreak+" feature is active.  In that case, GDB wants
> -   us to report whether a trap is explained by a hardware breakpoint.
> -   Only enabled if the target supports it.  */
> -extern int hwbreak_feature;
> -
> -extern int disable_randomization;
> -
>  #if USE_WIN32API
>  #include <winsock2.h>
>  typedef SOCKET gdb_fildes_t;
> @@ -158,8 +125,161 @@ extern void post_fork_inferior (int pid, const char *program);
>  /* Get the gdb_environ being used in the current session.  */
>  extern gdb_environ *get_environ ();
> 
> -extern target_waitstatus last_status;
> -extern ptid_t last_ptid;
> -extern unsigned long signal_pid;
> +// extern ptid_t cs->ss->last_ptid;
> +// extern unsigned long cs->ss->signal_pid;
> 
>  #endif /* SERVER_H */
> +
> +/* Description of the remote protocol state for the currently
> +   connected target.  This is per-target state, and independent of the
> +   selected architecture. */
> +
> +struct server_state
> +{
> +  int attach_count;

This looks like not used in this patch yet.

> +  /* From server.c */
> +  /* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
> +     `vCont'.  Note the multi-process extensions made `vCont' a
> +     requirement, so `Hc pPID.TID' is pretty much undefined.  So
> +     CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
> +     resuming all threads of the process (again, `Hc' isn't used for
> +     multi-process), or a specific thread ptid_t.  */
> +  ptid_t cont_thread;
> +  /* The thread set with an `Hg' packet.  */
> +  ptid_t general_thread;
> +  /* The PID of the originally created or attached inferior.  Used to
> +     send signals to the process when GDB sends us an asynchronous interrupt
> +     (user hitting Control-C in the client), and to wait for the child to exit
> +     when no longer debugging it.  */
> +
> +  unsigned long signal_pid;
> +  /* Last status reported to GDB.  */
> +  struct target_waitstatus last_status;
> +  /* Was last status an exit status? (sticky if yes) */
> +  int last_status_exited;

Ditto.

> +  ptid_t last_ptid;
> +  unsigned char *mem_buf;
> +
> +  /* from remote-utils.c */
> +  /* Internal buffer used by readchar.
> +     These are global to readchar because reschedule_remote needs to be
> +     able to tell whether the buffer is empty.  */
> +  unsigned char readchar_buf[BUFSIZ];
> +  int readchar_bufcnt;
> +  unsigned char *readchar_bufp;
> +  /* from inferiors.c */
> +  std::list<process_info *> all_processes;
> +  std::list<thread_info *> all_threads;
> +
> +  struct thread_info *current_thread;
> +};

But as I asked before, do we need this structure if
there is only ever one server?

> +
> +typedef struct server_state server_state;
> +
> +
> +enum packet_types { other_packet, vContc, vConts, vContt, vRun, vAttach, Hg, g_or_m, vStopped };
> +typedef enum packet_types packet_types;
> +
> +enum exit_types { no_exit, have_exit, sent_exit };
> +typedef enum exit_types exit_types;
> +
> +
> +struct client_state
> +{
> +  gdb_fildes_t file_desc;
> +  int attached_to_client;

More things not used in this patch.  There could be
more.

> +  int packet_type;
> +  int last_packet_type;
> +  int pending;
> +  int nonstop_pending;
> +  int catch_syscalls;
> +  ptid_t last_cont_ptid;
> +  ptid_t new_general_thread;
> +
> +  /* From server.c */
> +  int server_waiting;
> +
> +  int extended_protocol;
> +  int response_needed;
> +  int exit_requested;
> +
> +  /* --once: Exit after the first connection has closed.  */
> +  int run_once;

Is this one really per client?

> +
> +  int multi_process;
> +  int report_fork_events;
> +  int report_vfork_events;
> +  int report_exec_events;
> +  int report_thread_events;
> +  /* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
> +  int report_no_resumed;
> +  int non_stop;

So what will happen if one client is in non-stop mode, and another
is in all-stop mode?  There are checks for cs->non_stop in the target
backend (linux-low.c).  I suspect that will not work correctly.  In
such cases, I wonder why make the global be per-client?

> +  /* True if the "swbreak+" feature is active.  In that case, GDB wants
> +     us to report whether a trap is explained by a software breakpoint
> +     and for the server to handle PC adjustment if necessary on this
> +     target.  Only enabled if the target supports it.  */
> +  int swbreak_feature;
> +  /* True if the "hwbreak+" feature is active.  In that case, GDB wants
> +     us to report whether a trap is explained by a hardware breakpoint.
> +     Only enabled if the target supports it.  */
> +  int hwbreak_feature;
> +
> +  /* True if the "vContSupported" feature is active.  In that case, GDB
> +     wants us to report whether single step is supported in the reply to
> +     "vCont?" packet.  */
> +  int vCont_supported;
> +
> +  /* Whether we should attempt to disable the operating system's address
> +     space randomization feature before starting an inferior.  */
> +  int disable_randomization;
> +
> +  char *program_name = NULL;
> +  std::vector<char *> program_args;
> +  std::string wrapper_argv;
> +
> +  int packet_length;
> +
> +  int pass_signals[GDB_SIGNAL_LAST];
> +  int program_signals[GDB_SIGNAL_LAST];
> +  int program_signals_p;
> +
> +  char *notify_buffer;
> +  /* Renamed from own_buf to avoid macro name conflict with a common local variable name */
> +  char *own_buf;

As mentioned, such renames can be reverted.

> +
> +  /* from remote-utils.c */
> +  int remote_debug;
> +  /* If true, then GDB has requested noack mode.  */
> +  int noack_mode;
> +  /* If true, then we tell GDB to use noack mode by default.  */
> +  int transport_is_reliable;
> +
> +  server_state *ss;
> +
> +  client_state () {};
> +  client_state (gdb_fildes_t, client_state*);
> +};
> +
> +typedef struct client_state client_state;
> +

> diff --git a/gdb/nat/linux-personality.h b/gdb/nat/linux-personality.h
> index 229cc3ef1c9..3f2e0724c49 100644
> --- a/gdb/nat/linux-personality.h
> +++ b/gdb/nat/linux-personality.h
> @@ -27,7 +27,7 @@ public:
>    /* Disable the inferior's address space randomization if
>       DISABLE_RANDOMIZATION is not zero and if we have
>       <sys/personality.h>. */
> -  maybe_disable_address_space_randomization (int disable_randomization);
> +  maybe_disable_address_space_randomization (int p_disable_randomization);

This looks like a spurious change.

On your next update, please make sure to wrap the text in the
proposed commit log to 74-columns, so that it's easier to read
in "git show", "git log", etc.

Please address the comments above, squash the patches together,
rebased on current master, and repost a new self-contained
version (including updated proposed git commit log) with
"PATCH v2" in the subject line.  That should make it easier
to iterate on, and see if someone else has further
comments, too.

Thanks for the patience,
Pedro Alves

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v2] Consolidate gdbserver global variables
  2018-04-23 17:58   ` Pedro Alves
@ 2018-05-03 15:06     ` Stan Cox
  2018-05-04 14:14       ` Pedro Alves
  0 siblings, 1 reply; 15+ messages in thread
From: Stan Cox @ 2018-05-03 15:06 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

> Why do we need server_state, if the value is the same for
> all clients?

That was an effort to treat all global data similarly but I see your
point about adding complexity, so this was removed.

> The first patch would only move the globals to structures, and start
> with a single global instance of such structures.

This patch does that.  Any global data that reflects a client view of 
the state of things, those items that would be unique if there was more 
than one client, are moved to the structure client_state.  No change to 
other global data items.

> There is _always_ a client_state, right?  I.e., get_client_state()
> never returns NULL?  If so, sounds like get_client_state()
> could return a reference instead of a pointer?

Yes, good suggestion, changed throughout.

> Can we use in-class initialization?

Ah yes indeed.

> ... all this indirection for each iteration.

Removing server_state removed all of this and simplified things 
considerably.

>> int run_once
> Is this one really per client?

Kept run_once and non_stop as globals in server.c.

> On your next update, please make sure to wrap the text in the
> proposed commit log to 74-columns, so that it's easier to read
> in "git show", "git log", etc.
> 
> Please address the comments above, squash the patches together,
> rebased on current master, and repost a new self-contained
> version (including updated proposed git commit log) with
> "PATCH v2" in the subject line.  That should make it easier
> to iterate on, and see if someone else has further
> comments, too.

Tested on linux with native-gdbserver.  (Two other targets required a 
simple change.)

Add client_state struct.

Collect per client specific global data items into struct client_state,
which is similar in purpose to remote.c::remote_state.

	* server.h (struct client_state): New.
	* server.c (cont_thread, server_waiting, multi_process)
	(report_fork_events, report_vfork_events, report_exec_events)
	(report_thread_events, swbreak_feature, hwbreak_feature)
	(vCont_supported, disable_randomization, pass_signals)
	(program_signals, program_signals_p, own_buf):
	Moved to client_state.
	* remote-utils.c (remote-debug, noack_mode)
	(transport_is_reliable): Moved to client_state.
	* tracepoint.c (current_traceframe): Moved to client_state.

	Update all callers.
	* (server.c, remote-utils.c, tracepoint.c, fork-child.c,
	gdbthread.h, hostio.c, linux-arm-low.c, linux-low.c, notif.c,
	remote-utils.h, spu-low.c, target.c, win32-low.c):  Use 	
	client_state.



gdb/gdbserver/fork-child.c    |   1 +
  gdb/gdbserver/gdbthread.h     |   3 +
  gdb/gdbserver/hostio.c        |   2 -
  gdb/gdbserver/linux-arm-low.c |   1 +
  gdb/gdbserver/linux-low.c     |  32 +++++----
  gdb/gdbserver/notif.c         |   6 +-
  gdb/gdbserver/remote-utils.c  | 143 
++++++++++++++++++++-------------------
  gdb/gdbserver/remote-utils.h  |   4 --
  gdb/gdbserver/server.c        | 344 
++++++++++++++++++++++++++++++++++++++++++++++++----------------------------------------------
  gdb/gdbserver/server.h        |  86 ++++++++++++++++--------
  gdb/gdbserver/spu-low.c       |   5 +-
  gdb/gdbserver/target.c        |   6 +-
  gdb/gdbserver/tracepoint.c    |  25 +++----
  gdb/gdbserver/win32-low.c     |   3 +-
  14 files changed, 358 insertions(+), 303 deletions(-)




--- a/gdb/gdbserver/fork-child.c
+++ b/gdb/gdbserver/fork-child.c
@@ -44,6 +44,7 @@ restore_old_foreground_pgrp (void)
  void
  prefork_hook (const char *args)
  {
+  struct client_state & cs = get_client_state ();
    if (debug_threads)
      {
        debug_printf ("args: %s\n", args);
diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
index 0edf870c56..9a8c72e780 100644
--- a/gdb/gdbserver/gdbthread.h
+++ b/gdb/gdbserver/gdbthread.h
@@ -224,4 +224,7 @@ lwpid_of (const thread_info *thread)
    return thread->id.lwp ();
  }

+/* Create a cleanup to restore current_thread.  */
+struct cleanup *make_cleanup_restore_current_thread (void);
+
  #endif /* GDB_THREAD_H */
diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
index d2b5a71bad..4e388a85dc 100644
--- a/gdb/gdbserver/hostio.c
+++ b/gdb/gdbserver/hostio.c
@@ -29,8 +29,6 @@
  #include <sys/stat.h>
  #include "fileio.h"

-extern int remote_debug;
-
  struct fd_list
  {
    int fd;
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index 6c2dcead03..3004018e5b 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -160,6 +160,7 @@ static struct arm_get_next_pcs_ops get_next_pcs_ops = {
    arm_linux_get_next_pcs_fixup,
  };

+
  static int
  arm_cannot_store_register (int regno)
  {
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index e64949504d..47dea21e5a 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -475,6 +475,7 @@ linux_arch_setup_thread (struct thread_info *thread)
  static int
  handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
  {
+  struct client_state & cs = get_client_state ();
    struct lwp_info *event_lwp = *orig_event_lwp;
    int event = linux_ptrace_get_extended_event (wstat);
    struct thread_info *event_thr = get_lwp_thread (event_lwp);
@@ -655,7 +656,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
  	  new_lwp->status_pending_p = 1;
  	  new_lwp->status_pending = status;
  	}
-      else if (report_thread_events)
+      else if (cs.report_thread_events)
  	{
  	  new_lwp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED;
  	  new_lwp->status_pending_p = 1;
@@ -683,7 +684,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
        /* Report the event.  */
        return 0;
      }
-  else if (event == PTRACE_EVENT_EXEC && report_exec_events)
+  else if (event == PTRACE_EVENT_EXEC && cs.report_exec_events)
      {
        struct process_info *proc;
        std::vector<int> syscalls_to_catch;
@@ -998,13 +999,14 @@ static int
  linux_create_inferior (const char *program,
  		       const std::vector<char *> &program_args)
  {
+  struct client_state & cs = get_client_state ();
    struct lwp_info *new_lwp;
    int pid;
    ptid_t ptid;

    {
      maybe_disable_address_space_randomization restore_personality
-      (disable_randomization);
+      (cs.disable_randomization);
      std::string str_program_args = stringify_argv (program_args);

      pid = fork_inferior (program,
@@ -1429,6 +1431,7 @@ linux_kill (int pid)
  static int
  get_detach_signal (struct thread_info *thread)
  {
+  struct client_state & cs = get_client_state ();
    enum gdb_signal signo = GDB_SIGNAL_0;
    int status;
    struct lwp_info *lp = get_thread_lwp (thread);
@@ -1469,7 +1472,7 @@ get_detach_signal (struct thread_info *thread)

    signo = gdb_signal_from_host (WSTOPSIG (status));

-  if (program_signals_p && !program_signals[signo])
+  if (cs.program_signals_p && !cs.program_signals[signo])
      {
        if (debug_threads)
  	debug_printf ("GPS: lwp %s had signal %s, but it is in nopass state\n",
@@ -1477,7 +1480,7 @@ get_detach_signal (struct thread_info *thread)
  		      gdb_signal_to_string (signo));
        return 0;
      }
-  else if (!program_signals_p
+  else if (!cs.program_signals_p
  	   /* If we have no way to know which signals GDB does not
  	      want to have passed to the program, assume
  	      SIGTRAP/SIGINT, which is GDB's default.  */
@@ -2328,18 +2331,19 @@ check_stopped_by_watchpoint (struct lwp_info *child)
  static int
  linux_low_ptrace_options (int attached)
  {
+  struct client_state & cs = get_client_state ();
    int options = 0;

    if (!attached)
      options |= PTRACE_O_EXITKILL;

-  if (report_fork_events)
+  if (cs.report_fork_events)
      options |= PTRACE_O_TRACEFORK;

-  if (report_vfork_events)
+  if (cs.report_vfork_events)
      options |= (PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE);

-  if (report_exec_events)
+  if (cs.report_exec_events)
      options |= PTRACE_O_TRACEEXEC;

    options |= PTRACE_O_TRACESYSGOOD;
@@ -2354,6 +2358,7 @@ linux_low_ptrace_options (int attached)
  static struct lwp_info *
  linux_low_filter_event (int lwpid, int wstat)
  {
+  struct client_state & cs = get_client_state ();
    struct lwp_info *child;
    struct thread_info *thread;
    int have_stop_pc = 0;
@@ -2425,7 +2430,7 @@ linux_low_filter_event (int lwpid, int wstat)
        /* If there is at least one more LWP, then the exit signal was
  	 not the end of the debugged application and should be
  	 ignored, unless GDB wants to hear about thread exits.  */
-      if (report_thread_events
+      if (cs.report_thread_events
  	  || last_thread_of_process_p (pid_of (thread)))
  	{
  	  /* Since events are serialized to GDB core, and we can't
@@ -3049,12 +3054,13 @@ static ptid_t
  filter_exit_event (struct lwp_info *event_child,
  		   struct target_waitstatus *ourstatus)
  {
+  struct client_state & cs = get_client_state ();
    struct thread_info *thread = get_lwp_thread (event_child);
    ptid_t ptid = ptid_of (thread);

    if (!last_thread_of_process_p (pid_of (thread)))
      {
-      if (report_thread_events)
+      if (cs.report_thread_events)
  	ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
        else
  	ourstatus->kind = TARGET_WAITKIND_IGNORE;
@@ -3106,6 +3112,7 @@ static ptid_t
  linux_wait_1 (ptid_t ptid,
  	      struct target_waitstatus *ourstatus, int target_options)
  {
+  struct client_state & cs = get_client_state ();
    int w;
    struct lwp_info *event_child;
    int options;
@@ -3475,7 +3482,7 @@ linux_wait_1 (ptid_t ptid,
  	       || WSTOPSIG (w) == __SIGRTMIN + 1))
  	  ||
  #endif
-	  (pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
+	  (cs.pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
  	   && !(WSTOPSIG (w) == SIGSTOP
  		&& current_thread->last_resume_kind == resume_stop)
  	   && !linux_wstatus_maybe_breakpoint (w))))
@@ -3782,7 +3789,7 @@ linux_wait_1 (ptid_t ptid,
       it was a software breakpoint, and the client doesn't know we can
       adjust the breakpoint ourselves.  */
    if (event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
-      && !swbreak_feature)
+      && !cs.swbreak_feature)
      {
        int decr_pc = the_low_target.decr_pc_after_break;

@@ -5036,6 +5043,7 @@ linux_resume_one_thread (thread_info *thread, bool 
leave_all_stopped)
  static void
  linux_resume (struct thread_resume *resume_info, size_t n)
  {
+  struct client_state & cs = get_client_state ();
    struct thread_info *need_step_over = NULL;

    if (debug_threads)
diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 5ff7079123..2cd411f9bb 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -79,6 +79,7 @@ notif_write_event (struct notif_server *notif, char 
*own_buf)
  int
  handle_notif_ack (char *own_buf, int packet_len)
  {
+  struct client_state & cs = get_client_state ();
    size_t i;
    struct notif_server *np;

@@ -103,7 +104,7 @@ handle_notif_ack (char *own_buf, int packet_len)
        struct notif_event *head
  	= QUEUE_deque (notif_event_p, np->queue);

-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf ("%s: acking %d\n", np->ack_name,
  		      QUEUE_length (notif_event_p, np->queue));

@@ -121,9 +122,10 @@ void
  notif_event_enque (struct notif_server *notif,
  		   struct notif_event *event)
  {
+  struct client_state & cs = get_client_state ();
    QUEUE_enque (notif_event_p, notif->queue, event);

-  if (remote_debug)
+  if (cs.remote_debug)
      debug_printf ("pending events: %s %d\n", notif->notif_name,
  		  QUEUE_length (notif_event_p, notif->queue));

diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 3b5a459ae4..ea02631444 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -26,6 +26,7 @@
  #include "dll.h"
  #include "rsp-low.h"
  #include "gdbthread.h"
+#include "server.h"
  #include <ctype.h>
  #if HAVE_SYS_IOCTL_H
  #include <sys/ioctl.h>
@@ -103,7 +104,6 @@ struct sym_cache
    struct sym_cache *next;
  };

-int remote_debug = 0;
  struct ui_file *gdb_stdlog;

  static int remote_is_stdio = 0;
@@ -115,11 +115,6 @@ static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
  extern int using_threads;
  extern int debug_threads;

-/* If true, then GDB has requested noack mode.  */
-int noack_mode = 0;
-/* If true, then we tell GDB to use noack mode by default.  */
-int transport_is_reliable = 0;
-
  #ifdef USE_WIN32API
  # define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)
@@ -222,6 +217,7 @@ handle_accept_event (int err, gdb_client_data 
client_data)
  void
  remote_prepare (const char *name)
  {
+  struct client_state & cs = get_client_state ();
    const char *port_str;
  #ifdef USE_WIN32API
    static int winsock_initialized;
@@ -238,14 +234,14 @@ remote_prepare (const char *name)
  	 call to remote_open so start_inferior knows the connection is
  	 via stdio.  */
        remote_is_stdio = 1;
-      transport_is_reliable = 1;
+      cs.transport_is_reliable = 1;
        return;
      }

    port_str = strchr (name, ':');
    if (port_str == NULL)
      {
-      transport_is_reliable = 0;
+      cs.transport_is_reliable = 0;
        return;
      }

@@ -280,7 +276,7 @@ remote_prepare (const char *name)
        || listen (listen_desc, 1))
      perror_with_name ("Can't bind address");

-  transport_is_reliable = 1;
+  cs.transport_is_reliable = 1;
  }

  /* Open a connection to a remote debugger.
@@ -485,9 +481,10 @@ try_rle (char *buf, int remaining, unsigned char 
*csum, char **p)
  char *
  write_ptid (char *buf, ptid_t ptid)
  {
+  struct client_state & cs = get_client_state ();
    int pid, tid;

-  if (multi_process)
+  if (cs.multi_process)
      {
        pid = ptid_get_pid (ptid);
        if (pid < 0)
@@ -594,6 +591,7 @@ read_prim (void *buf, int count)
  static int
  putpkt_binary_1 (char *buf, int cnt, int is_notif)
  {
+  struct client_state & cs = get_client_state ();
    int i;
    unsigned char csum = 0;
    char *buf2;
@@ -631,10 +629,10 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  return -1;
  	}

-      if (noack_mode || is_notif)
+      if (cs.noack_mode || is_notif)
  	{
  	  /* Don't expect an ack then.  */
-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    {
  	      if (is_notif)
  		debug_printf ("putpkt (\"%s\"); [notif]\n", buf2);
@@ -645,7 +643,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  break;
  	}

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("putpkt (\"%s\"); [looking for ack]\n", buf2);
  	  debug_flush ();
@@ -659,7 +657,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  return -1;
  	}

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("[received '%c' (0x%x)]\n", cc, cc);
  	  debug_flush ();
@@ -851,6 +849,7 @@ static unsigned char *readchar_bufp;
  static int
  readchar (void)
  {
+  struct client_state & cs = get_client_state ();
    int ch;

    if (readchar_bufcnt == 0)
@@ -861,7 +860,7 @@ readchar (void)
  	{
  	  if (readchar_bufcnt == 0)
  	    {
-	      if (remote_debug)
+	      if (cs.remote_debug)
  		debug_printf ("readchar: Got EOF\n");
  	    }
  	  else
@@ -926,6 +925,7 @@ reschedule (void)
  int
  getpkt (char *buf)
  {
+  struct client_state & cs = get_client_state ();
    char *bp;
    unsigned char csum, c1, c2;
    int c;
@@ -948,7 +948,7 @@ getpkt (char *buf)

  	  if (c == '$')
  	    break;
-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    {
  	      debug_printf ("[getpkt: discarding char '%c']\n", c);
  	      debug_flush ();
@@ -977,7 +977,7 @@ getpkt (char *buf)
        if (csum == (c1 << 4) + c2)
  	break;

-      if (noack_mode)
+      if (cs.noack_mode)
  	{
  	  fprintf (stderr,
  		   "Bad checksum, sentsum=0x%x, csum=0x%x, "
@@ -993,9 +993,9 @@ getpkt (char *buf)
  	return -1;
      }

-  if (!noack_mode)
+  if (!cs.noack_mode)
      {
-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("getpkt (\"%s\");  [sending ack] \n", buf);
  	  debug_flush ();
@@ -1004,7 +1004,7 @@ getpkt (char *buf)
        if (write_prim ("+", 1) != 1)
  	return -1;

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("[sent ack]\n");
  	  debug_flush ();
@@ -1012,7 +1012,7 @@ getpkt (char *buf)
      }
    else
      {
-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("getpkt (\"%s\");  [no ack sent] \n", buf);
  	  debug_flush ();
@@ -1081,6 +1081,7 @@ void
  prepare_resume_reply (char *buf, ptid_t ptid,
  		      struct target_waitstatus *status)
  {
+  struct client_state & cs = get_client_state ();
    if (debug_threads)
      debug_printf ("Writing resume reply for %s:%d\n",
  		  target_pid_to_str (ptid), status->kind);
@@ -1100,8 +1101,9 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	const char **regp;
  	struct regcache *regcache;

-	if ((status->kind == TARGET_WAITKIND_FORKED && report_fork_events)
-	    || (status->kind == TARGET_WAITKIND_VFORKED && report_vfork_events))
+	if ((status->kind == TARGET_WAITKIND_FORKED && cs.report_fork_events)
+	    || (status->kind == TARGET_WAITKIND_VFORKED
+		&& cs.report_vfork_events))
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;
  	    const char *event = (status->kind == TARGET_WAITKIND_FORKED
@@ -1112,13 +1114,14 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	    buf = write_ptid (buf, status->value.related_pid);
  	    strcat (buf, ";");
  	  }
-	else if (status->kind == TARGET_WAITKIND_VFORK_DONE && 
report_vfork_events)
+	else if (status->kind == TARGET_WAITKIND_VFORK_DONE
+		 && cs.report_vfork_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;

  	    sprintf (buf, "T%02xvforkdone:;", signal);
  	  }
-	else if (status->kind == TARGET_WAITKIND_EXECD && report_exec_events)
+	else if (status->kind == TARGET_WAITKIND_EXECD && cs.report_exec_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;
  	    const char *event = "exec";
@@ -1138,7 +1141,7 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	    buf += strlen (buf);
  	  }
  	else if (status->kind == TARGET_WAITKIND_THREAD_CREATED
-		 && report_thread_events)
+		 && cs.report_thread_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;

@@ -1186,12 +1189,12 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	      *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
  	    *buf++ = ';';
  	  }
-	else if (swbreak_feature && target_stopped_by_sw_breakpoint ())
+	else if (cs.swbreak_feature && target_stopped_by_sw_breakpoint ())
  	  {
  	    sprintf (buf, "swbreak:;");
  	    buf += strlen (buf);
  	  }
-	else if (hwbreak_feature && target_stopped_by_hw_breakpoint ())
+	else if (cs.hwbreak_feature && target_stopped_by_hw_breakpoint ())
  	  {
  	    sprintf (buf, "hwbreak:;");
  	    buf += strlen (buf);
@@ -1256,14 +1259,14 @@ prepare_resume_reply (char *buf, ptid_t ptid,
        }
        break;
      case TARGET_WAITKIND_EXITED:
-      if (multi_process)
+      if (cs.multi_process)
  	sprintf (buf, "W%x;process:%x",
  		 status->value.integer, ptid_get_pid (ptid));
        else
  	sprintf (buf, "W%02x", status->value.integer);
        break;
      case TARGET_WAITKIND_SIGNALLED:
-      if (multi_process)
+      if (cs.multi_process)
  	sprintf (buf, "X%x;process:%x",
  		 status->value.sig, ptid_get_pid (ptid));
        else
@@ -1435,6 +1438,7 @@ clear_symbol_cache (struct sym_cache **symcache_p)
  int
  look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb)
  {
+  struct client_state & cs = get_client_state ();
    char *p, *q;
    int len;
    struct sym_cache *sym;
@@ -1456,14 +1460,14 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
      return 0;

    /* Send the request.  */
-  strcpy (own_buf, "qSymbol:");
-  bin2hex ((const gdb_byte *) name, own_buf + strlen ("qSymbol:"),
+  strcpy (cs.own_buf, "qSymbol:");
+  bin2hex ((const gdb_byte *) name, cs.own_buf + strlen ("qSymbol:"),
  	  strlen (name));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (cs.own_buf) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (cs.own_buf);
    if (len < 0)
      return -1;

@@ -1474,45 +1478,45 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
       while it figures out the address of the symbol.  */
    while (1)
      {
-      if (own_buf[0] == 'm')
+      if (cs.own_buf[0] == 'm')
  	{
  	  CORE_ADDR mem_addr;
  	  unsigned char *mem_buf;
  	  unsigned int mem_len;

-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
+	  decode_m_packet (&cs.own_buf[1], &mem_addr, &mem_len);
  	  mem_buf = (unsigned char *) xmalloc (mem_len);
  	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	    bin2hex (mem_buf, cs.own_buf, mem_len);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  free (mem_buf);
-	  if (putpkt (own_buf) < 0)
+	  if (putpkt (cs.own_buf) < 0)
  	    return -1;
  	}
-      else if (own_buf[0] == 'v')
+      else if (cs.own_buf[0] == 'v')
  	{
  	  int new_len = -1;
-	  handle_v_requests (own_buf, len, &new_len);
+	  handle_v_requests (cs.own_buf, len, &new_len);
  	  if (new_len != -1)
-	    putpkt_binary (own_buf, new_len);
+	    putpkt_binary (cs.own_buf, new_len);
  	  else
-	    putpkt (own_buf);
+	    putpkt (cs.own_buf);
  	}
        else
  	break;
-      len = getpkt (own_buf);
+      len = getpkt (cs.own_buf);
        if (len < 0)
  	return -1;
      }

-  if (!startswith (own_buf, "qSymbol:"))
+  if (!startswith (cs.own_buf, "qSymbol:"))
      {
-      warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf);
+      warning ("Malformed response to qSymbol, ignoring: %s\n", 
cs.own_buf);
        return -1;
      }

-  p = own_buf + strlen ("qSymbol:");
+  p = cs.own_buf + strlen ("qSymbol:");
    q = p;
    while (*q && *q != ':')
      q++;
@@ -1548,17 +1552,18 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
  int
  relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
  {
+  struct client_state & cs = get_client_state ();
    int len;
    ULONGEST written = 0;

    /* Send the request.  */
-  sprintf (own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
+  sprintf (cs.own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
  	   paddress (*to));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (cs.own_buf) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (cs.own_buf);
    if (len < 0)
      return -1;

@@ -1566,61 +1571,61 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR 
oldloc)
       wait for the qRelocInsn "response".  That requires re-entering
       the main loop.  For now, this is an adequate approximation; allow
       GDB to access memory.  */
-  while (own_buf[0] == 'm' || own_buf[0] == 'M' || own_buf[0] == 'X')
+  while (cs.own_buf[0] == 'm' || cs.own_buf[0] == 'M' || cs.own_buf[0] 
== 'X')
      {
        CORE_ADDR mem_addr;
        unsigned char *mem_buf = NULL;
        unsigned int mem_len;

-      if (own_buf[0] == 'm')
+      if (cs.own_buf[0] == 'm')
  	{
-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
+	  decode_m_packet (&cs.own_buf[1], &mem_addr, &mem_len);
  	  mem_buf = (unsigned char *) xmalloc (mem_len);
  	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	    bin2hex (mem_buf, cs.own_buf, mem_len);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	}
-      else if (own_buf[0] == 'X')
+      else if (cs.own_buf[0] == 'X')
  	{
-	  if (decode_X_packet (&own_buf[1], len - 1, &mem_addr,
+	  if (decode_X_packet (&cs.own_buf[1], len - 1, &mem_addr,
  			       &mem_len, &mem_buf) < 0
  	      || write_inferior_memory (mem_addr, mem_buf, mem_len) != 0)
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  else
-	    write_ok (own_buf);
+	    write_ok (cs.own_buf);
  	}
        else
  	{
-	  decode_M_packet (&own_buf[1], &mem_addr, &mem_len, &mem_buf);
+	  decode_M_packet (&cs.own_buf[1], &mem_addr, &mem_len, &mem_buf);
  	  if (write_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    write_ok (own_buf);
+	    write_ok (cs.own_buf);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	}
        free (mem_buf);
-      if (putpkt (own_buf) < 0)
+      if (putpkt (cs.own_buf) < 0)
  	return -1;
-      len = getpkt (own_buf);
+      len = getpkt (cs.own_buf);
        if (len < 0)
  	return -1;
      }

-  if (own_buf[0] == 'E')
+  if (cs.own_buf[0] == 'E')
      {
        warning ("An error occurred while relocating an instruction: %s\n",
-	       own_buf);
+	       cs.own_buf);
        return -1;
      }

-  if (!startswith (own_buf, "qRelocInsn:"))
+  if (!startswith (cs.own_buf, "qRelocInsn:"))
      {
        warning ("Malformed response to qRelocInsn, ignoring: %s\n",
-	       own_buf);
+	       cs.own_buf);
        return -1;
      }

-  unpack_varlen_hex (own_buf + strlen ("qRelocInsn:"), &written);
+  unpack_varlen_hex (cs.own_buf + strlen ("qRelocInsn:"), &written);

    *to += written;
    return 0;
diff --git a/gdb/gdbserver/remote-utils.h b/gdb/gdbserver/remote-utils.h
index c64807f406..a28c5ae035 100644
--- a/gdb/gdbserver/remote-utils.h
+++ b/gdb/gdbserver/remote-utils.h
@@ -19,10 +19,6 @@
  #ifndef REMOTE_UTILS_H
  #define REMOTE_UTILS_H

-extern int remote_debug;
-extern int noack_mode;
-extern int transport_is_reliable;
-
  int gdb_connected (void);

  #define STDIO_CONNECTION_NAME "stdio"
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 5027df5e10..b4b72b55f8 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -83,36 +83,17 @@ ptid_t cont_thread;
  /* The thread set with an `Hg' packet.  */
  ptid_t general_thread;

-int server_waiting;
-
  static int extended_protocol;
  static int response_needed;
  static int exit_requested;

  /* --once: Exit after the first connection has closed.  */
-int run_once;
-
-int multi_process;
-int report_fork_events;
-int report_vfork_events;
-int report_exec_events;
-int report_thread_events;
+int run_once = 0;

  /* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
  static int report_no_resumed;

  int non_stop;
-int swbreak_feature;
-int hwbreak_feature;
-
-/* True if the "vContSupported" feature is active.  In that case, GDB
-   wants us to report whether single step is supported in the reply to
-   "vCont?" packet.  */
-static int vCont_supported;
-
-/* Whether we should attempt to disable the operating system's address
-   space randomization feature before starting an inferior.  */
-int disable_randomization = 1;

  static struct {
    /* Set the PROGRAM_PATH.  Here we adjust the path of the provided
@@ -146,10 +127,6 @@ private:
  static std::vector<char *> program_args;
  static std::string wrapper_argv;

-int pass_signals[GDB_SIGNAL_LAST];
-int program_signals[GDB_SIGNAL_LAST];
-int program_signals_p;
-
  /* The PID of the originally created or attached inferior.  Used to
     send signals to the process when GDB sends us an asynchronous interrupt
     (user hitting Control-C in the client), and to wait for the child 
to exit
@@ -169,7 +146,6 @@ int disable_packet_qfThreadInfo;
  struct target_waitstatus last_status;
  ptid_t last_ptid;

-char *own_buf;
  static unsigned char *mem_buf;

  /* A sub-class of 'struct notif_event' for stop, holding information
@@ -193,6 +169,18 @@ static struct btrace_config current_btrace_conf;

  DEFINE_QUEUE_P (notif_event_p);

+/* The client remote protocol state. */
+
+static struct client_state *client_state;
+
+struct client_state &
+get_client_state (void)
+{
+  struct client_state & cs = *client_state;
+  return cs;
+}
+
+
  /* Put a stop reply to the stop reply queue.  */

  static void
@@ -348,7 +336,6 @@ attach_inferior (int pid)
    return 0;
  }

-extern int remote_debug;

  /* Decode a qXfer read request.  Return 0 if everything looks OK,
     or -1 otherwise.  */
@@ -572,6 +559,7 @@ handle_btrace_conf_general_set (char *own_buf)
  static void
  handle_general_set (char *own_buf)
  {
+  struct client_state & cs = get_client_state ();
    if (startswith (own_buf, "QPassSignals:"))
      {
        int numsigs = (int) GDB_SIGNAL_LAST, i;
@@ -583,7 +571,7 @@ handle_general_set (char *own_buf)
  	{
  	  if (i == cursig)
  	    {
-	      pass_signals[i] = 1;
+	      cs.pass_signals[i] = 1;
  	      if (*p == '\0')
  		/* Keep looping, to clear the remaining signals.  */
  		cursig = -1;
@@ -591,7 +579,7 @@ handle_general_set (char *own_buf)
  		p = decode_address_to_semicolon (&cursig, p);
  	    }
  	  else
-	    pass_signals[i] = 0;
+	    cs.pass_signals[i] = 0;
  	}
        strcpy (own_buf, "OK");
        return;
@@ -603,14 +591,14 @@ handle_general_set (char *own_buf)
        const char *p = own_buf + strlen ("QProgramSignals:");
        CORE_ADDR cursig;

-      program_signals_p = 1;
+      cs.program_signals_p = 1;

        p = decode_address_to_semicolon (&cursig, p);
        for (i = 0; i < numsigs; i++)
  	{
  	  if (i == cursig)
  	    {
-	      program_signals[i] = 1;
+	      cs.program_signals[i] = 1;
  	      if (*p == '\0')
  		/* Keep looping, to clear the remaining signals.  */
  		cursig = -1;
@@ -618,7 +606,7 @@ handle_general_set (char *own_buf)
  		p = decode_address_to_semicolon (&cursig, p);
  	    }
  	  else
-	    program_signals[i] = 0;
+	    cs.program_signals[i] = 0;
  	}
        strcpy (own_buf, "OK");
        return;
@@ -688,7 +676,7 @@ handle_general_set (char *own_buf)
        std::string final_var = hex2str (p);
        std::string var_name, var_value;

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf (_("[QEnvironmentHexEncoded received '%s']\n"), p);
  	  debug_printf (_("[Environment variable to be set: '%s']\n"),
@@ -719,7 +707,7 @@ handle_general_set (char *own_buf)
        const char *p = own_buf + sizeof ("QEnvironmentUnset:") - 1;
        std::string varname = hex2str (p);

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf (_("[QEnvironmentUnset received '%s']\n"), p);
  	  debug_printf (_("[Environment variable to be unset: '%s']\n"),
@@ -735,13 +723,13 @@ handle_general_set (char *own_buf)

    if (strcmp (own_buf, "QStartNoAckMode") == 0)
      {
-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("[noack mode enabled]\n");
  	  debug_flush ();
  	}

-      noack_mode = 1;
+      cs.noack_mode = 1;
        write_ok (own_buf);
        return;
      }
@@ -776,7 +764,7 @@ handle_general_set (char *own_buf)

        non_stop = req;

-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf ("[%s mode enabled]\n", req_str);

        write_ok (own_buf);
@@ -789,11 +777,11 @@ handle_general_set (char *own_buf)
        ULONGEST setting;

        unpack_varlen_hex (packet, &setting);
-      disable_randomization = setting;
+      cs.disable_randomization = setting;

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
-	  debug_printf (disable_randomization
+	  debug_printf (cs.disable_randomization
  			? "[address space randomization disabled]\n"
  			: "[address space randomization enabled]\n");
  	}
@@ -824,7 +812,7 @@ handle_general_set (char *own_buf)

        /* Update the flag.  */
        use_agent = req;
-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf ("[%s agent]\n", req ? "Enable" : "Disable");
        write_ok (own_buf);
        return;
@@ -853,11 +841,11 @@ handle_general_set (char *own_buf)
  	  return;
  	}

-      report_thread_events = (req == TRIBOOL_TRUE);
+      cs.report_thread_events = (req == TRIBOOL_TRUE);

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
-	  const char *req_str = report_thread_events ? "enabled" : "disabled";
+	  const char *req_str = cs.report_thread_events ? "enabled" : "disabled";

  	  debug_printf ("[thread events are now %s]\n", req_str);
  	}
@@ -883,7 +871,7 @@ handle_general_set (char *own_buf)
  	  return;
  	}

-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf (_("[Inferior will %s started with shell]"),
  		      startup_with_shell ? "be" : "not be");

@@ -901,7 +889,7 @@ handle_general_set (char *own_buf)

  	  set_inferior_cwd (path.c_str ());

-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    debug_printf (_("[Set the inferior's current directory to %s]\n"),
  			  path.c_str ());
  	}
@@ -911,7 +899,7 @@ handle_general_set (char *own_buf)
  	     previously set cwd for the inferior.  */
  	  set_inferior_cwd (NULL);

-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    debug_printf (_("\
  [Unset the inferior's current directory; will use gdbserver's cwd]\n"));
  	}
@@ -998,14 +986,15 @@ monitor_show_help (void)
  static int
  gdb_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
  {
+  struct client_state & cs = get_client_state ();
    int res;

-  if (current_traceframe >= 0)
+  if (cs.current_traceframe >= 0)
      {
        ULONGEST nbytes;
        ULONGEST length = len;

-      if (traceframe_read_mem (current_traceframe,
+      if (traceframe_read_mem (cs.current_traceframe,
  			       memaddr, myaddr, len, &nbytes))
  	return -1;
        /* Data read from trace buffer, we're done.  */
@@ -1038,7 +1027,8 @@ gdb_read_memory (CORE_ADDR memaddr, unsigned char 
*myaddr, int len)
  static int
  gdb_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
  {
-  if (current_traceframe >= 0)
+  struct client_state & cs = get_client_state ();
+  if (cs.current_traceframe >= 0)
      return EIO;
    else
      {
@@ -1213,11 +1203,12 @@ handle_search_memory (char *own_buf, int packet_len)
  static void
  handle_detach (char *own_buf)
  {
+  struct client_state & cs = get_client_state ();
    require_running_or_return (own_buf);

    int pid;

-  if (multi_process)
+  if (cs.multi_process)
      {
        /* skip 'D;' */
        pid = strtol (&own_buf[2], NULL, 16);
@@ -1370,6 +1361,7 @@ parse_debug_format_options (const char *arg, int 
is_monitor)
  static void
  handle_monitor_command (char *mon, char *own_buf)
  {
+  struct client_state & cs = get_client_state ();
    if (strcmp (mon, "set debug 1") == 0)
      {
        debug_threads = 1;
@@ -1392,12 +1384,12 @@ handle_monitor_command (char *mon, char *own_buf)
      }
    else if (strcmp (mon, "set remote-debug 1") == 0)
      {
-      remote_debug = 1;
+      cs.remote_debug = 1;
        monitor_output ("Protocol debug output enabled.\n");
      }
    else if (strcmp (mon, "set remote-debug 0") == 0)
      {
-      remote_debug = 0;
+      cs.remote_debug = 0;
        monitor_output ("Protocol debug output disabled.\n");
      }
    else if (startswith (mon, "set debug-format "))
@@ -1646,15 +1638,17 @@ handle_qxfer_statictrace (const char *annex,
  			  gdb_byte *readbuf, const gdb_byte *writebuf,
  			  ULONGEST offset, LONGEST len)
  {
+  struct client_state & cs = get_client_state ();
    ULONGEST nbytes;

    if (writebuf != NULL)
      return -2;

-  if (annex[0] != '\0' || current_thread == NULL || current_traceframe 
== -1)
+  if (annex[0] != '\0' || current_thread == NULL
+      || cs.current_traceframe == -1)
      return -1;

-  if (traceframe_read_sdata (current_traceframe, offset,
+  if (traceframe_read_sdata (cs.current_traceframe, offset,
  			     readbuf, len, &nbytes))
      return -1;
    return nbytes;
@@ -1770,13 +1764,14 @@ handle_qxfer_traceframe_info (const char *annex,
  			      gdb_byte *readbuf, const gdb_byte *writebuf,
  			      ULONGEST offset, LONGEST len)
  {
+  struct client_state & cs = get_client_state ();
    static char *result = 0;
    static unsigned int result_length = 0;

    if (writebuf != NULL)
      return -2;

-  if (!target_running () || annex[0] != '\0' || current_traceframe == -1)
+  if (!target_running () || annex[0] != '\0' || cs.current_traceframe 
== -1)
      return -1;

    if (offset == 0)
@@ -1790,7 +1785,7 @@ handle_qxfer_traceframe_info (const char *annex,

        buffer_init (&buffer);

-      traceframe_read_info (current_traceframe, &buffer);
+      traceframe_read_info (cs.current_traceframe, &buffer);

        result = buffer_finish (&buffer);
        result_length = strlen (result);
@@ -1835,10 +1830,11 @@ handle_qxfer_btrace (const char *annex,
  		     gdb_byte *readbuf, const gdb_byte *writebuf,
  		     ULONGEST offset, LONGEST len)
  {
+  struct client_state & cs = get_client_state ();
    static struct buffer cache;
    struct thread_info *thread;
    enum btrace_read_type type;
-  int result;
+  int result = 0;

    if (writebuf != NULL)
      return -2;
@@ -1846,20 +1842,20 @@ handle_qxfer_btrace (const char *annex,
    if (ptid_equal (general_thread, null_ptid)
        || ptid_equal (general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (cs.own_buf, "E.Must select a single thread.");
        return -3;
      }

    thread = find_thread_ptid (general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (cs.own_buf, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (cs.own_buf, "E.Btrace not enabled.");
        return -3;
      }

@@ -1871,7 +1867,7 @@ handle_qxfer_btrace (const char *annex,
      type = BTRACE_READ_DELTA;
    else
      {
-      strcpy (own_buf, "E.Bad annex.");
+      strcpy (cs.own_buf, "E.Bad annex.");
        return -3;
      }

@@ -1883,11 +1879,11 @@ handle_qxfer_btrace (const char *annex,
  	{
  	  result = target_read_btrace (thread->btrace, &cache, type);
  	  if (result != 0)
-	    memcpy (own_buf, cache.buffer, cache.used_size);
+	    memcpy (cs.own_buf, cache.buffer, cache.used_size);
  	}
        CATCH (exception, RETURN_MASK_ERROR)
  	{
-	  sprintf (own_buf, "E.%s", exception.message);
+	  sprintf (cs.own_buf, "E.%s", exception.message);
  	  result = -1;
  	}
        END_CATCH
@@ -1916,9 +1912,10 @@ handle_qxfer_btrace_conf (const char *annex,
  			  gdb_byte *readbuf, const gdb_byte *writebuf,
  			  ULONGEST offset, LONGEST len)
  {
+  struct client_state & cs = get_client_state ();
    static struct buffer cache;
    struct thread_info *thread;
-  int result;
+  int result = 0;

    if (writebuf != NULL)
      return -2;
@@ -1929,20 +1926,20 @@ handle_qxfer_btrace_conf (const char *annex,
    if (ptid_equal (general_thread, null_ptid)
        || ptid_equal (general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (cs.own_buf, "E.Must select a single thread.");
        return -3;
      }

    thread = find_thread_ptid (general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (cs.own_buf, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (cs.own_buf, "E.Btrace not enabled.");
        return -3;
      }

@@ -1954,11 +1951,11 @@ handle_qxfer_btrace_conf (const char *annex,
  	{
  	  result = target_read_btrace_conf (thread->btrace, &cache);
  	  if (result != 0)
-	    memcpy (own_buf, cache.buffer, cache.used_size);
+	    memcpy (cs.own_buf, cache.buffer, cache.used_size);
  	}
        CATCH (exception, RETURN_MASK_ERROR)
  	{
-	  sprintf (own_buf, "E.%s", exception.message);
+	  sprintf (cs.own_buf, "E.%s", exception.message);
  	  result = -1;
  	}
        END_CATCH
@@ -2158,6 +2155,7 @@ supported_btrace_packets (char *buf)
  static void
  handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
  {
+  struct client_state & cs = get_client_state ();
    static std::list<thread_info *>::const_iterator thread_iter;

    /* Reply the current thread id.  */
@@ -2312,7 +2310,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  		  /* GDB supports and wants multi-process support if
  		     possible.  */
  		  if (target_supports_multi_process ())
-		    multi_process = 1;
+		    cs.multi_process = 1;
  		}
  	      else if (strcmp (p, "qRelocInsn+") == 0)
  		{
@@ -2325,35 +2323,35 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  		     by a software breakpoint and for us to handle PC
  		     adjustment if necessary on this target.  */
  		  if (target_supports_stopped_by_sw_breakpoint ())
-		    swbreak_feature = 1;
+		    cs.swbreak_feature = 1;
  		}
  	      else if (strcmp (p, "hwbreak+") == 0)
  		{
  		  /* GDB wants us to report whether a trap is caused
  		     by a hardware breakpoint.  */
  		  if (target_supports_stopped_by_hw_breakpoint ())
-		    hwbreak_feature = 1;
+		    cs.hwbreak_feature = 1;
  		}
  	      else if (strcmp (p, "fork-events+") == 0)
  		{
  		  /* GDB supports and wants fork events if possible.  */
  		  if (target_supports_fork_events ())
-		    report_fork_events = 1;
+		    cs.report_fork_events = 1;
  		}
  	      else if (strcmp (p, "vfork-events+") == 0)
  		{
  		  /* GDB supports and wants vfork events if possible.  */
  		  if (target_supports_vfork_events ())
-		    report_vfork_events = 1;
+		    cs.report_vfork_events = 1;
  		}
  	      else if (strcmp (p, "exec-events+") == 0)
  		{
  		  /* GDB supports and wants exec events if possible.  */
  		  if (target_supports_exec_events ())
-		    report_exec_events = 1;
+		    cs.report_exec_events = 1;
  		}
  	      else if (strcmp (p, "vContSupported+") == 0)
-		vCont_supported = 1;
+		cs.vCont_supported = 1;
  	      else if (strcmp (p, "QThreadEvents+") == 0)
  		;
  	      else if (strcmp (p, "no-resumed+") == 0)
@@ -2418,7 +2416,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  	 qXfer:feature:read at all, we will never be re-queried.  */
        strcat (own_buf, ";qXfer:features:read+");

-      if (transport_is_reliable)
+      if (cs.transport_is_reliable)
  	strcat (own_buf, ";QStartNoAckMode+");

        if (the_target->qxfer_osdata != NULL)
@@ -2729,13 +2727,14 @@ static int
  handle_pending_status (const struct thread_resume *resumption,
  		       struct thread_info *thread)
  {
+  struct client_state & cs = get_client_state ();
    if (thread->status_pending_p)
      {
        thread->status_pending_p = 0;

        last_status = thread->last_status;
        last_ptid = thread->id;
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (cs.own_buf, last_ptid, &last_status);
        return 1;
      }
    return 0;
@@ -2855,6 +2854,7 @@ err:
  static void
  resume (struct thread_resume *actions, size_t num_actions)
  {
+  struct client_state & cs = get_client_state ();
    if (!non_stop)
      {
        /* Check if among the threads that GDB wants actioned, there's
@@ -2877,7 +2877,7 @@ resume (struct thread_resume *actions, size_t 
num_actions)
    (*the_target->resume) (actions, num_actions);

    if (non_stop)
-    write_ok (own_buf);
+    write_ok (cs.own_buf);
    else
      {
        last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
@@ -2887,7 +2887,7 @@ resume (struct thread_resume *actions, size_t 
num_actions)
  	{
  	  /* The client does not support this stop reply.  At least
  	     return error.  */
-	  sprintf (own_buf, "E.No unwaited-for children left.");
+	  sprintf (cs.own_buf, "E.No unwaited-for children left.");
  	  disable_async_io ();
  	  return;
  	}
@@ -2902,7 +2902,7 @@ resume (struct thread_resume *actions, size_t 
num_actions)
  	 so by now).  Tag all threads as "want-stopped", so we don't
  	 resume them implicitly without the client telling us to.  */
        gdb_wants_all_threads_stopped ();
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (cs.own_buf, last_ptid, &last_status);
        disable_async_io ();

        if (last_status.kind == TARGET_WAITKIND_EXITED
@@ -3078,9 +3078,10 @@ handle_v_run (char *own_buf)
  static int
  handle_v_kill (char *own_buf)
  {
+  struct client_state & cs = get_client_state ();
    int pid;
    char *p = &own_buf[6];
-  if (multi_process)
+  if (cs.multi_process)
      pid = strtol (p, NULL, 16);
    else
      pid = signal_pid;
@@ -3104,6 +3105,7 @@ handle_v_kill (char *own_buf)
  void
  handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
  {
+  struct client_state & cs = get_client_state ();
    if (!disable_packet_vCont)
      {
        if (strcmp (own_buf, "vCtrlC") == 0)
@@ -3125,7 +3127,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

  	  if (target_supports_hardware_single_step ()
  	      || target_supports_software_single_step ()
-	      || !vCont_supported)
+	      || !cs.vCont_supported)
  	    {
  	      /* If target supports single step either by hardware or by
  		 software, add actions s and S to the list of supported
@@ -3151,7 +3153,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

    if (startswith (own_buf, "vAttach;"))
      {
-      if ((!extended_protocol || !multi_process) && target_running ())
+      if ((!extended_protocol || !cs.multi_process) && target_running ())
  	{
  	  fprintf (stderr, "Already debugging a process\n");
  	  write_enn (own_buf);
@@ -3163,7 +3165,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

    if (startswith (own_buf, "vRun;"))
      {
-      if ((!extended_protocol || !multi_process) && target_running ())
+      if ((!extended_protocol || !cs.multi_process) && target_running ())
  	{
  	  fprintf (stderr, "Already debugging a process\n");
  	  write_enn (own_buf);
@@ -3320,6 +3322,8 @@ set_pending_status_callback (thread_info *thread)
  static void
  handle_status (char *own_buf)
  {
+  struct client_state & cs = get_client_state ();
+
    /* GDB is connected, don't forward events to the target anymore.  */
    for_each_process ([] (process_info *process) {
      process->gdb_detached = 0;
@@ -3336,7 +3340,7 @@ handle_status (char *own_buf)
        /* The first is sent immediatly.  OK is sent if there is no
  	 stopped thread, which is the same handling of the vStopped
  	 packet (by design).  */
-      notif_write_event (&notif_stop, own_buf);
+      notif_write_event (&notif_stop, cs.own_buf);
      }
    else
      {
@@ -3577,6 +3581,9 @@ captured_main (int argc, char *argv[])
  #endif

    current_directory = getcwd (NULL, 0);
+  client_state = new (struct client_state);
+  struct client_state & cs = *client_state;
+
    if (current_directory == NULL)
      {
        error (_("Could not find current working directory: %s"),
@@ -3643,7 +3650,7 @@ captured_main (int argc, char *argv[])
  	    }
  	}
        else if (strcmp (*next_arg, "--remote-debug") == 0)
-	remote_debug = 1;
+	cs.remote_debug = 1;
        else if (strcmp (*next_arg, "--disable-packet") == 0)
  	{
  	  gdbserver_show_disableable (stdout);
@@ -3691,9 +3698,9 @@ captured_main (int argc, char *argv[])
  	  break;
  	}
        else if (strcmp (*next_arg, "--disable-randomization") == 0)
-	disable_randomization = 1;
+	cs.disable_randomization = 1;
        else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
-	disable_randomization = 0;
+	cs.disable_randomization = 0;
        else if (strcmp (*next_arg, "--startup-with-shell") == 0)
  	startup_with_shell = true;
        else if (strcmp (*next_arg, "--no-startup-with-shell") == 0)
@@ -3780,7 +3787,6 @@ captured_main (int argc, char *argv[])
      initialize_tracepoint ();
    initialize_notif ();

-  own_buf = (char *) xmalloc (PBUFSIZ + 1);
    mem_buf = (unsigned char *) xmalloc (PBUFSIZ);

    if (selftest)
@@ -3841,18 +3847,17 @@ captured_main (int argc, char *argv[])

    while (1)
      {
-
-      noack_mode = 0;
-      multi_process = 0;
-      report_fork_events = 0;
-      report_vfork_events = 0;
-      report_exec_events = 0;
+      cs.noack_mode = 0;
+      cs.multi_process = 0;
+      cs.report_fork_events = 0;
+      cs.report_vfork_events = 0;
+      cs.report_exec_events = 0;
        /* Be sure we're out of tfind mode.  */
-      current_traceframe = -1;
+      cs.current_traceframe = -1;
        cont_thread = null_ptid;
-      swbreak_feature = 0;
-      hwbreak_feature = 0;
-      vCont_supported = 0;
+      cs.swbreak_feature = 0;
+      cs.hwbreak_feature = 0;
+      cs.vCont_supported = 0;

        remote_open (port);

@@ -3928,8 +3933,8 @@ captured_main (int argc, char *argv[])

  	  if (response_needed)
  	    {
-	      write_enn (own_buf);
-	      putpkt (own_buf);
+	      write_enn (cs.own_buf);
+	      putpkt (cs.own_buf);
  	    }

  	  if (run_once)
@@ -4024,6 +4029,7 @@ process_point_options (struct gdb_breakpoint *bp, 
const char **packet)
  static int
  process_serial_event (void)
  {
+  struct client_state & cs = get_client_state ();
    int signal;
    unsigned int len;
    int res;
@@ -4035,7 +4041,7 @@ process_serial_event (void)
    disable_async_io ();

    response_needed = 0;
-  packet_len = getpkt (own_buf);
+  packet_len = getpkt (cs.own_buf);
    if (packet_len <= 0)
      {
        remote_close ();
@@ -4044,31 +4050,31 @@ process_serial_event (void)
      }
    response_needed = 1;

-  char ch = own_buf[0];
+  char ch = cs.own_buf[0];
    switch (ch)
      {
      case 'q':
-      handle_query (own_buf, packet_len, &new_packet_len);
+      handle_query (cs.own_buf, packet_len, &new_packet_len);
        break;
      case 'Q':
-      handle_general_set (own_buf);
+      handle_general_set (cs.own_buf);
        break;
      case 'D':
-      handle_detach (own_buf);
+      handle_detach (cs.own_buf);
        break;
      case '!':
        extended_protocol = 1;
-      write_ok (own_buf);
+      write_ok (cs.own_buf);
        break;
      case '?':
-      handle_status (own_buf);
+      handle_status (cs.own_buf);
        break;
      case 'H':
-      if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
+      if (cs.own_buf[1] == 'c' || cs.own_buf[1] == 'g' || cs.own_buf[1] 
== 's')
  	{
-	  require_running_or_break (own_buf);
+	  require_running_or_break (cs.own_buf);

-	  ptid_t thread_id = read_ptid (&own_buf[2], NULL);
+	  ptid_t thread_id = read_ptid (&cs.own_buf[2], NULL);

  	  if (thread_id == null_ptid || thread_id == minus_one_ptid)
  	    thread_id = null_ptid;
@@ -4079,7 +4085,7 @@ process_serial_event (void)

  	      if (thread == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (cs.own_buf);
  		  break;
  		}

@@ -4090,12 +4096,12 @@ process_serial_event (void)
  	      /* The ptid represents a lwp/tid.  */
  	      if (find_thread_ptid (thread_id) == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (cs.own_buf);
  		  break;
  		}
  	    }

-	  if (own_buf[1] == 'g')
+	  if (cs.own_buf[1] == 'g')
  	    {
  	      if (ptid_equal (thread_id, null_ptid))
  		{
@@ -4112,30 +4118,30 @@ process_serial_event (void)
  	      set_desired_thread ();
  	      gdb_assert (current_thread != NULL);
  	    }
-	  else if (own_buf[1] == 'c')
+	  else if (cs.own_buf[1] == 'c')
  	    cont_thread = thread_id;

-	  write_ok (own_buf);
+	  write_ok (cs.own_buf);
  	}
        else
  	{
  	  /* Silently ignore it so that gdb can extend the protocol
  	     without compatibility headaches.  */
-	  own_buf[0] = '\0';
+	  cs.own_buf[0] = '\0';
  	}
        break;
      case 'g':
-      require_running_or_break (own_buf);
-      if (current_traceframe >= 0)
+      require_running_or_break (cs.own_buf);
+      if (cs.current_traceframe >= 0)
  	{
  	  struct regcache *regcache
  	    = new_register_cache (current_target_desc ());

-	  if (fetch_traceframe_registers (current_traceframe,
+	  if (fetch_traceframe_registers (cs.current_traceframe,
  					  regcache, -1) == 0)
-	    registers_to_string (regcache, own_buf);
+	    registers_to_string (regcache, cs.own_buf);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  free_register_cache (regcache);
  	}
        else
@@ -4143,85 +4149,85 @@ process_serial_event (void)
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  else
  	    {
  	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_to_string (regcache, own_buf);
+	      registers_to_string (regcache, cs.own_buf);
  	    }
  	}
        break;
      case 'G':
-      require_running_or_break (own_buf);
-      if (current_traceframe >= 0)
-	write_enn (own_buf);
+      require_running_or_break (cs.own_buf);
+      if (cs.current_traceframe >= 0)
+	write_enn (cs.own_buf);
        else
  	{
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  else
  	    {
  	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_from_string (regcache, &own_buf[1]);
-	      write_ok (own_buf);
+	      registers_from_string (regcache, &cs.own_buf[1]);
+	      write_ok (cs.own_buf);
  	    }
  	}
        break;
      case 'm':
-      require_running_or_break (own_buf);
-      decode_m_packet (&own_buf[1], &mem_addr, &len);
+      require_running_or_break (cs.own_buf);
+      decode_m_packet (&cs.own_buf[1], &mem_addr, &len);
        res = gdb_read_memory (mem_addr, mem_buf, len);
        if (res < 0)
-	write_enn (own_buf);
+	write_enn (cs.own_buf);
        else
-	bin2hex (mem_buf, own_buf, res);
+	bin2hex (mem_buf, cs.own_buf, res);
        break;
      case 'M':
-      require_running_or_break (own_buf);
-      decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf);
+      require_running_or_break (cs.own_buf);
+      decode_M_packet (&cs.own_buf[1], &mem_addr, &len, &mem_buf);
        if (gdb_write_memory (mem_addr, mem_buf, len) == 0)
-	write_ok (own_buf);
+	write_ok (cs.own_buf);
        else
-	write_enn (own_buf);
+	write_enn (cs.own_buf);
        break;
      case 'X':
-      require_running_or_break (own_buf);
-      if (decode_X_packet (&own_buf[1], packet_len - 1,
+      require_running_or_break (cs.own_buf);
+      if (decode_X_packet (&cs.own_buf[1], packet_len - 1,
  			   &mem_addr, &len, &mem_buf) < 0
  	  || gdb_write_memory (mem_addr, mem_buf, len) != 0)
-	write_enn (own_buf);
+	write_enn (cs.own_buf);
        else
-	write_ok (own_buf);
+	write_ok (cs.own_buf);
        break;
      case 'C':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (cs.own_buf);
+      hex2bin (cs.own_buf + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (cs.own_buf, 0, signal);
        break;
      case 'S':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (cs.own_buf);
+      hex2bin (cs.own_buf + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (cs.own_buf, 1, signal);
        break;
      case 'c':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs.own_buf);
        signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (cs.own_buf, 0, signal);
        break;
      case 's':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs.own_buf);
        signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (cs.own_buf, 1, signal);
        break;
      case 'Z':  /* insert_ ... */
        /* Fallthrough.  */
@@ -4230,10 +4236,10 @@ process_serial_event (void)
  	char *dataptr;
  	ULONGEST addr;
  	int kind;
-	char type = own_buf[1];
+	char type = cs.own_buf[1];
  	int res;
  	const int insert = ch == 'Z';
-	const char *p = &own_buf[3];
+	const char *p = &cs.own_buf[3];

  	p = unpack_varlen_hex (p, &addr);
  	kind = strtol (p + 1, &dataptr, 16);
@@ -4261,12 +4267,12 @@ process_serial_event (void)
  	  res = delete_gdb_breakpoint (type, addr, kind);

  	if (res == 0)
-	  write_ok (own_buf);
+	  write_ok (cs.own_buf);
  	else if (res == 1)
  	  /* Unsupported.  */
-	  own_buf[0] = '\0';
+	  cs.own_buf[0] = '\0';
  	else
-	  write_enn (own_buf);
+	  write_enn (cs.own_buf);
  	break;
        }
      case 'k':
@@ -4293,19 +4299,19 @@ process_serial_event (void)

      case 'T':
        {
-	require_running_or_break (own_buf);
+	require_running_or_break (cs.own_buf);

-	ptid_t thread_id = read_ptid (&own_buf[1], NULL);
+	ptid_t thread_id = read_ptid (&cs.own_buf[1], NULL);
  	if (find_thread_ptid (thread_id) == NULL)
  	  {
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	    break;
  	  }

  	if (mythread_alive (thread_id))
-	  write_ok (own_buf);
+	  write_ok (cs.own_buf);
  	else
-	  write_enn (own_buf);
+	  write_enn (cs.own_buf);
        }
        break;
      case 'R':
@@ -4349,26 +4355,26 @@ process_serial_event (void)
  	  /* It is a request we don't understand.  Respond with an
  	     empty packet so that gdb knows that we don't support this
  	     request.  */
-	  own_buf[0] = '\0';
+	  cs.own_buf[0] = '\0';
  	  break;
  	}
      case 'v':
        /* Extended (long) request.  */
-      handle_v_requests (own_buf, packet_len, &new_packet_len);
+      handle_v_requests (cs.own_buf, packet_len, &new_packet_len);
        break;

      default:
        /* It is a request we don't understand.  Respond with an empty
  	 packet so that gdb knows that we don't support this
  	 request.  */
-      own_buf[0] = '\0';
+      cs.own_buf[0] = '\0';
        break;
      }

    if (new_packet_len != -1)
-    putpkt_binary (own_buf, new_packet_len);
+    putpkt_binary (cs.own_buf, new_packet_len);
    else
-    putpkt (own_buf);
+    putpkt (cs.own_buf);

    response_needed = 0;

diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 5970431d8e..7518309988 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -60,8 +60,6 @@ int vsnprintf(char *str, size_t size, const char 
*format, va_list ap);
  #include "gdb_signals.h"
  #include "target.h"
  #include "mem-break.h"
-#include "gdbthread.h"
-#include "inferiors.h"
  #include "environ.h"

  /* Target-specific functions */
@@ -72,40 +70,14 @@ void initialize_low ();

  extern ptid_t cont_thread;
  extern ptid_t general_thread;
-
-extern int server_waiting;
-extern int pass_signals[];
-extern int program_signals[];
-extern int program_signals_p;
-
  extern int disable_packet_vCont;
  extern int disable_packet_Tthread;
  extern int disable_packet_qC;
  extern int disable_packet_qfThreadInfo;

-extern char *own_buf;
-
  extern int run_once;
-extern int multi_process;
-extern int report_fork_events;
-extern int report_vfork_events;
-extern int report_exec_events;
-extern int report_thread_events;
  extern int non_stop;

-/* True if the "swbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a software breakpoint
-   and for the server to handle PC adjustment if necessary on this
-   target.  Only enabled if the target supports it.  */
-extern int swbreak_feature;
-
-/* True if the "hwbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a hardware breakpoint.
-   Only enabled if the target supports it.  */
-extern int hwbreak_feature;
-
-extern int disable_randomization;
-
  #if USE_WIN32API
  #include <winsock2.h>
  typedef SOCKET gdb_fildes_t;
@@ -162,4 +134,62 @@ extern target_waitstatus last_status;
  extern ptid_t last_ptid;
  extern unsigned long signal_pid;

+
+/* Description of the client remote protocol state for the currently
+   connected target.  */
+
+struct client_state
+{
+  /* From server.c */
+  int server_waiting = 0;
+  int multi_process = 0;
+  int report_fork_events = 0;
+  int report_vfork_events = 0;
+  int report_exec_events = 0;
+  int report_thread_events = 0;
+
+  /* True if the "swbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a software breakpoint
+     and for the server to handle PC adjustment if necessary on this
+     target.  Only enabled if the target supports it.  */
+  int swbreak_feature = 0;
+  /* True if the "hwbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a hardware breakpoint.
+     Only enabled if the target supports it.  */
+  int hwbreak_feature = 0;
+
+  /* True if the "vContSupported" feature is active.  In that case, GDB
+     wants us to report whether single step is supported in the reply to
+     "vCont?" packet.  */
+  int vCont_supported = 0;
+
+  /* Whether we should attempt to disable the operating system's address
+     space randomization feature before starting an inferior.  */
+  int disable_randomization = 0;
+  int pass_signals[GDB_SIGNAL_LAST];
+  int program_signals[GDB_SIGNAL_LAST];
+  int program_signals_p = 0;
+  char *own_buf;
+
+  /* from remote-utils.c */
+  int remote_debug = 0;
+  /* If true, then GDB has requested noack mode.  */
+  int noack_mode = 0;
+  /* If true, then we tell GDB to use noack mode by default.  */
+  int transport_is_reliable = 0;
+  /* from tracepoint.c */
+  /* The traceframe to be used as the source of data to send back to
+     GDB.  A value of -1 means to get data from the live program.  */
+
+  int current_traceframe = -1;
+
+  client_state ():
+    own_buf ((char *) xmalloc (PBUFSIZ + 1)) {}
+};
+
+struct client_state& get_client_state (void);
+
+#include "gdbthread.h"
+#include "inferiors.h"
+
  #endif /* SERVER_H */
diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
index 5b880d2a42..d909966199 100644
--- a/gdb/gdbserver/spu-low.c
+++ b/gdb/gdbserver/spu-low.c
@@ -418,6 +418,7 @@ spu_resume (struct thread_resume *resume_info, size_t n)
  static ptid_t
  spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
  {
+  struct client_state & cs = get_client_state ();
    int pid = ptid_get_pid (ptid);
    int w;
    int ret;
@@ -439,7 +440,7 @@ spu_wait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options)

    /* On the first wait, continue running the inferior until we are
       blocked inside an spu_run system call.  */
-  if (!server_waiting)
+  if (!cs.server_waiting)
      {
        int fd;
        CORE_ADDR addr;
@@ -470,7 +471,7 @@ spu_wait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options)

    /* After attach, we may have received a SIGSTOP.  Do not return this
       as signal to GDB, or else it will try to continue with SIGSTOP 
...  */
-  if (!server_waiting)
+  if (!cs.server_waiting)
      {
        ourstatus->kind = TARGET_WAITKIND_STOPPED;
        ourstatus->value.sig = GDB_SIGNAL_0;
diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c
index fe40b94db7..7ba1b96223 100644
--- a/gdb/gdbserver/target.c
+++ b/gdb/gdbserver/target.c
@@ -52,7 +52,6 @@ prepare_to_access_memory (void)
    /* Save the general thread value, since prepare_to_access_memory 
could change
       it.  */
    prev_general_thread = general_thread;
-
    if (the_target->prepare_to_access_memory != NULL)
      {
        int res;
@@ -176,10 +175,11 @@ ptid_t
  mywait (ptid_t ptid, struct target_waitstatus *ourstatus, int options,
  	int connected_wait)
  {
+  struct client_state & cs = get_client_state ();
    ptid_t ret;

    if (connected_wait)
-    server_waiting = 1;
+    cs.server_waiting = 1;

    ret = target_wait (ptid, ourstatus, options);

@@ -206,7 +206,7 @@ mywait (ptid_t ptid, struct target_waitstatus 
*ourstatus, int options,
      }

    if (connected_wait)
-    server_waiting = 0;
+    cs.server_waiting = 0;

    return ret;
  }
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 4172756192..61a01b218d 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -973,11 +973,6 @@ struct traceframe
     fields (and no data) marks the end of trace data.  */
  #define TRACEFRAME_EOB_MARKER_SIZE offsetof (struct traceframe, data)

-/* The traceframe to be used as the source of data to send back to
-   GDB.  A value of -1 means to get data from the live program.  */
-
-int current_traceframe = -1;
-
  /* This flag is true if the trace buffer is circular, meaning that
     when it fills, the oldest trace frames are discarded in order to
     make room.  */
@@ -2279,10 +2274,11 @@ static struct traceframe *
  find_next_traceframe_in_range (CORE_ADDR lo, CORE_ADDR hi, int inside_p,
  			       int *tfnump)
  {
+  struct client_state & cs = get_client_state ();
    struct traceframe *tframe;
    CORE_ADDR tfaddr;

-  *tfnump = current_traceframe + 1;
+  *tfnump = cs.current_traceframe + 1;
    tframe = find_traceframe (*tfnump);
    /* The search is not supposed to wrap around.  */
    if (!tframe)
@@ -2312,9 +2308,10 @@ find_next_traceframe_in_range (CORE_ADDR lo, 
CORE_ADDR hi, int inside_p,
  static struct traceframe *
  find_next_traceframe_by_tracepoint (int num, int *tfnump)
  {
+  struct client_state & cs = get_client_state ();
    struct traceframe *tframe;

-  *tfnump = current_traceframe + 1;
+  *tfnump = cs.current_traceframe + 1;
    tframe = find_traceframe (*tfnump);
    /* The search is not supposed to wrap around.  */
    if (!tframe)
@@ -2343,6 +2340,7 @@ find_next_traceframe_by_tracepoint (int num, int 
*tfnump)
  static void
  cmd_qtinit (char *packet)
  {
+  struct client_state & cs = get_client_state ();
    struct trace_state_variable *tsv, *prev, *next;

    /* Can't do this command without a pid attached.  */
@@ -2353,7 +2351,7 @@ cmd_qtinit (char *packet)
      }

    /* Make sure we don't try to read from a trace frame.  */
-  current_traceframe = -1;
+  cs.current_traceframe = -1;

    stop_tracing ();

@@ -2813,6 +2811,7 @@ cmd_qtenable_disable (char *own_buf, int enable)
  static void
  cmd_qtv (char *own_buf)
  {
+  struct client_state & cs = get_client_state ();
    ULONGEST num;
    LONGEST val = 0;
    int err;
@@ -2821,7 +2820,7 @@ cmd_qtv (char *own_buf)
    packet += strlen ("qTV:");
    unpack_varlen_hex (packet, &num);

-  if (current_traceframe >= 0)
+  if (cs.current_traceframe >= 0)
      {
        err = traceframe_read_tsv ((int) num, &val);
        if (err)
@@ -3552,6 +3551,7 @@ cmd_qtdisconnected (char *own_buf)
  static void
  cmd_qtframe (char *own_buf)
  {
+  struct client_state & cs = get_client_state ();
    ULONGEST frame, pc, lo, hi, num;
    int tfnum, tpnum;
    struct traceframe *tframe;
@@ -3602,7 +3602,7 @@ cmd_qtframe (char *own_buf)
        if (tfnum == -1)
  	{
  	  trace_debug ("Want to stop looking at traceframes");
-	  current_traceframe = -1;
+	  cs.current_traceframe = -1;
  	  write_ok (own_buf);
  	  return;
  	}
@@ -3612,7 +3612,7 @@ cmd_qtframe (char *own_buf)

    if (tframe)
      {
-      current_traceframe = tfnum;
+      cs.current_traceframe = tfnum;
        sprintf (own_buf, "F%xT%x", tfnum, tframe->tpnum);
      }
    else
@@ -5297,6 +5297,7 @@ traceframe_read_mem (int tfnum, CORE_ADDR addr,
  static int
  traceframe_read_tsv (int tsvnum, LONGEST *val)
  {
+  struct client_state & cs = get_client_state ();
    int tfnum;
    struct traceframe *tframe;
    unsigned char *database, *dataptr;
@@ -5306,7 +5307,7 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)

    trace_debug ("traceframe_read_tsv");

-  tfnum = current_traceframe;
+  tfnum = cs.current_traceframe;

    if (tfnum < 0)
      {
diff --git a/gdb/gdbserver/win32-low.c b/gdb/gdbserver/win32-low.c
index 9f0c4e46c1..bbb4a04345 100644
--- a/gdb/gdbserver/win32-low.c
+++ b/gdb/gdbserver/win32-low.c
@@ -747,6 +747,7 @@ static void
  handle_output_debug_string (void)
  {
  #define READ_BUFFER_LEN 1024
+  struct client_state & cs = get_client_state ();
    CORE_ADDR addr;
    char s[READ_BUFFER_LEN + 1] = { 0 };
    DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
@@ -776,7 +777,7 @@ handle_output_debug_string (void)

    if (!startswith (s, "cYg"))
      {
-      if (!server_waiting)
+      if (!cs.server_waiting)
  	{
  	  OUTMSG2(("%s", s));
  	  return;

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v2] Consolidate gdbserver global variables
  2018-05-03 15:06     ` [RFC][PATCH v2] " Stan Cox
@ 2018-05-04 14:14       ` Pedro Alves
  2018-05-07 19:17         ` Frank Ch. Eigler
  2018-05-08 20:58         ` [RFC][PATCH v3] " Stan Cox
  0 siblings, 2 replies; 15+ messages in thread
From: Pedro Alves @ 2018-05-04 14:14 UTC (permalink / raw)
  To: Stan Cox, gdb-patches

Hi Stan,

On 05/03/2018 04:06 PM, Stan Cox wrote:

> Removing server_state removed all of this and simplified things considerably.

Great.

This makes it easier to see where we're going.

Some comments more.  I still have some design reservations.
It seems to me that simply making some of the globals be
per client along won't work correctly.  Particularly, the
cases where the globals are used in the backends.

More details below.

> Add client_state struct.
> 
> Collect per client specific global data items into struct client_state,
> which is similar in purpose to remote.c::remote_state.
> 
>     * server.h (struct client_state): New.
>     * server.c (cont_thread, server_waiting, multi_process)
>     (report_fork_events, report_vfork_events, report_exec_events)
>     (report_thread_events, swbreak_feature, hwbreak_feature)
>     (vCont_supported, disable_randomization, pass_signals)
>     (program_signals, program_signals_p, own_buf):
>     Moved to client_state.
>     * remote-utils.c (remote-debug, noack_mode)
>     (transport_is_reliable): Moved to client_state.
>     * tracepoint.c (current_traceframe): Moved to client_state.
> 
>     Update all callers.
>     * (server.c, remote-utils.c, tracepoint.c, fork-child.c,
>     gdbthread.h, hostio.c, linux-arm-low.c, linux-low.c, notif.c,
>     remote-utils.h, spu-low.c, target.c, win32-low.c):  Use    
>     client_state.

Remove ()s around files list after "Update all callers".

There's spurious whitespace before and after "Use" in the
last entry.

> 
> --- a/gdb/gdbserver/fork-child.c
> +++ b/gdb/gdbserver/fork-child.c
> @@ -44,6 +44,7 @@ restore_old_foreground_pgrp (void)
>  void
>  prefork_hook (const char *args)
>  {
> +  struct client_state & cs = get_client_state ();

Just like with * for pointers, no space after &.

While at it, no need for spelling out "struct" in C++, so,
please write:

     client_state &cs = get_client_state ();

throughout.

>    if (debug_threads)
>      {
>        debug_printf ("args: %s\n", args);
> diff --git a/gdb/gdbserver/gdbthread.h b/gdb/gdbserver/gdbthread.h
> index 0edf870c56..9a8c72e780 100644
> --- a/gdb/gdbserver/gdbthread.h
> +++ b/gdb/gdbserver/gdbthread.h
> @@ -224,4 +224,7 @@ lwpid_of (const thread_info *thread)
>    return thread->id.lwp ();
>  }
> 
> +/* Create a cleanup to restore current_thread.  */
> +struct cleanup *make_cleanup_restore_current_thread (void);

Please mention this in the ChangeLog.

> +
>  #endif /* GDB_THREAD_H */
> diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
> index d2b5a71bad..4e388a85dc 100644
> --- a/gdb/gdbserver/hostio.c
> +++ b/gdb/gdbserver/hostio.c
> @@ -29,8 +29,6 @@
>  #include <sys/stat.h>
>  #include "fileio.h"
> 
> -extern int remote_debug;
> -

This wasn't mentioned in the ChangeLog.

>  struct fd_list
>  {
>    int fd;
> diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
> index 6c2dcead03..3004018e5b 100644
> --- a/gdb/gdbserver/linux-arm-low.c
> +++ b/gdb/gdbserver/linux-arm-low.c
> @@ -160,6 +160,7 @@ static struct arm_get_next_pcs_ops get_next_pcs_ops = {
>    arm_linux_get_next_pcs_fixup,
>  };
> 
> +
>  static int
>  arm_cannot_store_register (int regno)
>  {

Spurious change.  Please remove it.

> diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
> index e64949504d..47dea21e5a 100644
> --- a/gdb/gdbserver/linux-low.c
> +++ b/gdb/gdbserver/linux-low.c
> @@ -475,6 +475,7 @@ linux_arch_setup_thread (struct thread_info *thread)
>  static int
>  handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
>  {
> +  struct client_state & cs = get_client_state ();
>    struct lwp_info *event_lwp = *orig_event_lwp;
>    int event = linux_ptrace_get_extended_event (wstat);
>    struct thread_info *event_thr = get_lwp_thread (event_lwp);
> @@ -655,7 +656,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
>        new_lwp->status_pending_p = 1;
>        new_lwp->status_pending = status;
>      }
> -      else if (report_thread_events)
> +      else if (cs.report_thread_events)
>      {
>        new_lwp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED;
>        new_lwp->status_pending_p = 1;
> @@ -683,7 +684,7 @@ handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
>        /* Report the event.  */
>        return 0;
>      }
> -  else if (event == PTRACE_EVENT_EXEC && report_exec_events)
> +  else if (event == PTRACE_EVENT_EXEC && cs.report_exec_events)
>      {
>        struct process_info *proc;
>        std::vector<int> syscalls_to_catch;

As mentioned, I'm skeptical of all client_state references
in the backends.

How will this work with multiple clients?   What if one client
wants exec events, and the other one doesn't?  This seems to
suggest that the backends need to enable exec events if _any_
client wants them (or unconditionally), and then filter out exec
events at a higher level, before reporting the event to
each client?

> @@ -998,13 +999,14 @@ static int
>  linux_create_inferior (const char *program,
>                 const std::vector<char *> &program_args)
>  {
> +  struct client_state & cs = get_client_state ();
>    struct lwp_info *new_lwp;
>    int pid;
>    ptid_t ptid;
> 
>    {
>      maybe_disable_address_space_randomization restore_personality
> -      (disable_randomization);
> +      (cs.disable_randomization);
>      std::string str_program_args = stringify_argv (program_args);
> 

This one might be OK-ish with the assumption that it's always
going to be the current client that is requesting the
inferior creation.

>      pid = fork_inferior (program,
> @@ -1429,6 +1431,7 @@ linux_kill (int pid)
>  static int
>  get_detach_signal (struct thread_info *thread)
>  {
> +  struct client_state & cs = get_client_state ();
>    enum gdb_signal signo = GDB_SIGNAL_0;
>    int status;
>    struct lwp_info *lp = get_thread_lwp (thread);
> @@ -1469,7 +1472,7 @@ get_detach_signal (struct thread_info *thread)
> 
>    signo = gdb_signal_from_host (WSTOPSIG (status));
> 
> -  if (program_signals_p && !program_signals[signo])
> +  if (cs.program_signals_p && !cs.program_signals[signo])

Similarly, what is the plan for multiple clients for this property,
when the clients don't agree, on both support for the packet,
and, what if they don't agree on pass/nopass state?

>      {
>        if (debug_threads)
>      debug_printf ("GPS: lwp %s had signal %s, but it is in nopass state\n",
> @@ -1477,7 +1480,7 @@ get_detach_signal (struct thread_info *thread)
>                gdb_signal_to_string (signo));
>        return 0;
>      }
> -  else if (!program_signals_p
> +  else if (!cs.program_signals_p
>         /* If we have no way to know which signals GDB does not
>            want to have passed to the program, assume
>            SIGTRAP/SIGINT, which is GDB's default.  */
> @@ -2328,18 +2331,19 @@ check_stopped_by_watchpoint (struct lwp_info *child)
>  static int
>  linux_low_ptrace_options (int attached)
>  {
> +  struct client_state & cs = get_client_state ();
>    int options = 0;
> 
>    if (!attached)
>      options |= PTRACE_O_EXITKILL;
> 
> -  if (report_fork_events)
> +  if (cs.report_fork_events)
>      options |= PTRACE_O_TRACEFORK;
> 
> -  if (report_vfork_events)
> +  if (cs.report_vfork_events)
>      options |= (PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE);
> 
> -  if (report_exec_events)
> +  if (cs.report_exec_events)
>      options |= PTRACE_O_TRACEEXEC;
> 
>    options |= PTRACE_O_TRACESYSGOOD;

Ditto.

> @@ -2354,6 +2358,7 @@ linux_low_ptrace_options (int attached)
>  static struct lwp_info *
>  linux_low_filter_event (int lwpid, int wstat)
>  {
> +  struct client_state & cs = get_client_state ();
>    struct lwp_info *child;
>    struct thread_info *thread;
>    int have_stop_pc = 0;
> @@ -2425,7 +2430,7 @@ linux_low_filter_event (int lwpid, int wstat)
>        /* If there is at least one more LWP, then the exit signal was
>       not the end of the debugged application and should be
>       ignored, unless GDB wants to hear about thread exits.  */
> -      if (report_thread_events
> +      if (cs.report_thread_events
>        || last_thread_of_process_p (pid_of (thread)))
>      {
>        /* Since events are serialized to GDB core, and we can't

Ditto.

> @@ -3049,12 +3054,13 @@ static ptid_t
>  filter_exit_event (struct lwp_info *event_child,
>             struct target_waitstatus *ourstatus)
>  {
> +  struct client_state & cs = get_client_state ();
>    struct thread_info *thread = get_lwp_thread (event_child);
>    ptid_t ptid = ptid_of (thread);
> 
>    if (!last_thread_of_process_p (pid_of (thread)))
>      {
> -      if (report_thread_events)
> +      if (cs.report_thread_events)
>      ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
>        else
>      ourstatus->kind = TARGET_WAITKIND_IGNORE;
> @@ -3106,6 +3112,7 @@ static ptid_t
>  linux_wait_1 (ptid_t ptid,
>            struct target_waitstatus *ourstatus, int target_options)
>  {
> +  struct client_state & cs = get_client_state ();
>    int w;
>    struct lwp_info *event_child;
>    int options;
> @@ -3475,7 +3482,7 @@ linux_wait_1 (ptid_t ptid,
>             || WSTOPSIG (w) == __SIGRTMIN + 1))
>        ||
>  #endif
> -      (pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
> +      (cs.pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
>         && !(WSTOPSIG (w) == SIGSTOP
>          && current_thread->last_resume_kind == resume_stop)
>         && !linux_wstatus_maybe_breakpoint (w))))
> @@ -3782,7 +3789,7 @@ linux_wait_1 (ptid_t ptid,
>       it was a software breakpoint, and the client doesn't know we can
>       adjust the breakpoint ourselves.  */
>    if (event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
> -      && !swbreak_feature)
> +      && !cs.swbreak_feature)
>      {
>        int decr_pc = the_low_target.decr_pc_after_break;
> 
> @@ -5036,6 +5043,7 @@ linux_resume_one_thread (thread_info *thread, bool leave_all_stopped)
>  static void
>  linux_resume (struct thread_resume *resume_info, size_t n)
>  {
> +  struct client_state & cs = get_client_state ();
>    struct thread_info *need_step_over = NULL;
> 

This one looks unnecessary/unused.  'cs' is not used.

>    if (debug_threads)
> diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
> index 5ff7079123..2cd411f9bb 100644
> --- a/gdb/gdbserver/notif.c
> +++ b/gdb/gdbserver/notif.c
> @@ -79,6 +79,7 @@ notif_write_event (struct notif_server *notif, char *own_buf)
>  int
>  handle_notif_ack (char *own_buf, int packet_len)
>  {
> +  struct client_state & cs = get_client_state ();
>    size_t i;
>    struct notif_server *np;
> 
> @@ -103,7 +104,7 @@ handle_notif_ack (char *own_buf, int packet_len)
>        struct notif_event *head
>      = QUEUE_deque (notif_event_p, np->queue);
> 
> -      if (remote_debug)
> +      if (cs.remote_debug)
>      debug_printf ("%s: acking %d\n", np->ack_name,
>                QUEUE_length (notif_event_p, np->queue));
> 
> @@ -121,9 +122,10 @@ void
>  notif_event_enque (struct notif_server *notif,
>             struct notif_event *event)
>  {
> +  struct client_state & cs = get_client_state ();
>    QUEUE_enque (notif_event_p, notif->queue, event);
> 
> -  if (remote_debug)
> +  if (cs.remote_debug)
>      debug_printf ("pending events: %s %d\n", notif->notif_name,
>            QUEUE_length (notif_event_p, notif->queue));
> 
> diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
> index 3b5a459ae4..ea02631444 100644
> --- a/gdb/gdbserver/remote-utils.c
> +++ b/gdb/gdbserver/remote-utils.c
> @@ -26,6 +26,7 @@
>  #include "dll.h"
>  #include "rsp-low.h"
>  #include "gdbthread.h"
> +#include "server.h"

This should be unnecessary - "server.h" is already included above.
I could tell because "server.h" must always be the
first include in all .c files.

>  #include <ctype.h>
>  #if HAVE_SYS_IOCTL_H
>  #include <sys/ioctl.h>
> @@ -103,7 +104,6 @@ struct sym_cache
>    struct sym_cache *next;
>  };
> 
> -int remote_debug = 0;
>  struct ui_file *gdb_stdlog;
> 
>  static int remote_is_stdio = 0;
> @@ -115,11 +115,6 @@ static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
>  extern int using_threads;
>  extern int debug_threads;
> 
> -/* If true, then GDB has requested noack mode.  */
> -int noack_mode = 0;
> -/* If true, then we tell GDB to use noack mode by default.  */
> -int transport_is_reliable = 0;
> -
>  #ifdef USE_WIN32API
>  # define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
>  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)


> diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
> index 5027df5e10..b4b72b55f8 100644
> --- a/gdb/gdbserver/server.c
> +++ b/gdb/gdbserver/server.c
> @@ -83,36 +83,17 @@ ptid_t cont_thread;
>  /* The thread set with an `Hg' packet.  */
>  ptid_t general_thread;
> 
> -int server_waiting;
> -
>  static int extended_protocol;
>  static int response_needed;
>  static int exit_requested;
> 
>  /* --once: Exit after the first connection has closed.  */
> -int run_once;
> -
> -int multi_process;
> -int report_fork_events;
> -int report_vfork_events;
> -int report_exec_events;
> -int report_thread_events;
> +int run_once = 0;

This "= 0" is a spurious change.  Remove it.

> 
>  /* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
>  static int report_no_resumed;
> 
>  int non_stop;
> -int swbreak_feature;
> -int hwbreak_feature;
> -
> -/* True if the "vContSupported" feature is active.  In that case, GDB
> -   wants us to report whether single step is supported in the reply to
> -   "vCont?" packet.  */
> -static int vCont_supported;
> -
> -/* Whether we should attempt to disable the operating system's address
> -   space randomization feature before starting an inferior.  */
> -int disable_randomization = 1;
> 
>  static struct {
>    /* Set the PROGRAM_PATH.  Here we adjust the path of the provided

> 
>  /* A sub-class of 'struct notif_event' for stop, holding information
> @@ -193,6 +169,18 @@ static struct btrace_config current_btrace_conf;
> 
>  DEFINE_QUEUE_P (notif_event_p);
> 
> +/* The client remote protocol state. */
> +
> +static struct client_state *client_state;

Give the global different name to avoid conflict with
the type name.  Maybe "g_client_state" or "the_client_state".

> +
> +struct client_state &
> +get_client_state (void)

We use (void) in many places because of C heritage, but it's
no longer needed in C++, so:

  (void) -> ()

> +{
> +  struct client_state & cs = *client_state;
> +  return cs;

Simply write:

  return *g_client_state;

Thus:

 client_state &
 get_client_state ()
 {
   return *g_client_state;
 }

> @@ -1835,10 +1830,11 @@ handle_qxfer_btrace (const char *annex,
>               gdb_byte *readbuf, const gdb_byte *writebuf,
>               ULONGEST offset, LONGEST len)
>  {
> +  struct client_state & cs = get_client_state ();
>    static struct buffer cache;
>    struct thread_info *thread;
>    enum btrace_read_type type;
> -  int result;
> +  int result = 0;

This "= 0" looks like a spurious change.

> 
>    if (writebuf != NULL)
>      return -2;
> @@ -1846,20 +1842,20 @@ handle_qxfer_btrace (const char *annex,
>    if (ptid_equal (general_thread, null_ptid)
>        || ptid_equal (general_thread, minus_one_ptid))
>      {
> -      strcpy (own_buf, "E.Must select a single thread.");
> +      strcpy (cs.own_buf, "E.Must select a single thread.");
>        return -3;
>      }
> 
>    thread = find_thread_ptid (general_thread);
>    if (thread == NULL)
>      {
> -      strcpy (own_buf, "E.No such thread.");
> +      strcpy (cs.own_buf, "E.No such thread.");
>        return -3;
>      }
> 
>    if (thread->btrace == NULL)
>      {
> -      strcpy (own_buf, "E.Btrace not enabled.");
> +      strcpy (cs.own_buf, "E.Btrace not enabled.");
>        return -3;
>      }
> 
> @@ -1871,7 +1867,7 @@ handle_qxfer_btrace (const char *annex,
>      type = BTRACE_READ_DELTA;
>    else
>      {
> -      strcpy (own_buf, "E.Bad annex.");
> +      strcpy (cs.own_buf, "E.Bad annex.");
>        return -3;
>      }
> 
> @@ -1883,11 +1879,11 @@ handle_qxfer_btrace (const char *annex,
>      {
>        result = target_read_btrace (thread->btrace, &cache, type);
>        if (result != 0)
> -        memcpy (own_buf, cache.buffer, cache.used_size);
> +        memcpy (cs.own_buf, cache.buffer, cache.used_size);
>      }
>        CATCH (exception, RETURN_MASK_ERROR)
>      {
> -      sprintf (own_buf, "E.%s", exception.message);
> +      sprintf (cs.own_buf, "E.%s", exception.message);
>        result = -1;
>      }
>        END_CATCH
> @@ -1916,9 +1912,10 @@ handle_qxfer_btrace_conf (const char *annex,
>                gdb_byte *readbuf, const gdb_byte *writebuf,
>                ULONGEST offset, LONGEST len)
>  {
> +  struct client_state & cs = get_client_state ();
>    static struct buffer cache;
>    struct thread_info *thread;
> -  int result;
> +  int result = 0;

Ditto.

> 
>    if (writebuf != NULL)
>      return -2;

> @@ -2729,13 +2727,14 @@ static int
>  handle_pending_status (const struct thread_resume *resumption,
>                 struct thread_info *thread)
>  {
> +  struct client_state & cs = get_client_state ();
>    if (thread->status_pending_p)
>      {
>        thread->status_pending_p = 0;
> 
>        last_status = thread->last_status;
>        last_ptid = thread->id;

What's the plan for last_status/last_ptid?
Shouldn't those be per-client too?

> -      prepare_resume_reply (own_buf, last_ptid, &last_status);
> +      prepare_resume_reply (cs.own_buf, last_ptid, &last_status);
>        return 1;
>      }
>    return 0;
> @@ -2855,6 +2854,7 @@ err:
>  static void
>  resume (struct thread_resume *actions, size_t num_actions)
>  {
> +  struct client_state & cs = get_client_state ();
>    if (!non_stop)
>      {
>        /* Check if among the threads that GDB wants actioned, there's


> @@ -3577,6 +3581,9 @@ captured_main (int argc, char *argv[])
>  #endif
> 
>    current_directory = getcwd (NULL, 0);
> +  client_state = new (struct client_state);

Write:

  g_client_state = new client_state ();

Or better, at this point (in this patch) there's really no
need to allocate this object on the heap, so let's remove the
'new' line, and make the g_client_state global not-a-pointer:

 client_state g_client_state;

We can move it to the heap in the patch that actually 
allocates more than one such objects.

> diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
> index 5970431d8e..7518309988 100644
> --- a/gdb/gdbserver/server.h
> +++ b/gdb/gdbserver/server.h
> @@ -60,8 +60,6 @@ int vsnprintf(char *str, size_t size, const char *format, va_list ap);
>  #include "gdb_signals.h"
>  #include "target.h"
>  #include "mem-break.h"
> -#include "gdbthread.h"
> -#include "inferiors.h"
>  #include "environ.h"
> 
>  /* Target-specific functions */
> @@ -72,40 +70,14 @@ void initialize_low ();
> 
>  extern ptid_t cont_thread;
>  extern ptid_t general_thread;

Should these two be per client?  I'd think so off hand,
since they correspond to the Hc/Hg threads?

> @@ -162,4 +134,62 @@ extern target_waitstatus last_status;
>  extern ptid_t last_ptid;
>  extern unsigned long signal_pid;
> 
> +
> +/* Description of the client remote protocol state for the currently
> +   connected target.  */

What is a "target" in this context?  Did you mean "connected client"
instead of "connected target"?

> +
> +struct client_state
> +{
> +  /* From server.c */

I'm thinking that this "From foo.c" comments won't make much sense
after this is merged.  (Ideally we'd add descriptions for what
the fields are instead, but we don't have one today, so this can
go without.)

> +  int server_waiting = 0;
> +  int multi_process = 0;
> +  int report_fork_events = 0;
> +  int report_vfork_events = 0;
> +  int report_exec_events = 0;
> +  int report_thread_events = 0;
> +
> +  /* True if the "swbreak+" feature is active.  In that case, GDB wants
> +     us to report whether a trap is explained by a software breakpoint
> +     and for the server to handle PC adjustment if necessary on this
> +     target.  Only enabled if the target supports it.  */
> +  int swbreak_feature = 0;
> +  /* True if the "hwbreak+" feature is active.  In that case, GDB wants
> +     us to report whether a trap is explained by a hardware breakpoint.
> +     Only enabled if the target supports it.  */
> +  int hwbreak_feature = 0;
> +
> +  /* True if the "vContSupported" feature is active.  In that case, GDB
> +     wants us to report whether single step is supported in the reply to
> +     "vCont?" packet.  */
> +  int vCont_supported = 0;
> +
> +  /* Whether we should attempt to disable the operating system's address
> +     space randomization feature before starting an inferior.  */
> +  int disable_randomization = 0;
> +  int pass_signals[GDB_SIGNAL_LAST];

Add line break between the two above, they're unrelated.

> +  int program_signals[GDB_SIGNAL_LAST];
> +  int program_signals_p = 0;
> +  char *own_buf;

Add line break between the two above, they're unrelated.

> +
> +  /* from remote-utils.c */
> +  int remote_debug = 0;
> +  /* If true, then GDB has requested noack mode.  */
> +  int noack_mode = 0;
> +  /* If true, then we tell GDB to use noack mode by default.  */
> +  int transport_is_reliable = 0;
> +  /* from tracepoint.c */
> +  /* The traceframe to be used as the source of data to send back to
> +     GDB.  A value of -1 means to get data from the live program.  */
> +
> +  int current_traceframe = -1;
> +
> +  client_state ():
> +    own_buf ((char *) xmalloc (PBUFSIZ + 1)) {}

Contructors should go above the data fields.  Please make
this the first entry in the struct.  Also, formatting, please
write:

  client_state ()
    : own_buf ((char *) xmalloc (PBUFSIZ + 1)) 
  {}

> +};
> +
> +struct client_state& get_client_state (void);

Write:

 extern client_state &get_client_state ();

> diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c
> index 5b880d2a42..d909966199 100644
> --- a/gdb/gdbserver/spu-low.c
> +++ b/gdb/gdbserver/spu-low.c
> @@ -418,6 +418,7 @@ spu_resume (struct thread_resume *resume_info, size_t n)
>  static ptid_t
>  spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
>  {
> +  struct client_state & cs = get_client_state ();
>    int pid = ptid_get_pid (ptid);
>    int w;
>    int ret;
> @@ -439,7 +440,7 @@ spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
> 
>    /* On the first wait, continue running the inferior until we are
>       blocked inside an spu_run system call.  */
> -  if (!server_waiting)
> +  if (!cs.server_waiting)

This is another case of what does this mean for
multiple clients?  One will be waiting, but another
one won't.  How can the backend know what to do?

I suspect that it'd be better to make the server_waiting
global be per-process instead (and likely renamed), though
I haven't studied in detail what are all the cases it is
used for.

> --- a/gdb/gdbserver/target.c
> +++ b/gdb/gdbserver/target.c
> @@ -52,7 +52,6 @@ prepare_to_access_memory (void)
>    /* Save the general thread value, since prepare_to_access_memory could change
>       it.  */
>    prev_general_thread = general_thread;
> -
>    if (the_target->prepare_to_access_memory != NULL)

Spurious change.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v2] Consolidate gdbserver global variables
  2018-05-04 14:14       ` Pedro Alves
@ 2018-05-07 19:17         ` Frank Ch. Eigler
  2018-05-25 14:31           ` Pedro Alves
  2018-05-08 20:58         ` [RFC][PATCH v3] " Stan Cox
  1 sibling, 1 reply; 15+ messages in thread
From: Frank Ch. Eigler @ 2018-05-07 19:17 UTC (permalink / raw)
  To: Pedro Alves; +Cc: Stan Cox, gdb-patches


palves wrote:

> [...]
> Some comments more.  I still have some design reservations.
> It seems to me that simply making some of the globals be
> per client along won't work correctly.  Particularly, the
> cases where the globals are used in the backends.
> [...]

I don't want to speak for Stan here, but I suspect all this is about is
the breaking up of the multi-client work along the patchset path your
requested.  Yup, indeed backends have to do the logical 'union' of the
work that all the clients request, and each client interface will have
to filter the notifications correspondingly to undo the 'union'.  

But all that is in a separate patch; this part seems to simply
reorganize the globals in preparation for that, as you asked.

- FChE

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-05-04 14:14       ` Pedro Alves
  2018-05-07 19:17         ` Frank Ch. Eigler
@ 2018-05-08 20:58         ` Stan Cox
  2018-05-25 15:01           ` Pedro Alves
                             ` (2 more replies)
  1 sibling, 3 replies; 15+ messages in thread
From: Stan Cox @ 2018-05-08 20:58 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches

(Addressed formatting and ChangeLog issues)

> As mentioned, I'm skeptical of all client_state references
> in the backends.
> 
> How will this work with multiple clients?   What if one client
> wants exec events, and the other one doesn't?  This seems to
> suggest that the backends need to enable exec events if _any_
> client wants them (or unconditionally), and then filter out exec
> events at a higher level, before reporting the event to
> each client?

Perhaps filtering that is roughly analogous to the way
gdb_catch_this_syscall_p filters for particular syscalls.

> This "= 0" is a spurious change.  Remove it.

Removed (it eliminated a compiler warning with gcc 7.3.1)

> Give the global different name to avoid conflict with
> the type name.  Maybe "g_client_state" or "the_client_state".

Used g_client_state and also made it static instead of allocating it
with new.

> What's the plan for last_status/last_ptid?
> Shouldn't those be per-client too?

Added those.

> Should these two be per client?  I'd think so off hand,
> since they correspond to the Hc/Hg threads?

Added cont_thread and general_thread

> I suspect that it'd be better to make the server_waiting
> global be per-process instead

Returned to server_waiting being a global for now.


Thanks Pedro!


Tested on linux with native-gdbserver.

Add client_state struct.

Collect per client specific global data items into struct client_state,
which is similar in purpose to remote.c::remote_state.

     * server.h (struct client_state): New.
     * server.c (cont_thread, general_thread, multi_process)
     (report_fork_events, report_vfork_events, report_exec_events)
     (report_thread_events, swbreak_feature, hwbreak_feature)
     (vCont_supported, disable_randomization, pass_signals)
     (program_signals, program_signals_p, last_status, last_ptid, own_buf):
     Moved to client_state.
     * remote-utils.c (remote_debug, noack_mode)
     (transport_is_reliable): Moved to client_state.
     * tracepoint.c (current_traceframe): Moved to client_state.

     Update all callers.
     * server.c, remote-utils.c, tracepoint.c, fork-child.c,
     gdbthread.h, hostio.c, linux-arm-low.c, linux-low.c, notif.c,
     remote-utils.h, spu-low.c, target.c, win32-low.c: Use
     client_state.


  gdb/gdbserver/fork-child.c   |   8 +-
  gdb/gdbserver/hostio.c       |   2 -
  gdb/gdbserver/linux-low.c    |  31 +++---
  gdb/gdbserver/notif.c        |   6 +-
  gdb/gdbserver/remote-utils.c | 146 ++++++++++++++-------------
  gdb/gdbserver/remote-utils.h |   4 -
  gdb/gdbserver/server.c       | 523 
+++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------
  gdb/gdbserver/server.h       | 104 +++++++++++++------
  gdb/gdbserver/target.c       |  15 ++-
  gdb/gdbserver/tracepoint.c   |  25 ++---
  10 files changed, 461 insertions(+), 403 deletions(-)


diff --git a/gdb/gdbserver/fork-child.c b/gdb/gdbserver/fork-child.c
index 831e7e1310..0dfd69d626 100644
--- a/gdb/gdbserver/fork-child.c
+++ b/gdb/gdbserver/fork-child.c
@@ -44,6 +44,7 @@ restore_old_foreground_pgrp (void)
  void
  prefork_hook (const char *args)
  {
+  client_state &cs = get_client_state ();
    if (debug_threads)
      {
        debug_printf ("args: %s\n", args);
@@ -57,7 +58,7 @@ prefork_hook (const char *args)

    /* Clear this so the backend doesn't get confused, thinking
       CONT_THREAD died, and it needs to resume all threads.  */
-  cont_thread = null_ptid;
+  cs.cont_thread = null_ptid;
  }

  /* See nat/fork-inferior.h.  */
@@ -96,6 +97,7 @@ gdb_flush_out_err ()
  void
  post_fork_inferior (int pid, const char *program)
  {
+  client_state &cs = get_client_state ();
  #ifdef SIGTTOU
    signal (SIGTTOU, SIG_IGN);
    signal (SIGTTIN, SIG_IGN);
@@ -106,9 +108,9 @@ post_fork_inferior (int pid, const char *program)
  #endif

    startup_inferior (pid, START_INFERIOR_TRAPS_EXPECTED,
-		    &last_status, &last_ptid);
+		    &cs.last_status, &cs.last_ptid);
    current_thread->last_resume_kind = resume_stop;
-  current_thread->last_status = last_status;
+  current_thread->last_status = cs.last_status;
    signal_pid = pid;
    target_post_create_inferior ();
    fprintf (stderr, "Process %s created; pid = %d\n", program, pid);
diff --git a/gdb/gdbserver/hostio.c b/gdb/gdbserver/hostio.c
index d2b5a71bad..4e388a85dc 100644
--- a/gdb/gdbserver/hostio.c
+++ b/gdb/gdbserver/hostio.c
@@ -29,8 +29,6 @@
  #include <sys/stat.h>
  #include "fileio.h"

-extern int remote_debug;
-
  struct fd_list
  {
    int fd;
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index e64949504d..f8507b7968 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -475,6 +475,7 @@ linux_arch_setup_thread (struct thread_info *thread)
  static int
  handle_extended_wait (struct lwp_info **orig_event_lwp, int wstat)
  {
+  client_state &cs = get_client_state ();
    struct lwp_info *event_lwp = *orig_event_lwp;
    int event = linux_ptrace_get_extended_event (wstat);
    struct thread_info *event_thr = get_lwp_thread (event_lwp);
@@ -655,7 +656,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
  	  new_lwp->status_pending_p = 1;
  	  new_lwp->status_pending = status;
  	}
-      else if (report_thread_events)
+      else if (cs.report_thread_events)
  	{
  	  new_lwp->waitstatus.kind = TARGET_WAITKIND_THREAD_CREATED;
  	  new_lwp->status_pending_p = 1;
@@ -683,7 +684,7 @@ handle_extended_wait (struct lwp_info 
**orig_event_lwp, int wstat)
        /* Report the event.  */
        return 0;
      }
-  else if (event == PTRACE_EVENT_EXEC && report_exec_events)
+  else if (event == PTRACE_EVENT_EXEC && cs.report_exec_events)
      {
        struct process_info *proc;
        std::vector<int> syscalls_to_catch;
@@ -998,13 +999,14 @@ static int
  linux_create_inferior (const char *program,
  		       const std::vector<char *> &program_args)
  {
+  client_state &cs = get_client_state ();
    struct lwp_info *new_lwp;
    int pid;
    ptid_t ptid;

    {
      maybe_disable_address_space_randomization restore_personality
-      (disable_randomization);
+      (cs.disable_randomization);
      std::string str_program_args = stringify_argv (program_args);

      pid = fork_inferior (program,
@@ -1429,6 +1431,7 @@ linux_kill (int pid)
  static int
  get_detach_signal (struct thread_info *thread)
  {
+  client_state &cs = get_client_state ();
    enum gdb_signal signo = GDB_SIGNAL_0;
    int status;
    struct lwp_info *lp = get_thread_lwp (thread);
@@ -1469,7 +1472,7 @@ get_detach_signal (struct thread_info *thread)

    signo = gdb_signal_from_host (WSTOPSIG (status));

-  if (program_signals_p && !program_signals[signo])
+  if (cs.program_signals_p && !cs.program_signals[signo])
      {
        if (debug_threads)
  	debug_printf ("GPS: lwp %s had signal %s, but it is in nopass state\n",
@@ -1477,7 +1480,7 @@ get_detach_signal (struct thread_info *thread)
  		      gdb_signal_to_string (signo));
        return 0;
      }
-  else if (!program_signals_p
+  else if (!cs.program_signals_p
  	   /* If we have no way to know which signals GDB does not
  	      want to have passed to the program, assume
  	      SIGTRAP/SIGINT, which is GDB's default.  */
@@ -2328,18 +2331,19 @@ check_stopped_by_watchpoint (struct lwp_info *child)
  static int
  linux_low_ptrace_options (int attached)
  {
+  client_state &cs = get_client_state ();
    int options = 0;

    if (!attached)
      options |= PTRACE_O_EXITKILL;

-  if (report_fork_events)
+  if (cs.report_fork_events)
      options |= PTRACE_O_TRACEFORK;

-  if (report_vfork_events)
+  if (cs.report_vfork_events)
      options |= (PTRACE_O_TRACEVFORK | PTRACE_O_TRACEVFORKDONE);

-  if (report_exec_events)
+  if (cs.report_exec_events)
      options |= PTRACE_O_TRACEEXEC;

    options |= PTRACE_O_TRACESYSGOOD;
@@ -2354,6 +2358,7 @@ linux_low_ptrace_options (int attached)
  static struct lwp_info *
  linux_low_filter_event (int lwpid, int wstat)
  {
+  client_state &cs = get_client_state ();
    struct lwp_info *child;
    struct thread_info *thread;
    int have_stop_pc = 0;
@@ -2425,7 +2430,7 @@ linux_low_filter_event (int lwpid, int wstat)
        /* If there is at least one more LWP, then the exit signal was
  	 not the end of the debugged application and should be
  	 ignored, unless GDB wants to hear about thread exits.  */
-      if (report_thread_events
+      if (cs.report_thread_events
  	  || last_thread_of_process_p (pid_of (thread)))
  	{
  	  /* Since events are serialized to GDB core, and we can't
@@ -3049,12 +3054,13 @@ static ptid_t
  filter_exit_event (struct lwp_info *event_child,
  		   struct target_waitstatus *ourstatus)
  {
+  client_state &cs = get_client_state ();
    struct thread_info *thread = get_lwp_thread (event_child);
    ptid_t ptid = ptid_of (thread);

    if (!last_thread_of_process_p (pid_of (thread)))
      {
-      if (report_thread_events)
+      if (cs.report_thread_events)
  	ourstatus->kind = TARGET_WAITKIND_THREAD_EXITED;
        else
  	ourstatus->kind = TARGET_WAITKIND_IGNORE;
@@ -3106,6 +3112,7 @@ static ptid_t
  linux_wait_1 (ptid_t ptid,
  	      struct target_waitstatus *ourstatus, int target_options)
  {
+  client_state &cs = get_client_state ();
    int w;
    struct lwp_info *event_child;
    int options;
@@ -3475,7 +3482,7 @@ linux_wait_1 (ptid_t ptid,
  	       || WSTOPSIG (w) == __SIGRTMIN + 1))
  	  ||
  #endif
-	  (pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
+	  (cs.pass_signals[gdb_signal_from_host (WSTOPSIG (w))]
  	   && !(WSTOPSIG (w) == SIGSTOP
  		&& current_thread->last_resume_kind == resume_stop)
  	   && !linux_wstatus_maybe_breakpoint (w))))
@@ -3782,7 +3789,7 @@ linux_wait_1 (ptid_t ptid,
       it was a software breakpoint, and the client doesn't know we can
       adjust the breakpoint ourselves.  */
    if (event_child->stop_reason == TARGET_STOPPED_BY_SW_BREAKPOINT
-      && !swbreak_feature)
+      && !cs.swbreak_feature)
      {
        int decr_pc = the_low_target.decr_pc_after_break;

diff --git a/gdb/gdbserver/notif.c b/gdb/gdbserver/notif.c
index 5ff7079123..6480c3abc9 100644
--- a/gdb/gdbserver/notif.c
+++ b/gdb/gdbserver/notif.c
@@ -79,6 +79,7 @@ notif_write_event (struct notif_server *notif, char 
*own_buf)
  int
  handle_notif_ack (char *own_buf, int packet_len)
  {
+  client_state &cs = get_client_state ();
    size_t i;
    struct notif_server *np;

@@ -103,7 +104,7 @@ handle_notif_ack (char *own_buf, int packet_len)
        struct notif_event *head
  	= QUEUE_deque (notif_event_p, np->queue);

-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf ("%s: acking %d\n", np->ack_name,
  		      QUEUE_length (notif_event_p, np->queue));

@@ -121,9 +122,10 @@ void
  notif_event_enque (struct notif_server *notif,
  		   struct notif_event *event)
  {
+  client_state &cs = get_client_state ();
    QUEUE_enque (notif_event_p, notif->queue, event);

-  if (remote_debug)
+  if (cs.remote_debug)
      debug_printf ("pending events: %s %d\n", notif->notif_name,
  		  QUEUE_length (notif_event_p, notif->queue));

diff --git a/gdb/gdbserver/remote-utils.c b/gdb/gdbserver/remote-utils.c
index 3b5a459ae4..22c8187464 100644
--- a/gdb/gdbserver/remote-utils.c
+++ b/gdb/gdbserver/remote-utils.c
@@ -103,7 +103,6 @@ struct sym_cache
    struct sym_cache *next;
  };

-int remote_debug = 0;
  struct ui_file *gdb_stdlog;

  static int remote_is_stdio = 0;
@@ -115,11 +114,6 @@ static gdb_fildes_t listen_desc = INVALID_DESCRIPTOR;
  extern int using_threads;
  extern int debug_threads;

-/* If true, then GDB has requested noack mode.  */
-int noack_mode = 0;
-/* If true, then we tell GDB to use noack mode by default.  */
-int transport_is_reliable = 0;
-
  #ifdef USE_WIN32API
  # define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
  # define write(fd, buf, len) send (fd, (char *) buf, len, 0)
@@ -222,6 +216,7 @@ handle_accept_event (int err, gdb_client_data 
client_data)
  void
  remote_prepare (const char *name)
  {
+  client_state &cs = get_client_state ();
    const char *port_str;
  #ifdef USE_WIN32API
    static int winsock_initialized;
@@ -238,14 +233,14 @@ remote_prepare (const char *name)
  	 call to remote_open so start_inferior knows the connection is
  	 via stdio.  */
        remote_is_stdio = 1;
-      transport_is_reliable = 1;
+      cs.transport_is_reliable = 1;
        return;
      }

    port_str = strchr (name, ':');
    if (port_str == NULL)
      {
-      transport_is_reliable = 0;
+      cs.transport_is_reliable = 0;
        return;
      }

@@ -280,7 +275,7 @@ remote_prepare (const char *name)
        || listen (listen_desc, 1))
      perror_with_name ("Can't bind address");

-  transport_is_reliable = 1;
+  cs.transport_is_reliable = 1;
  }

  /* Open a connection to a remote debugger.
@@ -485,9 +480,10 @@ try_rle (char *buf, int remaining, unsigned char 
*csum, char **p)
  char *
  write_ptid (char *buf, ptid_t ptid)
  {
+  client_state &cs = get_client_state ();
    int pid, tid;

-  if (multi_process)
+  if (cs.multi_process)
      {
        pid = ptid_get_pid (ptid);
        if (pid < 0)
@@ -594,6 +590,7 @@ read_prim (void *buf, int count)
  static int
  putpkt_binary_1 (char *buf, int cnt, int is_notif)
  {
+  client_state &cs = get_client_state ();
    int i;
    unsigned char csum = 0;
    char *buf2;
@@ -631,10 +628,10 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  return -1;
  	}

-      if (noack_mode || is_notif)
+      if (cs.noack_mode || is_notif)
  	{
  	  /* Don't expect an ack then.  */
-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    {
  	      if (is_notif)
  		debug_printf ("putpkt (\"%s\"); [notif]\n", buf2);
@@ -645,7 +642,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  break;
  	}

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("putpkt (\"%s\"); [looking for ack]\n", buf2);
  	  debug_flush ();
@@ -659,7 +656,7 @@ putpkt_binary_1 (char *buf, int cnt, int is_notif)
  	  return -1;
  	}

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("[received '%c' (0x%x)]\n", cc, cc);
  	  debug_flush ();
@@ -851,6 +848,7 @@ static unsigned char *readchar_bufp;
  static int
  readchar (void)
  {
+  client_state &cs = get_client_state ();
    int ch;

    if (readchar_bufcnt == 0)
@@ -861,7 +859,7 @@ readchar (void)
  	{
  	  if (readchar_bufcnt == 0)
  	    {
-	      if (remote_debug)
+	      if (cs.remote_debug)
  		debug_printf ("readchar: Got EOF\n");
  	    }
  	  else
@@ -926,6 +924,7 @@ reschedule (void)
  int
  getpkt (char *buf)
  {
+  client_state &cs = get_client_state ();
    char *bp;
    unsigned char csum, c1, c2;
    int c;
@@ -948,7 +947,7 @@ getpkt (char *buf)

  	  if (c == '$')
  	    break;
-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    {
  	      debug_printf ("[getpkt: discarding char '%c']\n", c);
  	      debug_flush ();
@@ -977,7 +976,7 @@ getpkt (char *buf)
        if (csum == (c1 << 4) + c2)
  	break;

-      if (noack_mode)
+      if (cs.noack_mode)
  	{
  	  fprintf (stderr,
  		   "Bad checksum, sentsum=0x%x, csum=0x%x, "
@@ -993,9 +992,9 @@ getpkt (char *buf)
  	return -1;
      }

-  if (!noack_mode)
+  if (!cs.noack_mode)
      {
-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("getpkt (\"%s\");  [sending ack] \n", buf);
  	  debug_flush ();
@@ -1004,7 +1003,7 @@ getpkt (char *buf)
        if (write_prim ("+", 1) != 1)
  	return -1;

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("[sent ack]\n");
  	  debug_flush ();
@@ -1012,7 +1011,7 @@ getpkt (char *buf)
      }
    else
      {
-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("getpkt (\"%s\");  [no ack sent] \n", buf);
  	  debug_flush ();
@@ -1081,6 +1080,7 @@ void
  prepare_resume_reply (char *buf, ptid_t ptid,
  		      struct target_waitstatus *status)
  {
+  client_state &cs = get_client_state ();
    if (debug_threads)
      debug_printf ("Writing resume reply for %s:%d\n",
  		  target_pid_to_str (ptid), status->kind);
@@ -1100,8 +1100,9 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	const char **regp;
  	struct regcache *regcache;

-	if ((status->kind == TARGET_WAITKIND_FORKED && report_fork_events)
-	    || (status->kind == TARGET_WAITKIND_VFORKED && report_vfork_events))
+	if ((status->kind == TARGET_WAITKIND_FORKED && cs.report_fork_events)
+	    || (status->kind == TARGET_WAITKIND_VFORKED
+		&& cs.report_vfork_events))
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;
  	    const char *event = (status->kind == TARGET_WAITKIND_FORKED
@@ -1112,13 +1113,14 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	    buf = write_ptid (buf, status->value.related_pid);
  	    strcat (buf, ";");
  	  }
-	else if (status->kind == TARGET_WAITKIND_VFORK_DONE && 
report_vfork_events)
+	else if (status->kind == TARGET_WAITKIND_VFORK_DONE
+		 && cs.report_vfork_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;

  	    sprintf (buf, "T%02xvforkdone:;", signal);
  	  }
-	else if (status->kind == TARGET_WAITKIND_EXECD && report_exec_events)
+	else if (status->kind == TARGET_WAITKIND_EXECD && cs.report_exec_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;
  	    const char *event = "exec";
@@ -1138,7 +1140,7 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	    buf += strlen (buf);
  	  }
  	else if (status->kind == TARGET_WAITKIND_THREAD_CREATED
-		 && report_thread_events)
+		 && cs.report_thread_events)
  	  {
  	    enum gdb_signal signal = GDB_SIGNAL_TRAP;

@@ -1186,12 +1188,12 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	      *buf++ = tohex ((addr >> (i - 1) * 4) & 0xf);
  	    *buf++ = ';';
  	  }
-	else if (swbreak_feature && target_stopped_by_sw_breakpoint ())
+	else if (cs.swbreak_feature && target_stopped_by_sw_breakpoint ())
  	  {
  	    sprintf (buf, "swbreak:;");
  	    buf += strlen (buf);
  	  }
-	else if (hwbreak_feature && target_stopped_by_hw_breakpoint ())
+	else if (cs.hwbreak_feature && target_stopped_by_hw_breakpoint ())
  	  {
  	    sprintf (buf, "hwbreak:;");
  	    buf += strlen (buf);
@@ -1219,13 +1221,13 @@ prepare_resume_reply (char *buf, ptid_t ptid,
  	       in GDB will claim this event belongs to inferior_ptid
  	       if we do not specify a thread, and there's no way for
  	       gdbserver to know what inferior_ptid is.  */
-	    if (1 || !ptid_equal (general_thread, ptid))
+	    if (1 || !ptid_equal (cs.general_thread, ptid))
  	      {
  		int core = -1;
  		/* In non-stop, don't change the general thread behind
  		   GDB's back.  */
  		if (!non_stop)
-		  general_thread = ptid;
+		  cs.general_thread = ptid;
  		sprintf (buf, "thread:");
  		buf += strlen (buf);
  		buf = write_ptid (buf, ptid);
@@ -1256,14 +1258,14 @@ prepare_resume_reply (char *buf, ptid_t ptid,
        }
        break;
      case TARGET_WAITKIND_EXITED:
-      if (multi_process)
+      if (cs.multi_process)
  	sprintf (buf, "W%x;process:%x",
  		 status->value.integer, ptid_get_pid (ptid));
        else
  	sprintf (buf, "W%02x", status->value.integer);
        break;
      case TARGET_WAITKIND_SIGNALLED:
-      if (multi_process)
+      if (cs.multi_process)
  	sprintf (buf, "X%x;process:%x",
  		 status->value.sig, ptid_get_pid (ptid));
        else
@@ -1435,6 +1437,7 @@ clear_symbol_cache (struct sym_cache **symcache_p)
  int
  look_up_one_symbol (const char *name, CORE_ADDR *addrp, int may_ask_gdb)
  {
+  client_state &cs = get_client_state ();
    char *p, *q;
    int len;
    struct sym_cache *sym;
@@ -1456,14 +1459,14 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
      return 0;

    /* Send the request.  */
-  strcpy (own_buf, "qSymbol:");
-  bin2hex ((const gdb_byte *) name, own_buf + strlen ("qSymbol:"),
+  strcpy (cs.own_buf, "qSymbol:");
+  bin2hex ((const gdb_byte *) name, cs.own_buf + strlen ("qSymbol:"),
  	  strlen (name));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (cs.own_buf) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (cs.own_buf);
    if (len < 0)
      return -1;

@@ -1474,45 +1477,45 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
       while it figures out the address of the symbol.  */
    while (1)
      {
-      if (own_buf[0] == 'm')
+      if (cs.own_buf[0] == 'm')
  	{
  	  CORE_ADDR mem_addr;
  	  unsigned char *mem_buf;
  	  unsigned int mem_len;

-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
+	  decode_m_packet (&cs.own_buf[1], &mem_addr, &mem_len);
  	  mem_buf = (unsigned char *) xmalloc (mem_len);
  	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	    bin2hex (mem_buf, cs.own_buf, mem_len);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  free (mem_buf);
-	  if (putpkt (own_buf) < 0)
+	  if (putpkt (cs.own_buf) < 0)
  	    return -1;
  	}
-      else if (own_buf[0] == 'v')
+      else if (cs.own_buf[0] == 'v')
  	{
  	  int new_len = -1;
-	  handle_v_requests (own_buf, len, &new_len);
+	  handle_v_requests (cs.own_buf, len, &new_len);
  	  if (new_len != -1)
-	    putpkt_binary (own_buf, new_len);
+	    putpkt_binary (cs.own_buf, new_len);
  	  else
-	    putpkt (own_buf);
+	    putpkt (cs.own_buf);
  	}
        else
  	break;
-      len = getpkt (own_buf);
+      len = getpkt (cs.own_buf);
        if (len < 0)
  	return -1;
      }

-  if (!startswith (own_buf, "qSymbol:"))
+  if (!startswith (cs.own_buf, "qSymbol:"))
      {
-      warning ("Malformed response to qSymbol, ignoring: %s\n", own_buf);
+      warning ("Malformed response to qSymbol, ignoring: %s\n", 
cs.own_buf);
        return -1;
      }

-  p = own_buf + strlen ("qSymbol:");
+  p = cs.own_buf + strlen ("qSymbol:");
    q = p;
    while (*q && *q != ':')
      q++;
@@ -1548,17 +1551,18 @@ look_up_one_symbol (const char *name, CORE_ADDR 
*addrp, int may_ask_gdb)
  int
  relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
  {
+  client_state &cs = get_client_state ();
    int len;
    ULONGEST written = 0;

    /* Send the request.  */
-  sprintf (own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
+  sprintf (cs.own_buf, "qRelocInsn:%s;%s", paddress (oldloc),
  	   paddress (*to));
-  if (putpkt (own_buf) < 0)
+  if (putpkt (cs.own_buf) < 0)
      return -1;

    /* FIXME:  Eventually add buffer overflow checking (to getpkt?)  */
-  len = getpkt (own_buf);
+  len = getpkt (cs.own_buf);
    if (len < 0)
      return -1;

@@ -1566,61 +1570,61 @@ relocate_instruction (CORE_ADDR *to, CORE_ADDR 
oldloc)
       wait for the qRelocInsn "response".  That requires re-entering
       the main loop.  For now, this is an adequate approximation; allow
       GDB to access memory.  */
-  while (own_buf[0] == 'm' || own_buf[0] == 'M' || own_buf[0] == 'X')
+  while (cs.own_buf[0] == 'm' || cs.own_buf[0] == 'M' || cs.own_buf[0] 
== 'X')
      {
        CORE_ADDR mem_addr;
        unsigned char *mem_buf = NULL;
        unsigned int mem_len;

-      if (own_buf[0] == 'm')
+      if (cs.own_buf[0] == 'm')
  	{
-	  decode_m_packet (&own_buf[1], &mem_addr, &mem_len);
+	  decode_m_packet (&cs.own_buf[1], &mem_addr, &mem_len);
  	  mem_buf = (unsigned char *) xmalloc (mem_len);
  	  if (read_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    bin2hex (mem_buf, own_buf, mem_len);
+	    bin2hex (mem_buf, cs.own_buf, mem_len);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	}
-      else if (own_buf[0] == 'X')
+      else if (cs.own_buf[0] == 'X')
  	{
-	  if (decode_X_packet (&own_buf[1], len - 1, &mem_addr,
+	  if (decode_X_packet (&cs.own_buf[1], len - 1, &mem_addr,
  			       &mem_len, &mem_buf) < 0
  	      || write_inferior_memory (mem_addr, mem_buf, mem_len) != 0)
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  else
-	    write_ok (own_buf);
+	    write_ok (cs.own_buf);
  	}
        else
  	{
-	  decode_M_packet (&own_buf[1], &mem_addr, &mem_len, &mem_buf);
+	  decode_M_packet (&cs.own_buf[1], &mem_addr, &mem_len, &mem_buf);
  	  if (write_inferior_memory (mem_addr, mem_buf, mem_len) == 0)
-	    write_ok (own_buf);
+	    write_ok (cs.own_buf);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	}
        free (mem_buf);
-      if (putpkt (own_buf) < 0)
+      if (putpkt (cs.own_buf) < 0)
  	return -1;
-      len = getpkt (own_buf);
+      len = getpkt (cs.own_buf);
        if (len < 0)
  	return -1;
      }

-  if (own_buf[0] == 'E')
+  if (cs.own_buf[0] == 'E')
      {
        warning ("An error occurred while relocating an instruction: %s\n",
-	       own_buf);
+	       cs.own_buf);
        return -1;
      }

-  if (!startswith (own_buf, "qRelocInsn:"))
+  if (!startswith (cs.own_buf, "qRelocInsn:"))
      {
        warning ("Malformed response to qRelocInsn, ignoring: %s\n",
-	       own_buf);
+	       cs.own_buf);
        return -1;
      }

-  unpack_varlen_hex (own_buf + strlen ("qRelocInsn:"), &written);
+  unpack_varlen_hex (cs.own_buf + strlen ("qRelocInsn:"), &written);

    *to += written;
    return 0;
diff --git a/gdb/gdbserver/remote-utils.h b/gdb/gdbserver/remote-utils.h
index c64807f406..a28c5ae035 100644
--- a/gdb/gdbserver/remote-utils.h
+++ b/gdb/gdbserver/remote-utils.h
@@ -19,10 +19,6 @@
  #ifndef REMOTE_UTILS_H
  #define REMOTE_UTILS_H

-extern int remote_debug;
-extern int noack_mode;
-extern int transport_is_reliable;
-
  int gdb_connected (void);

  #define STDIO_CONNECTION_NAME "stdio"
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index 5027df5e10..fcdd7725f5 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -72,17 +72,6 @@ static gdb_environ our_environ;

  int startup_with_shell = 1;

-/* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
-   `vCont'.  Note the multi-process extensions made `vCont' a
-   requirement, so `Hc pPID.TID' is pretty much undefined.  So
-   CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
-   resuming all threads of the process (again, `Hc' isn't used for
-   multi-process), or a specific thread ptid_t.  */
-ptid_t cont_thread;
-
-/* The thread set with an `Hg' packet.  */
-ptid_t general_thread;
-
  int server_waiting;

  static int extended_protocol;
@@ -92,27 +81,10 @@ static int exit_requested;
  /* --once: Exit after the first connection has closed.  */
  int run_once;

-int multi_process;
-int report_fork_events;
-int report_vfork_events;
-int report_exec_events;
-int report_thread_events;
-
  /* Whether to report TARGET_WAITKING_NO_RESUMED events.  */
  static int report_no_resumed;

  int non_stop;
-int swbreak_feature;
-int hwbreak_feature;
-
-/* True if the "vContSupported" feature is active.  In that case, GDB
-   wants us to report whether single step is supported in the reply to
-   "vCont?" packet.  */
-static int vCont_supported;
-
-/* Whether we should attempt to disable the operating system's address
-   space randomization feature before starting an inferior.  */
-int disable_randomization = 1;

  static struct {
    /* Set the PROGRAM_PATH.  Here we adjust the path of the provided
@@ -146,10 +118,6 @@ private:
  static std::vector<char *> program_args;
  static std::string wrapper_argv;

-int pass_signals[GDB_SIGNAL_LAST];
-int program_signals[GDB_SIGNAL_LAST];
-int program_signals_p;
-
  /* The PID of the originally created or attached inferior.  Used to
     send signals to the process when GDB sends us an asynchronous interrupt
     (user hitting Control-C in the client), and to wait for the child 
to exit
@@ -165,11 +133,6 @@ int disable_packet_Tthread;
  int disable_packet_qC;
  int disable_packet_qfThreadInfo;

-/* Last status reported to GDB.  */
-struct target_waitstatus last_status;
-ptid_t last_ptid;
-
-char *own_buf;
  static unsigned char *mem_buf;

  /* A sub-class of 'struct notif_event' for stop, holding information
@@ -193,6 +156,18 @@ static struct btrace_config current_btrace_conf;

  DEFINE_QUEUE_P (notif_event_p);

+/* The client remote protocol state. */
+
+static client_state g_client_state;
+
+client_state &
+get_client_state ()
+{
+  client_state &cs = g_client_state;
+  return cs;
+}
+
+
  /* Put a stop reply to the stop reply queue.  */

  static void
@@ -316,6 +291,7 @@ get_environ ()
  static int
  attach_inferior (int pid)
  {
+  client_state &cs = get_client_state ();
    /* myattach should return -1 if attaching is unsupported,
       0 if it succeeded, and call error() otherwise.  */

@@ -332,23 +308,22 @@ attach_inferior (int pid)

    if (!non_stop)
      {
-      last_ptid = mywait (pid_to_ptid (pid), &last_status, 0, 0);
+      cs.last_ptid = mywait (pid_to_ptid (pid), &cs.last_status, 0, 0);

        /* GDB knows to ignore the first SIGSTOP after attaching to a 
running
  	 process using the "attach" command, but this is different; it's
  	 just using "target remote".  Pretend it's just starting up.  */
-      if (last_status.kind == TARGET_WAITKIND_STOPPED
-	  && last_status.value.sig == GDB_SIGNAL_STOP)
-	last_status.value.sig = GDB_SIGNAL_TRAP;
+      if (cs.last_status.kind == TARGET_WAITKIND_STOPPED
+	  && cs.last_status.value.sig == GDB_SIGNAL_STOP)
+	cs.last_status.value.sig = GDB_SIGNAL_TRAP;

        current_thread->last_resume_kind = resume_stop;
-      current_thread->last_status = last_status;
+      current_thread->last_status = cs.last_status;
      }

    return 0;
  }

-extern int remote_debug;

  /* Decode a qXfer read request.  Return 0 if everything looks OK,
     or -1 otherwise.  */
@@ -456,6 +431,7 @@ handle_btrace_disable (struct thread_info *thread)
  static int
  handle_btrace_general_set (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    struct thread_info *thread;
    char *op;

@@ -464,14 +440,14 @@ handle_btrace_general_set (char *own_buf)

    op = own_buf + strlen ("Qbtrace:");

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs.general_thread, null_ptid)
+      || ptid_equal (cs.general_thread, minus_one_ptid))
      {
        strcpy (own_buf, "E.Must select a single thread.");
        return -1;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs.general_thread);
    if (thread == NULL)
      {
        strcpy (own_buf, "E.No such thread.");
@@ -505,6 +481,7 @@ handle_btrace_general_set (char *own_buf)
  static int
  handle_btrace_conf_general_set (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    struct thread_info *thread;
    char *op;

@@ -513,14 +490,14 @@ handle_btrace_conf_general_set (char *own_buf)

    op = own_buf + strlen ("Qbtrace-conf:");

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs.general_thread, null_ptid)
+      || ptid_equal (cs.general_thread, minus_one_ptid))
      {
        strcpy (own_buf, "E.Must select a single thread.");
        return -1;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs.general_thread);
    if (thread == NULL)
      {
        strcpy (own_buf, "E.No such thread.");
@@ -572,6 +549,7 @@ handle_btrace_conf_general_set (char *own_buf)
  static void
  handle_general_set (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    if (startswith (own_buf, "QPassSignals:"))
      {
        int numsigs = (int) GDB_SIGNAL_LAST, i;
@@ -583,7 +561,7 @@ handle_general_set (char *own_buf)
  	{
  	  if (i == cursig)
  	    {
-	      pass_signals[i] = 1;
+	      cs.pass_signals[i] = 1;
  	      if (*p == '\0')
  		/* Keep looping, to clear the remaining signals.  */
  		cursig = -1;
@@ -591,7 +569,7 @@ handle_general_set (char *own_buf)
  		p = decode_address_to_semicolon (&cursig, p);
  	    }
  	  else
-	    pass_signals[i] = 0;
+	    cs.pass_signals[i] = 0;
  	}
        strcpy (own_buf, "OK");
        return;
@@ -603,14 +581,14 @@ handle_general_set (char *own_buf)
        const char *p = own_buf + strlen ("QProgramSignals:");
        CORE_ADDR cursig;

-      program_signals_p = 1;
+      cs.program_signals_p = 1;

        p = decode_address_to_semicolon (&cursig, p);
        for (i = 0; i < numsigs; i++)
  	{
  	  if (i == cursig)
  	    {
-	      program_signals[i] = 1;
+	      cs.program_signals[i] = 1;
  	      if (*p == '\0')
  		/* Keep looping, to clear the remaining signals.  */
  		cursig = -1;
@@ -618,7 +596,7 @@ handle_general_set (char *own_buf)
  		p = decode_address_to_semicolon (&cursig, p);
  	    }
  	  else
-	    program_signals[i] = 0;
+	    cs.program_signals[i] = 0;
  	}
        strcpy (own_buf, "OK");
        return;
@@ -688,7 +666,7 @@ handle_general_set (char *own_buf)
        std::string final_var = hex2str (p);
        std::string var_name, var_value;

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf (_("[QEnvironmentHexEncoded received '%s']\n"), p);
  	  debug_printf (_("[Environment variable to be set: '%s']\n"),
@@ -719,7 +697,7 @@ handle_general_set (char *own_buf)
        const char *p = own_buf + sizeof ("QEnvironmentUnset:") - 1;
        std::string varname = hex2str (p);

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf (_("[QEnvironmentUnset received '%s']\n"), p);
  	  debug_printf (_("[Environment variable to be unset: '%s']\n"),
@@ -735,13 +713,13 @@ handle_general_set (char *own_buf)

    if (strcmp (own_buf, "QStartNoAckMode") == 0)
      {
-      if (remote_debug)
+      if (cs.remote_debug)
  	{
  	  debug_printf ("[noack mode enabled]\n");
  	  debug_flush ();
  	}

-      noack_mode = 1;
+      cs.noack_mode = 1;
        write_ok (own_buf);
        return;
      }
@@ -776,7 +754,7 @@ handle_general_set (char *own_buf)

        non_stop = req;

-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf ("[%s mode enabled]\n", req_str);

        write_ok (own_buf);
@@ -789,11 +767,11 @@ handle_general_set (char *own_buf)
        ULONGEST setting;

        unpack_varlen_hex (packet, &setting);
-      disable_randomization = setting;
+      cs.disable_randomization = setting;

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
-	  debug_printf (disable_randomization
+	  debug_printf (cs.disable_randomization
  			? "[address space randomization disabled]\n"
  			: "[address space randomization enabled]\n");
  	}
@@ -824,7 +802,7 @@ handle_general_set (char *own_buf)

        /* Update the flag.  */
        use_agent = req;
-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf ("[%s agent]\n", req ? "Enable" : "Disable");
        write_ok (own_buf);
        return;
@@ -853,11 +831,11 @@ handle_general_set (char *own_buf)
  	  return;
  	}

-      report_thread_events = (req == TRIBOOL_TRUE);
+      cs.report_thread_events = (req == TRIBOOL_TRUE);

-      if (remote_debug)
+      if (cs.remote_debug)
  	{
-	  const char *req_str = report_thread_events ? "enabled" : "disabled";
+	  const char *req_str = cs.report_thread_events ? "enabled" : "disabled";

  	  debug_printf ("[thread events are now %s]\n", req_str);
  	}
@@ -883,7 +861,7 @@ handle_general_set (char *own_buf)
  	  return;
  	}

-      if (remote_debug)
+      if (cs.remote_debug)
  	debug_printf (_("[Inferior will %s started with shell]"),
  		      startup_with_shell ? "be" : "not be");

@@ -901,7 +879,7 @@ handle_general_set (char *own_buf)

  	  set_inferior_cwd (path.c_str ());

-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    debug_printf (_("[Set the inferior's current directory to %s]\n"),
  			  path.c_str ());
  	}
@@ -911,7 +889,7 @@ handle_general_set (char *own_buf)
  	     previously set cwd for the inferior.  */
  	  set_inferior_cwd (NULL);

-	  if (remote_debug)
+	  if (cs.remote_debug)
  	    debug_printf (_("\
  [Unset the inferior's current directory; will use gdbserver's cwd]\n"));
  	}
@@ -998,14 +976,15 @@ monitor_show_help (void)
  static int
  gdb_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
  {
+  client_state &cs = get_client_state ();
    int res;

-  if (current_traceframe >= 0)
+  if (cs.current_traceframe >= 0)
      {
        ULONGEST nbytes;
        ULONGEST length = len;

-      if (traceframe_read_mem (current_traceframe,
+      if (traceframe_read_mem (cs.current_traceframe,
  			       memaddr, myaddr, len, &nbytes))
  	return -1;
        /* Data read from trace buffer, we're done.  */
@@ -1038,7 +1017,8 @@ gdb_read_memory (CORE_ADDR memaddr, unsigned char 
*myaddr, int len)
  static int
  gdb_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len)
  {
-  if (current_traceframe >= 0)
+  client_state &cs = get_client_state ();
+  if (cs.current_traceframe >= 0)
      return EIO;
    else
      {
@@ -1213,11 +1193,12 @@ handle_search_memory (char *own_buf, int packet_len)
  static void
  handle_detach (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    require_running_or_return (own_buf);

    int pid;

-  if (multi_process)
+  if (cs.multi_process)
      {
        /* skip 'D;' */
        pid = strtol (&own_buf[2], NULL, 16);
@@ -1282,9 +1263,9 @@ handle_detach (char *own_buf)
  	  /* There is still at least one inferior remaining or
  	     we are in extended mode, so don't terminate gdbserver,
  	     and instead treat this like a normal program exit.  */
-	  last_status.kind = TARGET_WAITKIND_EXITED;
-	  last_status.value.integer = 0;
-	  last_ptid = pid_to_ptid (pid);
+	  cs.last_status.kind = TARGET_WAITKIND_EXITED;
+	  cs.last_status.value.integer = 0;
+	  cs.last_ptid = pid_to_ptid (pid);

  	  current_thread = NULL;
  	}
@@ -1370,6 +1351,7 @@ parse_debug_format_options (const char *arg, int 
is_monitor)
  static void
  handle_monitor_command (char *mon, char *own_buf)
  {
+  client_state &cs = get_client_state ();
    if (strcmp (mon, "set debug 1") == 0)
      {
        debug_threads = 1;
@@ -1392,12 +1374,12 @@ handle_monitor_command (char *mon, char *own_buf)
      }
    else if (strcmp (mon, "set remote-debug 1") == 0)
      {
-      remote_debug = 1;
+      cs.remote_debug = 1;
        monitor_output ("Protocol debug output enabled.\n");
      }
    else if (strcmp (mon, "set remote-debug 0") == 0)
      {
-      remote_debug = 0;
+      cs.remote_debug = 0;
        monitor_output ("Protocol debug output disabled.\n");
      }
    else if (startswith (mon, "set debug-format "))
@@ -1646,15 +1628,17 @@ handle_qxfer_statictrace (const char *annex,
  			  gdb_byte *readbuf, const gdb_byte *writebuf,
  			  ULONGEST offset, LONGEST len)
  {
+  client_state &cs = get_client_state ();
    ULONGEST nbytes;

    if (writebuf != NULL)
      return -2;

-  if (annex[0] != '\0' || current_thread == NULL || current_traceframe 
== -1)
+  if (annex[0] != '\0' || current_thread == NULL
+      || cs.current_traceframe == -1)
      return -1;

-  if (traceframe_read_sdata (current_traceframe, offset,
+  if (traceframe_read_sdata (cs.current_traceframe, offset,
  			     readbuf, len, &nbytes))
      return -1;
    return nbytes;
@@ -1770,13 +1754,14 @@ handle_qxfer_traceframe_info (const char *annex,
  			      gdb_byte *readbuf, const gdb_byte *writebuf,
  			      ULONGEST offset, LONGEST len)
  {
+  client_state &cs = get_client_state ();
    static char *result = 0;
    static unsigned int result_length = 0;

    if (writebuf != NULL)
      return -2;

-  if (!target_running () || annex[0] != '\0' || current_traceframe == -1)
+  if (!target_running () || annex[0] != '\0' || cs.current_traceframe 
== -1)
      return -1;

    if (offset == 0)
@@ -1790,7 +1775,7 @@ handle_qxfer_traceframe_info (const char *annex,

        buffer_init (&buffer);

-      traceframe_read_info (current_traceframe, &buffer);
+      traceframe_read_info (cs.current_traceframe, &buffer);

        result = buffer_finish (&buffer);
        result_length = strlen (result);
@@ -1835,6 +1820,7 @@ handle_qxfer_btrace (const char *annex,
  		     gdb_byte *readbuf, const gdb_byte *writebuf,
  		     ULONGEST offset, LONGEST len)
  {
+  client_state &cs = get_client_state ();
    static struct buffer cache;
    struct thread_info *thread;
    enum btrace_read_type type;
@@ -1843,23 +1829,23 @@ handle_qxfer_btrace (const char *annex,
    if (writebuf != NULL)
      return -2;

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs.general_thread, null_ptid)
+      || ptid_equal (cs.general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (cs.own_buf, "E.Must select a single thread.");
        return -3;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs.general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (cs.own_buf, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (cs.own_buf, "E.Btrace not enabled.");
        return -3;
      }

@@ -1871,7 +1857,7 @@ handle_qxfer_btrace (const char *annex,
      type = BTRACE_READ_DELTA;
    else
      {
-      strcpy (own_buf, "E.Bad annex.");
+      strcpy (cs.own_buf, "E.Bad annex.");
        return -3;
      }

@@ -1883,11 +1869,11 @@ handle_qxfer_btrace (const char *annex,
  	{
  	  result = target_read_btrace (thread->btrace, &cache, type);
  	  if (result != 0)
-	    memcpy (own_buf, cache.buffer, cache.used_size);
+	    memcpy (cs.own_buf, cache.buffer, cache.used_size);
  	}
        CATCH (exception, RETURN_MASK_ERROR)
  	{
-	  sprintf (own_buf, "E.%s", exception.message);
+	  sprintf (cs.own_buf, "E.%s", exception.message);
  	  result = -1;
  	}
        END_CATCH
@@ -1916,6 +1902,7 @@ handle_qxfer_btrace_conf (const char *annex,
  			  gdb_byte *readbuf, const gdb_byte *writebuf,
  			  ULONGEST offset, LONGEST len)
  {
+  client_state &cs = get_client_state ();
    static struct buffer cache;
    struct thread_info *thread;
    int result;
@@ -1926,23 +1913,23 @@ handle_qxfer_btrace_conf (const char *annex,
    if (annex[0] != '\0')
      return -1;

-  if (ptid_equal (general_thread, null_ptid)
-      || ptid_equal (general_thread, minus_one_ptid))
+  if (ptid_equal (cs.general_thread, null_ptid)
+      || ptid_equal (cs.general_thread, minus_one_ptid))
      {
-      strcpy (own_buf, "E.Must select a single thread.");
+      strcpy (cs.own_buf, "E.Must select a single thread.");
        return -3;
      }

-  thread = find_thread_ptid (general_thread);
+  thread = find_thread_ptid (cs.general_thread);
    if (thread == NULL)
      {
-      strcpy (own_buf, "E.No such thread.");
+      strcpy (cs.own_buf, "E.No such thread.");
        return -3;
      }

    if (thread->btrace == NULL)
      {
-      strcpy (own_buf, "E.Btrace not enabled.");
+      strcpy (cs.own_buf, "E.Btrace not enabled.");
        return -3;
      }

@@ -1954,11 +1941,11 @@ handle_qxfer_btrace_conf (const char *annex,
  	{
  	  result = target_read_btrace_conf (thread->btrace, &cache);
  	  if (result != 0)
-	    memcpy (own_buf, cache.buffer, cache.used_size);
+	    memcpy (cs.own_buf, cache.buffer, cache.used_size);
  	}
        CATCH (exception, RETURN_MASK_ERROR)
  	{
-	  sprintf (own_buf, "E.%s", exception.message);
+	  sprintf (cs.own_buf, "E.%s", exception.message);
  	  result = -1;
  	}
        END_CATCH
@@ -2158,6 +2145,7 @@ supported_btrace_packets (char *buf)
  static void
  handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
  {
+  client_state &cs = get_client_state ();
    static std::list<thread_info *>::const_iterator thread_iter;

    /* Reply the current thread id.  */
@@ -2166,8 +2154,8 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
        ptid_t ptid;
        require_running_or_return (own_buf);

-      if (general_thread != null_ptid && general_thread != minus_one_ptid)
-	ptid = general_thread;
+      if (cs.general_thread != null_ptid && cs.general_thread != 
minus_one_ptid)
+	ptid = cs.general_thread;
        else
  	{
  	  thread_iter = all_threads.begin ();
@@ -2192,7 +2180,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
        if (current_thread == NULL)
  	{
  	  current_thread
-	    = find_any_thread_of_pid (ptid_get_pid (general_thread));
+	    = find_any_thread_of_pid (ptid_get_pid (cs.general_thread));

  	  /* Just in case, if we didn't find a thread, then bail out
  	     instead of crashing.  */
@@ -2312,7 +2300,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  		  /* GDB supports and wants multi-process support if
  		     possible.  */
  		  if (target_supports_multi_process ())
-		    multi_process = 1;
+		    cs.multi_process = 1;
  		}
  	      else if (strcmp (p, "qRelocInsn+") == 0)
  		{
@@ -2325,35 +2313,35 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  		     by a software breakpoint and for us to handle PC
  		     adjustment if necessary on this target.  */
  		  if (target_supports_stopped_by_sw_breakpoint ())
-		    swbreak_feature = 1;
+		    cs.swbreak_feature = 1;
  		}
  	      else if (strcmp (p, "hwbreak+") == 0)
  		{
  		  /* GDB wants us to report whether a trap is caused
  		     by a hardware breakpoint.  */
  		  if (target_supports_stopped_by_hw_breakpoint ())
-		    hwbreak_feature = 1;
+		    cs.hwbreak_feature = 1;
  		}
  	      else if (strcmp (p, "fork-events+") == 0)
  		{
  		  /* GDB supports and wants fork events if possible.  */
  		  if (target_supports_fork_events ())
-		    report_fork_events = 1;
+		    cs.report_fork_events = 1;
  		}
  	      else if (strcmp (p, "vfork-events+") == 0)
  		{
  		  /* GDB supports and wants vfork events if possible.  */
  		  if (target_supports_vfork_events ())
-		    report_vfork_events = 1;
+		    cs.report_vfork_events = 1;
  		}
  	      else if (strcmp (p, "exec-events+") == 0)
  		{
  		  /* GDB supports and wants exec events if possible.  */
  		  if (target_supports_exec_events ())
-		    report_exec_events = 1;
+		    cs.report_exec_events = 1;
  		}
  	      else if (strcmp (p, "vContSupported+") == 0)
-		vCont_supported = 1;
+		cs.vCont_supported = 1;
  	      else if (strcmp (p, "QThreadEvents+") == 0)
  		;
  	      else if (strcmp (p, "no-resumed+") == 0)
@@ -2418,7 +2406,7 @@ handle_query (char *own_buf, int packet_len, int 
*new_packet_len_p)
  	 qXfer:feature:read at all, we will never be re-queried.  */
        strcat (own_buf, ";qXfer:features:read+");

-      if (transport_is_reliable)
+      if (cs.transport_is_reliable)
  	strcat (own_buf, ";QStartNoAckMode+");

        if (the_target->qxfer_osdata != NULL)
@@ -2729,13 +2717,14 @@ static int
  handle_pending_status (const struct thread_resume *resumption,
  		       struct thread_info *thread)
  {
+  client_state &cs = get_client_state ();
    if (thread->status_pending_p)
      {
        thread->status_pending_p = 0;

-      last_status = thread->last_status;
-      last_ptid = thread->id;
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      cs.last_status = thread->last_status;
+      cs.last_ptid = thread->id;
+      prepare_resume_reply (cs.own_buf, cs.last_ptid, &cs.last_status);
        return 1;
      }
    return 0;
@@ -2855,6 +2844,7 @@ err:
  static void
  resume (struct thread_resume *actions, size_t num_actions)
  {
+  client_state &cs = get_client_state ();
    if (!non_stop)
      {
        /* Check if among the threads that GDB wants actioned, there's
@@ -2877,37 +2867,37 @@ resume (struct thread_resume *actions, size_t 
num_actions)
    (*the_target->resume) (actions, num_actions);

    if (non_stop)
-    write_ok (own_buf);
+    write_ok (cs.own_buf);
    else
      {
-      last_ptid = mywait (minus_one_ptid, &last_status, 0, 1);
+      cs.last_ptid = mywait (minus_one_ptid, &cs.last_status, 0, 1);

-      if (last_status.kind == TARGET_WAITKIND_NO_RESUMED
+      if (cs.last_status.kind == TARGET_WAITKIND_NO_RESUMED
  	  && !report_no_resumed)
  	{
  	  /* The client does not support this stop reply.  At least
  	     return error.  */
-	  sprintf (own_buf, "E.No unwaited-for children left.");
+	  sprintf (cs.own_buf, "E.No unwaited-for children left.");
  	  disable_async_io ();
  	  return;
  	}

-      if (last_status.kind != TARGET_WAITKIND_EXITED
-          && last_status.kind != TARGET_WAITKIND_SIGNALLED
-	  && last_status.kind != TARGET_WAITKIND_NO_RESUMED)
-	current_thread->last_status = last_status;
+      if (cs.last_status.kind != TARGET_WAITKIND_EXITED
+          && cs.last_status.kind != TARGET_WAITKIND_SIGNALLED
+	  && cs.last_status.kind != TARGET_WAITKIND_NO_RESUMED)
+	current_thread->last_status = cs.last_status;

        /* From the client's perspective, all-stop mode always stops all
  	 threads implicitly (and the target backend has already done
  	 so by now).  Tag all threads as "want-stopped", so we don't
  	 resume them implicitly without the client telling us to.  */
        gdb_wants_all_threads_stopped ();
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (cs.own_buf, cs.last_ptid, &cs.last_status);
        disable_async_io ();

-      if (last_status.kind == TARGET_WAITKIND_EXITED
-          || last_status.kind == TARGET_WAITKIND_SIGNALLED)
-        target_mourn_inferior (last_ptid);
+      if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+          || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED)
+        target_mourn_inferior (cs.last_ptid);
      }
  }

@@ -2915,6 +2905,7 @@ resume (struct thread_resume *actions, size_t 
num_actions)
  static int
  handle_v_attach (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    int pid;

    pid = strtol (own_buf + 8, NULL, 16);
@@ -2934,7 +2925,7 @@ handle_v_attach (char *own_buf)
  	  write_ok (own_buf);
  	}
        else
-	prepare_resume_reply (own_buf, last_ptid, &last_status);
+	prepare_resume_reply (own_buf, cs.last_ptid, &cs.last_status);

        return 1;
      }
@@ -2949,6 +2940,7 @@ handle_v_attach (char *own_buf)
  static int
  handle_v_run (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    char *p, *next_p;
    std::vector<char *> new_argv;
    char *new_program_name = NULL;
@@ -3055,15 +3047,15 @@ handle_v_run (char *own_buf)

    create_inferior (program_path.get (), program_args);

-  if (last_status.kind == TARGET_WAITKIND_STOPPED)
+  if (cs.last_status.kind == TARGET_WAITKIND_STOPPED)
      {
-      prepare_resume_reply (own_buf, last_ptid, &last_status);
+      prepare_resume_reply (own_buf, cs.last_ptid, &cs.last_status);

        /* In non-stop, sending a resume reply doesn't set the general
  	 thread, but GDB assumes a vRun sets it (this is so GDB can
  	 query which is the main thread of the new inferior.  */
        if (non_stop)
-	general_thread = last_ptid;
+	cs.general_thread = cs.last_ptid;

        return 1;
      }
@@ -3078,18 +3070,19 @@ handle_v_run (char *own_buf)
  static int
  handle_v_kill (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    int pid;
    char *p = &own_buf[6];
-  if (multi_process)
+  if (cs.multi_process)
      pid = strtol (p, NULL, 16);
    else
      pid = signal_pid;
    if (pid != 0 && kill_inferior (pid) == 0)
      {
-      last_status.kind = TARGET_WAITKIND_SIGNALLED;
-      last_status.value.sig = GDB_SIGNAL_KILL;
-      last_ptid = pid_to_ptid (pid);
-      discard_queued_stop_replies (last_ptid);
+      cs.last_status.kind = TARGET_WAITKIND_SIGNALLED;
+      cs.last_status.value.sig = GDB_SIGNAL_KILL;
+      cs.last_ptid = pid_to_ptid (pid);
+      discard_queued_stop_replies (cs.last_ptid);
        write_ok (own_buf);
        return 1;
      }
@@ -3104,6 +3097,7 @@ handle_v_kill (char *own_buf)
  void
  handle_v_requests (char *own_buf, int packet_len, int *new_packet_len)
  {
+  client_state &cs = get_client_state ();
    if (!disable_packet_vCont)
      {
        if (strcmp (own_buf, "vCtrlC") == 0)
@@ -3125,7 +3119,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

  	  if (target_supports_hardware_single_step ()
  	      || target_supports_software_single_step ()
-	      || !vCont_supported)
+	      || !cs.vCont_supported)
  	    {
  	      /* If target supports single step either by hardware or by
  		 software, add actions s and S to the list of supported
@@ -3151,7 +3145,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

    if (startswith (own_buf, "vAttach;"))
      {
-      if ((!extended_protocol || !multi_process) && target_running ())
+      if ((!extended_protocol || !cs.multi_process) && target_running ())
  	{
  	  fprintf (stderr, "Already debugging a process\n");
  	  write_enn (own_buf);
@@ -3163,7 +3157,7 @@ handle_v_requests (char *own_buf, int packet_len, 
int *new_packet_len)

    if (startswith (own_buf, "vRun;"))
      {
-      if ((!extended_protocol || !multi_process) && target_running ())
+      if ((!extended_protocol || !cs.multi_process) && target_running ())
  	{
  	  fprintf (stderr, "Already debugging a process\n");
  	  write_enn (own_buf);
@@ -3200,12 +3194,13 @@ handle_v_requests (char *own_buf, int 
packet_len, int *new_packet_len)
  static void
  myresume (char *own_buf, int step, int sig)
  {
+  client_state &cs = get_client_state ();
    struct thread_resume resume_info[2];
    int n = 0;
    int valid_cont_thread;

-  valid_cont_thread = (!ptid_equal (cont_thread, null_ptid)
-			 && !ptid_equal (cont_thread, minus_one_ptid));
+  valid_cont_thread = (!ptid_equal (cs.cont_thread, null_ptid)
+			 && !ptid_equal (cs.cont_thread, minus_one_ptid));

    if (step || sig || valid_cont_thread)
      {
@@ -3320,6 +3315,8 @@ set_pending_status_callback (thread_info *thread)
  static void
  handle_status (char *own_buf)
  {
+  client_state &cs = get_client_state ();
+
    /* GDB is connected, don't forward events to the target anymore.  */
    for_each_process ([] (process_info *process) {
      process->gdb_detached = 0;
@@ -3336,7 +3333,7 @@ handle_status (char *own_buf)
        /* The first is sent immediatly.  OK is sent if there is no
  	 stopped thread, which is the same handling of the vStopped
  	 packet (by design).  */
-      notif_write_event (&notif_stop, own_buf);
+      notif_write_event (&notif_stop, cs.own_buf);
      }
    else
      {
@@ -3356,10 +3353,10 @@ handle_status (char *own_buf)

        /* Prefer the last thread that reported an event to GDB (even if
  	 that was a GDB_SIGNAL_TRAP).  */
-      if (last_status.kind != TARGET_WAITKIND_IGNORE
-	  && last_status.kind != TARGET_WAITKIND_EXITED
-	  && last_status.kind != TARGET_WAITKIND_SIGNALLED)
-	thread = find_thread_ptid (last_ptid);
+      if (cs.last_status.kind != TARGET_WAITKIND_IGNORE
+	  && cs.last_status.kind != TARGET_WAITKIND_EXITED
+	  && cs.last_status.kind != TARGET_WAITKIND_SIGNALLED)
+	thread = find_thread_ptid (cs.last_ptid);

        /* If the last event thread is not found for some reason, look
  	 for some other thread that might have an event to report.  */
@@ -3384,7 +3381,7 @@ handle_status (char *own_buf)

  	  /* GDB assumes the current thread is the thread we're
  	     reporting the status for.  */
-	  general_thread = thread->id;
+	  cs.general_thread = thread->id;
  	  set_desired_thread ();

  	  gdb_assert (tp->last_status.kind != TARGET_WAITKIND_IGNORE);
@@ -3577,6 +3574,8 @@ captured_main (int argc, char *argv[])
  #endif

    current_directory = getcwd (NULL, 0);
+  client_state &cs = get_client_state ();
+
    if (current_directory == NULL)
      {
        error (_("Could not find current working directory: %s"),
@@ -3643,7 +3642,7 @@ captured_main (int argc, char *argv[])
  	    }
  	}
        else if (strcmp (*next_arg, "--remote-debug") == 0)
-	remote_debug = 1;
+	cs.remote_debug = 1;
        else if (strcmp (*next_arg, "--disable-packet") == 0)
  	{
  	  gdbserver_show_disableable (stdout);
@@ -3691,9 +3690,9 @@ captured_main (int argc, char *argv[])
  	  break;
  	}
        else if (strcmp (*next_arg, "--disable-randomization") == 0)
-	disable_randomization = 1;
+	cs.disable_randomization = 1;
        else if (strcmp (*next_arg, "--no-disable-randomization") == 0)
-	disable_randomization = 0;
+	cs.disable_randomization = 0;
        else if (strcmp (*next_arg, "--startup-with-shell") == 0)
  	startup_with_shell = true;
        else if (strcmp (*next_arg, "--no-startup-with-shell") == 0)
@@ -3780,7 +3779,6 @@ captured_main (int argc, char *argv[])
      initialize_tracepoint ();
    initialize_notif ();

-  own_buf = (char *) xmalloc (PBUFSIZ + 1);
    mem_buf = (unsigned char *) xmalloc (PBUFSIZ);

    if (selftest)
@@ -3819,9 +3817,9 @@ captured_main (int argc, char *argv[])
      }
    else
      {
-      last_status.kind = TARGET_WAITKIND_EXITED;
-      last_status.value.integer = 0;
-      last_ptid = minus_one_ptid;
+      cs.last_status.kind = TARGET_WAITKIND_EXITED;
+      cs.last_status.value.integer = 0;
+      cs.last_ptid = minus_one_ptid;
      }
    make_cleanup (detach_or_kill_for_exit_cleanup, NULL);

@@ -3830,8 +3828,8 @@ captured_main (int argc, char *argv[])
       shared library event" notice on gdb side.  */
    dlls_changed = 0;

-  if (last_status.kind == TARGET_WAITKIND_EXITED
-      || last_status.kind == TARGET_WAITKIND_SIGNALLED)
+  if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+      || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED)
      was_running = 0;
    else
      was_running = 1;
@@ -3841,18 +3839,17 @@ captured_main (int argc, char *argv[])

    while (1)
      {
-
-      noack_mode = 0;
-      multi_process = 0;
-      report_fork_events = 0;
-      report_vfork_events = 0;
-      report_exec_events = 0;
+      cs.noack_mode = 0;
+      cs.multi_process = 0;
+      cs.report_fork_events = 0;
+      cs.report_vfork_events = 0;
+      cs.report_exec_events = 0;
        /* Be sure we're out of tfind mode.  */
-      current_traceframe = -1;
-      cont_thread = null_ptid;
-      swbreak_feature = 0;
-      hwbreak_feature = 0;
-      vCont_supported = 0;
+      cs.current_traceframe = -1;
+      cs.cont_thread = null_ptid;
+      cs.swbreak_feature = 0;
+      cs.hwbreak_feature = 0;
+      cs.vCont_supported = 0;

        remote_open (port);

@@ -3928,8 +3925,8 @@ captured_main (int argc, char *argv[])

  	  if (response_needed)
  	    {
-	      write_enn (own_buf);
-	      putpkt (own_buf);
+	      write_enn (cs.own_buf);
+	      putpkt (cs.own_buf);
  	    }

  	  if (run_once)
@@ -4024,6 +4021,7 @@ process_point_options (struct gdb_breakpoint *bp, 
const char **packet)
  static int
  process_serial_event (void)
  {
+  client_state &cs = get_client_state ();
    int signal;
    unsigned int len;
    int res;
@@ -4035,7 +4033,7 @@ process_serial_event (void)
    disable_async_io ();

    response_needed = 0;
-  packet_len = getpkt (own_buf);
+  packet_len = getpkt (cs.own_buf);
    if (packet_len <= 0)
      {
        remote_close ();
@@ -4044,31 +4042,31 @@ process_serial_event (void)
      }
    response_needed = 1;

-  char ch = own_buf[0];
+  char ch = cs.own_buf[0];
    switch (ch)
      {
      case 'q':
-      handle_query (own_buf, packet_len, &new_packet_len);
+      handle_query (cs.own_buf, packet_len, &new_packet_len);
        break;
      case 'Q':
-      handle_general_set (own_buf);
+      handle_general_set (cs.own_buf);
        break;
      case 'D':
-      handle_detach (own_buf);
+      handle_detach (cs.own_buf);
        break;
      case '!':
        extended_protocol = 1;
-      write_ok (own_buf);
+      write_ok (cs.own_buf);
        break;
      case '?':
-      handle_status (own_buf);
+      handle_status (cs.own_buf);
        break;
      case 'H':
-      if (own_buf[1] == 'c' || own_buf[1] == 'g' || own_buf[1] == 's')
+      if (cs.own_buf[1] == 'c' || cs.own_buf[1] == 'g' || cs.own_buf[1] 
== 's')
  	{
-	  require_running_or_break (own_buf);
+	  require_running_or_break (cs.own_buf);

-	  ptid_t thread_id = read_ptid (&own_buf[2], NULL);
+	  ptid_t thread_id = read_ptid (&cs.own_buf[2], NULL);

  	  if (thread_id == null_ptid || thread_id == minus_one_ptid)
  	    thread_id = null_ptid;
@@ -4079,7 +4077,7 @@ process_serial_event (void)

  	      if (thread == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (cs.own_buf);
  		  break;
  		}

@@ -4090,52 +4088,52 @@ process_serial_event (void)
  	      /* The ptid represents a lwp/tid.  */
  	      if (find_thread_ptid (thread_id) == NULL)
  		{
-		  write_enn (own_buf);
+		  write_enn (cs.own_buf);
  		  break;
  		}
  	    }

-	  if (own_buf[1] == 'g')
+	  if (cs.own_buf[1] == 'g')
  	    {
  	      if (ptid_equal (thread_id, null_ptid))
  		{
  		  /* GDB is telling us to choose any thread.  Check if
  		     the currently selected thread is still valid. If
  		     it is not, select the first available.  */
-		  thread_info *thread = find_thread_ptid (general_thread);
+		  thread_info *thread = find_thread_ptid (cs.general_thread);
  		  if (thread == NULL)
  		    thread = get_first_thread ();
  		  thread_id = thread->id;
  		}

-	      general_thread = thread_id;
+	      cs.general_thread = thread_id;
  	      set_desired_thread ();
  	      gdb_assert (current_thread != NULL);
  	    }
-	  else if (own_buf[1] == 'c')
-	    cont_thread = thread_id;
+	  else if (cs.own_buf[1] == 'c')
+	    cs.cont_thread = thread_id;

-	  write_ok (own_buf);
+	  write_ok (cs.own_buf);
  	}
        else
  	{
  	  /* Silently ignore it so that gdb can extend the protocol
  	     without compatibility headaches.  */
-	  own_buf[0] = '\0';
+	  cs.own_buf[0] = '\0';
  	}
        break;
      case 'g':
-      require_running_or_break (own_buf);
-      if (current_traceframe >= 0)
+      require_running_or_break (cs.own_buf);
+      if (cs.current_traceframe >= 0)
  	{
  	  struct regcache *regcache
  	    = new_register_cache (current_target_desc ());

-	  if (fetch_traceframe_registers (current_traceframe,
+	  if (fetch_traceframe_registers (cs.current_traceframe,
  					  regcache, -1) == 0)
-	    registers_to_string (regcache, own_buf);
+	    registers_to_string (regcache, cs.own_buf);
  	  else
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  free_register_cache (regcache);
  	}
        else
@@ -4143,85 +4141,85 @@ process_serial_event (void)
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  else
  	    {
  	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_to_string (regcache, own_buf);
+	      registers_to_string (regcache, cs.own_buf);
  	    }
  	}
        break;
      case 'G':
-      require_running_or_break (own_buf);
-      if (current_traceframe >= 0)
-	write_enn (own_buf);
+      require_running_or_break (cs.own_buf);
+      if (cs.current_traceframe >= 0)
+	write_enn (cs.own_buf);
        else
  	{
  	  struct regcache *regcache;

  	  if (!set_desired_thread ())
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	  else
  	    {
  	      regcache = get_thread_regcache (current_thread, 1);
-	      registers_from_string (regcache, &own_buf[1]);
-	      write_ok (own_buf);
+	      registers_from_string (regcache, &cs.own_buf[1]);
+	      write_ok (cs.own_buf);
  	    }
  	}
        break;
      case 'm':
-      require_running_or_break (own_buf);
-      decode_m_packet (&own_buf[1], &mem_addr, &len);
+      require_running_or_break (cs.own_buf);
+      decode_m_packet (&cs.own_buf[1], &mem_addr, &len);
        res = gdb_read_memory (mem_addr, mem_buf, len);
        if (res < 0)
-	write_enn (own_buf);
+	write_enn (cs.own_buf);
        else
-	bin2hex (mem_buf, own_buf, res);
+	bin2hex (mem_buf, cs.own_buf, res);
        break;
      case 'M':
-      require_running_or_break (own_buf);
-      decode_M_packet (&own_buf[1], &mem_addr, &len, &mem_buf);
+      require_running_or_break (cs.own_buf);
+      decode_M_packet (&cs.own_buf[1], &mem_addr, &len, &mem_buf);
        if (gdb_write_memory (mem_addr, mem_buf, len) == 0)
-	write_ok (own_buf);
+	write_ok (cs.own_buf);
        else
-	write_enn (own_buf);
+	write_enn (cs.own_buf);
        break;
      case 'X':
-      require_running_or_break (own_buf);
-      if (decode_X_packet (&own_buf[1], packet_len - 1,
+      require_running_or_break (cs.own_buf);
+      if (decode_X_packet (&cs.own_buf[1], packet_len - 1,
  			   &mem_addr, &len, &mem_buf) < 0
  	  || gdb_write_memory (mem_addr, mem_buf, len) != 0)
-	write_enn (own_buf);
+	write_enn (cs.own_buf);
        else
-	write_ok (own_buf);
+	write_ok (cs.own_buf);
        break;
      case 'C':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (cs.own_buf);
+      hex2bin (cs.own_buf + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (cs.own_buf, 0, signal);
        break;
      case 'S':
-      require_running_or_break (own_buf);
-      hex2bin (own_buf + 1, &sig, 1);
+      require_running_or_break (cs.own_buf);
+      hex2bin (cs.own_buf + 1, &sig, 1);
        if (gdb_signal_to_host_p ((enum gdb_signal) sig))
  	signal = gdb_signal_to_host ((enum gdb_signal) sig);
        else
  	signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (cs.own_buf, 1, signal);
        break;
      case 'c':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs.own_buf);
        signal = 0;
-      myresume (own_buf, 0, signal);
+      myresume (cs.own_buf, 0, signal);
        break;
      case 's':
-      require_running_or_break (own_buf);
+      require_running_or_break (cs.own_buf);
        signal = 0;
-      myresume (own_buf, 1, signal);
+      myresume (cs.own_buf, 1, signal);
        break;
      case 'Z':  /* insert_ ... */
        /* Fallthrough.  */
@@ -4230,10 +4228,10 @@ process_serial_event (void)
  	char *dataptr;
  	ULONGEST addr;
  	int kind;
-	char type = own_buf[1];
+	char type = cs.own_buf[1];
  	int res;
  	const int insert = ch == 'Z';
-	const char *p = &own_buf[3];
+	const char *p = &cs.own_buf[3];

  	p = unpack_varlen_hex (p, &addr);
  	kind = strtol (p + 1, &dataptr, 16);
@@ -4261,12 +4259,12 @@ process_serial_event (void)
  	  res = delete_gdb_breakpoint (type, addr, kind);

  	if (res == 0)
-	  write_ok (own_buf);
+	  write_ok (cs.own_buf);
  	else if (res == 1)
  	  /* Unsupported.  */
-	  own_buf[0] = '\0';
+	  cs.own_buf[0] = '\0';
  	else
-	  write_enn (own_buf);
+	  write_enn (cs.own_buf);
  	break;
        }
      case 'k':
@@ -4284,8 +4282,8 @@ process_serial_event (void)
  	 running.  The traditional protocol will exit instead.  */
        if (extended_protocol)
  	{
-	  last_status.kind = TARGET_WAITKIND_EXITED;
-	  last_status.value.sig = GDB_SIGNAL_KILL;
+	  cs.last_status.kind = TARGET_WAITKIND_EXITED;
+	  cs.last_status.value.sig = GDB_SIGNAL_KILL;
  	  return 0;
  	}
        else
@@ -4293,19 +4291,19 @@ process_serial_event (void)

      case 'T':
        {
-	require_running_or_break (own_buf);
+	require_running_or_break (cs.own_buf);

-	ptid_t thread_id = read_ptid (&own_buf[1], NULL);
+	ptid_t thread_id = read_ptid (&cs.own_buf[1], NULL);
  	if (find_thread_ptid (thread_id) == NULL)
  	  {
-	    write_enn (own_buf);
+	    write_enn (cs.own_buf);
  	    break;
  	  }

  	if (mythread_alive (thread_id))
-	  write_ok (own_buf);
+	  write_ok (cs.own_buf);
  	else
-	  write_enn (own_buf);
+	  write_enn (cs.own_buf);
        }
        break;
      case 'R':
@@ -4325,22 +4323,22 @@ process_serial_event (void)
  	    {
  	      create_inferior (program_path.get (), program_args);

-	      if (last_status.kind == TARGET_WAITKIND_STOPPED)
+	      if (cs.last_status.kind == TARGET_WAITKIND_STOPPED)
  		{
  		  /* Stopped at the first instruction of the target
  		     process.  */
-		  general_thread = last_ptid;
+		  cs.general_thread = cs.last_ptid;
  		}
  	      else
  		{
  		  /* Something went wrong.  */
-		  general_thread = null_ptid;
+		  cs.general_thread = null_ptid;
  		}
  	    }
  	  else
  	    {
-	      last_status.kind = TARGET_WAITKIND_EXITED;
-	      last_status.value.sig = GDB_SIGNAL_KILL;
+	      cs.last_status.kind = TARGET_WAITKIND_EXITED;
+	      cs.last_status.value.sig = GDB_SIGNAL_KILL;
  	    }
  	  return 0;
  	}
@@ -4349,26 +4347,26 @@ process_serial_event (void)
  	  /* It is a request we don't understand.  Respond with an
  	     empty packet so that gdb knows that we don't support this
  	     request.  */
-	  own_buf[0] = '\0';
+	  cs.own_buf[0] = '\0';
  	  break;
  	}
      case 'v':
        /* Extended (long) request.  */
-      handle_v_requests (own_buf, packet_len, &new_packet_len);
+      handle_v_requests (cs.own_buf, packet_len, &new_packet_len);
        break;

      default:
        /* It is a request we don't understand.  Respond with an empty
  	 packet so that gdb knows that we don't support this
  	 request.  */
-      own_buf[0] = '\0';
+      cs.own_buf[0] = '\0';
        break;
      }

    if (new_packet_len != -1)
-    putpkt_binary (own_buf, new_packet_len);
+    putpkt_binary (cs.own_buf, new_packet_len);
    else
-    putpkt (own_buf);
+    putpkt (cs.own_buf);

    response_needed = 0;

@@ -4415,30 +4413,31 @@ push_stop_notification (ptid_t ptid, struct 
target_waitstatus *status)
  int
  handle_target_event (int err, gdb_client_data client_data)
  {
+  client_state &cs = get_client_state ();
    if (debug_threads)
      debug_printf ("handling possible target event\n");

-  last_ptid = mywait (minus_one_ptid, &last_status,
+  cs.last_ptid = mywait (minus_one_ptid, &cs.last_status,
  		      TARGET_WNOHANG, 1);

-  if (last_status.kind == TARGET_WAITKIND_NO_RESUMED)
+  if (cs.last_status.kind == TARGET_WAITKIND_NO_RESUMED)
      {
        if (gdb_connected () && report_no_resumed)
-	push_stop_notification (null_ptid, &last_status);
+	push_stop_notification (null_ptid, &cs.last_status);
      }
-  else if (last_status.kind != TARGET_WAITKIND_IGNORE)
+  else if (cs.last_status.kind != TARGET_WAITKIND_IGNORE)
      {
-      int pid = ptid_get_pid (last_ptid);
+      int pid = ptid_get_pid (cs.last_ptid);
        struct process_info *process = find_process_pid (pid);
        int forward_event = !gdb_connected () || process->gdb_detached;

-      if (last_status.kind == TARGET_WAITKIND_EXITED
-	  || last_status.kind == TARGET_WAITKIND_SIGNALLED)
+      if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+	  || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED)
  	{
  	  mark_breakpoints_out (process);
-	  target_mourn_inferior (last_ptid);
+	  target_mourn_inferior (cs.last_ptid);
  	}
-      else if (last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+      else if (cs.last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
  	;
        else
  	{
@@ -4446,7 +4445,7 @@ handle_target_event (int err, gdb_client_data 
client_data)
  	     "want-stopped" state to what the client wants, until it
  	     gets a new resume action.  */
  	  current_thread->last_resume_kind = resume_stop;
-	  current_thread->last_status = last_status;
+	  current_thread->last_status = cs.last_status;
  	}

        if (forward_event)
@@ -4457,9 +4456,9 @@ handle_target_event (int err, gdb_client_data 
client_data)
  	      exit (0);
  	    }

-	  if (last_status.kind == TARGET_WAITKIND_EXITED
-	      || last_status.kind == TARGET_WAITKIND_SIGNALLED
-	      || last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
+	  if (cs.last_status.kind == TARGET_WAITKIND_EXITED
+	      || cs.last_status.kind == TARGET_WAITKIND_SIGNALLED
+	      || cs.last_status.kind == TARGET_WAITKIND_THREAD_EXITED)
  	    ;
  	  else
  	    {
@@ -4471,18 +4470,18 @@ handle_target_event (int err, gdb_client_data 
client_data)
  	      if (debug_threads)
  		debug_printf ("GDB not connected; forwarding event %d for"
  			      " [%s]\n",
-			      (int) last_status.kind,
-			      target_pid_to_str (last_ptid));
+			      (int) cs.last_status.kind,
+			      target_pid_to_str (cs.last_ptid));

-	      if (last_status.kind == TARGET_WAITKIND_STOPPED)
-		signal = last_status.value.sig;
+	      if (cs.last_status.kind == TARGET_WAITKIND_STOPPED)
+		signal = cs.last_status.value.sig;
  	      else
  		signal = GDB_SIGNAL_0;
-	      target_continue (last_ptid, signal);
+	      target_continue (cs.last_ptid, signal);
  	    }
  	}
        else
-	push_stop_notification (last_ptid, &last_status);
+	push_stop_notification (cs.last_ptid, &cs.last_status);
      }

    /* Be sure to not change the selected thread behind GDB's back.
diff --git a/gdb/gdbserver/server.h b/gdb/gdbserver/server.h
index 5970431d8e..fea007c6b6 100644
--- a/gdb/gdbserver/server.h
+++ b/gdb/gdbserver/server.h
@@ -60,8 +60,6 @@ int vsnprintf(char *str, size_t size, const char 
*format, va_list ap);
  #include "gdb_signals.h"
  #include "target.h"
  #include "mem-break.h"
-#include "gdbthread.h"
-#include "inferiors.h"
  #include "environ.h"

  /* Target-specific functions */
@@ -70,42 +68,16 @@ void initialize_low ();

  /* Public variables in server.c */

-extern ptid_t cont_thread;
-extern ptid_t general_thread;
-
  extern int server_waiting;
-extern int pass_signals[];
-extern int program_signals[];
-extern int program_signals_p;

  extern int disable_packet_vCont;
  extern int disable_packet_Tthread;
  extern int disable_packet_qC;
  extern int disable_packet_qfThreadInfo;

-extern char *own_buf;
-
  extern int run_once;
-extern int multi_process;
-extern int report_fork_events;
-extern int report_vfork_events;
-extern int report_exec_events;
-extern int report_thread_events;
  extern int non_stop;

-/* True if the "swbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a software breakpoint
-   and for the server to handle PC adjustment if necessary on this
-   target.  Only enabled if the target supports it.  */
-extern int swbreak_feature;
-
-/* True if the "hwbreak+" feature is active.  In that case, GDB wants
-   us to report whether a trap is explained by a hardware breakpoint.
-   Only enabled if the target supports it.  */
-extern int hwbreak_feature;
-
-extern int disable_randomization;
-
  #if USE_WIN32API
  #include <winsock2.h>
  typedef SOCKET gdb_fildes_t;
@@ -158,8 +130,80 @@ extern void post_fork_inferior (int pid, const char 
*program);
  /* Get the gdb_environ being used in the current session.  */
  extern gdb_environ *get_environ ();

-extern target_waitstatus last_status;
-extern ptid_t last_ptid;
  extern unsigned long signal_pid;

+
+/* Description of the client remote protocol state for the currently
+   connected client.  */
+
+struct client_state
+{
+  client_state ():
+    own_buf ((char *) xmalloc (PBUFSIZ + 1))
+  {}
+
+  /* The thread set with an `Hc' packet.  `Hc' is deprecated in favor of
+     `vCont'.  Note the multi-process extensions made `vCont' a
+     requirement, so `Hc pPID.TID' is pretty much undefined.  So
+     CONT_THREAD can be null_ptid for no `Hc' thread, minus_one_ptid for
+     resuming all threads of the process (again, `Hc' isn't used for
+     multi-process), or a specific thread ptid_t.  */
+  ptid_t cont_thread;
+
+  /* The thread set with an `Hg' packet.  */
+  ptid_t general_thread;
+
+  int multi_process = 0;
+  int report_fork_events = 0;
+  int report_vfork_events = 0;
+  int report_exec_events = 0;
+  int report_thread_events = 0;
+
+  /* True if the "swbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a software breakpoint
+     and for the server to handle PC adjustment if necessary on this
+     target.  Only enabled if the target supports it.  */
+  int swbreak_feature = 0;
+  /* True if the "hwbreak+" feature is active.  In that case, GDB wants
+     us to report whether a trap is explained by a hardware breakpoint.
+     Only enabled if the target supports it.  */
+  int hwbreak_feature = 0;
+
+  /* True if the "vContSupported" feature is active.  In that case, GDB
+     wants us to report whether single step is supported in the reply to
+     "vCont?" packet.  */
+  int vCont_supported = 0;
+
+  /* Whether we should attempt to disable the operating system's address
+     space randomization feature before starting an inferior.  */
+  int disable_randomization = 0;
+
+  int pass_signals[GDB_SIGNAL_LAST];
+  int program_signals[GDB_SIGNAL_LAST];
+  int program_signals_p = 0;
+
+  /* Last status reported to GDB.  */
+  struct target_waitstatus last_status;
+  ptid_t last_ptid;
+
+  char *own_buf;
+
+  int remote_debug = 0;
+  /* If true, then GDB has requested noack mode.  */
+  int noack_mode = 0;
+  /* If true, then we tell GDB to use noack mode by default.  */
+  int transport_is_reliable = 0;
+
+  /* The traceframe to be used as the source of data to send back to
+     GDB.  A value of -1 means to get data from the live program.  */
+
+  int current_traceframe = -1;
+
+};
+
+client_state &get_client_state ();
+
+#include "gdbthread.h"
+#include "inferiors.h"
+
  #endif /* SERVER_H */
diff --git a/gdb/gdbserver/target.c b/gdb/gdbserver/target.c
index fe40b94db7..c2763294af 100644
--- a/gdb/gdbserver/target.c
+++ b/gdb/gdbserver/target.c
@@ -26,7 +26,8 @@ struct target_ops *the_target;
  int
  set_desired_thread ()
  {
-  thread_info *found = find_thread_ptid (general_thread);
+  client_state &cs = get_client_state ();
+  thread_info *found = find_thread_ptid (cs.general_thread);

    current_thread = found;
    return (current_thread != NULL);
@@ -42,6 +43,8 @@ static ptid_t prev_general_thread;
  int
  prepare_to_access_memory (void)
  {
+  client_state &cs = get_client_state ();
+
    /* The first thread found.  */
    struct thread_info *first = NULL;
    /* The first stopped thread found.  */
@@ -51,7 +54,7 @@ prepare_to_access_memory (void)

    /* Save the general thread value, since prepare_to_access_memory 
could change
       it.  */
-  prev_general_thread = general_thread;
+  prev_general_thread = cs.general_thread;

    if (the_target->prepare_to_access_memory != NULL)
      {
@@ -98,7 +101,7 @@ prepare_to_access_memory (void)
      }

    current_thread = thread;
-  general_thread = ptid_of (thread);
+  cs.general_thread = ptid_of (thread);

    return 0;
  }
@@ -108,12 +111,14 @@ prepare_to_access_memory (void)
  void
  done_accessing_memory (void)
  {
+  client_state &cs = get_client_state ();
+
    if (the_target->done_accessing_memory != NULL)
      the_target->done_accessing_memory ();

    /* Restore the previous selected thread.  */
-  general_thread = prev_general_thread;
-  switch_to_thread (general_thread);
+  cs.general_thread = prev_general_thread;
+  switch_to_thread (cs.general_thread);
  }

  int
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 4172756192..c203080dff 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -973,11 +973,6 @@ struct traceframe
     fields (and no data) marks the end of trace data.  */
  #define TRACEFRAME_EOB_MARKER_SIZE offsetof (struct traceframe, data)

-/* The traceframe to be used as the source of data to send back to
-   GDB.  A value of -1 means to get data from the live program.  */
-
-int current_traceframe = -1;
-
  /* This flag is true if the trace buffer is circular, meaning that
     when it fills, the oldest trace frames are discarded in order to
     make room.  */
@@ -2279,10 +2274,11 @@ static struct traceframe *
  find_next_traceframe_in_range (CORE_ADDR lo, CORE_ADDR hi, int inside_p,
  			       int *tfnump)
  {
+  client_state &cs = get_client_state ();
    struct traceframe *tframe;
    CORE_ADDR tfaddr;

-  *tfnump = current_traceframe + 1;
+  *tfnump = cs.current_traceframe + 1;
    tframe = find_traceframe (*tfnump);
    /* The search is not supposed to wrap around.  */
    if (!tframe)
@@ -2312,9 +2308,10 @@ find_next_traceframe_in_range (CORE_ADDR lo, 
CORE_ADDR hi, int inside_p,
  static struct traceframe *
  find_next_traceframe_by_tracepoint (int num, int *tfnump)
  {
+  client_state &cs = get_client_state ();
    struct traceframe *tframe;

-  *tfnump = current_traceframe + 1;
+  *tfnump = cs.current_traceframe + 1;
    tframe = find_traceframe (*tfnump);
    /* The search is not supposed to wrap around.  */
    if (!tframe)
@@ -2343,6 +2340,7 @@ find_next_traceframe_by_tracepoint (int num, int 
*tfnump)
  static void
  cmd_qtinit (char *packet)
  {
+  client_state &cs = get_client_state ();
    struct trace_state_variable *tsv, *prev, *next;

    /* Can't do this command without a pid attached.  */
@@ -2353,7 +2351,7 @@ cmd_qtinit (char *packet)
      }

    /* Make sure we don't try to read from a trace frame.  */
-  current_traceframe = -1;
+  cs.current_traceframe = -1;

    stop_tracing ();

@@ -2813,6 +2811,7 @@ cmd_qtenable_disable (char *own_buf, int enable)
  static void
  cmd_qtv (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    ULONGEST num;
    LONGEST val = 0;
    int err;
@@ -2821,7 +2820,7 @@ cmd_qtv (char *own_buf)
    packet += strlen ("qTV:");
    unpack_varlen_hex (packet, &num);

-  if (current_traceframe >= 0)
+  if (cs.current_traceframe >= 0)
      {
        err = traceframe_read_tsv ((int) num, &val);
        if (err)
@@ -3552,6 +3551,7 @@ cmd_qtdisconnected (char *own_buf)
  static void
  cmd_qtframe (char *own_buf)
  {
+  client_state &cs = get_client_state ();
    ULONGEST frame, pc, lo, hi, num;
    int tfnum, tpnum;
    struct traceframe *tframe;
@@ -3602,7 +3602,7 @@ cmd_qtframe (char *own_buf)
        if (tfnum == -1)
  	{
  	  trace_debug ("Want to stop looking at traceframes");
-	  current_traceframe = -1;
+	  cs.current_traceframe = -1;
  	  write_ok (own_buf);
  	  return;
  	}
@@ -3612,7 +3612,7 @@ cmd_qtframe (char *own_buf)

    if (tframe)
      {
-      current_traceframe = tfnum;
+      cs.current_traceframe = tfnum;
        sprintf (own_buf, "F%xT%x", tfnum, tframe->tpnum);
      }
    else
@@ -5297,6 +5297,7 @@ traceframe_read_mem (int tfnum, CORE_ADDR addr,
  static int
  traceframe_read_tsv (int tsvnum, LONGEST *val)
  {
+  client_state &cs = get_client_state ();
    int tfnum;
    struct traceframe *tframe;
    unsigned char *database, *dataptr;
@@ -5306,7 +5307,7 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)

    trace_debug ("traceframe_read_tsv");

-  tfnum = current_traceframe;
+  tfnum = cs.current_traceframe;

    if (tfnum < 0)
      {

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v2] Consolidate gdbserver global variables
  2018-05-07 19:17         ` Frank Ch. Eigler
@ 2018-05-25 14:31           ` Pedro Alves
  0 siblings, 0 replies; 15+ messages in thread
From: Pedro Alves @ 2018-05-25 14:31 UTC (permalink / raw)
  To: Frank Ch. Eigler; +Cc: Stan Cox, gdb-patches

On 05/07/2018 08:16 PM, Frank Ch. Eigler wrote:
> 
> palves wrote:
> 
>> [...]
>> Some comments more.  I still have some design reservations.
>> It seems to me that simply making some of the globals be
>> per client along won't work correctly.  Particularly, the
>> cases where the globals are used in the backends.
>> [...]
> 

> I don't want to speak for Stan here, 

;-)

> but I suspect all this is about is
> the breaking up of the multi-client work along the patchset path your
> requested.  Yup, indeed backends have to do the logical 'union' of the
> work that all the clients request, and each client interface will have
> to filter the notifications correspondingly to undo the 'union'.  

Note that in some cases it's not just even filtering.  Globals
can control modes of operation, like the cs->non_stop case I pointed
out in a previous review.

> 
> But all that is in a separate patch; this part seems to simply
> reorganize the globals in preparation for that, as you asked.

Right, but it doesn't hurt to think about the plan for the
issues I pointed out a bit, since it may avoid churn in a
direction that we may not want.  In the original version of the patch,
when macros were used, these references to client_state fields
from the backends were pretty much invisible (because of the macros),
so it would be unsurprising to me if the full multi-client prototype
that is based on the macros version does not consider these issues.

I'll go look at the updated patch.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-05-08 20:58         ` [RFC][PATCH v3] " Stan Cox
@ 2018-05-25 15:01           ` Pedro Alves
  2018-05-29 20:46             ` Stan Cox
  2018-06-08 16:11           ` Tom Tromey
  2018-07-10  1:14           ` Sergio Durigan Junior
  2 siblings, 1 reply; 15+ messages in thread
From: Pedro Alves @ 2018-05-25 15:01 UTC (permalink / raw)
  To: Stan Cox, gdb-patches

On 05/08/2018 09:58 PM, Stan Cox wrote:
> (Addressed formatting and ChangeLog issues)

Thanks.  This is looking great now.  Some comments below,
but no need for another round of review.

> 
>> As mentioned, I'm skeptical of all client_state references
>> in the backends.
>>
>> How will this work with multiple clients?   What if one client
>> wants exec events, and the other one doesn't?  This seems to
>> suggest that the backends need to enable exec events if _any_
>> client wants them (or unconditionally), and then filter out exec
>> events at a higher level, before reporting the event to
>> each client?
> 
> Perhaps filtering that is roughly analogous to the way
> gdb_catch_this_syscall_p filters for particular syscalls.
> 

>> This "= 0" is a spurious change.  Remove it.
> 
> Removed (it eliminated a compiler warning with gcc 7.3.1)

You mean, without the change, we trigger a warning?  What
does it look like?  If we do, then we'll need to address it
somehow, of course, given -Werror.  But I'd like to see
it first.

> Tested on linux with native-gdbserver.
> 
> Add client_state struct.
> 
> Collect per client specific global data items into struct client_state,
> which is similar in purpose to remote.c::remote_state.
> @@ -1835,6 +1820,7 @@ handle_qxfer_btrace (const char *annex,
>               gdb_byte *readbuf, const gdb_byte *writebuf,
>               ULONGEST offset, LONGEST len)
>  {
> +  client_state &cs = get_client_state ();
>    static struct buffer cache;

This "static" here made me notice that there is more global
state stored as function local static variables that should
be moved to client_state.  E.g.,:

$ nm -A server.o | c++filt  | grep " b " | grep "::"
server.o:0000000000000700 b guard variable for handle_query(char*, int, int*)::thread_iter
server.o:00000000000006f8 b handle_query(char*, int, int*)::thread_iter
server.o:00000000000006c0 b handle_qxfer_btrace(char const*, unsigned char*, unsigned char const*, unsigned long long, long long)::cache
server.o:00000000000006a0 b handle_qxfer_threads(char const*, unsigned char*, unsigned char const*, unsigned long long, long long)::result_length
server.o:0000000000000698 b handle_qxfer_threads(char const*, unsigned char*, unsigned char const*, unsigned long long, long long)::result
server.o:00000000000006e0 b handle_qxfer_btrace_conf(char const*, unsigned char*, unsigned char const*, unsigned long long, long long)::cache
server.o:00000000000006b0 b handle_qxfer_traceframe_info(char const*, unsigned char*, unsigned char const*, unsigned long long, long long)::result_length
server.o:00000000000006a8 b handle_qxfer_traceframe_info(char const*, unsigned char*, unsigned char const*, unsigned long long, long long)::result

That can be done as follow up.

> @@ -3643,7 +3642,7 @@ captured_main (int argc, char *argv[])
>          }
>      }
>        else if (strcmp (*next_arg, "--remote-debug") == 0)
> -    remote_debug = 1;
> +    cs.remote_debug = 1;

remote_debug controls whether to print debug output to gdbserver'
own terminal, so I'm thinking that it should probably remain
a global.

Otherwise it looks good to me.  If we don't need to handle
a warning, then feel free to push this in with the
remote_debug issue above addressed.

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-05-25 15:01           ` Pedro Alves
@ 2018-05-29 20:46             ` Stan Cox
  2018-05-30 14:30               ` Pedro Alves
  0 siblings, 1 reply; 15+ messages in thread
From: Stan Cox @ 2018-05-29 20:46 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches



On 05/25/2018 10:31 AM, Pedro Alves wrote:

> You mean, without the change, we trigger a warning?  What
> does it look like?  If we do, then we'll need to address it
> somehow, of course, given -Werror.

This is vanilla upstream gdb, no patches, with gcc 7.3.1 on F27

../../../src/gdb/gdbserver/server.c: In function ‘int 
handle_qxfer_btrace_conf(const char*, gdb_byte*, const gdb_byte*, 
ULONGEST, LONGEST)’:
../../../src/gdb/gdbserver/server.c:1966:7: warning: ‘result’ may be 
used uninitialized in this function [-Wmaybe-uninitialized]
        if (result != 0)
        ^~
../../../src/gdb/gdbserver/server.c: In function ‘int 
handle_qxfer_btrace(const char*, gdb_byte*, const gdb_byte*, ULONGEST, 
LONGEST)’:
../../../src/gdb/gdbserver/server.c:1895:7: warning: ‘result’ may be 
used uninitialized in this function [-Wmaybe-uninitialized]
        if (result != 0)
        ^~
The source is an assignment in a TRY/CATCH
       TRY
         {
           result = target_read_btrace_conf (thread->btrace, &cache);
           if (result != 0)
             memcpy (own_buf, cache.buffer, cache.used_size);
         }
       CATCH (exception, RETURN_MASK_ERROR)
         {
           sprintf (own_buf, "E.%s", exception.message);
           result = -1;
         }
       END_CATCH

       if (result != 0)
         return -3;

> This "static" here made me notice that there is more global
> state stored as function local static variables that should
> be moved to client_state.  E.g.,:
> That can be done as follow up.

Will do

> remote_debug controls whether to print debug output to gdbserver'
> own terminal, so I'm thinking that it should probably remain
> a global.

Ah yes; I'll do that.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-05-29 20:46             ` Stan Cox
@ 2018-05-30 14:30               ` Pedro Alves
  0 siblings, 0 replies; 15+ messages in thread
From: Pedro Alves @ 2018-05-30 14:30 UTC (permalink / raw)
  To: Stan Cox, gdb-patches

On 05/29/2018 08:52 PM, Stan Cox wrote:
> 
> 
> On 05/25/2018 10:31 AM, Pedro Alves wrote:
> 
>> You mean, without the change, we trigger a warning?  What
>> does it look like?  If we do, then we'll need to address it
>> somehow, of course, given -Werror.
> 
> This is vanilla upstream gdb, no patches, 

Ah, alright, since this happens on pristine master, it's unrelated
to your patch.  Please leave it out.  And ...

> with gcc 7.3.1 on F27
> 
> ../../../src/gdb/gdbserver/server.c: In function ‘int handle_qxfer_btrace_conf(const char*, gdb_byte*, const gdb_byte*, ULONGEST, LONGEST)’:
> ../../../src/gdb/gdbserver/server.c:1966:7: warning: ‘result’ may be used uninitialized in this function [-Wmaybe-uninitialized]
>        if (result != 0)
>        ^~
> ../../../src/gdb/gdbserver/server.c: In function ‘int handle_qxfer_btrace(const char*, gdb_byte*, const gdb_byte*, ULONGEST, LONGEST)’:
> ../../../src/gdb/gdbserver/server.c:1895:7: warning: ‘result’ may be used uninitialized in this function [-Wmaybe-uninitialized]
>        if (result != 0)
>        ^~

I've looked into this and pushed a fix, here:

 https://sourceware.org/ml/gdb-patches/2018-05/msg00783.html

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-05-08 20:58         ` [RFC][PATCH v3] " Stan Cox
  2018-05-25 15:01           ` Pedro Alves
@ 2018-06-08 16:11           ` Tom Tromey
  2018-06-08 16:46             ` Stan Cox
  2018-07-10  1:14           ` Sergio Durigan Junior
  2 siblings, 1 reply; 15+ messages in thread
From: Tom Tromey @ 2018-06-08 16:11 UTC (permalink / raw)
  To: Stan Cox; +Cc: Pedro Alves, gdb-patches

>>>>> "Stan" == Stan Cox <scox@redhat.com> writes:

Stan>     * server.h (struct client_state): New.
Stan>     * server.c (cont_thread, general_thread, multi_process)
Stan>     (report_fork_events, report_vfork_events, report_exec_events)
Stan>     (report_thread_events, swbreak_feature, hwbreak_feature)
Stan>     (vCont_supported, disable_randomization, pass_signals)
Stan>     (program_signals, program_signals_p, last_status, last_ptid, own_buf):
Stan>     Moved to client_state.
Stan>     * remote-utils.c (remote_debug, noack_mode)
Stan>     (transport_is_reliable): Moved to client_state.
Stan>     * tracepoint.c (current_traceframe): Moved to client_state.

I think this broke the mingw build.

I configured with:

../binutils-gdb/configure --disable-{binutils,gas,gold,gprof,ld,sim} \
  --host i686-w64-mingw32 --target i686-w64-mingw32

Then building:

../../../binutils-gdb/gdb/gdbserver/win32-low.c: In function 'int win32_create_inferior(const char*, const std::vector<char*>&)':
../../../binutils-gdb/gdb/gdbserver/win32-low.c:709:3: error: 'last_ptid' was not declared in this scope
   last_ptid = win32_wait (pid_to_ptid (current_process_id), &last_status, 0);
   ^~~~~~~~~
../../../binutils-gdb/gdb/gdbserver/win32-low.c:709:3: note: suggested alternative: 'last_sig'
   last_ptid = win32_wait (pid_to_ptid (current_process_id), &last_status, 0);
   ^~~~~~~~~
   last_sig
../../../binutils-gdb/gdb/gdbserver/win32-low.c:709:62: error: 'last_status' was not declared in this scope
   last_ptid = win32_wait (pid_to_ptid (current_process_id), &last_status, 0);
                                                              ^~~~~~~~~~~
../../../binutils-gdb/gdb/gdbserver/win32-low.c:709:62: note: suggested alternative: 'cached_status'
   last_ptid = win32_wait (pid_to_ptid (current_process_id), &last_status, 0);
                                                              ^~~~~~~~~~~
                                                              cached_status

thanks,
Tom

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-06-08 16:11           ` Tom Tromey
@ 2018-06-08 16:46             ` Stan Cox
  2018-06-08 16:52               ` Tom Tromey
  0 siblings, 1 reply; 15+ messages in thread
From: Stan Cox @ 2018-06-08 16:46 UTC (permalink / raw)
  To: Tom Tromey; +Cc: Pedro Alves, gdb-patches


> I think this broke the mingw build.
I have an old laptop with mingw on it; I'll take a look.

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-06-08 16:46             ` Stan Cox
@ 2018-06-08 16:52               ` Tom Tromey
  0 siblings, 0 replies; 15+ messages in thread
From: Tom Tromey @ 2018-06-08 16:52 UTC (permalink / raw)
  To: Stan Cox; +Cc: Tom Tromey, Pedro Alves, gdb-patches

>>>>> "Stan" == Stan Cox <scox@redhat.com> writes:

>> I think this broke the mingw build.
Stan> I have an old laptop with mingw on it; I'll take a look.

FWIW I just installed the mingw cross compilers on Fedora.  It's super
easy, just "dnf install" a few things and you're ready to build.

Tom

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [RFC][PATCH v3] Consolidate gdbserver global variables
  2018-05-08 20:58         ` [RFC][PATCH v3] " Stan Cox
  2018-05-25 15:01           ` Pedro Alves
  2018-06-08 16:11           ` Tom Tromey
@ 2018-07-10  1:14           ` Sergio Durigan Junior
  2 siblings, 0 replies; 15+ messages in thread
From: Sergio Durigan Junior @ 2018-07-10  1:14 UTC (permalink / raw)
  To: Stan Cox; +Cc: Pedro Alves, gdb-patches

On Tuesday, May 08 2018, Stan Cox wrote:

> (Addressed formatting and ChangeLog issues)
>
>> As mentioned, I'm skeptical of all client_state references
>> in the backends.
>>
>> How will this work with multiple clients?   What if one client
>> wants exec events, and the other one doesn't?  This seems to
>> suggest that the backends need to enable exec events if _any_
>> client wants them (or unconditionally), and then filter out exec
>> events at a higher level, before reporting the event to
>> each client?
>
> Perhaps filtering that is roughly analogous to the way
> gdb_catch_this_syscall_p filters for particular syscalls.
>
>> This "= 0" is a spurious change.  Remove it.
>
> Removed (it eliminated a compiler warning with gcc 7.3.1)
>
>> Give the global different name to avoid conflict with
>> the type name.  Maybe "g_client_state" or "the_client_state".
>
> Used g_client_state and also made it static instead of allocating it
> with new.
>
>> What's the plan for last_status/last_ptid?
>> Shouldn't those be per-client too?
>
> Added those.
>
>> Should these two be per client?  I'd think so off hand,
>> since they correspond to the Hc/Hg threads?
>
> Added cont_thread and general_thread
>
>> I suspect that it'd be better to make the server_waiting
>> global be per-process instead
>
> Returned to server_waiting being a global for now.
>
>
> Thanks Pedro!
>
>
> Tested on linux with native-gdbserver.

Hi Stan,

This patch introduced a regression on GDB when testing with
--target_board=native-gdbserver.  The failure is described here:

  https://sourceware.org/bugzilla/show_bug.cgi?id=23378

I've been trying to narrow down the cause, but so far have not been very
successful.  It seems that everything was covered by your patch, so I'm
guessing there must be some hidden spot where we're forgetting to update
some internal state and the failure ends up happening.

For the sake of comparison, here's the output that should have been
printed:

  Expecting: ^(-var-update L[
  ]+)?(\^done,changelist=\[{name="L",in_scope="true",type_changed="false",has_more="0"}\][
  ]+[(]gdb[)] 
  [ ]*)
  -var-update L
  ^done,changelist=[{name="L",in_scope="true",type_changed="false",has_more="0"}]
  (gdb) 
  PASS: gdb.mi/mi-var-cmd.exp: in-and-out-of-scope: in scope now

And this is what the failure looks like:

  Expecting: ^(-var-update L[
  ]+)?(\^done,changelist=\[{name="L",in_scope="true",type_changed="false",has_more="0"}\][
  ]+[(]gdb[)] 
  [ ]*)
  -var-update L
  ^done,changelist=[]
  (gdb) 
  FAIL: gdb.mi/mi-var-cmd.exp: in-and-out-of-scope: in scope now (unexpected output)

Something to take into consideration is that gdbserver is restarted
many times during the testcase.  I think this may have something to do
with it, because the test doesn't fail on native-extended-gdbserver.

Thanks,

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2018-07-10  1:14 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-11-07 22:03 [RFC][PATCH] Consolidate gdbserver global variables Stan Cox
2018-01-31  3:41 ` Stan Cox
2018-04-23 17:58   ` Pedro Alves
2018-05-03 15:06     ` [RFC][PATCH v2] " Stan Cox
2018-05-04 14:14       ` Pedro Alves
2018-05-07 19:17         ` Frank Ch. Eigler
2018-05-25 14:31           ` Pedro Alves
2018-05-08 20:58         ` [RFC][PATCH v3] " Stan Cox
2018-05-25 15:01           ` Pedro Alves
2018-05-29 20:46             ` Stan Cox
2018-05-30 14:30               ` Pedro Alves
2018-06-08 16:11           ` Tom Tromey
2018-06-08 16:46             ` Stan Cox
2018-06-08 16:52               ` Tom Tromey
2018-07-10  1:14           ` Sergio Durigan Junior

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).