* NEWS: Add information about win32 and arm code.
authorSteve Chamberlain <sac@cygnus>
Mon, 9 Oct 1995 21:54:26 +0000 (21:54 +0000)
committerSteve Chamberlain <sac@cygnus>
Mon, 9 Oct 1995 21:54:26 +0000 (21:54 +0000)
* win32-nat.c: Renamed from win32.c
* config/i386/win32.mh: Renamed from config/i386/i386win32.mh.
* config/i386/win32.mt: Renamed from config/i386/i386win32.mt.
* config/i386/tm-win32.h: Renamed from config/i386/tm-i386win32.h.
* config/i386/xm-win32.h: Renamed from config/i386/xm-i386win32.h.
* configure.in (i[345]86-*-win32): Updated to cope with filename changes.
* configure: Regenerated.

16 files changed:
gdb/.Sanitize
gdb/ChangeLog
gdb/NEWS
gdb/config/i386/.Sanitize
gdb/config/i386/i386win32.mh [deleted file]
gdb/config/i386/i386win32.mt [deleted file]
gdb/config/i386/tm-i386win32.h [deleted file]
gdb/config/i386/tm-win32.h [new file with mode: 0644]
gdb/config/i386/win32.mh [new file with mode: 0644]
gdb/config/i386/win32.mt [new file with mode: 0644]
gdb/config/i386/xm-i386win32.h [deleted file]
gdb/config/i386/xm-win32.h [new file with mode: 0644]
gdb/configure
gdb/configure.in
gdb/win32-nat.c [new file with mode: 0644]
gdb/win32.c

index 219fac72d2efa4dd3491d4ecf6ebc4b02b4ac1b8..d8e70f769cd8feab125564473684e5a51e1b13bd 100644 (file)
@@ -351,7 +351,7 @@ vax-tdep.c
 vx-share
 w65-tdep.c
 w89k-rom.c
-win32.c
+win32-nat.c
 xcoffread.c
 xcoffsolib.c
 xcoffsolib.h
index 5d0489a2bf5998011e985ba65852865e76207cbd..0e6e5a3cfd240910052ad9e0c9f8e3ad2c71231d 100644 (file)
@@ -1,3 +1,14 @@
+Mon Oct  9 14:36:29 1995  steve chamberlain  <sac@slash.cygnus.com>
+
+       * NEWS:  Add information about win32 and arm code.
+       * win32-nat.c: Renamed from win32.c
+       * config/i386/win32.mh: Renamed from config/i386/i386win32.mh.
+       * config/i386/win32.mt: Renamed from config/i386/i386win32.mt.
+       * config/i386/tm-win32.h: Renamed from config/i386/tm-i386win32.h.
+       * config/i386/xm-win32.h: Renamed from config/i386/xm-i386win32.h.
+       * configure.in (i[345]86-*-win32): Updated to cope with filename changes.
+       * configure: Regenerated.       
+
 Sun Oct  8 18:01:04 1995  Per Bothner  <bothner@kalessin.cygnus.com>
 
        * ch-exp.y (yylex):  Also look for '$' following '$'.
