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]

[New WinCE support] [patch 4/4] The bulk of the code.


This patch is the bulk of the new WinCE support.
It contains:

     - The new WinCE support on gdb/ side.
     - The gdbserver port.

WinCE has the following (and a few more) twists:
         - No errno/perror/strerror - The runtime only knows about
           GetLastError/SetLastError.
         - No signals support.
         - The initial breakpoint (the automatically inserted
           at the entry point breakpoint) must be inserted manually.
         - All programs link to coredll.dll instead of kernel32.dll.
         - CreateProcess has the same signature as the 9x/NT Windows,
           but a bunch of parameters are unsupported, and the
           image name (first param) must never be null.

There was a little bug in win32-low.c
(original win32-i386-low.c).  There was a call to
strerror (GetLastError ()), but strerror should take an errno
value, not a winerror, as the error codes are not compatible.
That was fixed by using a new strwinerror function, that is
used also as a replacement for strerror on WinCE.

The patch moves the gdbserver i386 specifics into a new
win32-i386-low.c, and the new arm stuff into
win32-arm-low.c.  The changes were modelled on the linux
support.  It was done this way to minimize the #ifdefery.

The arm/i386 differences are mostly:
    - the gdb/'win32 Context' register mappings
    - I need to store the ARM WinCE breakpoint opcode somewhere - it
      is used to insert the initial breakpoint.
    - The i386 debug registers handling (although watchpoint support isn't
      really implemented in win32-i386-low.c currently; gdb/i386-nat.c
      would have to be copied/used from gdbserver).

Note that i386/arm is orthogonal to 9x/NT/CE. WinCE can also be i386.

I stashed the i386 debug registers copying into a
load/store interface, mainly because I needed to get them out
of the generic win32-low.c.  I'm open to better suggestions.
Note that although the debug registers handling code was copied from
gdb/win32-nat.c, watchpoints are not supported, making the
debug registers copying unneeded; they could be disabled until
proper watchpoint support is implemented.

With this patch, the old config/arm/tm-wince.h, wince.c,
wince-stub.h and wince-stub.c file can finally go away.

Cheers,
Pedro Alves





ChangeLog

	* arm-wince-tdep.c: New.
	* config/arm/wince.mt (DEPRECATED_TM_FILE): Use tm-arm.h.
	(MT_CFLAGS): Delete.
	(TM_CLIBS): Delete.
	(TDEPFILES): Add arm-wince-tdep.o, corelow.o, solib.o,
	solib-legacy.o, solib-svr4.o, and remove wince.o.
	* configure.tgt (arm*-*-mingw32ce*): Add.
	* signals/signals.c [HAVE_SIGNAL_H]: Check.
	(do_target_signal_to_host): Silence 'not used' warning.
	* config/arm/tm-wince.h: Remove.
	* wince.c: Remove.
	* wince-stub.h: Remove.
	* wince-stub.c: Remove.

doc/ChangeLog

	* gdb.texinfo (WinCE): Delete subsection.

gdbserver/ChangeLog

	* gdbserver/configure.ac: Add errno checking.
	(AC_CHECK_HEADERS): Add errno.h, fcntl.h, signal.h,
	sys/file.h, malloc.h and windows.h.
	(AC_CHECK_DECLS): Add perror.
	(srv_mingwce): Handle.
	* gdbserver/configure.srv (i[34567]86-*-cygwin*): Add
	win32-i386-low.o to srv_tgtobj.
	(i[34567]86-*-mingw*): Likewise.
	(arm*-*-mingw32ce*): Add case.
	* gdbreplay.c [HAVE_SYS_FILE_H, HAVE_SIGNAL_H,
	HAVE_FCNTL_H, HAVE_ERRNO_H, HAVE_MALLOC_H]: Check.
	(strwinerror): New function.
	(perror_with_name): Call strwinerr on Windows CE.
	(remote_open): Remove extra close call.
	* mem-break.c (delete_breakpoint_at): New function.
	* mem-break.h (delete_breakpoint_at): Declare.
	* remote-utils.c [HAVE_SYS_FILE_H, HAVE_SIGNAL_H,
	HAVE_FCNTL_H, HAVE_UNISTD_H, HAVE_ERRNO_H]: Check.
	[USE_WIN32API] (read, write): Add char* casts.
	* server.c [HAVE_UNISTD_H, HAVE_SIGNAL_H]: Check.
	* server.h [HAVE_ERRNO_H]: Check.
	(perror): Declare if not declared.
	(strwinerror): Declare.
	* utils.c: Add stdlib.h, errno.h, malloc.h and
	windows.h includes.
	(perror_with_name): Remove errno declaration.
	Call strwinerror on Windows CE.
	(strwinerror): New function.
	* wincecompat.c: New.
	* win32-low.h: New.
	* win32-arm-low.c: New.
	* win32-i386-low.c: New.
	(win32-low.c): Include mem-break.h and win32-low.h, and winnt.h.
	(OUTMSG2): Make it safe.
	(_T): Define.
	(NUM_REGS): Get it from the low target.
	(CONTEXT_EXTENDED_REGISTERS, CONTEXT_FLOATING_POINT,
	CONTEXT_DEBUG_REGISTERS): Add fallbacks to 0.
	(thread_rec): Let low target handle debug registers.
	(child_add_thread): Likewise.
	(child_init_thread_list): Likewise.
	(continue_one_thread): Likewise.
	(regptr): New.
	(do_child_fetch_inferior_registers): Move to ...
	* win32-i386-low.c: ... here, and rename to ...
	(do_fetch_inferior_registers): ... this.
	* win32-low.c (child_fetch_inferior_registers): 
	Go through the low target.
	(do_child_store_inferior_registers): Use regptr.
	(win32_create_inferior): Handle Windows CE.
	Use strwinerror instead of strerror on Windows error
	codes.  Add program to the error output.
	Don't close the main thread handle on Windows CE.
	(win32_attach): Use coredll.dll on Windows CE.
	(win32_kill): Close current process and current
	thread handles.
	(win32_detach): Use coredll.dll on Windows CE.
	(win32_resume): Let low target handle debug registers, and
	step request.
	(handle_exception): Add/Remove initial breakpoint.  Avoid
	non-existant WSTOPSIG on Windows CE.
	(win32_read_inferior_memory): Cast to remove warning.
	(win32_arch_string): Go through the low target.
	(initialize_low): Call set_breakpoint_data with the low
	target's breakpoint.
	* win32-low.c (dr, FLAG_TRACE_BIT, FCS_REGNUM,
	FOP_REGNUM, mappings): Move to ...
	* win32-i386-low.c: ... here.
	* win32-low.c (win32_thread_info): Move to ...
	* win32-low.h: ... here.
	* Makefile.in (SFILES): Add win32-low.c, win32-i386-low.c,
	win32-arm-low.c and wincecompat.c.
	(all:): Add $EXEEXT.
	(install-only:): Likewise.
	(gdbserver:): Likewise.
	(gdbreplay:): Likewise.
	* config.in: Regenerate.
	* configure: Regenerate.

