This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Gdbserver for Windows


Some time ago Leo Zayas sent me a working port of gdbserver to Windows.
It's been languishing in my mailbox.  This week and last week I updated it,
reformatted it, and added some bits like basic Cygwin support.  I've tested
this somewhat; it works, even with multi-threaded applications, but
something in pthread_cond_wait.exp makes it blow up in a way I can't work
out.  But it is definitely good enough to be useful!

It doesn't have support for interrupts - pressing C-c in GDB won't stop it.
Leo and I had been talking about how to do that, but I'm afraid I've run
out of time for this project for now.  Leo, you'll see I've moved a lot
of the code around.  If you have any comments, please let me know.

Chris, since this is part of gdbserver, it doesn't actually need your
review.  However, if you want to eyeball it for anything we've obviously
mucked up...

This also deserves a NEWS entry.  I'll do that separately.

-- 
Daniel Jacobowitz
CodeSourcery

2006-07-18  Daniel Jacobowitz  <dan@codesourcery.com>

	* configure.tgt: Build gdbserver for Cygwin and mingw32.

2006-07-18  Daniel Jacobowitz  <dan@codesourcery.com>

	* configure.ac: Check for more headers which are missing on
	Windows.  Automatically supply -lwsock32 and USE_WIN32API.
	* configure.srv: Add Cygwin and mingw32.
	* remote-utils.c: Don't include headers unconditionally which
	are missing on mingw32.  Include <winsock.h> for mingw32.
	(remote_open): Adjust for mingw32 support.  Flush
	standard error after writing to it.
	(remote_close, putpkt_binary, input_interrupt, block_async_io)
	(unblock_async_io, enable_async_io, disable_async_io)
	(readchar, getpkt): Update for Winsock support.
	(prepare_resume_reply): Expect a protocol signal number.
	* server.c: Disable <sys/wait.h> on mingw32.
	(start_inferior): Adjust for mingw32 support.  Flush
	standard error after writing to it.
	(attach_inferior): Likewise.  Use protocol signal
	numbers.
	(main): Skip 'D' packet on mingw32.  Use protocol signal numbers
	and names.
	* win32-i386-low.c: New file.
	* Makefile.in (XM_CLIBS): Set.
	(gdbserver, gdbreplay): Use $(INTERNAL_CFLAGS).
	(win32-i386-low.o): New dependency rule.
	* linux-low.c (linux_wait): Use target signal numbers.
	* target.h (struct target_ops): Doc fix.
	* server.h (target_signal_to_name): New prototype.
	* gdbreplay.c: Don't include headers unconditionally which
	are missing on mingw32.  Include <winsock.h> for mingw32.
	(remote_close, remote_open): Adjust for Winsock support.
	* configure, config.in: Regenerated.

---
 gdb/configure.tgt              |    7 
 gdb/gdbserver/Makefile.in      |    7 
 gdb/gdbserver/config.in        |   29 +
 gdb/gdbserver/configure        |   95 ++-
 gdb/gdbserver/configure.ac     |   13 
 gdb/gdbserver/configure.srv    |    7 
 gdb/gdbserver/gdbreplay.c      |   47 +
 gdb/gdbserver/linux-low.c      |    6 
 gdb/gdbserver/remote-utils.c   |   87 ++-
 gdb/gdbserver/server.c         |   21 
 gdb/gdbserver/server.h         |    1 
 gdb/gdbserver/target.h         |    6 
 gdb/gdbserver/win32-i386-low.c | 1077 +++++++++++++++++++++++++++++++++++++++++
 13 files changed, 1341 insertions(+), 62 deletions(-)

Index: src/gdb/gdbserver/configure.ac
===================================================================
--- src.orig/gdb/gdbserver/configure.ac	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/configure.ac	2006-07-18 15:46:33.000000000 -0400
@@ -38,7 +38,9 @@ AC_HEADER_STDC
 
 AC_CHECK_HEADERS(sgtty.h termio.h termios.h sys/reg.h string.h dnl
 		 proc_service.h sys/procfs.h thread_db.h linux/elf.h dnl
-		 stdlib.h unistd.h)
+		 stdlib.h unistd.h dnl
+		 terminal.h sys/ioctl.h netinet/in.h sys/socket.h netdb.h dnl
+		 netinet/tcp.h arpa/inet.h sys/wait.h)
 
 AC_CHECK_DECLS(strerror)
 
@@ -48,6 +50,15 @@ AC_CHECK_TYPES(socklen_t, [], [],
 ])
 . ${srcdir}/configure.srv
 
+if test "${srv_mingw}" = "yes"; then
+  LIBS="$LIBS -lwsock32"
+  AC_DEFINE(USE_WIN32API, 1,
+	    [Define if we should use the Windows API, instead of the
+	     POSIX API.  On Windows, we use the Windows API when
+	     building for MinGW, but the POSIX API when building
+	     for Cygwin.])
+fi
+
 if test "${srv_linux_usrregs}" = "yes"; then
   AC_DEFINE(HAVE_LINUX_USRREGS, 1,
 	    [Define if the target supports PTRACE_PEEKUSR for register ]
Index: src/gdb/gdbserver/configure.srv
===================================================================
--- src.orig/gdb/gdbserver/configure.srv	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/configure.srv	2006-07-18 15:33:50.000000000 -0400
@@ -33,12 +33,19 @@ case "${target}" in
 			srv_linux_usrregs=yes
 			srv_linux_thread_db=yes
 			;;
+  i[34567]86-*-cygwin*)	srv_regobj=reg-i386.o
+			srv_tgtobj="win32-i386-low.o"
+			;;
   i[34567]86-*-linux*)	srv_regobj=reg-i386-linux.o
 			srv_tgtobj="linux-low.o linux-i386-low.o i387-fp.o"
 			srv_linux_usrregs=yes
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
 			;;
+  i[34567]86-*-mingw*)	srv_regobj=reg-i386.o
+			srv_tgtobj="win32-i386-low.o"
+			srv_mingw=yes
+			;;
   ia64-*-linux*)	srv_regobj=reg-ia64.o
 			srv_tgtobj="linux-low.o linux-ia64-low.o"
 			srv_linux_usrregs=yes
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/remote-utils.c	2006-07-18 15:28:45.000000000 -0400
@@ -21,21 +21,41 @@
    Boston, MA 02110-1301, USA.  */
 
 #include "server.h"
+#if HAVE_TERMINAL_H
 #include "terminal.h"
+#endif
 #include <stdio.h>
 #include <string.h>
+#if HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
+#endif
 #include <sys/file.h>
+#if HAVE_NETINET_IN_H
 #include <netinet/in.h>
+#endif
+#if HAVE_SYS_SOCKET_H
 #include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
 #include <netdb.h>
+#endif
+#if HAVE_NETINET_TCP_H
 #include <netinet/tcp.h>
+#endif
+#if HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
+#endif
 #include <signal.h>
 #include <fcntl.h>
 #include <sys/time.h>
 #include <unistd.h>
+#if HAVE_ARPA_INET_H
 #include <arpa/inet.h>
+#endif
+
+#if USE_WIN32API
+#include <winsock.h>
+#endif
 
 #ifndef HAVE_SOCKLEN_T
 typedef int socklen_t;