index a39a797b2eb8bb10996ed1fce9e3101ba1597eca..18ec89da73347f56e8e6a791e14d80e809f7c0ff 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -12,6 +12,14 @@ about volatile variables, thus making it impossible to debug targets
 which use memory mapped I/O devices. `set remotecache off' turns the
 the data cache off.
 
+* New native configurations
+
+Microsoft NT and Microsoft Windows95           i[345]86-*-win32
+
+* New Targets
+
+ARM via RDP protocol                           arm-*-*
+
 *** Changes in GDB-4.14:
 
 * New native configurations
index 232e03b8e86e737263ba5ed5dd77bd876aea5c4d..25f9c418a1e6005632d5d00fdfff16b4bed83031 100644 (file)
@@ -34,9 +34,9 @@ i386bsd.mh
 i386bsd.mt
 i386lynx.mh
 i386lynx.mt
-i386mach.mh
 i386m3.mh
 i386m3.mt
+i386mach.mh
 i386mk.mh
 i386mk.mt
 i386nw.mt
@@ -50,14 +50,13 @@ i386v.mt
 i386v32.mh
 i386v4.mh
 i386v4.mt
-i386win32.mh
-i386win32.mt
 linux.mh
 linux.mt
 nbsd.mh
 nbsd.mt
 ncr3000.mh
 ncr3000.mt
+nm-fbsd.h
 nm-i386aix.h
 nm-i386bsd.h
 nm-i386lynx.h
@@ -66,7 +65,6 @@ nm-i386sco.h
 nm-i386sco4.h
 nm-i386v.h
 nm-i386v4.h
-nm-fbsd.h
 nm-linux.h
 nm-m3.h
 nm-nbsd.h
@@ -90,13 +88,15 @@ tm-i386nw.h
 tm-i386os9k.h
 tm-i386v.h
 tm-i386v4.h
-tm-i386win32.h
 tm-linux.h
 tm-nbsd.h
 tm-ptx.h
 tm-ptx4.h
 tm-sun386.h
 tm-symmetry.h
+tm-win32.h
+win32.mh
+win32.mt
 xm-go32.h
 xm-i386aix.h
 xm-i386bsd.h
@@ -108,13 +108,13 @@ xm-i386sco.h
 xm-i386v.h
 xm-i386v32.h
 xm-i386v4.h
-xm-i386win32.h
 xm-linux.h
 xm-nbsd.h
 xm-ptx.h
 xm-ptx4.h
 xm-sun386.h
 xm-symmetry.h
+xm-win32.h
 
 Things-to-lose:
 
diff --git a/gdb/config/i386/i386win32.mh b/gdb/config/i386/i386win32.mh
deleted file mode 100644 (file)
index 1b01fa9..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-MH_CFLAGS=
-XM_FILE=xm-i386win32.h
-TERMCAP= 
-XDEPFILES=win32.o
-
diff --git a/gdb/config/i386/i386win32.mt b/gdb/config/i386/i386win32.mt
deleted file mode 100644 (file)
index b71b059..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-# Target: Intel 386 run win32
-TDEPFILES= i386-tdep.o i387-tdep.o
-TM_FILE= tm-i386win32.h
-
-
diff --git a/gdb/config/i386/tm-i386win32.h b/gdb/config/i386/tm-i386win32.h
deleted file mode 100644 (file)
index fece826..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Macro definitions for i386 running under the win32 API Unix.
-   Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-
-#include "i386/tm-i386v.h"
-
-#undef MAX_REGISTER_RAW_SIZE
-#undef MAX_REGISTER_VIRTUAL_SIZE
-#undef NUM_REGS
-#undef REGISTER_BYTE
-#undef REGISTER_BYTES
-#undef REGISTER_CONVERTIBLE
-#undef REGISTER_CONVERT_TO_RAW
-#undef REGISTER_CONVERT_TO_VIRTUAL
-#undef REGISTER_NAMES
-#undef REGISTER_RAW_SIZE
-#undef REGISTER_VIRTUAL_SIZE
-#undef REGISTER_VIRTUAL_TYPE
-
-/* Number of machine registers */
-
-#define NUM_REGS 24
-
-/* Initializer for an array of names of registers.
-   There should be NUM_REGS strings in this initializer.  */
-
-/* the order of the first 8 registers must match the compiler's 
- * numbering scheme (which is the same as the 386 scheme)
- * also, this table must match regmap in i386-pinsn.c.
- */
-
-#define REGISTER_NAMES { "eax",  "ecx",  "edx",  "ebx",  \
-                        "esp",  "ebp",  "esi",  "edi",  \
-                        "eip",  "ps",   "cs",   "ss",   \
-                        "ds",   "es",   "fs",   "gs",   \
-                        "st",   "st(1)","st(2)","st(3)",\
-                         "st(4)","st(5)","st(6)","st(7)",}
-
-#define FP0_REGNUM 16
-
-/* Total amount of space needed to store our copies of the machine's
-   register state, the array `registers'.  */
-
-#define REGISTER_BYTES (16 * 4 + 8 * 10)
-
-/* Index within `registers' of the first byte of the space for
-   register N.  */
-
-#define REGISTER_BYTE(N) (((N) < 16) ? (N) * 4 : (((N) - 16) * 10) + (16 * 4))
-
-/* Number of bytes of storage in the actual machine representation
-   for register N.  */
-
-#define REGISTER_RAW_SIZE(N) (((N) < 16) ? 4 : 10)
-
-/* Number of bytes of storage in the program's representation
-   for register N. */
-
-#define REGISTER_VIRTUAL_SIZE(N) (((N) < 16) ? 4 : 10)
-
-/* Largest value REGISTER_RAW_SIZE can have.  */
-
-#define MAX_REGISTER_RAW_SIZE 10
-
-/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
-
-#define MAX_REGISTER_VIRTUAL_SIZE 10
-
-/* Nonzero if register N requires conversion
-   from raw format to virtual format.  */
-
-#define REGISTER_CONVERTIBLE(N) \
-  ((N < FP0_REGNUM) ? 0 : 1)
-
-/* Convert data from raw format for register REGNUM in buffer FROM
-   to virtual format with type TYPE in buffer TO.  */
-extern void
-i387_to_double PARAMS ((char *, char *));
-
-
-#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
-{ \
-  double val; \
-  i387_to_double ((FROM), (char *)&val); \
-  store_floating ((TO), TYPE_LENGTH (TYPE), val); \
-}
-
-extern void
-double_to_i387 PARAMS ((char *, char *));
-
-#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
-{ \
-  double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
-  double_to_i387((char *)&val, (TO)); \
-}
-
-/* Return the GDB type object for the "standard" data type
-   of data in register N.  */
-
-#define REGISTER_VIRTUAL_TYPE(N) \
-  ((N < FP0_REGNUM) ? builtin_type_int : \
-   builtin_type_double)
-
-#define NAMES_HAVE_UNDERSCORE
diff --git a/gdb/config/i386/tm-win32.h b/gdb/config/i386/tm-win32.h
new file mode 100644 (file)
index 0000000..fece826
--- /dev/null
@@ -0,0 +1,120 @@
+/* Macro definitions for i386 running under the win32 API Unix.
+   Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+
+#include "i386/tm-i386v.h"
+
+#undef MAX_REGISTER_RAW_SIZE
+#undef MAX_REGISTER_VIRTUAL_SIZE
+#undef NUM_REGS
+#undef REGISTER_BYTE
+#undef REGISTER_BYTES
+#undef REGISTER_CONVERTIBLE
+#undef REGISTER_CONVERT_TO_RAW
+#undef REGISTER_CONVERT_TO_VIRTUAL
+#undef REGISTER_NAMES
+#undef REGISTER_RAW_SIZE
+#undef REGISTER_VIRTUAL_SIZE
+#undef REGISTER_VIRTUAL_TYPE
+
+/* Number of machine registers */
+
+#define NUM_REGS 24
+
+/* Initializer for an array of names of registers.
+   There should be NUM_REGS strings in this initializer.  */
+
+/* the order of the first 8 registers must match the compiler's 
+ * numbering scheme (which is the same as the 386 scheme)
+ * also, this table must match regmap in i386-pinsn.c.
+ */
+
+#define REGISTER_NAMES { "eax",  "ecx",  "edx",  "ebx",  \
+                        "esp",  "ebp",  "esi",  "edi",  \
+                        "eip",  "ps",   "cs",   "ss",   \
+                        "ds",   "es",   "fs",   "gs",   \
+                        "st",   "st(1)","st(2)","st(3)",\
+                         "st(4)","st(5)","st(6)","st(7)",}
+
+#define FP0_REGNUM 16
+
+/* Total amount of space needed to store our copies of the machine's
+   register state, the array `registers'.  */
+
+#define REGISTER_BYTES (16 * 4 + 8 * 10)
+
+/* Index within `registers' of the first byte of the space for
+   register N.  */
+
+#define REGISTER_BYTE(N) (((N) < 16) ? (N) * 4 : (((N) - 16) * 10) + (16 * 4))
+
+/* Number of bytes of storage in the actual machine representation
+   for register N.  */
+
+#define REGISTER_RAW_SIZE(N) (((N) < 16) ? 4 : 10)
+
+/* Number of bytes of storage in the program's representation
+   for register N. */
+
+#define REGISTER_VIRTUAL_SIZE(N) (((N) < 16) ? 4 : 10)
+
+/* Largest value REGISTER_RAW_SIZE can have.  */
+
+#define MAX_REGISTER_RAW_SIZE 10
+
+/* Largest value REGISTER_VIRTUAL_SIZE can have.  */
+
+#define MAX_REGISTER_VIRTUAL_SIZE 10
+
+/* Nonzero if register N requires conversion
+   from raw format to virtual format.  */
+
+#define REGISTER_CONVERTIBLE(N) \
+  ((N < FP0_REGNUM) ? 0 : 1)
+
+/* Convert data from raw format for register REGNUM in buffer FROM
+   to virtual format with type TYPE in buffer TO.  */
+extern void
+i387_to_double PARAMS ((char *, char *));
+
+
+#define REGISTER_CONVERT_TO_VIRTUAL(REGNUM,TYPE,FROM,TO) \
+{ \
+  double val; \
+  i387_to_double ((FROM), (char *)&val); \
+  store_floating ((TO), TYPE_LENGTH (TYPE), val); \
+}
+
+extern void
+double_to_i387 PARAMS ((char *, char *));
+
+#define REGISTER_CONVERT_TO_RAW(TYPE,REGNUM,FROM,TO) \
+{ \
+  double val = extract_floating ((FROM), TYPE_LENGTH (TYPE)); \
+  double_to_i387((char *)&val, (TO)); \
+}
+
+/* Return the GDB type object for the "standard" data type
+   of data in register N.  */
+
+#define REGISTER_VIRTUAL_TYPE(N) \
+  ((N < FP0_REGNUM) ? builtin_type_int : \
+   builtin_type_double)
+
+#define NAMES_HAVE_UNDERSCORE
diff --git a/gdb/config/i386/win32.mh b/gdb/config/i386/win32.mh
new file mode 100644 (file)
index 0000000..e1713a0
--- /dev/null
@@ -0,0 +1,5 @@
+MH_CFLAGS=
+XM_FILE=xm-win32.h
+TERMCAP= 
+NATDEPFILES=win32-nat.o
+
diff --git a/gdb/config/i386/win32.mt b/gdb/config/i386/win32.mt
new file mode 100644 (file)
index 0000000..be484c4
--- /dev/null
@@ -0,0 +1,6 @@
+# Target: Intel 386 run win32
+TDEPFILES= i386-tdep.o i387-tdep.o
+TM_FILE= tm-win32.h
+
+
+
diff --git a/gdb/config/i386/xm-i386win32.h b/gdb/config/i386/xm-i386win32.h
deleted file mode 100644 (file)
index 8ba5bb2..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Definitions for hosting on WIN32, for GDB.
-   Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-#define HOST_BYTE_ORDER LITTLE_ENDIAN
-
-#include "fopen-bin.h"
-
-#define CANT_FORK
-
-
-#define GDBINIT_FILENAME "gdb.ini"
-
-#define SLASH_P(X) ((X)=='\\' || (X) == '/')
-#define ROOTED_P(X) ((SLASH_P((X)[0]))|| ((X)[1] ==':'))
-#define SLASH_CHAR '/'
-#define SLASH_STRING "/"
-
-/* If we longjmp out of the signal handler we never get another one.
-   So disable immediate_quit inside request_quit */
-#define REQUEST_QUIT 
-
-
-
diff --git a/gdb/config/i386/xm-win32.h b/gdb/config/i386/xm-win32.h
new file mode 100644 (file)
index 0000000..8ba5bb2
--- /dev/null
@@ -0,0 +1,39 @@
+/* Definitions for hosting on WIN32, for GDB.
+   Copyright 1995 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+#define HOST_BYTE_ORDER LITTLE_ENDIAN
+
+#include "fopen-bin.h"
+
+#define CANT_FORK
+
+
+#define GDBINIT_FILENAME "gdb.ini"
+
+#define SLASH_P(X) ((X)=='\\' || (X) == '/')
+#define ROOTED_P(X) ((SLASH_P((X)[0]))|| ((X)[1] ==':'))
+#define SLASH_CHAR '/'
+#define SLASH_STRING "/"
+
+/* If we longjmp out of the signal handler we never get another one.
+   So disable immediate_quit inside request_quit */
+#define REQUEST_QUIT 
+
+
+
index 8b043680e79e0582980871ea4971d2b7657f6c6b..d16de480f89749a3add4cc1b058055a0b5b9a911 100755 (executable)
@@ -2039,7 +2039,7 @@ i[345]86-*-unixware)      gdb_host=i386v4 ;;
 i[345]86-*-sysv*)      gdb_host=i386v ;;
 i[345]86-*-isc*)       gdb_host=i386v32 ;;
 i[345]86-*-os9k)       gdb_host=i386os9k ;;