---

 gdb/arm-wince-tdep.c           |   84 ++++++++++
 gdb/config/arm/wince.mt        |    9 -
 gdb/configure.tgt              |    5 
 gdb/doc/gdb.texinfo            |   40 -----
 gdb/gdbserver/Makefile.in      |   20 +-
 gdb/gdbserver/config.in        |   28 +++
 gdb/gdbserver/configure        |  203 +++++++++++++++++++++++++
 gdb/gdbserver/configure.ac     |   26 +++
 gdb/gdbserver/configure.srv    |   10 +
 gdb/gdbserver/gdbreplay.c      |   52 ++++++
 gdb/gdbserver/mem-break.c      |    8 +
 gdb/gdbserver/mem-break.h      |    5 
 gdb/gdbserver/remote-utils.c   |   14 +
 gdb/gdbserver/server.c         |    4 
 gdb/gdbserver/server.h         |    9 +
 gdb/gdbserver/utils.c          |   53 ++++++
 gdb/gdbserver/win32-arm-low.c  |   57 +++++++
 gdb/gdbserver/win32-i386-low.c |  133 ++++++++++++++++
 gdb/gdbserver/win32-low.c      |  323 ++++++++++++++++++++---------------------
 gdb/gdbserver/win32-low.h      |   76 +++++++++
 gdb/gdbserver/wincecompat.c    |   41 +++++
 gdb/signals/signals.c          |    5 
 22 files changed, 976 insertions(+), 229 deletions(-)

Index: src/gdb/arm-wince-tdep.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/arm-wince-tdep.c	2007-03-15 22:00:18.000000000 +0000
@@ -0,0 +1,84 @@
+/* Target-dependent code for Windows CE running on ARM processors,
+   for GDB.
+
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 "defs.h"
+#include "osabi.h"
+#include "solib-svr4.h"
+#include "target.h"
+
+#include "gdb_string.h"
+
+#include "arm-tdep.h"
+
+static const char arm_wince_le_breakpoint[] = { 0x10, 0x00, 0x00, 0xe6 };
+
+/* Description of the longjmp buffer.  */
+#define ARM_WINCE_JB_ELEMENT_SIZE	INT_REGISTER_SIZE
+#define ARM_WINCE_JB_PC			21
+
+static void
+arm_wince_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+  tdep->arm_breakpoint = arm_wince_le_breakpoint;
+  tdep->arm_breakpoint_size = sizeof (arm_wince_le_breakpoint);
+  tdep->struct_return = pcc_struct_return;
+
+  tdep->fp_model = ARM_FLOAT_SOFT_VFP;
+
+  tdep->jb_pc = ARM_WINCE_JB_PC;
+  tdep->jb_elt_size = ARM_WINCE_JB_ELEMENT_SIZE;
+
+  /* On ARM WinCE char defaults to signed.  */
+  set_gdbarch_char_signed (gdbarch, 1);
+
+  set_solib_svr4_fetch_link_map_offsets
+    (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+
+  /* Shared library handling.  */
+  set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
+}
+
+static enum gdb_osabi
+arm_wince_osabi_sniffer (bfd *abfd)
+{
+  const char *target_name = bfd_get_target (abfd);
+
+  if (strcmp (target_name, "pei-arm-wince-little") == 0)
+    return GDB_OSABI_WINCE;
+
+  return GDB_OSABI_UNKNOWN;
+}
+
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+void _initialize_arm_wince_tdep (void);
+
+void
+_initialize_arm_wince_tdep (void)
+{
+  gdbarch_register_osabi_sniffer (bfd_arch_arm, bfd_target_coff_flavour,
+                                  arm_wince_osabi_sniffer);
+
+  gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_WINCE,
+                          arm_wince_init_abi);
+}
Index: src/gdb/config/arm/wince.mt
===================================================================
--- src.orig/gdb/config/arm/wince.mt	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/config/arm/wince.mt	2007-03-15 22:00:18.000000000 +0000
@@ -1,5 +1,4 @@
-# Target: Acorn RISC machine (ARM) with simulator
-TDEPFILES= arm-tdep.o wince.o
-DEPRECATED_TM_FILE= tm-wince.h
-MT_CFLAGS=-DARM -U_X86_ -U_M_IX86 -U__i386__ -U__i486__ -U__i586__ -U__i686__ -DUNICODE -D_WIN32_WCE -DWINCE_STUB='"${target_alias}-stub.exe"'
-TM_CLIBS=-lrapi
+# Target: ARM based machine running Windows CE (win32)
+DEPRECATED_TM_FILE= tm-arm.h
+TDEPFILES= arm-tdep.o arm-wince-tdep.o corelow.o \
+  solib.o solib-legacy.o solib-svr4.o
Index: src/gdb/configure.tgt
===================================================================
--- src.orig/gdb/configure.tgt	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/configure.tgt	2007-03-15 22:00:18.000000000 +0000
@@ -54,7 +54,10 @@ alpha*-*-*)		gdb_target=alpha ;;
 # mn10300 / am33 liunux
 am33_2.0*-*-linux*)	gdb_target=linux ;;
 
-arm*-wince-pe)		gdb_target=wince ;;
+arm*-wince-pe | arm*-*-mingw32ce*)
+			gdb_target=wince
+			build_gdbserver=yes
+			;;
 arm*-*-linux*)		gdb_target=linux
 			build_gdbserver=yes
 			;;
Index: src/gdb/gdbserver/configure.ac
===================================================================
--- src.orig/gdb/gdbserver/configure.ac	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/configure.ac	2007-03-15 22:00:18.000000000 +0000
@@ -39,10 +39,27 @@ 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 dnl
+ 		 errno.h fcntl.h signal.h sys/file.h malloc.h windows.h dnl
 		 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)