@@ -71,10 +91,15 @@ extern int debug_threads;
 void
 remote_open (char *name)
 {
+#if defined(F_SETFL) && defined (FASYNC)
   int save_fcntl_flags;
+#endif
   
   if (!strchr (name, ':'))
     {
+#ifdef USE_WIN32API
+      error ("Only <host>:<port> is supported on this platform.");
+#else
       remote_desc = open (name, O_RDWR);
       if (remote_desc < 0)
 	perror_with_name ("Could not open remote device");
@@ -124,9 +149,13 @@ remote_open (char *name)
 #endif
 
       fprintf (stderr, "Remote debugging using %s\n", name);
+#endif /* USE_WIN32API */
     }
   else
     {
+#ifdef USE_WIN32API
+      static int winsock_initialized;
+#endif
       char *port_str;
       int port;
       struct sockaddr_in sockaddr;
@@ -137,7 +166,17 @@ remote_open (char *name)
 
       port = atoi (port_str + 1);
 
-      tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
+#ifdef USE_WIN32API
+      if (!winsock_initialized)
+	{
+	  WSADATA wsad;
+
+	  WSAStartup (MAKEWORD (1, 0), &wsad);
+	  winsock_initialized = 1;
+	}
+#endif
+
+      tmp_desc = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
       if (tmp_desc < 0)
 	perror_with_name ("Can't open socket");
 
@@ -155,6 +194,7 @@ remote_open (char *name)
 	perror_with_name ("Can't bind address");
 
       fprintf (stderr, "Listening on port %d\n", port);
+      fflush (stderr);
 
       tmp = sizeof (sockaddr);
       remote_desc = accept (tmp_desc, (struct sockaddr *) &sockaddr, &tmp);
@@ -171,10 +211,15 @@ remote_open (char *name)
       setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
 		  (char *) &tmp, sizeof (tmp));
 
+
+#ifndef USE_WIN32API
       close (tmp_desc);		/* No longer need this */
 
       signal (SIGPIPE, SIG_IGN);	/* If we don't do this, then gdbserver simply
 					   exits when the remote side dies.  */
+#else
+      closesocket (tmp_desc);	/* No longer need this */
+#endif
 
       /* Convert IP address to string.  */
       fprintf (stderr, "Remote debugging from host %s\n", 
@@ -194,7 +239,11 @@ remote_open (char *name)
 void
 remote_close (void)
 {
+#ifdef USE_WIN32API
+  closesocket (remote_desc);
+#else
   close (remote_desc);
+#endif
 }
 
 /* Convert hex digit A to a number.  */
@@ -395,7 +444,7 @@ putpkt_binary (char *buf, int cnt)
     {
       int cc;
 
-      if (write (remote_desc, buf2, p - buf2) != p - buf2)
+      if (send (remote_desc, buf2, p - buf2, 0) != p - buf2)
 	{
 	  perror ("putpkt(write)");
 	  return -1;
@@ -406,7 +455,7 @@ putpkt_binary (char *buf, int cnt)
 	  fprintf (stderr, "putpkt (\"%s\"); [looking for ack]\n", buf2);
 	  fflush (stderr);
 	}
-      cc = read (remote_desc, buf3, 1);
+      cc = recv (remote_desc, buf3, 1, 0);
       if (remote_debug)
 	{
 	  fprintf (stderr, "[received '%c' (0x%x)]\n", buf3[0], buf3[0]);
@@ -444,6 +493,7 @@ putpkt (char *buf)
   return putpkt_binary (buf, strlen (buf));
 }
 
+#ifndef USE_WIN32API
 
 /* Come here when we get an input interrupt from the remote side.  This
    interrupt should only be active while we are waiting for the child to do
@@ -466,7 +516,7 @@ input_interrupt (int unused)
       int cc;
       char c = 0;
       
-      cc = read (remote_desc, &c, 1);
+      cc = recv (remote_desc, &c, 1, 0);
 
       if (cc != 1 || c != '\003')
 	{
@@ -478,29 +528,34 @@ input_interrupt (int unused)
       (*the_target->send_signal) (SIGINT);
     }
 }
+#endif
+
+/* Asynchronous I/O support.  SIGIO must be enabled when waiting, in order to
+   accept Control-C from the client, and must be disabled when talking to
+   the client.  */
 
 void
 block_async_io (void)
 {
+#ifndef USE_WIN32API
   sigset_t sigio_set;
   sigemptyset (&sigio_set);
   sigaddset (&sigio_set, SIGIO);
   sigprocmask (SIG_BLOCK, &sigio_set, NULL);
+#endif
 }
 
 void
 unblock_async_io (void)
 {
+#ifndef USE_WIN32API
   sigset_t sigio_set;
   sigemptyset (&sigio_set);
   sigaddset (&sigio_set, SIGIO);
   sigprocmask (SIG_UNBLOCK, &sigio_set, NULL);
+#endif
 }
 
-/* Asynchronous I/O support.  SIGIO must be enabled when waiting, in order to
-   accept Control-C from the client, and must be disabled when talking to
-   the client.  */
-
 /* Current state of asynchronous I/O.  */
 static int async_io_enabled;
 
@@ -511,7 +566,9 @@ enable_async_io (void)
   if (async_io_enabled)
     return;
 
+#ifndef USE_WIN32API
   signal (SIGIO, input_interrupt);
+#endif
   async_io_enabled = 1;
 }
 
@@ -522,7 +579,9 @@ disable_async_io (void)
   if (!async_io_enabled)
     return;
 
+#ifndef USE_WIN32API
   signal (SIGIO, SIG_IGN);
+#endif
   async_io_enabled = 0;
 }
 
@@ -538,7 +597,7 @@ readchar (void)
   if (bufcnt-- > 0)
     return *bufp++;
 
-  bufcnt = read (remote_desc, buf, sizeof (buf));
+  bufcnt = recv (remote_desc, buf, sizeof (buf), 0);
 
   if (bufcnt <= 0)
     {
@@ -605,7 +664,7 @@ getpkt (char *buf)
 
       fprintf (stderr, "Bad checksum, sentsum=0x%x, csum=0x%x, buf=%s\n",
 	       (c1 << 4) + c2, csum, buf);
-      write (remote_desc, "-", 1);
+      send (remote_desc, "-", 1, 0);
     }
 
   if (remote_debug)
@@ -614,7 +673,7 @@ getpkt (char *buf)
       fflush (stderr);
     }
 
-  write (remote_desc, "+", 1);
+  send (remote_desc, "+", 1, 0);
 
   if (remote_debug)
     {
@@ -723,14 +782,12 @@ dead_thread_notify (int id)
 }
 
 void