-i[345]86-*-win32*)     gdb_host=i386win32 ;;
+i[345]86-*-win32*)     gdb_host=win32 ;;
 m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;;
 m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;;
 m68030-sony-*)         gdb_host=news1000 ;;
@@ -2204,7 +2204,7 @@ i[345]86-*-mach*) gdb_target=i386mach ;;
 i[345]86-*-netware*)   gdb_target=i386nw
                configdirs="${configdirs} nlm" ;;
 i[345]86-*-osf1mk*)    gdb_target=i386mk ;;
-i[345]86-*-win32)      gdb_target=i386win32  ;;
+i[345]86-*-win32)      gdb_target=win32  ;;
 
 i960-*-bout*)          gdb_target=vxworks960 ;;
 i960-*-coff*)          gdb_target=nindy960 ;;
index 1f0ad095a4b352c82aa32efc81a31f35033b2eab..9e90f63d6593c5cfc1b7bffc748b3d451b49bb42 100644 (file)
@@ -152,7 +152,7 @@ i[345]86-*-unixware)        gdb_host=i386v4 ;;
 i[345]86-*-sysv*)      gdb_host=i386v ;;
 i[345]86-*-isc*)       gdb_host=i386v32 ;;
 i[345]86-*-os9k)       gdb_host=i386os9k ;;
-i[345]86-*-win32*)     gdb_host=i386win32 ;;
+i[345]86-*-win32*)     gdb_host=win32 ;;
 m680[01]0-sun-sunos3*) gdb_host=sun2os3 ;;
 m680[01]0-sun-sunos4*) gdb_host=sun2os4 ;;
 m68030-sony-*)         gdb_host=news1000 ;;
@@ -317,7 +317,7 @@ i[345]86-*-mach*)   gdb_target=i386mach ;;
 i[345]86-*-netware*)   gdb_target=i386nw
                configdirs="${configdirs} nlm" ;;
 i[345]86-*-osf1mk*)    gdb_target=i386mk ;;
-i[345]86-*-win32)      gdb_target=i386win32  ;;
+i[345]86-*-win32)      gdb_target=win32  ;;
 
 i960-*-bout*)          gdb_target=vxworks960 ;;
 i960-*-coff*)          gdb_target=nindy960 ;;