+have_errno=no
+AC_MSG_CHECKING(for errno)
+AC_TRY_LINK([
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif], [static int x; x = errno;],
+  [AC_MSG_RESULT(yes - in errno.h); AC_DEFINE(HAVE_ERRNO, 1, [Define if errno is available]) have_errno=yes])
+if test $have_errno = no; then
+AC_TRY_LINK([
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif], [extern int errno; static int x; x = errno;],
+  [AC_MSG_RESULT(yes - must define); AC_DEFINE(HAVE_ERRNO, 1, [Define if errno is available]) AC_DEFINE(MUST_DEFINE_ERRNO, 1, [Checking if errno must be defined])],
+  [AC_MSG_RESULT(no)])
+fi
+
+AC_CHECK_DECLS([strerror, perror])
 
 AC_CHECK_TYPES(socklen_t, [], [],
 [#include <sys/types.h>
@@ -68,8 +85,13 @@ esac
 
 . ${srcdir}/configure.srv
 
-if test "${srv_mingw}" = "yes"; then
+if test "${srv_mingwce}" = "yes"; then
+  LIBS="$LIBS -lws2"
+elif test "${srv_mingw}" = "yes"; then
   LIBS="$LIBS -lwsock32"
+fi
+
+if test "${srv_mingw}" = "yes"; then
   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
Index: src/gdb/gdbserver/configure.srv
===================================================================
--- src.orig/gdb/gdbserver/configure.srv	2007-03-15 22:00:16.000000000 +0000
+++ src/gdb/gdbserver/configure.srv	2007-03-15 22:00:18.000000000 +0000
@@ -44,7 +44,7 @@ case "${target}" in
 			srv_linux_thread_db=yes
 			;;
   i[34567]86-*-cygwin*)	srv_regobj=reg-i386.o
-			srv_tgtobj="win32-low.o"
+			srv_tgtobj="win32-low.o 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"
@@ -52,8 +52,14 @@ case "${target}" in
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
 			;;
+  arm*-*-mingw32ce*)	srv_regobj=reg-arm.o
+			srv_tgtobj="win32-low.o win32-arm-low.o"
+			srv_tgtobj="${srv_tgtobj} wincecompat.o"
+			srv_mingw=yes
+			srv_mingwce=yes
+			;;
   i[34567]86-*-mingw*)	srv_regobj=reg-i386.o
-			srv_tgtobj="win32-low.o"
+			srv_tgtobj="win32-low.o win32-i386-low.o"
 			srv_mingw=yes
 			;;
   ia64-*-linux*)	srv_regobj=reg-ia64.o
Index: src/gdb/gdbserver/gdbreplay.c
===================================================================
--- src.orig/gdb/gdbserver/gdbreplay.c	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/gdbreplay.c	2007-03-15 22:00:18.000000000 +0000
@@ -22,12 +22,19 @@
 
 #include "config.h"
 #include <stdio.h>
+#if HAVE_SYS_FILE_H
 #include <sys/file.h>
+#endif
+#if HAVE_SIGNAL_H
 #include <signal.h>
+#endif
 #include <ctype.h>
+#if HAVE_FCNTL_H
 #include <fcntl.h>
+#endif
+#if HAVE_ERRNO_H
 #include <errno.h>
-
+#endif
 #ifdef HAVE_STDLIB_H
 #include <stdlib.h>
 #endif
@@ -49,6 +56,9 @@
 #if HAVE_NETINET_TCP_H
 #include <netinet/tcp.h>
 #endif
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
 
 #if USE_WIN32API
 #include <winsock.h>
@@ -63,6 +73,40 @@ typedef int socklen_t;
 
 static int remote_desc;
 
+#ifdef __MINGW32CE__
+
+/* An strerror-like function that takes a Win32 error instead
+   of an errno error in ERROR.  */
+
+static char *
+strwinerror (DWORD error)
+{
+  static char buf[1024];
+  wchar_t msgbuf[1024];
+  DWORD chars = FormatMessageW (
+		FORMAT_MESSAGE_FROM_SYSTEM,
+                NULL,
+                error,
+                0, /* Default language */
+                (LPVOID)&msgbuf,
+                0,
+                NULL);
+  if (chars != 0)
+    {
+      /* If there is an \r\n appended, zap it.  */
+      if (chars >= 2
+	  && msgbuf[chars - 2] == '\r'
+	  && msgbuf[chars - 1] == '\n')
+	msgbuf[chars - 2] = 0;
+      wcstombs (buf, msgbuf, chars + 1);
+    }
+  else
+    sprintf (buf, "unknown win32 error (%ld)", error);
+  return buf;
+}
+
+#endif /* __MINGW32CE__ */
+
 /* Print the system error message for errno, and also mention STRING
    as the file name for which the error was encountered.
    Then return to command level.  */
@@ -76,7 +120,11 @@ perror_with_name (char *string)
   const char *err;
   char *combined;
 
+#ifdef __MINGW32CE__
+  err = strwinerror (GetLastError ());
+#else
   err = strerror (errno);
+#endif
   if (err == NULL)
     err = "unknown error";
 
@@ -178,8 +226,6 @@ remote_open (char *name)
       setsockopt (remote_desc, IPPROTO_TCP, TCP_NODELAY,
 		  (char *) &tmp, sizeof (tmp));
 
-      close (tmp_desc);		/* No longer need this */
-
 #ifndef USE_WIN32API
       close (tmp_desc);		/* No longer need this */
 
Index: src/gdb/gdbserver/mem-break.c
===================================================================
--- src.orig/gdb/gdbserver/mem-break.c	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/mem-break.c	2007-03-15 22:00:18.000000000 +0000
@@ -113,6 +113,14 @@ find_breakpoint_at (CORE_ADDR where)
   return NULL;
 }
 
