[RFC][PATCH] Consolidate gdbserver global variables

Stan Cox scox@redhat.com
Tue Nov 7 22:03:00 GMT 2017


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 */



More information about the Gdb-patches mailing list