diff --git a/gdb/win32-nat.c b/gdb/win32-nat.c
new file mode 100644 (file)
index 0000000..b7308c5
--- /dev/null
@@ -0,0 +1,643 @@
+/* Target-vector operations for controlling win32 child processes, for GDB.
+   Copyright 1996
+   Free Software Foundation, Inc.
+
+   Contributed by Cygnus Support.
+   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 eve nthe 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+
+/* by Steve Chamberlain, sac@cygnus.com */
+
+#include "defs.h"
+#include "frame.h"             /* required by inferior.h */
+#include "inferior.h"
+#include "target.h"
+#include "wait.h"
+#include "gdbcore.h"
+#include "command.h"
+#include <signal.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#include <windows.h>
+#include "buildsym.h"
+#include "gdb_string.h"
+#include "thread.h"
+#include "gdbcmd.h"
+
+#define CHECK(x) check (x, __FILE__,__LINE__)
+#define DEBUG(x) if (remote_debug) printf x
+
+
+/* Forward declaration */
+extern struct target_ops child_ops;
+
+/* The most recently read context. Inspect ContextFlags to see what 
+   bits are valid. */
+
+static CONTEXT context;
+
+/* The process and thread handles for the above context. */
+
+static HANDLE current_process;
+static HANDLE current_thread;
+static int current_process_id;
+static int current_thread_id;
+
+/* Counts of things. */
+static int exception_count = 0;
+static int event_count = 0;
+
+/* User options. */
+static int new_console = 0;
+static int new_group = 0;
+
+/* This vector maps GDB's idea of a register's number into an address
+   in the win32 exception context vector. 
+
+   It also contains the bit mask needed to load the register in question.  
+
+   One day we could read a reg, we could inspect the context we
+   already have loaded, if it doesn't have the bit set that we need,
+   we read that set of registers in using GetThreadContext.  If the
+   context already contains what we need, we just unpack it. Then to
+   write a register, first we have to ensure that the context contains
+   the other regs of the group, and then we copy the info in and set
+   out bit. */
+
+struct regmappings
+  {
+    char *incontext;
+    int mask;
+  };
+
+static const struct regmappings
+  mappings[] =
+{
+  {(char *) &context.Eax, CONTEXT_INTEGER},
+  {(char *) &context.Ecx, CONTEXT_INTEGER},
+  {(char *) &context.Edx, CONTEXT_INTEGER},
+  {(char *) &context.Ebx, CONTEXT_INTEGER},
+  {(char *) &context.Esp, CONTEXT_CONTROL},
+  {(char *) &context.Ebp, CONTEXT_CONTROL},
+  {(char *) &context.Esi, CONTEXT_INTEGER},
+  {(char *) &context.Edi, CONTEXT_INTEGER},
+  {(char *) &context.Eip, CONTEXT_CONTROL},
+  {(char *) &context.EFlags, CONTEXT_CONTROL},
+  {(char *) &context.SegCs, CONTEXT_SEGMENTS},
+  {(char *) &context.SegSs, CONTEXT_SEGMENTS},
+  {(char *) &context.SegDs, CONTEXT_SEGMENTS},
+  {(char *) &context.SegEs, CONTEXT_SEGMENTS},
+  {(char *) &context.SegFs, CONTEXT_SEGMENTS},
+  {(char *) &context.SegGs, CONTEXT_SEGMENTS},
+  {&context.FloatSave.RegisterArea[0 * 10], CONTEXT_FLOATING_POINT},
+  {&context.FloatSave.RegisterArea[1 * 10], CONTEXT_FLOATING_POINT},
+  {&context.FloatSave.RegisterArea[2 * 10], CONTEXT_FLOATING_POINT},
+  {&context.FloatSave.RegisterArea[3 * 10], CONTEXT_FLOATING_POINT},
+  {&context.FloatSave.RegisterArea[4 * 10], CONTEXT_FLOATING_POINT},
+  {&context.FloatSave.RegisterArea[5 * 10], CONTEXT_FLOATING_POINT},
+  {&context.FloatSave.RegisterArea[6 * 10], CONTEXT_FLOATING_POINT},
+  {&context.FloatSave.RegisterArea[7 * 10], CONTEXT_FLOATING_POINT},
+};
+
+
+/* This vector maps the target's idea of an exception (extracted
+   from the DEBUG_EVENT structure) to GDB's idea. */
+
+struct xlate_exception
+  {
+    int them;
+    enum target_signal us;
+  };
+
+
+static const struct xlate_exception
+  xlate[] =
+{
+  {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
+  {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
+  {DBG_CONTROL_C, TARGET_SIGNAL_INT},
+  {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
+  {-1, -1}};
+
+
+static void 
+check (BOOL ok, const char *file, int line)
+{
+  if (!ok)
+    printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
+}
+
+static void
+child_fetch_inferior_registers (int r)
+{
+  if (r < 0)
+    {
+      for (r = 0; r < NUM_REGS; r++)
+       child_fetch_inferior_registers (r);
+    }
+  else
+    {
+      supply_register (r, mappings[r].incontext);
+    }
+}
+
+static void
+child_store_inferior_registers (int r)
+{
+  if (r < 0)
+    {
+      for (r = 0; r < NUM_REGS; r++)
+       child_store_inferior_registers (r);
+    }
+  else
+    {
+      read_register_gen (r, mappings[r].incontext);
+    }
+}
+
+
+/* Wait for child to do something.  Return pid of child, or -1 in case
+   of error; store status through argument pointer OURSTATUS.  */
+
+
+static void 
+handle_load_dll (DEBUG_EVENT * event)
+{
+  DWORD dll_name_ptr;
+  DWORD done;
+
+  ReadProcessMemory (current_process,
+                    (DWORD) event->u.LoadDll.lpImageName,
+                    (char *) &dll_name_ptr,
+                    sizeof (dll_name_ptr), &done);
+
+  /* See if we could read the address of a string, and that the 
+     address isn't null. */
+
+  if (done == sizeof (dll_name_ptr) && dll_name_ptr)
+    {
+      char *dll_name;
+      int size = event->u.LoadDll.fUnicode ? sizeof (WCHAR) : sizeof (char);
+      int len = 0;
+      char b[2];
+      do
+       {
+         ReadProcessMemory (current_process,
+                            dll_name_ptr + len * size,
+                            &b,
+                            size,
+                            &done);
+         len++;
+       }
+      while ((b[0] != 0 || b[size - 1] != 0) && done == size);
+
+
+      dll_name = alloca (len);
+
+      if (event->u.LoadDll.fUnicode)
+       {
+         WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
+         ReadProcessMemory (current_process,
+                            dll_name_ptr,
+                            unicode_dll_name,
+                            len * sizeof (WCHAR),
+                            &done);
+
+         WideCharToMultiByte (CP_ACP, 0,
+                              unicode_dll_name, len,
+                              dll_name, len, 0, 0);
+       }
+      else
+       {
+         ReadProcessMemory (current_process,
+                            dll_name_ptr,
+                            dll_name,
+                            len,
+                            &done);
+       }
+
+      /* FIXME!! It would be nice to define one symbol which pointed to the 
+         front of the dll if we can't find any symbols. */
+
+      context.ContextFlags = CONTEXT_FULL;
+      GetThreadContext (current_thread, &context);
+
+      symbol_file_add (dll_name, 0, (int) event->u.LoadDll.lpBaseOfDll, 0, 0, 0);
+
+      /* We strip off the path of the dll for tidiness. */
+      if (strrchr (dll_name, '\\'))
+       dll_name = strrchr (dll_name, '\\') + 1;
+      printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll, dll_name);
+    }
+}
+
+
+static void
+handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
+{
+  int i;
+  int done = 0;
+  ourstatus->kind = TARGET_WAITKIND_STOPPED;
+
+  for (i = 0; !done && xlate[i].us > 0; i++)
+    {
+      if (xlate[i].them == event->u.Exception.ExceptionRecord.ExceptionCode)
+       {
+         ourstatus->value.sig = xlate[i].us;
+         done = 1;
+         break;
+       }
+    }
+
+  if (!done)
+    {
+      printf_unfiltered ("Want to know about exception code %08x\n",
+                        event->u.Exception.ExceptionRecord.ExceptionCode);
+      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
+    }
+  context.ContextFlags = CONTEXT_FULL;
+  GetThreadContext (current_thread, &context);
+  exception_count++;
+}
+
+static int
+child_wait (int pid, struct target_waitstatus *ourstatus)
+{
+  /* We loop when we get a non-standard exception rather than return
+     with a SPURIOUS because resume can try and step or modify things,
+     which needs a current_thread.  But some of these exceptions mark
+     the birth or death of threads, which mean that the current thread
+     isn't necessarily what you think it is. */
+
+  while (1)
+    {
+      DEBUG_EVENT event;
+      BOOL t = WaitForDebugEvent (&event, INFINITE);
+
+      DEBUG (("%d = WaitForDebugEvent() code=%d pid=%d tid=%d)\n",
+             t,
+             event.dwDebugEventCode,
+             event.dwProcessId,
+             event.dwThreadId));
+
+      event_count++;
+
+      current_thread_id = event.dwThreadId;
+      current_process_id = event.dwProcessId;
+
+      switch (event.dwDebugEventCode)
+       {
+       case CREATE_THREAD_DEBUG_EVENT:
+       case EXIT_THREAD_DEBUG_EVENT:
+       case CREATE_PROCESS_DEBUG_EVENT:
+         break;
+
+       case EXIT_PROCESS_DEBUG_EVENT:
+         ourstatus->kind = TARGET_WAITKIND_EXITED;
+         ourstatus->value.integer = event.u.ExitProcess.dwExitCode;
+         CloseHandle (current_process);
+         CloseHandle (current_thread);
+         return current_process_id;
+         break;
+
+       case LOAD_DLL_DEBUG_EVENT:
+         handle_load_dll (&event);
+         break;
+       case EXCEPTION_DEBUG_EVENT:
+         handle_exception (&event, ourstatus);
+         return current_process_id;
+       default:
+         printf_unfiltered ("waitfor it %d %d %d %d\n", t,
+                            event.dwDebugEventCode,
+                            event.dwProcessId,
+                            event.dwThreadId);
+         break;
+       }
+      CHECK (ContinueDebugEvent (current_process_id,
+                                current_thread_id,
+                                DBG_CONTINUE));
+    }
+}
+
+
+
+
+/* Attach to process PID, then initialize for debugging it.  */
+
+static void
+child_attach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  BOOL ok;
+
+  if (!args)
+    error_no_arg ("process-id to attach");
+
+  current_process_id = strtoul (args, 0, 0);
+
+  ok = DebugActiveProcess (current_process_id);
+
+  if (!ok)
+    error ("Can't attach to process.");
+
+
+  exception_count = 0;
+  event_count = 0;
+
+  if (from_tty)
+    {
+      char *exec_file = (char *) get_exec_file (0);
+
+      if (exec_file)
+       printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
+                          target_pid_to_str (current_process_id));
+      else
+       printf_unfiltered ("Attaching to %s\n",
+                          target_pid_to_str (current_process_id));
+
+      gdb_flush (gdb_stdout);
+    }
+
+  inferior_pid = current_process_id;
+  push_target (&child_ops);
+}
+
+
+static void
+child_detach (args, from_tty)
+     char *args;
+     int from_tty;
+{
+  if (from_tty)
+    {
+      char *exec_file = get_exec_file (0);
+      if (exec_file == 0)
+       exec_file = "";
+      printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
+                        target_pid_to_str (inferior_pid));
+      gdb_flush (gdb_stdout);
+    }
+  inferior_pid = 0;
+  unpush_target (&child_ops);
+}
+
+
+/* Print status information about what we're accessing.  */
+
+static void
+child_files_info (ignore)
+     struct target_ops *ignore;
+{
+  printf_unfiltered ("\tUsing the running image of %s %s.\n",
+      attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
+}
+
+/* ARGSUSED */
+static void
+child_open (arg, from_tty)
+     char *arg;
+     int from_tty;
+{
+  error ("Use the \"run\" command to start a Unix child process.");
+}
+
+/* Stub function which causes the inferior that runs it, to be ptrace-able
+   by its parent process.  */
+
+
+/* Start an inferior Unix child process and sets inferior_pid to its pid.
+   EXEC_FILE is the file to run.
+   ALLARGS is a string containing the arguments to the program.
+   ENV is the environment vector to pass.  Errors reported with error().  */
+
+
+static void
+child_create_inferior (exec_file, allargs, env)
+     char *exec_file;
+     char *allargs;
+     char **env;
+{
+  char *real_path;
+  STARTUPINFO si;
+  PROCESS_INFORMATION pi;
+  struct target_waitstatus dummy;
+  BOOL ret;
+  DWORD flags;
+
+  if (!exec_file)
+    {
+      error ("No executable specified, use `target exec'.\n");
+    }
+
+  memset (&si, 0, sizeof (si));
+  si.cb = sizeof (si);
+
+  /* A realpath is always the same size, or a bit shorter than a nice path. */
+  real_path = alloca (strlen (exec_file) + 1);
+  path_to_real_path (exec_file, real_path);
+
+  flags = DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS;
+
+  if (new_group)
+    flags |= CREATE_NEW_PROCESS_GROUP;
+
+  if (new_console)
+    flags |= CREATE_NEW_CONSOLE;
+
+  ret = CreateProcess (real_path,
+                      allargs,
+                      NULL,    /* Security */
+                      NULL,    /* thread */
+                      TRUE,    /* inherit handles */
+                      flags,   /* start flags */
+                      env,
+                      NULL,    /* current directory */
+                      &si,
+                      &pi);
+  if (!ret)
+    error ("Error creating process %s\n", exec_file);
+
+  exception_count = 0;
+  event_count = 0;
+
+  inferior_pid = pi.dwProcessId;
+  current_process = pi.hProcess;
+  current_thread = pi.hThread;
+  current_process_id = pi.dwProcessId;
+  current_thread_id = pi.dwThreadId;
+  push_target (&child_ops);
+  init_thread_list ();
+  init_wait_for_inferior ();
+  clear_proceed_status ();
+  target_terminal_init ();
+  target_terminal_inferior ();
+
+  /* Ignore the first trap */
+  child_wait (inferior_pid, &dummy);
+
+  proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
+}
+
+static void
+child_mourn_inferior ()
+{
+  unpush_target (&child_ops);
+  generic_mourn_inferior ();
+}
+
+
+/* Send a SIGINT to the process group.  This acts just like the user typed a
+   ^C on the controlling terminal. */
+
+void
+child_stop ()
+{
+  CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
+}
+
+int
+child_xfer_memory (CORE_ADDR memaddr, char *our, int len, int write, struct target_ops *target)
+{
+  DWORD done;
+  if (write)
+    {
+      WriteProcessMemory (current_process, memaddr, our, len, &done);
+      FlushInstructionCache (current_process, memaddr, len);
+    }
+  else
+    {
+      ReadProcessMemory (current_process, memaddr, our, len, &done);
+    }
+  return done;
+}
+
+void
+child_kill_inferior (void)
+{
+  CHECK (TerminateProcess (current_process, 0));
+  CHECK (CloseHandle (current_process));
+  CHECK (CloseHandle (current_thread));
+}
+
+void
+child_resume (int pid, int step, enum target_signal signal)
+{
+  DEBUG (("child_resume (%d, %d, %d);\n", pid, step, signal));
+
+  if (step)
+    {
+      /* Single step by setting t bit */
+      child_fetch_inferior_registers (PS_REGNUM);
+      context.EFlags |= FLAG_TRACE_BIT;
+    }
+
+  if (context.ContextFlags)
+    {
+      CHECK (SetThreadContext (current_thread, &context));
+      context.ContextFlags = 0;
+    }
+
+  if (signal)
+    {
+      fprintf_unfiltered (gdb_stderr, "Can't send signals to the child.\n");
+    }
+
+  CHECK (ContinueDebugEvent (current_process_id,
+                            current_thread_id,
+                            DBG_CONTINUE));
+}
+
+static void
+child_prepare_to_store ()
+{
+  /* Do nothing, since we can store individual regs */
+}
+
+static int
+child_can_run ()
+{
+  return 1;
+}
+
+static void
+child_close ()
+{
+
+}
+struct target_ops child_ops =
+{
+  "child",                     /* to_shortname */
+  "Win32 child process",       /* to_longname */
+  "Win32 child process (started by the \"run\" command).",     /* to_doc */
+  child_open,                  /* to_open */
+  child_close,                 /* to_close */
+  child_attach,                        /* to_attach */
+  child_detach,                        /* to_detach */
+  child_resume,                        /* to_resume */
+  child_wait,                  /* to_wait */
+  child_fetch_inferior_registers,/* to_fetch_registers */
+  child_store_inferior_registers,/* to_store_registers */
+  child_prepare_to_store,      /* to_child_prepare_to_store */
+  child_xfer_memory,           /* to_xfer_memory */
+  child_files_info,            /* to_files_info */
+  memory_insert_breakpoint,    /* to_insert_breakpoint */
+  memory_remove_breakpoint,    /* to_remove_breakpoint */
+  terminal_init_inferior,      /* to_terminal_init */
+  terminal_inferior,           /* to_terminal_inferior */
+  terminal_ours_for_output,    /* to_terminal_ours_for_output */
+  terminal_ours,               /* to_terminal_ours */
+  child_terminal_info,         /* to_terminal_info */
+  child_kill_inferior,         /* to_kill */
+  0,                           /* to_load */
+  0,                           /* to_lookup_symbol */
+  child_create_inferior,       /* to_create_inferior */
+  child_mourn_inferior,                /* to_mourn_inferior */
+  child_can_run,               /* to_can_run */
+  0,                           /* to_notice_signals */
+  0,                           /* to_thread_alive */
+  child_stop,                  /* to_stop */
+  process_stratum,             /* to_stratum */
+  0,                           /* to_next */
+  1,                           /* to_has_all_memory */
+  1,                           /* to_has_memory */
+  1,                           /* to_has_stack */
+  1,                           /* to_has_registers */
+  1,                           /* to_has_execution */
+  0,                           /* to_sections */
+  0,                           /* to_sections_end */
+  OPS_MAGIC                    /* to_magic */
+};
+
+void
+_initialize_inftarg ()
+{
+  add_show_from_set
+    (add_set_cmd ("new-console", class_support, var_boolean,
+                 (char *) &new_console,
+                 "Set creation of new console when creating child process.",
+                 &setlist),
+     &showlist);
+
+  add_show_from_set
+    (add_set_cmd ("new-group", class_support, var_boolean,
+                 (char *) &new_group,
+                 "Set creation of new group when creating child process.",
+                 &setlist),
+     &showlist);
+
+  add_target (&child_ops);
+}
index b7308c528a78088a780647c4bd8f9f7fccacfde7..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1,643 +0,0 @@
-/* Target-vector operations for controlling win32 child processes, for GDB.
-   Copyright 1996
-   Free Software Foundation, Inc.
-
-   Contributed by Cygnus Support.
-   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 eve nthe 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-/* by Steve Chamberlain, sac@cygnus.com */
-
-#include "defs.h"
-#include "frame.h"             /* required by inferior.h */
-#include "inferior.h"
-#include "target.h"
-#include "wait.h"
-#include "gdbcore.h"
-#include "command.h"
-#include <signal.h>
-#include <sys/types.h>
-#include <fcntl.h>
-#include <windows.h>
-#include "buildsym.h"
-#include "gdb_string.h"
-#include "thread.h"
-#include "gdbcmd.h"
-
-#define CHECK(x) check (x, __FILE__,__LINE__)
-#define DEBUG(x) if (remote_debug) printf x
-
-
-/* Forward declaration */
-extern struct target_ops child_ops;
-
-/* The most recently read context. Inspect ContextFlags to see what 
-   bits are valid. */
-
-static CONTEXT context;
-
-/* The process and thread handles for the above context. */
-
-static HANDLE current_process;
-static HANDLE current_thread;
-static int current_process_id;
-static int current_thread_id;
-
-/* Counts of things. */
-static int exception_count = 0;
-static int event_count = 0;
-
-/* User options. */
-static int new_console = 0;
-static int new_group = 0;
-
-/* This vector maps GDB's idea of a register's number into an address
-   in the win32 exception context vector. 
-
-   It also contains the bit mask needed to load the register in question.  
-
-   One day we could read a reg, we could inspect the context we
-   already have loaded, if it doesn't have the bit set that we need,
-   we read that set of registers in using GetThreadContext.  If the
-   context already contains what we need, we just unpack it. Then to
-   write a register, first we have to ensure that the context contains
-   the other regs of the group, and then we copy the info in and set
-   out bit. */
-
-struct regmappings
-  {
-    char *incontext;
-    int mask;
-  };
-
-static const struct regmappings
-  mappings[] =
-{
-  {(char *) &context.Eax, CONTEXT_INTEGER},
-  {(char *) &context.Ecx, CONTEXT_INTEGER},
-  {(char *) &context.Edx, CONTEXT_INTEGER},
-  {(char *) &context.Ebx, CONTEXT_INTEGER},
-  {(char *) &context.Esp, CONTEXT_CONTROL},
-  {(char *) &context.Ebp, CONTEXT_CONTROL},
-  {(char *) &context.Esi, CONTEXT_INTEGER},
-  {(char *) &context.Edi, CONTEXT_INTEGER},
-  {(char *) &context.Eip, CONTEXT_CONTROL},
-  {(char *) &context.EFlags, CONTEXT_CONTROL},
-  {(char *) &context.SegCs, CONTEXT_SEGMENTS},
-  {(char *) &context.SegSs, CONTEXT_SEGMENTS},
-  {(char *) &context.SegDs, CONTEXT_SEGMENTS},
-  {(char *) &context.SegEs, CONTEXT_SEGMENTS},
-  {(char *) &context.SegFs, CONTEXT_SEGMENTS},
-  {(char *) &context.SegGs, CONTEXT_SEGMENTS},
-  {&context.FloatSave.RegisterArea[0 * 10], CONTEXT_FLOATING_POINT},
-  {&context.FloatSave.RegisterArea[1 * 10], CONTEXT_FLOATING_POINT},
-  {&context.FloatSave.RegisterArea[2 * 10], CONTEXT_FLOATING_POINT},
-  {&context.FloatSave.RegisterArea[3 * 10], CONTEXT_FLOATING_POINT},
-  {&context.FloatSave.RegisterArea[4 * 10], CONTEXT_FLOATING_POINT},
-  {&context.FloatSave.RegisterArea[5 * 10], CONTEXT_FLOATING_POINT},
-  {&context.FloatSave.RegisterArea[6 * 10], CONTEXT_FLOATING_POINT},
-  {&context.FloatSave.RegisterArea[7 * 10], CONTEXT_FLOATING_POINT},
-};
-
-
-/* This vector maps the target's idea of an exception (extracted
-   from the DEBUG_EVENT structure) to GDB's idea. */
-
-struct xlate_exception
-  {
-    int them;
-    enum target_signal us;
-  };
-
-
-static const struct xlate_exception
-  xlate[] =
-{
-  {EXCEPTION_ACCESS_VIOLATION, TARGET_SIGNAL_SEGV},
-  {EXCEPTION_BREAKPOINT, TARGET_SIGNAL_TRAP},
-  {DBG_CONTROL_C, TARGET_SIGNAL_INT},
-  {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
-  {-1, -1}};
-
-
-static void 
-check (BOOL ok, const char *file, int line)
-{
-  if (!ok)
-    printf_filtered ("error return %s:%d was %d\n", file, line, GetLastError ());
-}
-
-static void
-child_fetch_inferior_registers (int r)
-{
-  if (r < 0)
-    {
-      for (r = 0; r < NUM_REGS; r++)
-       child_fetch_inferior_registers (r);
-    }
-  else
-    {
-      supply_register (r, mappings[r].incontext);
-    }
-}
-
-static void
-child_store_inferior_registers (int r)
-{
-  if (r < 0)
-    {
-      for (r = 0; r < NUM_REGS; r++)
-       child_store_inferior_registers (r);
-    }
-  else
-    {
-      read_register_gen (r, mappings[r].incontext);
-    }
-}
-
-
-/* Wait for child to do something.  Return pid of child, or -1 in case
-   of error; store status through argument pointer OURSTATUS.  */
-
-
-static void 
-handle_load_dll (DEBUG_EVENT * event)
-{
-  DWORD dll_name_ptr;
-  DWORD done;
-
-  ReadProcessMemory (current_process,
-                    (DWORD) event->u.LoadDll.lpImageName,
-                    (char *) &dll_name_ptr,
-                    sizeof (dll_name_ptr), &done);
-
-  /* See if we could read the address of a string, and that the 
-     address isn't null. */
-
-  if (done == sizeof (dll_name_ptr) && dll_name_ptr)
-    {
-      char *dll_name;
-      int size = event->u.LoadDll.fUnicode ? sizeof (WCHAR) : sizeof (char);
-      int len = 0;
-      char b[2];
-      do
-       {
-         ReadProcessMemory (current_process,
-                            dll_name_ptr + len * size,
-                            &b,
-                            size,
-                            &done);
-         len++;
-       }
-      while ((b[0] != 0 || b[size - 1] != 0) && done == size);
-
-
-      dll_name = alloca (len);
-
-      if (event->u.LoadDll.fUnicode)
-       {
-         WCHAR *unicode_dll_name = (WCHAR *) alloca (len * sizeof (WCHAR));
-         ReadProcessMemory (current_process,
-                            dll_name_ptr,
-                            unicode_dll_name,
-                            len * sizeof (WCHAR),
-                            &done);
-
-         WideCharToMultiByte (CP_ACP, 0,
-                              unicode_dll_name, len,
-                              dll_name, len, 0, 0);
-       }
-      else
-       {
-         ReadProcessMemory (current_process,
-                            dll_name_ptr,
-                            dll_name,
-                            len,
-                            &done);
-       }
-
-      /* FIXME!! It would be nice to define one symbol which pointed to the 
-         front of the dll if we can't find any symbols. */
-
-      context.ContextFlags = CONTEXT_FULL;
-      GetThreadContext (current_thread, &context);
-
-      symbol_file_add (dll_name, 0, (int) event->u.LoadDll.lpBaseOfDll, 0, 0, 0);
-
-      /* We strip off the path of the dll for tidiness. */
-      if (strrchr (dll_name, '\\'))
-       dll_name = strrchr (dll_name, '\\') + 1;
-      printf_unfiltered ("%x:%s\n", event->u.LoadDll.lpBaseOfDll, dll_name);
-    }
-}
-
-
-static void
-handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
-{
-  int i;
-  int done = 0;
-  ourstatus->kind = TARGET_WAITKIND_STOPPED;
-
-  for (i = 0; !done && xlate[i].us > 0; i++)
-    {
-      if (xlate[i].them == event->u.Exception.ExceptionRecord.ExceptionCode)
-       {
-         ourstatus->value.sig = xlate[i].us;
-         done = 1;
-         break;
-       }
-    }
-
-  if (!done)
-    {
-      printf_unfiltered ("Want to know about exception code %08x\n",
-                        event->u.Exception.ExceptionRecord.ExceptionCode);
-      ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
-    }
-  context.ContextFlags = CONTEXT_FULL;
-  GetThreadContext (current_thread, &context);
-  exception_count++;
-}
-
-static int
-child_wait (int pid, struct target_waitstatus *ourstatus)
-{
-  /* We loop when we get a non-standard exception rather than return
-     with a SPURIOUS because resume can try and step or modify things,
-     which needs a current_thread.  But some of these exceptions mark
-     the birth or death of threads, which mean that the current thread
-     isn't necessarily what you think it is. */
-
-  while (1)
-    {
-      DEBUG_EVENT event;
-      BOOL t = WaitForDebugEvent (&event, INFINITE);
-
-      DEBUG (("%d = WaitForDebugEvent() code=%d pid=%d tid=%d)\n",
-             t,
-             event.dwDebugEventCode,
-             event.dwProcessId,
-             event.dwThreadId));
-
-      event_count++;
-
-      current_thread_id = event.dwThreadId;
-      current_process_id = event.dwProcessId;
-
-      switch (event.dwDebugEventCode)
-       {
-       case CREATE_THREAD_DEBUG_EVENT:
-       case EXIT_THREAD_DEBUG_EVENT:
-       case CREATE_PROCESS_DEBUG_EVENT:
-         break;
-
-       case EXIT_PROCESS_DEBUG_EVENT:
-         ourstatus->kind = TARGET_WAITKIND_EXITED;
-         ourstatus->value.integer = event.u.ExitProcess.dwExitCode;
-         CloseHandle (current_process);
-         CloseHandle (current_thread);
-         return current_process_id;
-         break;
-
-       case LOAD_DLL_DEBUG_EVENT:
-         handle_load_dll (&event);
-         break;
-       case EXCEPTION_DEBUG_EVENT:
-         handle_exception (&event, ourstatus);
-         return current_process_id;
-       default:
-         printf_unfiltered ("waitfor it %d %d %d %d\n", t,
-                            event.dwDebugEventCode,
-                            event.dwProcessId,
-                            event.dwThreadId);
-         break;
-       }
-      CHECK (ContinueDebugEvent (current_process_id,
-                                current_thread_id,
-                                DBG_CONTINUE));
-    }
-}
-
-
-
-
-/* Attach to process PID, then initialize for debugging it.  */
-
-static void
-child_attach (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  BOOL ok;
-
-  if (!args)
-    error_no_arg ("process-id to attach");
-
-  current_process_id = strtoul (args, 0, 0);
-
-  ok = DebugActiveProcess (current_process_id);
-
-  if (!ok)
-    error ("Can't attach to process.");
-
-
-  exception_count = 0;
-  event_count = 0;
-
-  if (from_tty)
-    {
-      char *exec_file = (char *) get_exec_file (0);
-
-      if (exec_file)
-       printf_unfiltered ("Attaching to program `%s', %s\n", exec_file,
-                          target_pid_to_str (current_process_id));
-      else
-       printf_unfiltered ("Attaching to %s\n",
-                          target_pid_to_str (current_process_id));
-
-      gdb_flush (gdb_stdout);
-    }
-
-  inferior_pid = current_process_id;
-  push_target (&child_ops);
-}
-
-
-static void
-child_detach (args, from_tty)
-     char *args;
-     int from_tty;
-{
-  if (from_tty)
-    {
-      char *exec_file = get_exec_file (0);
-      if (exec_file == 0)
-       exec_file = "";
-      printf_unfiltered ("Detaching from program: %s %s\n", exec_file,
-                        target_pid_to_str (inferior_pid));
-      gdb_flush (gdb_stdout);
-    }
-  inferior_pid = 0;
-  unpush_target (&child_ops);
-}
-
-
-/* Print status information about what we're accessing.  */
-
-static void
-child_files_info (ignore)
-     struct target_ops *ignore;
-{
-  printf_unfiltered ("\tUsing the running image of %s %s.\n",
-      attach_flag ? "attached" : "child", target_pid_to_str (inferior_pid));
-}
-
-/* ARGSUSED */
-static void
-child_open (arg, from_tty)
-     char *arg;
-     int from_tty;
-{
-  error ("Use the \"run\" command to start a Unix child process.");
-}
-
-/* Stub function which causes the inferior that runs it, to be ptrace-able
-   by its parent process.  */
-
-
-/* Start an inferior Unix child process and sets inferior_pid to its pid.
-   EXEC_FILE is the file to run.
-   ALLARGS is a string containing the arguments to the program.
-   ENV is the environment vector to pass.  Errors reported with error().  */
-
-
-static void
-child_create_inferior (exec_file, allargs, env)
-     char *exec_file;
-     char *allargs;
-     char **env;
-{
-  char *real_path;
-  STARTUPINFO si;
-  PROCESS_INFORMATION pi;
-  struct target_waitstatus dummy;
-  BOOL ret;
-  DWORD flags;
-
-  if (!exec_file)
-    {
-      error ("No executable specified, use `target exec'.\n");
-    }
-
-  memset (&si, 0, sizeof (si));
-  si.cb = sizeof (si);
-
-  /* A realpath is always the same size, or a bit shorter than a nice path. */
-  real_path = alloca (strlen (exec_file) + 1);
-  path_to_real_path (exec_file, real_path);
-
-  flags = DEBUG_ONLY_THIS_PROCESS | DEBUG_PROCESS;
-
-  if (new_group)
-    flags |= CREATE_NEW_PROCESS_GROUP;
-
-  if (new_console)
-    flags |= CREATE_NEW_CONSOLE;
-
-  ret = CreateProcess (real_path,
-                      allargs,
-                      NULL,    /* Security */
-                      NULL,    /* thread */
-                      TRUE,    /* inherit handles */
-                      flags,   /* start flags */
-                      env,
-                      NULL,    /* current directory */
-                      &si,
-                      &pi);
-  if (!ret)
-    error ("Error creating process %s\n", exec_file);
-
-  exception_count = 0;
-  event_count = 0;
-
-  inferior_pid = pi.dwProcessId;
-  current_process = pi.hProcess;
-  current_thread = pi.hThread;
-  current_process_id = pi.dwProcessId;
-  current_thread_id = pi.dwThreadId;
-  push_target (&child_ops);
-  init_thread_list ();
-  init_wait_for_inferior ();
-  clear_proceed_status ();
-  target_terminal_init ();
-  target_terminal_inferior ();
-
-  /* Ignore the first trap */
-  child_wait (inferior_pid, &dummy);
-
-  proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
-}
-
-static void
-child_mourn_inferior ()
-{
-  unpush_target (&child_ops);
-  generic_mourn_inferior ();
-}
-
-
-/* Send a SIGINT to the process group.  This acts just like the user typed a
-   ^C on the controlling terminal. */
-
-void
-child_stop ()
-{
-  CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, 0));
-}
-
-int
-child_xfer_memory (CORE_ADDR memaddr, char *our, int len, int write, struct target_ops *target)
-{
-  DWORD done;
-  if (write)
-    {
-      WriteProcessMemory (current_process, memaddr, our, len, &done);
-      FlushInstructionCache (current_process, memaddr, len);
-    }
-  else
-    {
-      ReadProcessMemory (current_process, memaddr, our, len, &done);
-    }
-  return done;
-}
-
-void
-child_kill_inferior (void)
-{
-  CHECK (TerminateProcess (current_process, 0));
-  CHECK (CloseHandle (current_process));
-  CHECK (CloseHandle (current_thread));
-}
-
-void
-child_resume (int pid, int step, enum target_signal signal)
-{
-  DEBUG (("child_resume (%d, %d, %d);\n", pid, step, signal));
-
-  if (step)
-    {
-      /* Single step by setting t bit */
-      child_fetch_inferior_registers (PS_REGNUM);
-      context.EFlags |= FLAG_TRACE_BIT;
-    }
-
-  if (context.ContextFlags)
-    {
-      CHECK (SetThreadContext (current_thread, &context));
-      context.ContextFlags = 0;
-    }
-
-  if (signal)
-    {
-      fprintf_unfiltered (gdb_stderr, "Can't send signals to the child.\n");
-    }
-
-  CHECK (ContinueDebugEvent (current_process_id,
-                            current_thread_id,
-                            DBG_CONTINUE));
-}
-
-static void
-child_prepare_to_store ()
-{
-  /* Do nothing, since we can store individual regs */
-}
-
-static int
-child_can_run ()
-{
-  return 1;
-}
-
-static void
-child_close ()
-{
-
-}
-struct target_ops child_ops =
-{
-  "child",                     /* to_shortname */
-  "Win32 child process",       /* to_longname */
-  "Win32 child process (started by the \"run\" command).",     /* to_doc */
-  child_open,                  /* to_open */
-  child_close,                 /* to_close */
-  child_attach,                        /* to_attach */
-  child_detach,                        /* to_detach */
-  child_resume,                        /* to_resume */
-  child_wait,                  /* to_wait */
-  child_fetch_inferior_registers,/* to_fetch_registers */
-  child_store_inferior_registers,/* to_store_registers */
-  child_prepare_to_store,      /* to_child_prepare_to_store */
-  child_xfer_memory,           /* to_xfer_memory */
-  child_files_info,            /* to_files_info */
-  memory_insert_breakpoint,    /* to_insert_breakpoint */
-  memory_remove_breakpoint,    /* to_remove_breakpoint */
-  terminal_init_inferior,      /* to_terminal_init */
-  terminal_inferior,           /* to_terminal_inferior */
-  terminal_ours_for_output,    /* to_terminal_ours_for_output */
-  terminal_ours,               /* to_terminal_ours */
-  child_terminal_info,         /* to_terminal_info */
-  child_kill_inferior,         /* to_kill */
-  0,                           /* to_load */
-  0,                           /* to_lookup_symbol */
-  child_create_inferior,       /* to_create_inferior */
-  child_mourn_inferior,                /* to_mourn_inferior */
-  child_can_run,               /* to_can_run */
-  0,                           /* to_notice_signals */
-  0,                           /* to_thread_alive */
-  child_stop,                  /* to_stop */
-  process_stratum,             /* to_stratum */
-  0,                           /* to_next */
-  1,                           /* to_has_all_memory */
-  1,                           /* to_has_memory */
-  1,                           /* to_has_stack */
-  1,                           /* to_has_registers */
-  1,                           /* to_has_execution */
-  0,                           /* to_sections */
-  0,                           /* to_sections_end */
-  OPS_MAGIC                    /* to_magic */
-};
-
-void
-_initialize_inftarg ()
-{
-  add_show_from_set
-    (add_set_cmd ("new-console", class_support, var_boolean,
-                 (char *) &new_console,
-                 "Set creation of new console when creating child process.",
-                 &setlist),
-     &showlist);
-
-  add_show_from_set
-    (add_set_cmd ("new-group", class_support, var_boolean,
-                 (char *) &new_group,
-                 "Set creation of new group when creating child process.",
-                 &setlist),
-     &showlist);
-
-  add_target (&child_ops);
-}