+void
+delete_breakpoint_at (CORE_ADDR addr)
+{
+  struct breakpoint *bp = find_breakpoint_at (addr);
+  if (bp != NULL)
+    delete_breakpoint (bp);
+}
+
 static void
 reinsert_breakpoint_handler (CORE_ADDR stop_pc)
 {
Index: src/gdb/gdbserver/mem-break.h
===================================================================
--- src.orig/gdb/gdbserver/mem-break.h	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/mem-break.h	2007-03-15 22:00:18.000000000 +0000
@@ -31,6 +31,11 @@
 void set_breakpoint_at (CORE_ADDR where,
 			void (*handler) (CORE_ADDR));
 
+/* Delete a breakpoint previously inserted at ADDR with
+   set_breakpoint_at.  */
+
+void delete_breakpoint_at (CORE_ADDR addr);
+
 /* Create a reinsertion breakpoint at STOP_AT for the breakpoint
    currently at STOP_PC (and temporarily remove the breakpoint at
    STOP_PC).  */
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/remote-utils.c	2007-03-15 22:00:18.000000000 +0000
@@ -26,7 +26,9 @@
 #if HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif
+#if HAVE_SYS_FILE_H
 #include <sys/file.h>
+#endif
 #if HAVE_NETINET_IN_H
 #include <netinet/in.h>
 #endif
@@ -42,15 +44,23 @@
 #if HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
 #endif
+#if HAVE_SIGNAL_H
 #include <signal.h>
+#endif
+#if HAVE_FCNTL_H
 #include <fcntl.h>
+#endif
 #include <sys/time.h>
+#if HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #if HAVE_ARPA_INET_H
 #include <arpa/inet.h>
 #endif
 #include <sys/stat.h>
+#if HAVE_ERRNO_H
 #include <errno.h>
+#endif
 
 #if USE_WIN32API
 #include <winsock.h>
@@ -85,8 +95,8 @@ extern int using_threads;
 extern int debug_threads;
 
 #ifdef USE_WIN32API
-# define read(fd, buf, len) recv (fd, buf, len, 0)
-# define write(fd, buf, len) send (fd, buf, len, 0)
+# define read(fd, buf, len) recv (fd, (char *) buf, len, 0)
+# define write(fd, buf, len) send (fd, (char *) buf, len, 0)
 #endif
 
 /* Open a connection to a remote debugger.
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/server.c	2007-03-15 22:00:18.000000000 +0000
@@ -21,8 +21,12 @@
 
 #include "server.h"
 
+#if HAVE_UNISTD_H
 #include <unistd.h>
+#endif
+#if HAVE_SIGNAL_H
 #include <signal.h>
+#endif
 #if HAVE_SYS_WAIT_H
 #include <sys/wait.h>
 #endif
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/server.h	2007-03-15 22:00:18.000000000 +0000
@@ -27,7 +27,9 @@
 #include <stdarg.h>
 #include <stdio.h>
 #include <stdlib.h>
+#ifdef HAVE_ERRNO_H
 #include <errno.h>
+#endif
 #include <setjmp.h>
 
 #ifdef HAVE_STRING_H
@@ -40,6 +42,12 @@ extern char *strerror (int);	/* X3.159-1
 #endif
 #endif
 
+#if !HAVE_DECL_PERROR
+#ifndef perror
+extern void perror (const char *);
+#endif
+#endif
+
 #ifndef ATTR_NORETURN
 #if defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 7))
 #define ATTR_NORETURN __attribute__ ((noreturn))
@@ -186,6 +194,7 @@ void perror_with_name (char *string);
 void error (const char *string,...) ATTR_NORETURN ATTR_FORMAT (printf, 1, 2);
 void fatal (const char *string,...) ATTR_NORETURN ATTR_FORMAT (printf, 1, 2);
 void warning (const char *string,...) ATTR_FORMAT (printf, 1, 2);
+char *strwinerror (unsigned long error);
 
 /* Functions from the register cache definition.  */
 
Index: src/gdb/gdbserver/utils.c
===================================================================
--- src.orig/gdb/gdbserver/utils.c	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/gdbserver/utils.c	2007-03-15 22:00:18.000000000 +0000
@@ -22,6 +22,16 @@
 #include "server.h"
 #include <stdio.h>
 #include <string.h>
+#include <stdlib.h>
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_MALLOC_H
+#include <malloc.h>
+#endif
+#if HAVE_WINDOWS_H
+#include <windows.h>
+#endif
 
 /* Generally useful subroutines used throughout the program.  */
 
@@ -32,13 +42,14 @@
 void
 perror_with_name (char *string)
 {
-#ifndef STDC_HEADERS
-  extern int errno;
-#endif
   const char *err;
   char *combined;
 
+#ifdef __MINGW32CE__
+  err = strwinerror (GetLastError ());
+#else
   err = strerror (errno);
+#endif
   if (err == NULL)
     err = "unknown error";
 
@@ -94,3 +105,39 @@ warning (const char *string,...)
   fprintf (stderr, "\n");
   va_end (args);
 }
+
+/* An strerror-like function that takes a Win32 error instead
+   of an errno error in ERROR.  */
+
+char *
+strwinerror (unsigned long error)
+{
+  static char buf[1024];
+#if HAVE_WINDOWS_H
+  TCHAR msgbuf[1024];
+  DWORD chars = FormatMessage (
+		FORMAT_MESSAGE_FROM_SYSTEM,
+                NULL,
+                error,
+                0, /* Default language */
+                (LPVOID)&msgbuf,
+                0,
+                NULL);
+  if (chars != 0)
+    {
+      /* If there is an \r\n appended, zap it.  */
+      if (chars >= 2
+	  && msgbuf[chars - 2] == '\r'
+	  && msgbuf[chars - 1] == '\n')
+	msgbuf[chars - 2] = 0;
+#ifdef UNICODE
+      wcstombs (buf, msgbuf, chars + 1);
+#else
+      strncpy (buf, msgbuf, chars + 1);
+#endif
+    }
+  else
+#endif /* HAVE_WINDOWS_H */
+    sprintf (buf, "unknown win32 error (%ld)", error);
+  return buf;
+}
Index: src/gdb/gdbserver/win32-low.c
===================================================================
--- src.orig/gdb/gdbserver/win32-low.c	2007-03-15 22:00:16.000000000 +0000
+++ src/gdb/gdbserver/win32-low.c	2007-03-15 22:00:18.000000000 +0000
@@ -23,8 +23,11 @@
 #include "server.h"
 #include "regcache.h"
 #include "gdb/signals.h"
+#include "mem-break.h"
+#include "win32-low.h"
 
 #include <windows.h>
+#include <winnt.h>
 #include <imagehlp.h>
 #include <psapi.h>
 #include <sys/param.h>
@@ -41,7 +44,11 @@
 #if LOG
 #define OUTMSG2(X) do { printf X; fflush (stdout); } while (0)
 #else
-#define OUTMSG2(X)
+#define OUTMSG2(X) do ; while (0)
+#endif
+
+#ifndef _T
+#define _T(x) TEXT (x)
 #endif
 
 int using_threads = 1;
@@ -56,25 +63,28 @@ static DEBUG_EVENT current_event;
 
 static int debug_registers_changed = 0;
 static int debug_registers_used = 0;
-static unsigned dr[8];
+
+#define NUM_REGS (the_low_target.num_regs)
 
 typedef BOOL winapi_DebugActiveProcessStop (DWORD dwProcessId);
 typedef BOOL winapi_DebugSetProcessKillOnExit (BOOL KillOnExit);
 
-#define FLAG_TRACE_BIT 0x100
+#ifndef CONTEXT_EXTENDED_REGISTERS
+#define CONTEXT_EXTENDED_REGISTERS 0
+#endif
+
+#ifndef CONTEXT_FLOATING_POINT
+#define CONTEXT_FLOATING_POINT 0
+#endif
+
+#ifndef CONTEXT_DEBUG_REGISTERS
+#define CONTEXT_DEBUG_REGISTERS 0
+#endif
+
 #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 win32_thread_info
-{
-  DWORD tid;
-  HANDLE h;
-  int suspend_count;
-  CONTEXT context;
-} win32_thread_info;
 static DWORD main_thread_id = 0;
 
 /* Get the thread ID from the current selected inferior (the current
@@ -113,12 +123,8 @@ thread_rec (DWORD id, int get_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;
+	  if (the_low_target.store_debug_registers != NULL)
+	    (*the_low_target.store_debug_registers) (th);
 	}
     }
 
@@ -145,20 +151,16 @@ child_add_thread (DWORD tid, HANDLE h)
 			      new_register_cache ());
 
   /* Set the debug registers for the new thread if they are used.  */
-  if (debug_registers_used)
+  if (debug_registers_used
+      && the_low_target.load_debug_registers != NULL)
     {
       /* 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];
+      (*the_low_target.load_debug_registers) (th);
+
       SetThreadContext (th->h, &th->context);
       th->context.ContextFlags = 0;
     }
@@ -257,60 +259,26 @@ struct target_waitstatus
   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])
-};
+/* Return a pointer into a CONTEXT field indexed by gdb register number.
+   Return a pointer to an dummy register holding zero if there is no
+   corresponding CONTEXT field for the given register number.  */
+char *
+regptr (CONTEXT* c, int r)
+{
+  if (the_low_target.regmap[r] < 0)
+  {
+    static ULONG zero;
+    /* Always force value to zero, in case the user tried to write
+       to this register before.  */
+    zero = 0;
+    return (char *) &zero;
+  }
+  else
+    return (char *) c + the_low_target.regmap[r];
+}
 
-#undef context_offset
 
-/* Clear out any old thread list and reintialize it to a pristine
+/* Clear out any old thread list and reinitialize it to a pristine
    state. */
 static void
 child_init_thread_list (void)
@@ -321,17 +289,17 @@ child_init_thread_list (void)
 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 ();
+
+  if (the_low_target.initial_stuff != NULL)
+    (*the_low_target.initial_stuff) ();
 }
 
 /* Resume all artificially suspended threads if we are continuing
@@ -354,13 +322,10 @@ continue_one_thread (struct inferior_lis
 	{
 	  /* 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];
+
+	  if (the_low_target.load_debug_registers != NULL)
+	    the_low_target.load_debug_registers (th);
+
 	  SetThreadContext (th->h, &th->context);
 	  th->context.ContextFlags = 0;
 	}
@@ -384,26 +349,6 @@ child_continue (DWORD continue_status, i
   return res;
 }
 
-/* Fetch register(s) from gdbserver regcache data.  */
-static void
-do_child_fetch_inferior_registers (win32_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)
@@ -414,14 +359,14 @@ child_fetch_inferior_registers (int r)
     child_fetch_inferior_registers (NUM_REGS);
   else
     for (regno = 0; regno < r; regno++)
-      do_child_fetch_inferior_registers (th, regno);
+      (*the_low_target.fetch_inferior_registers) (th, regno);
 }
 
 /* Get register from gdbserver regcache data.  */
 static void
 do_child_store_inferior_registers (win32_thread_info *th, int r)
 {
-  collect_register (r, ((char *) &th->context) + mappings[r]);
+  collect_register (r, regptr (&th->context, r));
 }
 
 /* Store a new register value into the current thread context.  We don't
@@ -451,21 +396,22 @@ win32_create_inferior (char *program, ch
   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;
+  PROCESS_INFORMATION pi;
+#ifndef __MINGW32CE__
+  STARTUPINFO si = { sizeof (STARTUPINFO) };
+  char *winenv = NULL;
+#else
+  wchar_t *wargs, *wprogram;
+#endif
 
   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
@@ -483,11 +429,11 @@ win32_create_inferior (char *program, ch
   program = real_path;
 #endif
 
-  argslen = strlen (program) + 1;
+  argslen = 1;
   for (argc = 1; program_args[argc]; argc++)
     argslen += strlen (program_args[argc]) + 1;
   args = alloca (argslen);
-  strcpy (args, program);
+  args[0] = '\0';
   for (argc = 1; program_args[argc]; argc++)
     {
       /* FIXME: Can we do better about quoting?  How does Cygwin
@@ -495,17 +441,40 @@ win32_create_inferior (char *program, ch
       strcat (args, " ");
       strcat (args, program_args[argc]);
     }
-  OUTMSG2 (("Command line is %s\n", args));
+  OUTMSG2 (("Command line is \"%s\"\n", args));
 
+#ifdef CREATE_NEW_PROCESS_GROUP
   flags |= CREATE_NEW_PROCESS_GROUP;
+#endif
 
-  ret = CreateProcess (0, args,	/* command line */
-		       NULL,	/* Security */
+#ifdef __MINGW32CE__
+  to_back_slashes (program);
+  wargs = alloca (argslen * sizeof (wchar_t));
+  mbstowcs (wargs, args, argslen);
+  wprogram = alloca ((strlen (program) + 1) * sizeof (wchar_t));
+  mbstowcs (wprogram, program, strlen (program) + 1);
+  ret = CreateProcessW (wprogram, /* image name */
+                        wargs,    /* command line */
+                        NULL,     /* security, not supported */
+                        NULL,     /* thread, not supported */
+                        FALSE,    /* inherit handles, not supported */
+                        flags,    /* start flags */
+                        NULL,     /* environment, not supported */
+                        NULL,     /* current directory, not supported */
+                        NULL,     /* start info, not supported */
+                        &pi);     /* proc info */
+#else
+  ret = CreateProcess (program, /* image name */
+		       args,	/* command line */
+		       NULL,	/* security */
 		       NULL,	/* thread */
 		       TRUE,	/* inherit handles */
 		       flags,	/* start flags */
-		       winenv, NULL,	/* current directory */
-		       &si, &pi);
+		       winenv,  /* environment */
+		       NULL,	/* current directory */
+		       &si,     /* start info */
+		       &pi);    /* proc info */
+#endif
 
 #ifndef USE_WIN32API
   if (orig_path)