-prepare_resume_reply (char *buf, char status, unsigned char signo)
+prepare_resume_reply (char *buf, char status, unsigned char sig)
 {
-  int nib, sig;
+  int nib;
 
   *buf++ = status;
 
-  sig = (int)target_signal_from_host (signo);
-
   nib = ((sig & 0xf0) >> 4);
   *buf++ = tohex (nib);
   nib = sig & 0x0f;
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/server.c	2006-07-18 14:54:46.000000000 -0400
@@ -24,7 +24,9 @@
 
 #include <unistd.h>
 #include <signal.h>
+#if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
+#endif
 
 unsigned long cont_thread;
 unsigned long general_thread;
@@ -46,17 +48,22 @@ unsigned long signal_pid;
 static int
 start_inferior (char *argv[], char *statusptr)
 {
+#ifdef SIGTTOU
   signal (SIGTTOU, SIG_DFL);
   signal (SIGTTIN, SIG_DFL);
+#endif
 
   signal_pid = create_inferior (argv[0], argv);
 
   fprintf (stderr, "Process %s created; pid = %ld\n", argv[0],
 	   signal_pid);
+  fflush (stderr);
 
+#ifdef SIGTTOU
   signal (SIGTTOU, SIG_IGN);
   signal (SIGTTIN, SIG_IGN);
   tcsetpgrp (fileno (stderr), signal_pid);
+#endif
 
   /* Wait till we are at 1st instruction in program, return signal number.  */
   return mywait (statusptr, 0);
@@ -72,6 +79,7 @@ attach_inferior (int pid, char *statuspt
     return -1;
 
   fprintf (stderr, "Attached; pid = %d\n", pid);
+  fflush (stderr);
 
   /* 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
@@ -83,8 +91,8 @@ attach_inferior (int pid, char *statuspt
   /* 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 (*statusptr == 'T' && *sigptr == SIGSTOP)
-    *sigptr = SIGTRAP;
+  if (*statusptr == 'T' && *sigptr == TARGET_SIGNAL_STOP)
+    *sigptr = TARGET_SIGNAL_TRAP;
 
   return 0;
 }
@@ -516,6 +524,9 @@ main (int argc, char *argv[])
 	    case 'd':
 	      remote_debug = !remote_debug;
 	      break;
+#ifndef USE_WIN32API
+	    /* Skip "detach" support on mingw32, since we don't have
+	       waitpid.  */
 	    case 'D':
 	      fprintf (stderr, "Detaching from inferior\n");
 	      detach_inferior ();
@@ -537,6 +548,7 @@ main (int argc, char *argv[])
 		}
 
 	      exit (0);
+#endif
 
 	    case '!':
 	      if (attached == 0)
@@ -794,8 +806,9 @@ main (int argc, char *argv[])
 	    fprintf (stderr,
 		     "\nChild exited with status %d\n", signal);
 	  if (status == 'X')
-	    fprintf (stderr, "\nChild terminated with signal = 0x%x\n",
-		     signal);
+	    fprintf (stderr, "\nChild terminated with signal = 0x%x (%s)\n",
+		     target_signal_to_host (signal),
+		     target_signal_to_name (signal));
 	  if (status == 'W' || status == 'X')
 	    {
 	      if (extended_protocol)
Index: src/gdb/gdbserver/config.in
===================================================================
--- src.orig/gdb/gdbserver/config.in	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/config.in	2006-07-18 14:54:46.000000000 -0400
@@ -1,5 +1,8 @@
 /* config.in.  Generated from configure.ac by autoheader.  */
 
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
 /* Define to 1 if you have the declaration of `strerror', and to 0 if you
    don't. */
 #undef HAVE_DECL_STRERROR
@@ -25,6 +28,15 @@
 /* Define to 1 if you have the <memory.h> header file. */
 #undef HAVE_MEMORY_H
 
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the <netinet/tcp.h> header file. */
+#undef HAVE_NETINET_TCP_H
+
 /* Define if <sys/procfs.h> has prgregset_t. */
 #undef HAVE_PRGREGSET_T
 
@@ -59,21 +71,33 @@
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* Define to 1 if you have the <sys/ioctl.h> header file. */
+#undef HAVE_SYS_IOCTL_H
+
 /* Define to 1 if you have the <sys/procfs.h> header file. */
 #undef HAVE_SYS_PROCFS_H
 
 /* Define to 1 if you have the <sys/reg.h> header file. */
 #undef HAVE_SYS_REG_H
 
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
 /* Define to 1 if you have the <sys/stat.h> header file. */
 #undef HAVE_SYS_STAT_H
 
 /* Define to 1 if you have the <sys/types.h> header file. */
 #undef HAVE_SYS_TYPES_H
 
+/* Define to 1 if you have the <sys/wait.h> header file. */
+#undef HAVE_SYS_WAIT_H
+
 /* Define if TD_VERSION is available. */
 #undef HAVE_TD_VERSION
 
+/* Define to 1 if you have the <terminal.h> header file. */
+#undef HAVE_TERMINAL_H
+
 /* Define to 1 if you have the <termios.h> header file. */
 #undef HAVE_TERMIOS_H
 
@@ -103,3 +127,8 @@
 
 /* Define to 1 if you have the ANSI C header files. */
 #undef STDC_HEADERS
+
+/* Define if we should use the Windows API, instead of the POSIX API. On
+   Windows, we use the Windows API when building for MinGW, but the POSIX API
+   when building for Cygwin. */
+#undef USE_WIN32API
Index: src/gdb/gdbserver/configure
===================================================================
--- src.orig/gdb/gdbserver/configure	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/configure	2006-07-18 15:46:39.000000000 -0400
@@ -947,7 +947,7 @@ esac
     else
       echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
     fi
-    cd "$ac_popdir"
+    cd $ac_popdir
   done
 fi
 
@@ -1865,7 +1865,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -1923,7 +1924,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2039,7 +2041,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2093,7 +2096,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2138,7 +2142,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2182,7 +2187,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2708,7 +2714,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2879,7 +2886,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -2923,7 +2931,15 @@ done
 
 
 
-for ac_header in sgtty.h termio.h termios.h sys/reg.h string.h 		 proc_service.h sys/procfs.h thread_db.h linux/elf.h 		 stdlib.h unistd.h
+
+
+
+
+
+
+
+
+for ac_header in sgtty.h termio.h termios.h sys/reg.h string.h 		 proc_service.h sys/procfs.h thread_db.h linux/elf.h 		 stdlib.h unistd.h 		 terminal.h sys/ioctl.h netinet/in.h sys/socket.h netdb.h 		 netinet/tcp.h arpa/inet.h sys/wait.h
 do
 as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
 if eval "test \"\${$as_ac_Header+set}\" = set"; then
@@ -2956,7 +2972,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3104,7 +3121,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3179,7 +3197,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3213,6 +3232,15 @@ fi
 
 . ${srcdir}/configure.srv
 
+if test "${srv_mingw}" = "yes"; then
+  LIBS="$LIBS -lwsock32"
+
+cat >>confdefs.h <<\_ACEOF
+#define USE_WIN32API 1
+_ACEOF
+
+fi
+
 if test "${srv_linux_usrregs}" = "yes"; then
 
 cat >>confdefs.h <<\_ACEOF
@@ -3257,7 +3285,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3318,7 +3347,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3383,7 +3413,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3447,7 +3478,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3511,7 +3543,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3575,7 +3608,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3654,7 +3688,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_l
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3711,7 +3746,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_l
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3776,7 +3812,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_l
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -3833,7 +3870,8 @@ if { (eval echo "$as_me:$LINENO: \"$ac_c
   cat conftest.err >&5
   echo "$as_me:$LINENO: \$? = $ac_status" >&5
   (exit $ac_status); } &&
-	 { ac_try='test -z "$ac_c_werror_flag"			 || test ! -s conftest.err'
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
   { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
   (eval $ac_try) 2>&5
   ac_status=$?
@@ -4686,6 +4724,11 @@ esac
   *) ac_INSTALL=$ac_top_builddir$INSTALL ;;
   esac
 
+  if test x"$ac_file" != x-; then
+    { echo "$as_me:$LINENO: creating $ac_file" >&5
+echo "$as_me: creating $ac_file" >&6;}
+    rm -f "$ac_file"
+  fi
   # Let's still pretend it is `configure' which instantiates (i.e., don't
   # use $as_me), people would be surprised to read:
   #    /* config.h.  Generated by config.status.  */
@@ -4724,12 +4767,6 @@ echo "$as_me: error: cannot find input f
 	 fi;;
       esac
     done` || { (exit 1); exit 1; }
-
-  if test x"$ac_file" != x-; then
-    { echo "$as_me:$LINENO: creating $ac_file" >&5
-echo "$as_me: creating $ac_file" >&6;}
-    rm -f "$ac_file"
-  fi
 _ACEOF
 cat >>$CONFIG_STATUS <<_ACEOF
   sed "$ac_vpsub
Index: src/gdb/gdbserver/win32-i386-low.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/gdbserver/win32-i386-low.c	2006-07-18 15:17:54.000000000 -0400
@@ -0,0 +1,1077 @@
+/* Low level interface to Windows debugging, for gdbserver.
+   Copyright (C) 2006
+   Free Software Foundation, Inc.
+
+   Contributed by Leo Zayas.  Based on "win32-nat.c" from GDB.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "server.h"
+#include "regcache.h"
+#include "gdb/signals.h"
+
+#include <windows.h>
+#include <imagehlp.h>
+#include <psapi.h>
+#include <sys/param.h>
+#include <malloc.h>
+#include <process.h>
+
+#ifndef USE_WIN32API
+#include <sys/cygwin.h>
+#endif
+
+#define LOG 0
+
+#define OUTMSG(X) do { printf X; fflush (stdout); } while (0)
+#if LOG
+#define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
+#else
+#define OUTMSG2(X)
+#endif
+
+int debug_threads;
+int using_threads = 1;
+
+/* Globals.  */
+static HANDLE current_process_handle = NULL;
+static DWORD current_process_id = 0;
+static enum target_signal last_sig = TARGET_SIGNAL_0;
+
+/* The current debug event from WaitForDebugEvent.  */
+static DEBUG_EVENT current_event;
+
+static int debug_registers_changed = 0;
+static int debug_registers_used = 0;
+static unsigned dr[8];
+
+typedef BOOL winapi_DebugActiveProcessStop (DWORD dwProcessId);
+typedef BOOL winapi_DebugSetProcessKillOnExit (BOOL KillOnExit);
+
+#define FLAG_TRACE_BIT 0x100
+#define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
+#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS	\
+  | CONTEXT_EXTENDED_REGISTERS
+
+/* Thread information structure used to track extra information about
+   each thread.  */
+typedef struct thread_info_struct
+{
+  DWORD tid;
+  HANDLE h;
+  int suspend_count;
+  CONTEXT context;
+} thread_info;
+static DWORD main_thread_id = 0;
+
+/* Get the thread ID from the current selected inferior (the current
+   thread).  */
+static DWORD
+current_inferior_tid (void)
+{
+  thread_info *th = inferior_target_data (current_inferior);
+  return th->tid;
+}
+
+/* Find a thread record given a thread id.  If GET_CONTEXT is set then
+   also retrieve the context for this thread.  */
+static thread_info *
+thread_rec (DWORD id, int get_context)
+{
+  struct thread_info *thread;
+  thread_info *th;
+
+  thread = (struct thread_info *) find_inferior_id (&all_threads, id);
+  if (thread == NULL)
+    return NULL;
+
+  th = inferior_target_data (thread);
+  if (!th->suspend_count && get_context)
+    {
+      if (get_context > 0 && id != current_event.dwThreadId)
+	th->suspend_count = SuspendThread (th->h) + 1;
+      else if (get_context < 0)
+	th->suspend_count = -1;
+
+      th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
+
+      GetThreadContext (th->h, &th->context);
+
+      if (id == current_event.dwThreadId)
+	{
+	  /* Copy dr values from that thread.  */
+	  dr[0] = th->context.Dr0;
+	  dr[1] = th->context.Dr1;
+	  dr[2] = th->context.Dr2;
+	  dr[3] = th->context.Dr3;
+	  dr[6] = th->context.Dr6;
+	  dr[7] = th->context.Dr7;
+	}
+    }
+
+  return th;
+}
+
+/* Add a thread to the thread list.  */
+static thread_info *
+child_add_thread (DWORD tid, HANDLE h)
+{
+  thread_info *th;
+
+  if ((th = thread_rec (tid, FALSE)))
+    return th;
+
+  th = (thread_info *) malloc (sizeof (*th));
+  memset (th, 0, sizeof (*th));
+  th->tid = tid;
+  th->h = h;
+
+  add_thread (tid, th, (unsigned int) tid);
+  set_inferior_regcache_data ((struct thread_info *)
+			      find_inferior_id (&all_threads, tid),
+			      new_register_cache ());
+
+  /* Set the debug registers for the new thread if they are used.  */
+  if (debug_registers_used)
+    {
+      /* Only change the value of the debug registers.  */
+      th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
+
+      GetThreadContext (th->h, &th->context);
+
+      th->context.Dr0 = dr[0];
+      th->context.Dr1 = dr[1];
+      th->context.Dr2 = dr[2];
+      th->context.Dr3 = dr[3];
+      /* th->context.Dr6 = dr[6];
+         FIXME: should we set dr6 also ?? */
+      th->context.Dr7 = dr[7];
+      SetThreadContext (th->h, &th->context);
+      th->context.ContextFlags = 0;
+    }
+
+  return th;
+}
+
+/* Delete a thread from the list of threads.  */
+static void
+delete_thread_info (struct inferior_list_entry *thread)
+{
+  thread_info *th = inferior_target_data ((struct thread_info *) thread);
+
+  remove_thread ((struct thread_info *) thread);
+  CloseHandle (th->h);
+  free (th);
+}
+
+/* Delete a thread from the list of threads.  */
+static void
+child_delete_thread (DWORD id)
+{
+  struct inferior_list_entry *thread;
+
+  /* If the last thread is exiting, just return.  */
+  if (all_threads.head == all_threads.tail)
+    return;
+
+  thread = find_inferior_id (&all_threads, id);
+  if (thread == NULL)
+    return;
+
+  delete_thread_info (thread);
+}
+
+/* Transfer memory from/to the debugged process.  */
+static int
+child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
+		   int write, struct target_ops *target)
+{
+  SIZE_T done;
+  long addr = (long) memaddr;
+
+  if (write)
+    {
+      WriteProcessMemory (current_process_handle, (LPVOID) addr,
+			  (LPCVOID) our, len, &done);
+      FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
+    }
+  else
+    {
+      ReadProcessMemory (current_process_handle, (LPCVOID) addr, (LPVOID) our,
+			 len, &done);
+    }
+  return done;
+}
+
+/* Generally, what has the program done?  */
+enum target_waitkind
+{
+  /* The program has exited.  The exit status is in value.integer.  */
+  TARGET_WAITKIND_EXITED,
+
+  /* The program has stopped with a signal.  Which signal is in
+     value.sig.  */
+  TARGET_WAITKIND_STOPPED,
+
+  /* The program is letting us know that it dynamically loaded something
+     (e.g. it called load(2) on AIX).  */
+  TARGET_WAITKIND_LOADED,
+
+  /* The program has exec'ed a new executable file.  The new file's
+     pathname is pointed to by value.execd_pathname.  */
+
+  TARGET_WAITKIND_EXECD,
+
+  /* Nothing happened, but we stopped anyway.  This perhaps should be handled
+     within target_wait, but I'm not sure target_wait should be resuming the
+     inferior.  */
+  TARGET_WAITKIND_SPURIOUS,
+};
+
+struct target_waitstatus
+{
+  enum target_waitkind kind;
+
+  /* Forked child pid, execd pathname, exit status or signal number.  */
+  union
+  {
+    int integer;
+    enum target_signal sig;
+    int related_pid;
+    char *execd_pathname;
+    int syscall_id;
+  }
+  value;
+};
+
+#define NUM_REGS 41
+#define FCS_REGNUM 27
+#define FOP_REGNUM 31
+
+#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
+static const int mappings[] = {
+  context_offset (Eax),
+  context_offset (Ecx),
+  context_offset (Edx),
+  context_offset (Ebx),
+  context_offset (Esp),
+  context_offset (Ebp),
+  context_offset (Esi),
+  context_offset (Edi),
+  context_offset (Eip),
+  context_offset (EFlags),
+  context_offset (SegCs),
+  context_offset (SegSs),
+  context_offset (SegDs),
+  context_offset (SegEs),
+  context_offset (SegFs),
+  context_offset (SegGs),
+  context_offset (FloatSave.RegisterArea[0 * 10]),
+  context_offset (FloatSave.RegisterArea[1 * 10]),
+  context_offset (FloatSave.RegisterArea[2 * 10]),
+  context_offset (FloatSave.RegisterArea[3 * 10]),
+  context_offset (FloatSave.RegisterArea[4 * 10]),
+  context_offset (FloatSave.RegisterArea[5 * 10]),
+  context_offset (FloatSave.RegisterArea[6 * 10]),
+  context_offset (FloatSave.RegisterArea[7 * 10]),
+  context_offset (FloatSave.ControlWord),
+  context_offset (FloatSave.StatusWord),
+  context_offset (FloatSave.TagWord),
+  context_offset (FloatSave.ErrorSelector),
+  context_offset (FloatSave.ErrorOffset),
+  context_offset (FloatSave.DataSelector),
+  context_offset (FloatSave.DataOffset),
+  context_offset (FloatSave.ErrorSelector),
+  /* XMM0-7 */
+  context_offset (ExtendedRegisters[10 * 16]),
+  context_offset (ExtendedRegisters[11 * 16]),
+  context_offset (ExtendedRegisters[12 * 16]),
+  context_offset (ExtendedRegisters[13 * 16]),
+  context_offset (ExtendedRegisters[14 * 16]),
+  context_offset (ExtendedRegisters[15 * 16]),
+  context_offset (ExtendedRegisters[16 * 16]),
+  context_offset (ExtendedRegisters[17 * 16]),
+  /* MXCSR */
+  context_offset (ExtendedRegisters[24])
+};
+
+#undef context_offset
+
+/* Clear out any old thread list and reintialize it to a pristine
+   state. */
+static void
+child_init_thread_list (void)
+{
+  for_each_inferior (&all_threads, delete_thread_info);
+}
+
+static void
+do_initial_child_stuff (DWORD pid)
+{
+  int i;
+
+  last_sig = TARGET_SIGNAL_0;
+
+  debug_registers_changed = 0;
+  debug_registers_used = 0;
+  for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
+    dr[i] = 0;
+  memset (&current_event, 0, sizeof (current_event));
+
+  child_init_thread_list ();
+}
+
+/* Resume all artificially suspended threads if we are continuing
+   execution.  */
+static int
+continue_one_thread (struct inferior_list_entry *this_thread, void *id_ptr)
+{
+  struct thread_info *thread = (struct thread_info *) this_thread;
+  int thread_id = * (int *) id_ptr;
+  thread_info *th = inferior_target_data (thread);
+  int i;
+
+  if ((thread_id == -1 || thread_id == th->tid)
+      && th->suspend_count)
+    {
+      for (i = 0; i < th->suspend_count; i++)
+	(void) ResumeThread (th->h);
+      th->suspend_count = 0;
+      if (debug_registers_changed)
+	{
+	  /* Only change the value of the debug registers.  */
+	  th->context.ContextFlags = CONTEXT_DEBUG_REGISTERS;
+	  th->context.Dr0 = dr[0];
+	  th->context.Dr1 = dr[1];
+	  th->context.Dr2 = dr[2];
+	  th->context.Dr3 = dr[3];
+	  /* th->context.Dr6 = dr[6];
+	     FIXME: should we set dr6 also ?? */
+	  th->context.Dr7 = dr[7];
+	  SetThreadContext (th->h, &th->context);
+	  th->context.ContextFlags = 0;
+	}
+    }
+
+  return 0;
+}
+
+static BOOL
+child_continue (DWORD continue_status, int thread_id)
+{
+  BOOL res;
+
+  res = ContinueDebugEvent (current_event.dwProcessId,
+			    current_event.dwThreadId, continue_status);
+  continue_status = 0;
+  if (res)
+    find_inferior (&all_threads, continue_one_thread, &thread_id);
+
+  debug_registers_changed = 0;
+  return res;
+}
+
+/* Fetch register(s) from gdbserver regcache data.  */
+static void
+do_child_fetch_inferior_registers (thread_info *th, int r)
+{
+  char *context_offset = ((char *) &th->context) + mappings[r];
+  long l;
+  if (r == FCS_REGNUM)
+    {
+      l = *((long *) context_offset) & 0xffff;
+      supply_register (r, (char *) &l);
+    }
+  else if (r == FOP_REGNUM)
+    {
+      l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
+      supply_register (r, (char *) &l);
+    }
+  else
+    supply_register (r, context_offset);
+}
+
+/* Fetch register(s) from the current thread context.  */
+static void
+child_fetch_inferior_registers (int r)
+{
+  int regno;
+  thread_info *th = thread_rec (current_inferior_tid (), TRUE);
+  if (r == -1 || r == 0 || r > NUM_REGS)
+    child_fetch_inferior_registers (NUM_REGS);
+  else
+    for (regno = 0; regno < r; regno++)
+      do_child_fetch_inferior_registers (th, regno);
+}
+
+/* Get register from gdbserver regcache data.  */
+static void
+do_child_store_inferior_registers (thread_info *th, int r)
+{
+  collect_register (r, ((char *) &th->context) + mappings[r]);
+}
+
+/* Store a new register value into the current thread context.  We don't
+   change the program's context until later, when we resume it.  */
+static void
+child_store_inferior_registers (int r)
+{
+  int regno;
+  thread_info *th = thread_rec (current_inferior_tid (), TRUE);
+  if (r == -1 || r == 0 || r > NUM_REGS)
+    child_store_inferior_registers (NUM_REGS);
+  else
+    for (regno = 0; regno < r; regno++)
+      do_child_store_inferior_registers (th, regno);
+}
+
+/* Start a new process.
+   PROGRAM is a path to the program to execute.
+   ARGS is a standard NULL-terminated array of arguments,
+   to be passed to the inferior as ``argv''.
+   Returns the new PID on success, -1 on failure.  Registers the new
+   process with the process list.  */
+static int
+win32_create_inferior (char *program, char **program_args)
+{
+#ifndef USE_WIN32API
+  char real_path[MAXPATHLEN];
+  char *orig_path, *new_path, *path_ptr;
+#endif
+  char *winenv = NULL;
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+  BOOL ret;
+  DWORD flags;
+  char *args;
+  int argslen;
+  int argc;
+
+  if (!program)
+    error ("No executable specified, specify executable to debug.\n");
+
+  memset (&si, 0, sizeof (si));
+  si.cb = sizeof (si);
+
+  flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
+
+#ifndef USE_WIN32API
+  orig_path = NULL;
+  path_ptr = getenv ("PATH");
+  if (path_ptr)
+    {
+      orig_path = alloca (strlen (path_ptr) + 1);
+      new_path = alloca (cygwin_posix_to_win32_path_list_buf_size (path_ptr));
+      strcpy (orig_path, path_ptr);
+      cygwin_posix_to_win32_path_list (path_ptr, new_path);
+      setenv ("PATH", new_path, 1);
+    }
+  cygwin_conv_to_win32_path (program, real_path);
+  program = real_path;
+#endif
+
+  argslen = strlen (program) + 1;
+  for (argc = 1; program_args[argc]; argc++)
+    argslen += strlen (program_args[argc]) + 1;
+  args = alloca (argslen);
+  strcpy (args, program);
+  for (argc = 1; program_args[argc]; argc++)
+    {
+      /* FIXME: Can we do better about quoting?  How does Cygwin
+         handle this?  */
+      strcat (args, " ");
+      strcat (args, program_args[argc]);
+    }
+  OUTMSG2 (("Command line is %s\n", args));
+
+  flags |= CREATE_NEW_PROCESS_GROUP;
+
+  ret = CreateProcess (0, args,	/* command line */
+		       NULL,	/* Security */
+		       NULL,	/* thread */
+		       TRUE,	/* inherit handles */
+		       flags,	/* start flags */
+		       winenv, NULL,	/* current directory */
+		       &si, &pi);
+
+#ifndef USE_WIN32API
+  if (orig_path)
+    setenv ("PATH", orig_path, 1);
+#endif
+
+  if (!ret)
+    {
+      error ("Error creating process %s, (error %d): %s\n", args,
+	     (int) GetLastError (), strerror (GetLastError ()));
+    }
+  else
+    {
+      OUTMSG2 (("Process created: %s\n", (char *) args));
+    }
+
+  CloseHandle (pi.hThread);
+
+  current_process_handle = pi.hProcess;
+  current_process_id = pi.dwProcessId;
+
+  do_initial_child_stuff (current_process_id);
+
+  return current_process_id;
+}
+
+/* Attach to a running process.
+   PID is the process ID to attach to, specified by the user
+   or a higher layer.  */
+static int
+win32_attach (unsigned long pid)
+{
+  int res = 0;
+  HMODULE kernel32 = LoadLibrary ("KERNEL32.DLL");
+  winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
+  winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
+
+  DebugActiveProcessStop =
+    (winapi_DebugActiveProcessStop *) GetProcAddress (kernel32,
+						      "DebugActiveProcessStop");
+  DebugSetProcessKillOnExit =
+    (winapi_DebugSetProcessKillOnExit *) GetProcAddress (kernel32,
+							 "DebugSetProcessKillOnExit");
+
+  res = DebugActiveProcess (pid) ? 1 : 0;
+
+  if (!res)
+    error ("Attach to process failed.");
+
+  if (DebugSetProcessKillOnExit != NULL)
+    DebugSetProcessKillOnExit (FALSE);
+
+  current_process_id = pid;
+  current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
+
+  if (current_process_handle == NULL)
+    {
+      res = 0;
+      if (DebugActiveProcessStop != NULL)
+	DebugActiveProcessStop (current_process_id);
+    }
+
+  if (res)
+    do_initial_child_stuff (pid);
+
+  FreeLibrary (kernel32);
+
+  return res;
+}
+
+/* Kill all inferiors.  */
+static void
+win32_kill (void)
+{
+  TerminateProcess (current_process_handle, 0);
+  for (;;)
+    {
+      if (!child_continue (DBG_CONTINUE, -1))
+	break;
+      if (!WaitForDebugEvent (&current_event, INFINITE))
+	break;
+      if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
+	break;
+    }
+}
+
+/* Detach from all inferiors.  */
+static void
+win32_detach (void)
+{
+  HMODULE kernel32 = LoadLibrary ("KERNEL32.DLL");
+  winapi_DebugActiveProcessStop *DebugActiveProcessStop = NULL;
+  winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
+
+  DebugActiveProcessStop =
+    (winapi_DebugActiveProcessStop *) GetProcAddress (kernel32,
+						      "DebugActiveProcessStop");
+  DebugSetProcessKillOnExit =
+    (winapi_DebugSetProcessKillOnExit *) GetProcAddress (kernel32,
+							 "DebugSetProcessKillOnExit");
+
+  if (DebugSetProcessKillOnExit != NULL)
+    DebugSetProcessKillOnExit (FALSE);
+
+  if (DebugActiveProcessStop != NULL)
+    DebugActiveProcessStop (current_process_id);
+  else
+    win32_kill ();
+
+  FreeLibrary (kernel32);
+}
+
+/* Return 1 iff the thread with thread ID TID is alive.  */
+static int
+win32_thread_alive (unsigned long tid)
+{
+  int res;
+
+  /* Our thread list is reliable; don't bother to poll target
+     threads.  */
+  if (find_inferior_id (&all_threads, tid) != NULL)
+    res = 1;
+  else
+    res = 0;
+  return res;
+}
+
+/* Resume the inferior process.  RESUME_INFO describes how we want
+   to resume.  */
+static void
+win32_resume (struct thread_resume *resume_info)
+{
+  DWORD tid;
+  enum target_signal sig;
+  int step;
+  thread_info *th;
+  DWORD continue_status = DBG_CONTINUE;
+
+  /* This handles the very limited set of resume packets that GDB can
+     currently produce.  */
+
+  if (resume_info[0].thread == -1)
+    tid = -1;
+  else if (resume_info[1].thread == -1 && !resume_info[1].leave_stopped)
+    tid = -1;
+  else
+    /* Yes, we're ignoring resume_info[0].thread.  It'd be tricky to make
+       the Windows resume code do the right thing for thread switching.  */
+    tid = current_event.dwThreadId;
+
+  if (resume_info[0].thread != -1)
+    {
+      sig = resume_info[0].sig;
+      step = resume_info[0].step;
+    }
+  else
+    {
+      sig = 0;
+      step = 0;
+    }
+
+  if (sig != TARGET_SIGNAL_0)
+    {
+      if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
+	{
+	  OUTMSG (("Cannot continue with signal %d here.\n", sig));
+	}
+      else if (sig == last_sig)
+	continue_status = DBG_EXCEPTION_NOT_HANDLED;
+      else
+	OUTMSG (("Can only continue with recieved signal %d.\n", last_sig));
+    }
+
+  last_sig = TARGET_SIGNAL_0;
+
+  /* Get context for the currently selected thread.  */
+  th = thread_rec (current_event.dwThreadId, FALSE);
+  if (th)
+    {
+      if (th->context.ContextFlags)
+	{
+	  if (debug_registers_changed)
+	    {
+	      th->context.Dr0 = dr[0];
+	      th->context.Dr1 = dr[1];
+	      th->context.Dr2 = dr[2];
+	      th->context.Dr3 = dr[3];
+	      /* th->context.Dr6 = dr[6];
+	         FIXME: should we set dr6 also ?? */
+	      th->context.Dr7 = dr[7];
+	    }
+
+	  /* Move register values from the inferior into the thread
+	     context structure.  */
+	  regcache_invalidate ();
+
+	  if (step)
+	    th->context.EFlags |= FLAG_TRACE_BIT;
+
+	  SetThreadContext (th->h, &th->context);
+	  th->context.ContextFlags = 0;
+	}
+    }
+
+  /* Allow continuing with the same signal that interrupted us.
+     Otherwise complain.  */
+
+  child_continue (continue_status, tid);
+}
+
+static int
+handle_exception (struct target_waitstatus *ourstatus)
+{
+  thread_info *th;
+  DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
+
+  ourstatus->kind = TARGET_WAITKIND_STOPPED;
+
+  /* Record the context of the current thread.  */
+  th = thread_rec (current_event.dwThreadId, -1);
+
+  switch (code)
+    {
+    case EXCEPTION_ACCESS_VIOLATION:
+      OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
+      ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+      break;
+    case STATUS_STACK_OVERFLOW:
+      OUTMSG2 (("STATUS_STACK_OVERFLOW"));
+      ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+      break;
+    case STATUS_FLOAT_DENORMAL_OPERAND:
+      OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
+      OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_FLOAT_INEXACT_RESULT:
+      OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_FLOAT_INVALID_OPERATION:
+      OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_FLOAT_OVERFLOW:
+      OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_FLOAT_STACK_CHECK:
+      OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_FLOAT_UNDERFLOW:
+      OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_FLOAT_DIVIDE_BY_ZERO:
+      OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_INTEGER_DIVIDE_BY_ZERO:
+      OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case STATUS_INTEGER_OVERFLOW:
+      OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
+      ourstatus->value.sig = TARGET_SIGNAL_FPE;
+      break;
+    case EXCEPTION_BREAKPOINT:
+      OUTMSG2 (("EXCEPTION_BREAKPOINT"));
+      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+      break;
+    case DBG_CONTROL_C:
+      OUTMSG2 (("DBG_CONTROL_C"));
+      ourstatus->value.sig = TARGET_SIGNAL_INT;
+      break;
+    case DBG_CONTROL_BREAK:
+      OUTMSG2 (("DBG_CONTROL_BREAK"));
+      ourstatus->value.sig = TARGET_SIGNAL_INT;
+      break;
+    case EXCEPTION_SINGLE_STEP:
+      OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
+      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+      break;
+    case EXCEPTION_ILLEGAL_INSTRUCTION:
+      OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
+      ourstatus->value.sig = TARGET_SIGNAL_ILL;
+      break;
+    case EXCEPTION_PRIV_INSTRUCTION:
+      OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
+      ourstatus->value.sig = TARGET_SIGNAL_ILL;
+      break;
+    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
+      OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
+      ourstatus->value.sig = TARGET_SIGNAL_ILL;
+      break;
+    default:
+      if (current_event.u.Exception.dwFirstChance)
+	return 0;
+      OUTMSG2 (("gdbserver: unknown target exception 0x%08lx at 0x%08lx",
+		current_event.u.Exception.ExceptionRecord.ExceptionCode,
+		(DWORD) current_event.u.Exception.ExceptionRecord.
+		ExceptionAddress));
+      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+      break;
+    }
+  OUTMSG2 (("\n"));
+  last_sig = ourstatus->value.sig;
+  return 1;
+}
+
+/* Get the next event from the child.  Return 1 if the event requires
+   handling.  */
+static int
+get_child_debug_event (struct target_waitstatus *ourstatus)
+{
+  BOOL debug_event;
+  DWORD continue_status, event_code;
+  thread_info *th = NULL;
+  static thread_info dummy_thread_info;
+  int retval = 0;
+
+in:
+
+  last_sig = TARGET_SIGNAL_0;
+  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+
+  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
+    goto out;
+
+  current_inferior =
+    (struct thread_info *) find_inferior_id (&all_threads,
+					     current_event.dwThreadId);
+
+  continue_status = DBG_CONTINUE;
+  event_code = current_event.dwDebugEventCode;
+
+  switch (event_code)
+    {
+    case CREATE_THREAD_DEBUG_EVENT:
+      OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
+		"for pid=%d tid=%x)\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+
+      /* Record the existence of this thread.  */
+      th = child_add_thread (current_event.dwThreadId,
+			     current_event.u.CreateThread.hThread);
+
+      retval = current_event.dwThreadId;
+      break;
+
+    case EXIT_THREAD_DEBUG_EVENT:
+      OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
+		"for pid=%d tid=%x\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+      child_delete_thread (current_event.dwThreadId);
+      th = &dummy_thread_info;
+      break;
+
+    case CREATE_PROCESS_DEBUG_EVENT:
+      OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
+		"for pid=%d tid=%x\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+      CloseHandle (current_event.u.CreateProcessInfo.hFile);
+
+      current_process_handle = current_event.u.CreateProcessInfo.hProcess;
+      main_thread_id = current_event.dwThreadId;
+
+      ourstatus->kind = TARGET_WAITKIND_EXECD;
+      ourstatus->value.execd_pathname = "Main executable";
+
+      /* Add the main thread.  */
+      th =
+	child_add_thread (main_thread_id,
+			  current_event.u.CreateProcessInfo.hThread);
+
+      retval = ourstatus->value.related_pid = current_event.dwThreadId;
+      break;
+
+    case EXIT_PROCESS_DEBUG_EVENT:
+      OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
+		"for pid=%d tid=%x\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+      ourstatus->kind = TARGET_WAITKIND_EXITED;
+      ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
+      CloseHandle (current_process_handle);
+      retval = main_thread_id;
+      break;
+
+    case LOAD_DLL_DEBUG_EVENT:
+      OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
+		"for pid=%d tid=%x\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+      CloseHandle (current_event.u.LoadDll.hFile);
+
+      ourstatus->kind = TARGET_WAITKIND_LOADED;
+      ourstatus->value.integer = 0;
+      retval = main_thread_id;
+      break;
+
+    case UNLOAD_DLL_DEBUG_EVENT:
+      OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
+		"for pid=%d tid=%x\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+      break;
+
+    case EXCEPTION_DEBUG_EVENT:
+      OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
+		"for pid=%d tid=%x\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+      retval = handle_exception (ourstatus);
+      break;
+
+    case OUTPUT_DEBUG_STRING_EVENT:
+      /* A message from the kernel (or Cygwin).  */
+      OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
+		"for pid=%d tid=%x\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId));
+      break;
+
+    default:
+      OUTMSG2 (("gdbserver: kernel event unknown "
+		"for pid=%d tid=%x code=%ld\n",
+		(unsigned) current_event.dwProcessId,
+		(unsigned) current_event.dwThreadId,
+		current_event.dwDebugEventCode));
+      break;
+    }
+
+  current_inferior =
+    (struct thread_info *) find_inferior_id (&all_threads,
+					     current_event.dwThreadId);
+
+  if (!retval || (event_code != EXCEPTION_DEBUG_EVENT && event_code != EXIT_PROCESS_DEBUG_EVENT))
+    {
+      child_continue (continue_status, -1);
+      goto in;
+    }
+
+  if (th == NULL)
+    thread_rec (current_event.dwThreadId, TRUE);
+
+out:
+  return retval;
+}
+
+/* Wait for the inferior process to change state.
+   STATUS will be filled in with a response code to send to GDB.
+   Returns the signal which caused the process to stop. */
+static unsigned char
+win32_wait (char *status)
+{
+  struct target_waitstatus our_status;
+
+  *status = 'T';
+
+  while (1)
+    {
+      get_child_debug_event (&our_status);
+
+      if (our_status.kind == TARGET_WAITKIND_EXITED)
+	{
+	  OUTMSG2 (("Child exited with retcode = %x\n",
+		    our_status.value.integer));
+
+	  *status = 'W';
+
+	  child_fetch_inferior_registers (-1);
+
+	  return our_status.value.integer;
+	}
+      else if (our_status.kind == TARGET_WAITKIND_STOPPED)
+	{
+	  OUTMSG2 (("Child Stopped with signal = %x \n",
+		    WSTOPSIG (our_status.value.sig)));
+
+	  *status = 'T';
+
+	  child_fetch_inferior_registers (-1);
+
+	  return our_status.value.sig;
+	}
+      else
+	OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
+
+      {
+	struct thread_resume resume;
+	resume.thread = -1;
+	resume.step = 0;
+	resume.sig = 0;
+	resume.leave_stopped = 0;
+	win32_resume (&resume);
+      }
+    }
+}
+
+/* Fetch registers from the inferior process.
+   If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO.  */
+static void
+win32_fetch_inferior_registers (int regno)
+{
+  child_fetch_inferior_registers (regno);
+}
+
+/* Store registers to the inferior process.
+   If REGNO is -1, store all registers; otherwise, store at least REGNO.  */
+static void
+win32_store_inferior_registers (int regno)
+{
+  child_store_inferior_registers (regno);
+}
+
+/* Read memory from the inferior process.  This should generally be
+   called through read_inferior_memory, which handles breakpoint shadowing.
+   Read LEN bytes at MEMADDR into a buffer at MYADDR.  */
+static int
+win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
+{
+  return child_xfer_memory (memaddr, myaddr, len, 0, 0) != len;
+}
+
+/* Write memory to the inferior process.  This should generally be
+   called through write_inferior_memory, which handles breakpoint shadowing.
+   Write LEN bytes from the buffer at MYADDR to MEMADDR.
+   Returns 0 on success and errno on failure.  */
+static int
+win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
+			     int len)
+{
+  return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
+}
+
+static struct target_ops win32_target_ops = {
+  win32_create_inferior,
+  win32_attach,
+  win32_kill,
+  win32_detach,
+  win32_thread_alive,
+  win32_resume,
+  win32_wait,
+  win32_fetch_inferior_registers,
+  win32_store_inferior_registers,
+  win32_read_inferior_memory,
+  win32_write_inferior_memory,
+  0,
+  0
+};
+
+/* Initialize the Win32 backend.  */
+void
+initialize_low (void)
+{
+  set_target_ops (&win32_target_ops);
+
+  init_registers ();
+}
Index: src/gdb/gdbserver/Makefile.in
===================================================================
--- src.orig/gdb/gdbserver/Makefile.in	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/Makefile.in	2006-07-18 15:32:38.000000000 -0400
@@ -139,6 +139,7 @@ OBS = inferiors.o regcache.o remote-util
 	mem-break.o \
 	$(DEPFILES)
 GDBSERVER_LIBS = @GDBSERVER_LIBS@
+XM_CLIBS = @LIBS@
 
 # Prevent Sun make from putting in the machine type.  Setting
 # TARGET_ARCH to nothing works for SunOS 3, 4.0, but not for 4.1.
@@ -176,12 +177,12 @@ clean-info:
 
 gdbserver: $(OBS) ${ADD_DEPS} ${CDEPS}
 	rm -f gdbserver
-	${CC-LD} $(GLOBAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbserver $(OBS) \
+	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbserver $(OBS) \
 	  $(GDBSERVER_LIBS) $(XM_CLIBS)
 
 gdbreplay: gdbreplay.o
 	rm -f gdbreplay
-	${CC-LD} $(GLOBAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay gdbreplay.o \
+	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay gdbreplay.o \
 	  $(XM_CLIBS)
 
 # Put the proper machine-specific files first, so M-. on a machine
@@ -286,6 +287,8 @@ linux-sh-low.o: linux-sh-low.c $(linux_l
 linux-x86-64-low.o: linux-x86-64-low.c $(linux_low_h) $(server_h) \
 	$(gdb_proc_service_h)
 
+win32-i386-low.o: win32-i386-low.c $(server_h) $(regdef_h) $(regcache_h)
+
 reg-arm.o : reg-arm.c $(regdef_h)
 reg-arm.c : $(srcdir)/../regformats/reg-arm.dat $(regdat_sh)
 	sh $(regdat_sh) $(srcdir)/../regformats/reg-arm.dat reg-arm.c
Index: src/gdb/gdbserver/linux-low.c
===================================================================
--- src.orig/gdb/gdbserver/linux-low.c	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/linux-low.c	2006-07-18 14:54:46.000000000 -0400
@@ -714,7 +714,7 @@ retry:
 	  clear_inferiors ();
 	  free (all_processes.head);
 	  all_processes.head = all_processes.tail = NULL;
-	  return ((unsigned char) WEXITSTATUS (w));
+	  return WEXITSTATUS (w);
 	}
       else if (!WIFSTOPPED (w))
 	{
@@ -723,7 +723,7 @@ retry:
 	  clear_inferiors ();
 	  free (all_processes.head);
 	  all_processes.head = all_processes.tail = NULL;
-	  return ((unsigned char) WTERMSIG (w));
+	  return target_signal_from_host (WTERMSIG (w));
 	}
     }
   else
@@ -733,7 +733,7 @@ retry:
     }
 
   *status = 'T';
-  return ((unsigned char) WSTOPSIG (w));
+  return target_signal_from_host (WSTOPSIG (w));
 }
 
 /* Send a signal to an LWP.  For LinuxThreads, kill is enough; however, if
Index: src/gdb/gdbserver/target.h
===================================================================
--- src.orig/gdb/gdbserver/target.h	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/target.h	2006-07-18 14:54:46.000000000 -0400
@@ -81,9 +81,11 @@ struct target_ops
 
   /* Wait for the inferior process to change state.
 
-     STATUSP will be filled in with a response code to send to GDB.
+     STATUS will be filled in with a response code to send to GDB.
 
-     Returns the signal which caused the process to stop.  */
+     Returns the signal which caused the process to stop, in the
+     remote protocol numbering (e.g. TARGET_SIGNAL_STOP), or the
+     exit code as an integer if *STATUS is 'W'.  */
 
   unsigned char (*wait) (char *status);
 
Index: src/gdb/configure.tgt
===================================================================
--- src.orig/gdb/configure.tgt	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/configure.tgt	2006-07-18 14:54:46.000000000 -0400
@@ -97,7 +97,12 @@ i[34567]86-*-linux*)	gdb_target=linux
 			;;
 i[34567]86-*-gnu*)	gdb_target=i386gnu ;;
 i[34567]86-*-netware*)	gdb_target=i386 ;;
-i[34567]86-*-cygwin*)	gdb_target=cygwin  ;;
+i[34567]86-*-cygwin*)	gdb_target=cygwin
+			build_gdbserver=yes
+			;;
+i[34567]86-*-mingw32*)	gdb_target=i386
+			build_gdbserver=yes
+			;;
 i[34567]86-*-*)		gdb_target=i386 ;;
 
 ia64-*-linux*)		gdb_target=linux
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2006-07-18 14:54:36.000000000 -0400
+++ src/gdb/gdbserver/server.h	2006-07-18 14:54:46.000000000 -0400
@@ -171,6 +171,7 @@ int look_up_one_symbol (const char *name
 enum target_signal target_signal_from_host (int hostsig);
 int target_signal_to_host_p (enum target_signal oursig);
 int target_signal_to_host (enum target_signal oursig);
+char *target_signal_to_name (enum target_signal);
 
 /* Functions from utils.c */
 
Index: src/gdb/gdbserver/gdbreplay.c
===================================================================
--- src.orig/gdb/gdbserver/gdbreplay.c	2006-07-18 15:24:11.000000000 -0400
+++ src/gdb/gdbserver/gdbreplay.c	2006-07-18 15:29:31.000000000 -0400
@@ -1,5 +1,5 @@
 /* Replay a remote debug session logfile for GDB.
-   Copyright (C) 1996, 1998, 1999, 2000, 2002, 2003, 2005
+   Copyright (C) 1996, 1998, 1999, 2000, 2002, 2003, 2005, 2006
    Free Software Foundation, Inc.
    Written by Fred Fish (fnf@cygnus.com) from pieces of gdbserver.
 
@@ -23,10 +23,6 @@
 #include "config.h"
 #include <stdio.h>
 #include <sys/file.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <netdb.h>
-#include <netinet/tcp.h>
 #include <signal.h>
 #include <ctype.h>
 #include <fcntl.h>
@@ -41,6 +37,22 @@
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#if HAVE_NETDB_H
+#include <netdb.h>
+#endif
+#if HAVE_NETINET_TCP_H
+#include <netinet/tcp.h>
+#endif
+
+#if USE_WIN32API
+#include <winsock.h>
+#endif
 
 #ifndef HAVE_SOCKLEN_T
 typedef int socklen_t;
@@ -90,7 +102,11 @@ sync_error (FILE *fp, char *desc, int ex
 static void
 remote_close (void)
 {
+#ifdef USE_WIN32API
+  closesocket (remote_desc);
+#else
   close (remote_desc);
+#endif
 }
 
 /* Open a connection to a remote debugger.
@@ -107,6 +123,9 @@ remote_open (char *name)
     }
   else
     {
+#ifdef USE_WIN32API
+      static int winsock_initialized;
+#endif
       char *port_str;
       int port;
       struct sockaddr_in sockaddr;
@@ -117,6 +136,16 @@ remote_open (char *name)
 
       port = atoi (port_str + 1);
 
+#ifdef USE_WIN32API
+      if (!winsock_initialized)
+	{
+	  WSADATA wsad;
+
+	  WSAStartup (MAKEWORD (1, 0), &wsad);
+	  winsock_initialized = 1;
+	}
+#endif
+
       tmp_desc = socket (PF_INET, SOCK_STREAM, 0);
       if (tmp_desc < 0)
 	perror_with_name ("Can't open socket");
@@ -151,11 +180,19 @@ remote_open (char *name)
 
       close (tmp_desc);		/* No longer need this */
 
+#ifndef USE_WIN32API
+      close (tmp_desc);		/* No longer need this */
+
       signal (SIGPIPE, SIG_IGN);	/* If we don't do this, then gdbreplay simply
 					   exits when the remote side dies.  */
+#else
+      closesocket (tmp_desc);	/* No longer need this */
+#endif
     }
 
+#if defined(F_SETFL) && defined (FASYNC)
   fcntl (remote_desc, F_SETFL, FASYNC);
+#endif
 
   fprintf (stderr, "Replay logfile using %s\n", name);
   fflush (stderr);


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]