This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [New WinCE support] [patch 4/4] The bulk of the code.
Eli Zaretskii wrote:
Date: Fri, 16 Mar 2007 15:03:21 +0000
From: "pedro alves" <alves.ped@gmail.com>
Cc: gdb-patches@sourceware.org
I'm using the same api as strerror, which returns a pointer into a
static buffer.
In that case, I guess it's okay to use a static buffer. But please at
least check inside the function that the buffer size was enough, by
comparing the value returned by FormatMessageW with the size of the
buffer you passed to it.
I had thought that the message would be truncated, so I didn't
care about that check, but that's not what happens. If the buffer
isn't enough, 0 is returned. Ended up switching to
FORMAT_MESSAGE_ALLOCATE_BUFFER.
Hummm, I don't know how is it that I specified a buffer of size 0,
and Windows (at least CE) still fills the buffer.
I think it fills the buffer because the buffer is larger than 0. The
return value tells you how many characters it _really_ needed to
format the message. By comparing that value with the size of the
buffer, you can find out whether the buffer was large enough.
I have no idea how I missed it, but it doesn't fill the buffer
after all.
+#ifdef __MINGW32CE__
+ err = strwinerror (GetLastError ());
+#else
err = strerror (errno);
+#endif
Why not call strwinerror strerror and avoid the ifdef?
Because then I would have to:
#ifdef __MINGW32CE__
#define errno (GetLastError ())
#endif
err = strerror (errno);
That means I still must have an #ifdef somewhere.
But that ifdef would be in only one place, while with a different
function you need an ifdef each time you use the function.
Since there is only one instance of it (the #ifdef) in gdbserver, I
thought it is better to have strwinerror explicit.
There's only one instance _today_. Tomorrow we could have more of
them.
OK. Moved strwinerror to win32-low.c, and defined strerror to
strwinerror in wincecompat.h, which is then included in server.h.
Btw, I see in your patch two instances of strwinerror and two places
that call it: one in gdbreplay.c, the other in utils.c. Why did you
need two almost identical functions?
Well, gdbreplay (a separate application) has some other functionality
that is copied from gdbserver instead of sharing objects,
eg: perror_with_name. I didn't think it was worth it to change
how it is built for just one function.
They are not identical, because the gdbserver version only
cares about UNICODE (Win32 API on Windows CE is only wide).
When someone later uses errno as an lvalue, it breaks WinCE again.
I think such usage of errno is a bad idea anyway, since on many
platforms errno is a function already (to support multi-threading).
As Andreas said, it must still be an lvalue. The usual way to get
around it is to use something like __set_errno(VALUE) instead of
errno = VALUE, and define __set_errno to SetLastError on WinCE.
The other place I used strwinerror is in:
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 ()));
}
On Window 9x/NT it is wrong to do:
strerror (GetLastError ())
The errno values and the windows error codes are not the same.
This is not a problem: errno should not be used with any literal
values anyway, only with symbolical constants.
I don't understand what you mean here.
On MinGW, this:
printf ("%s\n", strerror (ERROR_TOO_MANY_OPEN_FILES));
prints:
"Interrupted function call"
Clearly not what was intended. This happens because:
errno.h
#define EINTR 4 /* Interrupted function call */
winerror.h
#define ERROR_TOO_MANY_OPEN_FILES 4L
Would you prefer to have that? That is, rewrite this last hunk to use
FormatMessage
directly, and rename strwinerror to strerror, put it wincecompat.c, and have a:
#ifdef __MINGW32CE__
#define errno (GetLastError ())
#endif
Yes, I'd prefer that solution. gdbserver/win32-low.c is already
Windows specific, so it's okay to use FormatMessage there.
Done. See new attached patch.
Are there any WinCE-specific commands or features left after your
patch? If there are, please describe them in this section. If not,
then it's okay to delete the section.
There aren't any left.
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 and malloc.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.
[__MINGW32CE__] (strerror): New function.
[__MINGW32CE__] (errno): Define to GetLastError.
[__MINGW32CE__] (COUNTOF): New macro.
(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: Include wincecompat.h on Windows CE.
[HAVE_ERRNO_H]: Check.
(perror): Declare if not declared.
* utils.c: Add stdlib.h, errno.h and malloc.h includes.
(perror_with_name): Remove errno declaration.
* wincecompat.h: New.
* 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): New macro.
(COUNTOF): New macro.
(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.
(strwinerror): New function.
(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/configure.ac | 26 ++
gdb/gdbserver/configure.srv | 10 -
gdb/gdbserver/gdbreplay.c | 65 ++++++
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 | 12 +
gdb/gdbserver/utils.c | 10 -
gdb/gdbserver/win32-arm-low.c | 76 ++++++++
gdb/gdbserver/win32-i386-low.c | 152 ++++++++++++++++
gdb/gdbserver/win32-low.c | 382 +++++++++++++++++++++++------------------
gdb/gdbserver/win32-low.h | 87 +++++++++
gdb/gdbserver/wincecompat.c | 41 ++++
gdb/gdbserver/wincecompat.h | 32 +++
gdb/signals/signals.c | 5
21 files changed, 860 insertions(+), 227 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-18 23:26:40.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 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-19 00:07:26.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,57 @@ typedef int socklen_t;
static int remote_desc;
+#ifdef __MINGW32CE__
+
+#ifndef COUNTOF
+#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
+#endif
+
+#define errno (GetLastError ())
+
+char *
+strerror (DWORD error)
+{
+ static char buf[1024];
+ WCHAR *msgbuf;
+ DWORD lasterr = GetLastError ();
+ DWORD chars = FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ 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')
+ {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > ((COUNTOF (buf)) - 1))
+ {
+ chars = COUNTOF (buf) - 1;
+ msgbuf [chars] = 0;
+ }
+
+ wcstombs (buf, msgbuf, chars + 1);
+ LocalFree (msgbuf);
+ }
+ else
+ sprintf (buf, "unknown win32 error (%ld)", error);
+
+ SetLastError (lasterr);
+ 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. */
@@ -178,8 +239,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-18 22:52:44.000000000 +0000
@@ -24,10 +24,16 @@
#include "config.h"
+#ifdef __MINGW32CE__
+#include "wincecompat.h"
+#endif
+
#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 +46,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))
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-18 23:38:00.000000000 +0000
@@ -22,6 +22,13 @@
#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
/* Generally useful subroutines used throughout the program. */
@@ -32,9 +39,6 @@
void
perror_with_name (char *string)
{
-#ifndef STDC_HEADERS
- extern int errno;
-#endif
const char *err;
char *combined;
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-19 00:06:14.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,15 @@
#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
+
+#ifndef COUNTOF
+#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
#endif
int using_threads = 1;
@@ -56,25 +67,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 +127,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 +155,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 +263,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 +293,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 +326,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 +353,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 +363,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
@@ -438,6 +387,61 @@ child_store_inferior_registers (int r)
do_child_store_inferior_registers (th, regno);
}
+/* Map the Windows error number in ERROR to a locale-dependent error
+ message string and return a pointer to it. Typically, the values
+ for ERROR come from GetLastError.
+
+ The string pointed to shall not be modified by the application,
+ but may be overwritten by a subsequent call to strwinerror
+
+ The strwinerror function does not change the current setting
+ of GetLastError. */
+
+char *
+strwinerror (DWORD error)
+{
+ static char buf[1024];
+ TCHAR *msgbuf;
+ DWORD lasterr = GetLastError ();
+ DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
+ | FORMAT_MESSAGE_ALLOCATE_BUFFER,
+ 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')
+ {
+ chars -= 2;
+ msgbuf[chars] = 0;
+ }
+
+ if (chars > ((COUNTOF (buf)) - 1))
+ {
+ chars = COUNTOF (buf) - 1;
+ msgbuf [chars] = 0;
+ }
+
+#ifdef UNICODE
+ wcstombs (buf, msgbuf, chars + 1);
+#else
+ strncpy (buf, msgbuf, chars + 1);
+#endif
+ LocalFree (msgbuf);
+ }
+ else
+ sprintf (buf, "unknown win32 error (%ld)", error);
+
+ SetLastError (lasterr);
+ return buf;
+}
+
/* Start a new process.
PROGRAM is a path to the program to execute.
ARGS is a standard NULL-terminated array of arguments,
@@ -451,21 +455,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 +488,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 +500,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 +542,21 @@ win32_create_inferior (char *program, ch
if (!ret)
{
- error ("Error creating process %s, (error %d): %s\n", args,
- (int) GetLastError (), strerror (GetLastError ()));
+ DWORD err = GetLastError ();
+ error ("Error creating process \"%s%s\", (error %d): %s\n",
+ program, args, (int) err, strwinerror (err));
}
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 +573,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 +607,6 @@ win32_attach (unsigned long pid)
if (res)
do_initial_child_stuff (pid);
- FreeLibrary (kernel32);
-
return res;
}
@@ -580,6 +614,8 @@ win32_attach (unsigned long pid)
static void
win32_kill (void)
{
+ win32_thread_info *current_thread;
+
if (current_process_handle == NULL)
return;
@@ -593,22 +629,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 +663,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 +735,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 ("Single stepping is not supported "
+ "in this configuration.\n");
+ }
SetThreadContext (th->h, &th->context);
th->context.ContextFlags = 0;
}
@@ -783,6 +825,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 +939,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 +1049,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 +1099,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 +1116,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 +1148,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-18 22:49:38.000000000 +0000
@@ -0,0 +1,87 @@
+/* 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);
+
+/* Map the Windows error number in ERROR to a locale-dependent error
+ message string and return a pointer to it. Typically, the values
+ for ERROR come from GetLastError.
+
+ The string pointed to shall not be modified by the application,
+ but may be overwritten by a subsequent call to strwinerror
+
+ The strwinerror function does not change the current setting
+ of GetLastError. */
+extern char * strwinerror (DWORD error);
+
+/* 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: src/gdb/gdbserver/wincecompat.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ src/gdb/gdbserver/wincecompat.h 2007-03-18 23:24:16.000000000 +0000
@@ -0,0 +1,32 @@
+/* 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. */
+
+#ifndef WINCECOMPAT_H
+#define WINCECOMPAT_H
+
+#include <windows.h>
+
+#define errno (GetLastError ())
+
+/* in win32-low.c */
+extern char * strwinerror (DWORD error);
+#define strerror strwinerror
+
+#endif