@@ -514,15 +483,21 @@ win32_create_inferior (char *program, ch
 
   if (!ret)
     {
-      error ("Error creating process %s, (error %d): %s\n", args,
-	     (int) GetLastError (), strerror (GetLastError ()));
+      error ("Error creating process \"%s%s\", (error %d): %s\n",
+	     program, args,
+	     (int) GetLastError (), strwinerror (GetLastError ()));
     }
   else
     {
       OUTMSG2 (("Process created: %s\n", (char *) args));
     }
 
+#ifndef _WIN32_WCE
+  /* On Windows CE this handle can't be closed.  The OS reuses
+     it in the debug events, while the 9x/NT versions of Windows
+     probably use a DuplicateHandle'd one.  */
   CloseHandle (pi.hThread);
+#endif
 
   current_process_handle = pi.hProcess;
   current_process_id = pi.dwProcessId;
@@ -539,16 +514,18 @@ 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");
+  winapi_DebugSetProcessKillOnExit *DebugSetProcessKillOnExit = NULL;
+#ifdef _WIN32_WCE
+  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
+#else
+  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
+#endif
+  DebugActiveProcessStop = (winapi_DebugActiveProcessStop *)
+    GetProcAddress (dll, _T("DebugActiveProcessStop"));
+  DebugSetProcessKillOnExit = (winapi_DebugSetProcessKillOnExit *)
+    GetProcAddress (dll, _T("DebugSetProcessKillOnExit"));
 
   res = DebugActiveProcess (pid) ? 1 : 0;
 
@@ -571,8 +548,6 @@ win32_attach (unsigned long pid)
   if (res)
     do_initial_child_stuff (pid);
 
-  FreeLibrary (kernel32);
-
   return res;
 }
 
