From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 26245 invoked by alias); 16 Mar 2007 02:10:51 -0000 Received: (qmail 26193 invoked by uid 22791); 16 Mar 2007 02:10:46 -0000 X-Spam-Check-By: sourceware.org Received: from elrond.portugalmail.pt (HELO elrond.portugalmail.pt) (195.245.179.181) by sourceware.org (qpsmtpd/0.31) with ESMTP; Fri, 16 Mar 2007 02:10:34 +0000 Received: from localhost (localhost [127.0.0.1]) by elrond.portugalmail.pt (Postfix) with ESMTP id 5EA413CAF8 for ; Fri, 16 Mar 2007 02:06:17 +0000 (WET) Received: from elrond.portugalmail.pt ([127.0.0.1]) by localhost (elrond.portugalmail.pt [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Uq1ol7wOX4a9 for ; Fri, 16 Mar 2007 02:06:13 +0000 (WET) Received: from [127.0.0.1] (62.169.93.152.rev.optimus.pt [62.169.93.152]) (Authenticated sender: pedro_alves@portugalmail.pt) by elrond.portugalmail.pt (Postfix) with ESMTP id 561593CB94 for ; Fri, 16 Mar 2007 02:06:03 +0000 (WET) Message-ID: <45F9FC33.9020106@portugalmail.pt> Date: Fri, 16 Mar 2007 02:10:00 -0000 From: Pedro Alves User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; pt-BR; rv:1.8.0.10) Gecko/20070221 Thunderbird/1.5.0.10 Mnenhy/0.7.4.0 MIME-Version: 1.0 To: gdb-patches@sourceware.org Subject: [New WinCE support] [patch 4/4] The bulk of the code. References: <20070315235008.243411000@portugalmail.pt> In-Reply-To: <20070315235008.243411000@portugalmail.pt> Content-Type: multipart/mixed; boundary="------------020700080105050906030104" X-Antivirus: avast! (VPS 000724-0, 15-03-2007), Outbound message X-Antivirus-Status: Clean X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2007-03/txt/msg00150.txt.bz2 This is a multi-part message in MIME format. --------------020700080105050906030104 Content-Type: text/plain; charset=iso-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 2284 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 --------------020700080105050906030104 Content-Type: text/plain; name="wince_gdbserver.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="wince_gdbserver.diff" Content-length: 54261 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 +#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 +#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 @@ -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 +#if HAVE_SYS_FILE_H #include +#endif +#if HAVE_SIGNAL_H #include +#endif #include +#if HAVE_FCNTL_H #include +#endif +#if HAVE_ERRNO_H #include - +#endif #ifdef HAVE_STDLIB_H #include #endif @@ -49,6 +56,9 @@ #if HAVE_NETINET_TCP_H #include #endif +#if HAVE_MALLOC_H +#include +#endif #if USE_WIN32API #include @@ -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 #endif +#if HAVE_SYS_FILE_H #include +#endif #if HAVE_NETINET_IN_H #include #endif @@ -42,15 +44,23 @@ #if HAVE_SYS_IOCTL_H #include #endif +#if HAVE_SIGNAL_H #include +#endif +#if HAVE_FCNTL_H #include +#endif #include +#if HAVE_UNISTD_H #include +#endif #if HAVE_ARPA_INET_H #include #endif #include +#if HAVE_ERRNO_H #include +#endif #if USE_WIN32API #include @@ -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 +#endif +#if HAVE_SIGNAL_H #include +#endif #if HAVE_SYS_WAIT_H #include #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 #include #include +#ifdef HAVE_ERRNO_H #include +#endif #include #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 #include +#include +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_MALLOC_H +#include +#endif +#if HAVE_WINDOWS_H +#include +#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 +#include #include #include #include @@ -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 +#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 +#include + +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 + +/* 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 --------------020700080105050906030104--