This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[New WinCE support] [patch 4/4] The bulk of the code.
- From: Pedro Alves <pedro_alves at portugalmail dot pt>
- To: gdb-patches at sourceware dot org
- Date: Fri, 16 Mar 2007 02:08:51 +0000
- Subject: [New WinCE support] [patch 4/4] The bulk of the code.
- References: <20070315235008.243411000@portugalmail.pt>
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 (¤t_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