@@ -580,6 +555,8 @@ win32_attach (unsigned long pid)
 static void
 win32_kill (void)
 {
+  win32_thread_info *current_thread;
+
   if (current_process_handle == NULL)
     return;
 
@@ -593,22 +570,32 @@ win32_kill (void)
       if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
 	break;
     }
+
+  CloseHandle (current_process_handle);
+
+  current_thread = inferior_target_data (current_inferior);
+  if (current_thread && current_thread->h)
+    {
+      /* This may fail in an attached process, so don't check.  */
+      (void) CloseHandle (current_thread->h);
+    }
 }
 
 /* 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");
+#ifdef _WIN32_WCE
+  HMODULE dll = GetModuleHandle (_T("COREDLL.DLL"));
+#else
+  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
+#endif
+  DebugActiveProcessStop = (winapi_DebugActiveProcessStop *)
+    GetProcAddress (dll, _T("DebugActiveProcessStop"));
+  DebugSetProcessKillOnExit = (winapi_DebugSetProcessKillOnExit *)
+    GetProcAddress (dll, _T("DebugSetProcessKillOnExit"));
 
   if (DebugSetProcessKillOnExit != NULL)
     DebugSetProcessKillOnExit (FALSE);
@@ -617,8 +604,6 @@ win32_detach (void)
     DebugActiveProcessStop (current_process_id);
   else
     win32_kill ();
-
-  FreeLibrary (kernel32);
 }
 
 /* Return 1 iff the thread with thread ID TID is alive.  */
@@ -691,23 +676,21 @@ win32_resume (struct thread_resume *resu
       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];
-	    }
+	    if (the_low_target.load_debug_registers != NULL)
+	      (*the_low_target.load_debug_registers) (th);
 
 	  /* Move register values from the inferior into the thread
 	     context structure.  */
 	  regcache_invalidate ();
 
 	  if (step)
-	    th->context.EFlags |= FLAG_TRACE_BIT;
-
+	    {
+	      if (the_low_target.single_step != NULL)
+		(*the_low_target.single_step) (th);
+	      else
+		error ("Software single stepping is not supported "
+		       "in this configuration.\n");
+	    }
 	  SetThreadContext (th->h, &th->context);
 	  th->context.ContextFlags = 0;
 	}
@@ -783,6 +766,11 @@ handle_exception (struct target_waitstat
     case EXCEPTION_BREAKPOINT:
       OUTMSG2 (("EXCEPTION_BREAKPOINT"));
       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
+#ifdef _WIN32_WCE
+      /* Remove the initial breakpoint.  */
+      check_breakpoints ((CORE_ADDR) (long) current_event
+                         .u.Exception.ExceptionRecord.ExceptionAddress);
+#endif
       break;
     case DBG_CONTROL_C:
       OUTMSG2 (("DBG_CONTROL_C"));
@@ -892,6 +880,14 @@ in:
 			  current_event.u.CreateProcessInfo.hThread);
 
       retval = ourstatus->value.related_pid = current_event.dwThreadId;
+#ifdef _WIN32_WCE
+      /* Windows CE doesn't set the initial breakpoint automatically
+	 like the desktop versions of Windows do.  We add it explicitly
+	 here.  It will be removed as soon as it is hit.  */
+      set_breakpoint_at ((CORE_ADDR) (long) current_event.u
+			 .CreateProcessInfo.lpStartAddress,
+			 delete_breakpoint_at);
+#endif
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
@@ -994,8 +990,13 @@ win32_wait (char *status)
 	}
       else if (our_status.kind == TARGET_WAITKIND_STOPPED)
 	{
+#ifndef __MINGW32CE__
 	  OUTMSG2 (("Child Stopped with signal = %x \n",
 		    WSTOPSIG (our_status.value.sig)));
+#else
+	  OUTMSG2 (("Child Stopped with signal = %x \n",
+		    our_status.value.sig));
+#endif
 
 	  *status = 'T';
 
@@ -1039,7 +1040,7 @@ win32_store_inferior_registers (int regn
 static int
 win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
 {
-  return child_xfer_memory (memaddr, myaddr, len, 0, 0) != len;
+  return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
 }
 
 /* Write memory to the inferior process.  This should generally be
@@ -1056,7 +1057,7 @@ win32_write_inferior_memory (CORE_ADDR m
 static const char *
 win32_arch_string (void)
 {
-  return "i386";
+  return the_low_target.arch_string;
 }
 
 static struct target_ops win32_target_ops = {
@@ -1088,6 +1089,8 @@ void
 initialize_low (void)
 {
   set_target_ops (&win32_target_ops);
-
+  if (the_low_target.breakpoint != NULL)
+    set_breakpoint_data (the_low_target.breakpoint,
+			 the_low_target.breakpoint_len);
   init_registers ();
 }
Index: src/gdb/signals/signals.c
===================================================================
--- src.orig/gdb/signals/signals.c	2007-03-15 02:25:20.000000000 +0000
+++ src/gdb/signals/signals.c	2007-03-15 22:00:18.000000000 +0000
@@ -28,7 +28,9 @@
 #include "gdb_string.h"
 #endif
 
+#ifdef HAVE_SIGNAL_H
 #include <signal.h>
+#endif
 
 /* Always use __SIGRTMIN if it's available.  SIGRTMIN is the lowest
    _available_ realtime signal, not the lowest supported; glibc takes
@@ -519,6 +521,9 @@ do_target_signal_to_host (enum target_si
 			  int *oursig_ok)
 {
   int retsig;
+  /* Silence the 'not used' warning, for targets that
+     do not support signals.  */
+  (void) retsig;
 
   *oursig_ok = 1;
   switch (oursig)
Index: src/gdb/gdbserver/Makefile.in
===================================================================
--- src.orig/gdb/gdbserver/Makefile.in	2007-03-15 22:00:16.000000000 +0000
+++ src/gdb/gdbserver/Makefile.in	2007-03-15 22:00:18.000000000 +0000
@@ -128,7 +128,9 @@ SFILES=	$(srcdir)/gdbreplay.c $(srcdir)/
 	$(srcdir)/linux-m68k-low.c $(srcdir)/linux-mips-low.c \
 	$(srcdir)/linux-ppc-low.c $(srcdir)/linux-ppc64-low.c \
 	$(srcdir)/linux-s390-low.c \
-	$(srcdir)/linux-sh-low.c $(srcdir)/linux-x86-64-low.c
+	$(srcdir)/linux-sh-low.c $(srcdir)/linux-x86-64-low.c \
+	$(srcdir)/win32-arm-low.c $(srcdir)/win32-i386-low.c \
+	$(srcdir)/win32-low.c $(srcdir)/wincecompat.c
 
 DEPFILES = @GDBSERVER_DEPFILES@
 
@@ -154,7 +156,7 @@ XML_BUILTIN = @srv_xmlbuiltin@
 .c.o:
 	${CC} -c ${INTERNAL_CFLAGS} $<
 
-all: gdbserver gdbreplay
+all: gdbserver$(EXEEXT) gdbreplay$(EXEEXT)
 
 # Traditionally "install" depends on "all".  But it may be useful
 # not to; for example, if the user has made some trivial change to a 
@@ -166,7 +168,7 @@ install-only: 
 	n=`echo gdbserver | sed '$(program_transform_name)'`; \
 	if [ x$$n = x ]; then n=gdbserver; else true; fi; \
 	$(SHELL) $(srcdir)/../../mkinstalldirs $(DESTDIR)$(bindir); \
-	$(INSTALL_PROGRAM) gdbserver $(DESTDIR)$(bindir)/$$n; \
+	$(INSTALL_PROGRAM) gdbserver$(EXEEXT) $(DESTDIR)$(bindir)/$$n$(EXEEXT); \
 	$(SHELL) $(srcdir)/../../mkinstalldirs $(DESTDIR)$(man1dir); \
 	$(INSTALL_DATA) $(srcdir)/gdbserver.1 $(DESTDIR)$(man1dir)/$$n.1
 
@@ -183,14 +185,14 @@ html:
 install-html:
 clean-info:
 
-gdbserver: $(OBS) ${ADD_DEPS} ${CDEPS}
-	rm -f gdbserver
-	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbserver $(OBS) \
+gdbserver$(EXEEXT): $(OBS) ${ADD_DEPS} ${CDEPS}
+	rm -f gdbserver$(EXEEXT)
+	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbserver$(EXEEXT) $(OBS) \
 	  $(GDBSERVER_LIBS) $(XM_CLIBS)
 
-gdbreplay: gdbreplay.o
-	rm -f gdbreplay
-	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay gdbreplay.o \
+gdbreplay$(EXEEXT): gdbreplay.o
+	rm -f gdbreplay$(EXEEXT)
+	${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) gdbreplay.o \
 	  $(XM_CLIBS)
 
 # Put the proper machine-specific files first, so M-. on a machine
Index: src/gdb/gdbserver/wincecompat.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/gdbserver/wincecompat.c	2007-03-15 22:00:18.000000000 +0000
@@ -0,0 +1,41 @@
+/* Compatibility routines for Windows CE.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 <stdio.h>
+#include <windows.h>
+
+void
+perror (const char *s)
+{
+  if (s && *s)
+    fprintf (stderr, "%s: %s\n", s, strwinerror (GetLastError ()));
+  else
+    fprintf (stderr, "%s\n", strwinerror (GetLastError ()));
+}
+
+void
+to_back_slashes (char *path)
+{
+  for (; *path; ++path)
+    if ('/' == *path)
+      *path = '\\';
+}
Index: src/gdb/gdbserver/win32-arm-low.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/gdbserver/win32-arm-low.c	2007-03-15 23:49:34.000000000 +0000
@@ -0,0 +1,76 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 "win32-low.h"
+
+/* Fetch register(s) from gdbserver regcache data.  */
+static void
+do_fetch_inferior_registers (win32_thread_info *th, int r)
+{
+  char *context_offset = regptr (&th->context, r);
+  supply_register (r, context_offset);
+}
+
+#define context_offset(x) ((int)&(((CONTEXT *)NULL)->x))
+static const int mappings[] = {
+  context_offset (R0),
+  context_offset (R1),
+  context_offset (R2),
+  context_offset (R3),
+  context_offset (R4),
+  context_offset (R5),
+  context_offset (R6),
+  context_offset (R7),
+  context_offset (R8),
+  context_offset (R9),
+  context_offset (R10),
+  context_offset (R11),
+  context_offset (R12),
+  context_offset (Sp),
+  context_offset (Lr),
+  context_offset (Pc),
+  -1, /* f0 */
+  -1, /* f1 */
+  -1, /* f2 */
+  -1, /* f3 */
+  -1, /* f4 */
+  -1, /* f5 */
+  -1, /* f6 */
+  -1, /* f7 */
+  -1, /* fps */
+  context_offset (Psr),
+};
+#undef context_offset
+
+static const unsigned char arm_wince_le_breakpoint[] =
+  { 0x10, 0x00, 0x00, 0xe6 };
+
+struct win32_target_ops the_low_target = {
+  mappings,
+  sizeof (mappings) / sizeof (mappings[0]),
+  NULL, /* initial_stuff */
+  NULL, /* store_debug_registers */
+  NULL, /* load_debug_registers */
+  do_fetch_inferior_registers,
+  NULL, /* single_step */
+  arm_wince_le_breakpoint,
+  sizeof (arm_wince_le_breakpoint) / sizeof (arm_wince_le_breakpoint[0]),
+  "arm" /* arch_string */
+};
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	2007-03-15 23:49:42.000000000 +0000
@@ -0,0 +1,152 @@
+/* Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 "win32-low.h"
+
+#define FCS_REGNUM 27
+#define FOP_REGNUM 31
+
+#define FLAG_TRACE_BIT 0x100
+
+static unsigned dr[8];
+
+static void
+initial_stuff (void)
+{
+  memset (&dr, 0, sizeof (dr));
+}
+
+static void
+store_debug_registers (win32_thread_info *th)
+{
+  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;
+}
+
+static void
+load_debug_registers (win32_thread_info *th)
+{
+  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];
+}
+
+/* Fetch register(s) from gdbserver regcache data.  */
+static void
+do_fetch_inferior_registers (win32_thread_info *th, int r)
+{
+  char *context_offset = regptr (&th->context, 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);
+}
+
+static void
+single_step (win32_thread_info *th)
+{
+  th->context.EFlags |= FLAG_TRACE_BIT;
+}
+
+/* An array of offset mappings into a Win32 Context structure.
+   This is a one-to-one mapping which is indexed by gdb's register
+   numbers.  It retrieves an offset into the context structure where
+   the 4 byte register is located.
+   An offset value of -1 indicates that Win32 does not provide this
+   register in it's CONTEXT structure.  In this case regptr will return
+   a pointer into a dummy register.  */
+#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
+
+struct win32_target_ops the_low_target = {
+  mappings,
+  sizeof (mappings) / sizeof (mappings[0]),
+  initial_stuff,
+  store_debug_registers,
+  load_debug_registers,
+  do_fetch_inferior_registers,
+  single_step,
+  (const char*)NULL, /* breakpoint */
+  0, /* breakpoint_len */
+  "i386" /* arch_string */
+};
Index: src/gdb/gdbserver/win32-low.h
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/gdbserver/win32-low.h	2007-03-15 22:00:18.000000000 +0000
@@ -0,0 +1,76 @@
+/* Internal interfaces for the Win32 specific target code for gdbserver.
+   Copyright (C) 2007 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 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 <windows.h>
+
+/* Thread information structure used to track extra information about
+   each thread.  */
+typedef struct win32_thread_info
+{
+  DWORD tid;
+  HANDLE h;
+  int suspend_count;
+  CONTEXT context;
+} win32_thread_info;
+
+struct win32_target_ops
+{
+  /* An array of offset mappings into a Win32 Context structure.
+     This is a one-to-one mapping which is indexed by gdb's register
+     numbers.  It retrieves an offset into the context structure where
+     the 4 byte register is located.
+     An offset value of -1 indicates that Win32 does not provide this
+     register in it's CONTEXT structure.  In this case regptr will return
+     a pointer into a dummy register.  */
+  const int *regmap;
+
+  /* The number of elements of regmap.  */
+  int num_regs;
+
+  void (*initial_stuff) (void);
+
+  void (*store_debug_registers) (win32_thread_info *);
+  void (*load_debug_registers) (win32_thread_info *);
+
+  /* Fetch register(s) from gdbserver regcache data.  */
+  void (*fetch_inferior_registers) (win32_thread_info *th, int r);
+
+  void (*single_step) (win32_thread_info *th);
+
+  const unsigned char *breakpoint;
+  int breakpoint_len;
+
+  /* What string to report to GDB when it asks for the architecture,
+     or NULL not to answer.  */
+  const char *arch_string;
+};
+
+extern struct win32_target_ops the_low_target;
+
+/* in win32-low.c */
+
+/* Return a pointer into a CONTEXT field indexed by gdb register number.
+   Return a pointer to an dummy register holding zero if there is no
+   corresponding CONTEXT field for the given register number.  */
+extern char * regptr (CONTEXT* c, int r);
+
+/* in wincecompat.c */
+
+extern void to_back_slashes (char *);
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2007-03-03 18:47:52.000000000 +0000
+++ src/gdb/doc/gdb.texinfo	2007-03-15 22:51:00.000000000 +0000
@@ -14312,7 +14312,6 @@ acceptable commands.
 * AVR::                         Atmel AVR
 * CRIS::                        CRIS
 * Super-H::                     Renesas Super-H
-* WinCE::                       Windows CE child processes
 @end menu
 
 @node ARM
@@ -15501,45 +15500,6 @@ commands:
 Show the values of all Super-H registers.
 @end table
 
-@node WinCE
-@subsection Windows CE
-@cindex Windows CE
-
-The following commands are available for Windows CE:
-
-@table @code
-@item set remotedirectory @var{dir}
-@kindex set remotedirectory
-Tell @value{GDBN} to upload files from the named directory @var{dir}.
-The default is @file{/gdb}, i.e.@: the root directory on the current
-drive.
-
-@item show remotedirectory
-@kindex show remotedirectory
-Show the current value of the upload directory.
-
-@item set remoteupload @var{method}
-@kindex set remoteupload
-Set the method used to upload files to remote device.  Valid values
-for @var{method} are @samp{always}, @samp{newer}, and @samp{never}.
-The default is @samp{newer}.
-
-@item show remoteupload
-@kindex show remoteupload
-Show the current setting of the upload method.
-
-@item set remoteaddhost
-@kindex set remoteaddhost
-Tell @value{GDBN} whether to add this host to the remote stub's
-arguments when you debug over a network.
-
-@item show remoteaddhost
-@kindex show remoteaddhost
-Show whether to add this host to remote stub's arguments when
-debugging over a network.
-@end table
-
-
 @node Architectures
 @section Architectures
 





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