* win32-nat.c (do_initial_win32_stuff): Set inferior_ptid.
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
index 350a9957319727399dbbebecb2a3b4d9e5e9843f..cd4d5333fbe27a8b942fe7e7d368d22e086a3b27 100644 (file)
@@ -1,7 +1,7 @@
 /* Target-vector operations for controlling win32 child processes, for GDB.
 
-   Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Free
-   Software Foundation, Inc.
+   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
+   2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
@@ -9,53 +9,69 @@
 
    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
+   the Free Software Foundation; either version 3 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
+   but WITHOUT ANY WARRANTY; without evethe 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.  */
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /* Originally by Steve Chamberlain, sac@cygnus.com */
 
-/* We assume we're being built with and will be used for cygwin.  */
-
 #include "defs.h"
-#include "tm.h"                        /* required for SSE registers */
 #include "frame.h"             /* required by inferior.h */
 #include "inferior.h"
 #include "target.h"
+#include "exceptions.h"
 #include "gdbcore.h"
 #include "command.h"
 #include "completer.h"
 #include "regcache.h"
 #include "top.h"
-#include "i386-tdep.h"
 #include <signal.h>
 #include <sys/types.h>
 #include <fcntl.h>
 #include <stdlib.h>
 #include <windows.h>
 #include <imagehlp.h>
+#ifdef __CYGWIN__
 #include <sys/cygwin.h>
+#endif
+#include <signal.h>
 
 #include "buildsym.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "gdb_obstack.h"
 #include "gdb_string.h"
 #include "gdbthread.h"
 #include "gdbcmd.h"
 #include <sys/param.h>
 #include <unistd.h>
+#include "exec.h"
+#include "solist.h"
+#include "solib.h"
+#include "xml-support.h"
+
+#include "i386-tdep.h"
+#include "i387-tdep.h"
+
+#include "i386-cygwin-tdep.h"
+
+static struct target_ops win32_ops;
 
-/* The ui's event loop. */
-extern int (*ui_loop_hook) (int signo);
+#ifdef __CYGWIN__
+/* The starting and ending address of the cygwin1.dll text segment. */
+static bfd_vma cygwin_load_start;
+static bfd_vma cygwin_load_end;
+#endif
+
+static int have_saved_context; /* True if we've saved context from a cygwin signal. */
+static CONTEXT saved_context;  /* Containes the saved context from a cygwin signal. */
 
 /* If we're not using the old Cygwin header file set, define the
    following which never should have been in the generic Win32 API
@@ -67,23 +83,21 @@ enum
     CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
   };
 #endif
-#include <sys/procfs.h>
 #include <psapi.h>
 
-#ifdef HAVE_SSE_REGS
 #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
        | CONTEXT_EXTENDED_REGISTERS
-#else
-#define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS
-#endif
 
 static unsigned dr[8];
-static int debug_registers_changed = 0;
-static int debug_registers_used = 0;
+static int debug_registers_changed;
+static int debug_registers_used;
+#define DR6_CLEAR_VALUE 0xffff0ff0
 
 /* The string sent by cygwin when it processes a signal.
    FIXME: This should be in a cygwin include file. */
-#define CYGWIN_SIGNAL_STRING "cygwin: signal"
+#ifndef _CYGWIN_SIGNAL_STRING
+#define _CYGWIN_SIGNAL_STRING "cYgSiGw00f"
+#endif
 
 #define CHECK(x)       check (x, __FILE__,__LINE__)
 #define DEBUG_EXEC(x)  if (debug_exec)         printf_unfiltered x
@@ -91,25 +105,23 @@ static int debug_registers_used = 0;
 #define DEBUG_MEM(x)   if (debug_memory)       printf_unfiltered x
 #define DEBUG_EXCEPT(x)        if (debug_exceptions)   printf_unfiltered x
 
-/* Forward declaration */
-extern struct target_ops child_ops;
-
-static void child_stop (void);
-static int win32_child_thread_alive (ptid_t);
-void child_kill_inferior (void);
+static void win32_stop (ptid_t);
+static int win32_win32_thread_alive (ptid_t);
+static void win32_kill_inferior (void);
 
 static enum target_signal last_sig = TARGET_SIGNAL_0;
 /* Set if a signal was received from the debugged process */
 
 /* Thread information structure used to track information that is
-   not available in gdb's thread structure. */
+   not available in gdb's thread structure.  */
 typedef struct thread_info_struct
   {
     struct thread_info_struct *next;
     DWORD id;
     HANDLE h;
     char *name;
-    int suspend_count;
+    int suspended;
+    int reload_context;
     CONTEXT context;
     STACKFRAME sf;
   }
@@ -129,9 +141,13 @@ static DWORD main_thread_id;               /* Thread ID of the main thread */
 static int exception_count = 0;
 static int event_count = 0;
 static int saw_create;
+static int open_process_used = 0;
 
 /* User options. */
 static int new_console = 0;
+#ifdef __CYGWIN__
+static int cygwin_exceptions = 0;
+#endif
 static int new_group = 1;
 static int debug_exec = 0;             /* show execution */
 static int debug_events = 0;           /* show events from kernel */
@@ -187,7 +203,6 @@ static const int mappings[] =
   context_offset (FloatSave.DataSelector),
   context_offset (FloatSave.DataOffset),
   context_offset (FloatSave.ErrorSelector)
-#ifdef HAVE_SSE_REGS
   /* XMM0-7 */ ,
   context_offset (ExtendedRegisters[10*16]),
   context_offset (ExtendedRegisters[11*16]),
@@ -199,7 +214,6 @@ static const int mappings[] =
   context_offset (ExtendedRegisters[17*16]),
   /* MXCSR */
   context_offset (ExtendedRegisters[24])
-#endif
 };
 
 #undef context_offset
@@ -232,10 +246,9 @@ check (BOOL ok, const char *file, int line)
                     GetLastError ());
 }
 
-
-/* Find a thread record given a thread id.
-   If get_context then also retrieve the context for this
-   thread. */
+/* Find a thread record given a thread id.  If GET_CONTEXT is not 0,
+   then also retrieve the context for this thread.  If GET_CONTEXT is
+   negative, then don't suspend the thread.  */
 static thread_info *
 thread_rec (DWORD id, int get_context)
 {
@@ -244,25 +257,22 @@ thread_rec (DWORD id, int get_context)
   for (th = &thread_head; (th = th->next) != NULL;)
     if (th->id == id)
       {
-       if (!th->suspend_count && get_context)
+       if (!th->suspended && get_context)
          {
            if (get_context > 0 && id != current_event.dwThreadId)
-             th->suspend_count = SuspendThread (th->h) + 1;
-           else if (get_context < 0)
-             th->suspend_count = -1;
-
-           th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
-           GetThreadContext (th->h, &th->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 (SuspendThread (th->h) == (DWORD) -1)
+                 {
+                   DWORD err = GetLastError ();
+                   warning (_("SuspendThread failed. (winerr %d)"),
+                            (int) err);
+                   return NULL;
+                 }
+               th->suspended = 1;
              }
+           else if (get_context < 0)
+             th->suspended = -1;
+           th->reload_context = 1;
          }
        return th;
       }
@@ -270,23 +280,27 @@ thread_rec (DWORD id, int get_context)
   return NULL;
 }
 
-/* Add a thread to the thread list */
+/* Add a thread to the thread list */
 static thread_info *
-child_add_thread (DWORD id, HANDLE h)
+win32_add_thread (ptid_t ptid, HANDLE h)
 {
   thread_info *th;
+  DWORD id;
+
+  gdb_assert (ptid_get_tid (ptid) != 0);
+
+  id = ptid_get_tid (ptid);
 
   if ((th = thread_rec (id, FALSE)))
     return th;
 
-  th = (thread_info *) xmalloc (sizeof (*th));
-  memset (th, 0, sizeof (*th));
+  th = XZALLOC (thread_info);
   th->id = id;
   th->h = h;
   th->next = thread_head.next;
   thread_head.next = th;
-  add_thread (pid_to_ptid (id));
-  /* Set the debug registers for the new thread in they are used.  */
+  add_thread (ptid);
+  /* Set the debug registers for the new thread if they are used.  */
   if (debug_registers_used)
     {
       /* Only change the value of the debug registers.  */
@@ -296,8 +310,7 @@ child_add_thread (DWORD id, HANDLE h)
       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.Dr6 = DR6_CLEAR_VALUE;
       th->context.Dr7 = dr[7];
       CHECK (SetThreadContext (th->h, &th->context));
       th->context.ContextFlags = 0;
@@ -308,30 +321,35 @@ child_add_thread (DWORD id, HANDLE h)
 /* Clear out any old thread list and reintialize it to a
    pristine state. */
 static void
-child_init_thread_list (void)
+win32_init_thread_list (void)
 {
   thread_info *th = &thread_head;
 
-  DEBUG_EVENTS (("gdb: child_init_thread_list\n"));
+  DEBUG_EVENTS (("gdb: win32_init_thread_list\n"));
   init_thread_list ();
   while (th->next != NULL)
     {
       thread_info *here = th->next;
       th->next = here->next;
-      (void) CloseHandle (here->h);
       xfree (here);
     }
+  thread_head.next = NULL;
 }
 
 /* Delete a thread from the list of threads */
 static void
-child_delete_thread (DWORD id)
+win32_delete_thread (ptid_t ptid)
 {
   thread_info *th;
+  DWORD id;
+
+  gdb_assert (ptid_get_tid (ptid) != 0);
+
+  id = ptid_get_tid (ptid);
 
   if (info_verbose)
-    printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (pid_to_ptid (id)));
-  delete_thread (pid_to_ptid (id));
+    printf_unfiltered ("[Deleting %s]\n", target_pid_to_str (ptid));
+  delete_thread (ptid);
 
   for (th = &thread_head;
        th->next != NULL && th->next->id != id;
@@ -342,145 +360,182 @@ child_delete_thread (DWORD id)
     {
       thread_info *here = th->next;
       th->next = here->next;
-      CloseHandle (here->h);
       xfree (here);
     }
 }
 
 static void
-do_child_fetch_inferior_registers (int r)
+do_win32_fetch_inferior_registers (struct regcache *regcache, int r)
 {
   char *context_offset = ((char *) &current_thread->context) + mappings[r];
+  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   long l;
-  if (r == FCS_REGNUM)
+
+  if (!current_thread)
+    return;    /* Windows sometimes uses a non-existent thread id in its
+                  events */
+
+  if (current_thread->reload_context)
+    {
+#ifdef __COPY_CONTEXT_SIZE
+      if (have_saved_context)
+       {
+         /* Lie about where the program actually is stopped since cygwin has informed us that
+            we should consider the signal to have occurred at another location which is stored
+            in "saved_context. */
+         memcpy (&current_thread->context, &saved_context, __COPY_CONTEXT_SIZE);
+         have_saved_context = 0;
+       }
+      else
+#endif
+       {
+         thread_info *th = current_thread;
+         th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
+         GetThreadContext (th->h, &th->context);
+         /* Copy dr values from that thread. 
+            But only if there were not modified since last stop. PR gdb/2388 */
+         if (!debug_registers_changed)
+           {
+             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;
+           }
+       }
+      current_thread->reload_context = 0;
+    }
+
+  if (r == I387_FISEG_REGNUM (tdep))
     {
       l = *((long *) context_offset) & 0xffff;
-      supply_register (r, (char *) &l);
+      regcache_raw_supply (regcache, r, (char *) &l);
     }
-  else if (r == FOP_REGNUM)
+  else if (r == I387_FOP_REGNUM (tdep))
     {
       l = (*((long *) context_offset) >> 16) & ((1 << 11) - 1);
-      supply_register (r, (char *) &l);
+      regcache_raw_supply (regcache, r, (char *) &l);
     }
   else if (r >= 0)
-    supply_register (r, context_offset);
+    regcache_raw_supply (regcache, r, context_offset);
   else
     {
-      for (r = 0; r < NUM_REGS; r++)
-       do_child_fetch_inferior_registers (r);
+      for (r = 0; r < gdbarch_num_regs (gdbarch); r++)
+       do_win32_fetch_inferior_registers (regcache, r);
     }
 }
 
 static void
-child_fetch_inferior_registers (int r)
+win32_fetch_inferior_registers (struct regcache *regcache, int r)
 {
-  current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
-  do_child_fetch_inferior_registers (r);
+  current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
+  /* Check if current_thread exists.  Windows sometimes uses a non-existent
+     thread id in its events */
+  if (current_thread)
+    do_win32_fetch_inferior_registers (regcache, r);
 }
 
 static void
-do_child_store_inferior_registers (int r)
+do_win32_store_inferior_registers (const struct regcache *regcache, int r)
 {
-  if (r >= 0)
-    regcache_collect (r, ((char *) &current_thread->context) + mappings[r]);
+  if (!current_thread)
+    /* Windows sometimes uses a non-existent thread id in its events */;
+  else if (r >= 0)
+    regcache_raw_collect (regcache, r,
+                         ((char *) &current_thread->context) + mappings[r]);
   else
     {
-      for (r = 0; r < NUM_REGS; r++)
-       do_child_store_inferior_registers (r);
+      for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++)
+       do_win32_store_inferior_registers (regcache, r);
     }
 }
 
 /* Store a new register value into the current thread context */
 static void
-child_store_inferior_registers (int r)
+win32_store_inferior_registers (struct regcache *regcache, int r)
 {
-  current_thread = thread_rec (PIDGET (inferior_ptid), TRUE);
-  do_child_store_inferior_registers (r);
+  current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
+  /* Check if current_thread exists.  Windows sometimes uses a non-existent
+     thread id in its events */
+  if (current_thread)
+    do_win32_store_inferior_registers (regcache, r);
 }
 
 static int psapi_loaded = 0;
-static HMODULE psapi_module_handle = NULL;
-static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
-static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
-static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
-
-int
-psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD,
+                                               LPDWORD);
+static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO,
+                                                 DWORD);
+static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR,
+                                                  DWORD);
+
+/* Get the name of a given module at at given base address.  If base_address
+   is zero return the first loaded module (which is always the name of the
+   executable).  */
+static int
+get_module_name (DWORD base_address, char *dll_name_ret)
 {
   DWORD len;
   MODULEINFO mi;
   int i;
   HMODULE dh_buf[1];
-  HMODULE *DllHandle = dh_buf;
+  HMODULE *DllHandle = dh_buf; /* Set to temporary storage for initial query */
   DWORD cbNeeded;
-  BOOL ok;
+#ifdef __CYGWIN__
+  char pathbuf[PATH_MAX + 1];  /* Temporary storage prior to converting to
+                                  posix form */
+#else
+  char *pathbuf = dll_name_ret;        /* Just copy directly to passed-in arg */
+#endif
 
-  if (!psapi_loaded ||
-      psapi_EnumProcessModules == NULL ||
-      psapi_GetModuleInformation == NULL ||
-      psapi_GetModuleFileNameExA == NULL)
-    {
-      if (psapi_loaded)
-       goto failed;
-      psapi_loaded = 1;
-      psapi_module_handle = LoadLibrary ("psapi.dll");
-      if (!psapi_module_handle)
-       {
-         /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
-         goto failed;
-       }
-      psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
-      psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
-      psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
-                                                   "GetModuleFileNameExA");
-      if (psapi_EnumProcessModules == NULL ||
-         psapi_GetModuleInformation == NULL ||
-         psapi_GetModuleFileNameExA == NULL)
-       goto failed;
-    }
+  /* If psapi_loaded < 0 either psapi.dll is not available or it does not contain
+     the needed functions. */
+  if (psapi_loaded <= 0)
+    goto failed;
 
   cbNeeded = 0;
-  ok = (*psapi_EnumProcessModules) (current_process_handle,
-                                   DllHandle,
-                                   sizeof (HMODULE),
-                                   &cbNeeded);
-
-  if (!ok || !cbNeeded)
+  /* Find size of buffer needed to handle list of modules loaded in inferior */
+  if (!psapi_EnumProcessModules (current_process_handle, DllHandle,
+                                sizeof (HMODULE), &cbNeeded) || !cbNeeded)
     goto failed;
 
+  /* Allocate correct amount of space for module list */
   DllHandle = (HMODULE *) alloca (cbNeeded);
   if (!DllHandle)
     goto failed;
 
-  ok = (*psapi_EnumProcessModules) (current_process_handle,
-                                   DllHandle,
-                                   cbNeeded,
-                                   &cbNeeded);
-  if (!ok)
+  /* Get the list of modules */
+  if (!psapi_EnumProcessModules (current_process_handle, DllHandle, cbNeeded,
+                                &cbNeeded))
     goto failed;
 
   for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
     {
-      if (!(*psapi_GetModuleInformation) (current_process_handle,
-                                         DllHandle[i],
-                                         &mi,
-                                         sizeof (mi)))
-       error ("Can't get module info");
-
-      len = (*psapi_GetModuleFileNameExA) (current_process_handle,
-                                          DllHandle[i],
-                                          dll_name_ret,
-                                          MAX_PATH);
-      if (len == 0)
-       error ("Error getting dll name: %u\n", (unsigned) GetLastError ());
-
-      if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
-       return 1;
+      /* Get information on this module */
+      if (!psapi_GetModuleInformation (current_process_handle, DllHandle[i],
+                                      &mi, sizeof (mi)))
+       error (_("Can't get module info"));
+
+      if (!base_address || (DWORD) (mi.lpBaseOfDll) == base_address)
+       {
+         /* Try to find the name of the given module */
+         len = psapi_GetModuleFileNameExA (current_process_handle,
+                                           DllHandle[i], pathbuf, MAX_PATH);
+         if (len == 0)
+           error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
+#ifdef __CYGWIN__
+         /* Cygwin prefers that the path be in /x/y/z format */
+         cygwin_conv_to_full_posix_path (pathbuf, dll_name_ret);
+#endif
+         return 1;     /* success */
+       }
     }
 
 failed:
   dll_name_ret[0] = '\0';
-  return 0;
+  return 0;            /* failure */
 }
 
 /* Encapsulate the information required in a call to
@@ -497,27 +552,19 @@ struct safe_symbol_file_add_args
 };
 
 /* Maintain a linked list of "so" information. */
-struct so_stuff
+struct lm_info
 {
-  struct so_stuff *next;
   DWORD load_addr;
-  DWORD end_addr;
-  int loaded;
-  struct objfile *objfile;
-  char name[1];
-} solib_start, *solib_end;
+};
+
+static struct so_list solib_start, *solib_end;
 
 /* Call symbol_file_add with stderr redirected.  We don't care if there
    are errors. */
 static int
 safe_symbol_file_add_stub (void *argv)
 {
-#define p ((struct safe_symbol_file_add_args *)argv)
-  struct so_stuff *so = &solib_start;
-
-  while ((so = so->next))
-    if (so->loaded && strcasecmp (so->name, p->name) == 0)
-      return 0;
+#define p ((struct safe_symbol_file_add_args *) argv)
   p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
   return !!p->ret;
 #undef p
@@ -565,21 +612,16 @@ safe_symbol_file_add (char *name, int from_tty,
   return p.ret;
 }
 
-/* Remember the maximum DLL length for printing in info dll command. */
-int max_dll_name_len;
-
-static void
-register_loaded_dll (const char *name, DWORD load_addr)
+static struct so_list *
+win32_make_so (const char *name, DWORD load_addr)
 {
-  struct so_stuff *so;
-  char ppath[MAX_PATH + 1];
+  struct so_list *so;
   char buf[MAX_PATH + 1];
   char cwd[MAX_PATH + 1];
   char *p;
   WIN32_FIND_DATA w32_fd;
   HANDLE h = FindFirstFile(name, &w32_fd);
   MEMORY_BASIC_INFORMATION m;
-  size_t len;
 
   if (h == INVALID_HANDLE_VALUE)
     strcpy (buf, name);
@@ -598,28 +640,55 @@ register_loaded_dll (const char *name, DWORD load_addr)
        }
     }
 
-  cygwin_conv_to_posix_path (buf, ppath);
-  so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) + strlen (ppath) + 8 + 1);
-  so->loaded = 0;
-  so->load_addr = load_addr;
-  if (!VirtualQueryEx (current_process_handle, (void *) load_addr, &m,
-                      sizeof (m)))
-    so->end_addr = (DWORD) m.AllocationBase + m.RegionSize;
-  else
-    so->end_addr = load_addr + 0x2000; /* completely arbitrary */
+  if (strcasecmp (buf, "ntdll.dll") == 0)
+    {
+      GetSystemDirectory (buf, sizeof (buf));
+      strcat (buf, "\\ntdll.dll");
+    }
+  so = XZALLOC (struct so_list);
+  so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
+  so->lm_info->load_addr = load_addr;
+  strcpy (so->so_original_name, name);
+#ifndef __CYGWIN__
+  strcpy (so->so_name, buf);
+#else
+  cygwin_conv_to_posix_path (buf, so->so_name);
+  /* Record cygwin1.dll .text start/end.  */
+  p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
+  if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
+    {
+      bfd *abfd;
+      asection *text = NULL;
+      CORE_ADDR text_vma;
+
+      abfd = bfd_openr (so->so_name, "pei-i386");
+
+      if (!abfd)
+       return so;
+
+      if (bfd_check_format (abfd, bfd_object))
+       text = bfd_get_section_by_name (abfd, ".text");
+
+      if (!text)
+       {
+         bfd_close (abfd);
+         return so;
+       }
+
+      /* The symbols in a dll are offset by 0x1000, which is the the
+        offset from 0 of the first byte in an image - because of the
+        file header and the section alignment. */
+      cygwin_load_start = load_addr + 0x1000;
+      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
 
-  so->next = NULL;
-  so->objfile = NULL;
-  strcpy (so->name, ppath);
+      bfd_close (abfd);
+    }
+#endif
 
-  solib_end->next = so;
-  solib_end = so;
-  len = strlen (ppath);
-  if (len > max_dll_name_len)
-    max_dll_name_len = len;
+  return so;
 }
 
-char *
+static char *
 get_image_name (HANDLE h, void *address, int unicode)
 {
   static char buf[(2 * MAX_PATH) + 1];
@@ -635,21 +704,16 @@ get_image_name (HANDLE h, void *address, int unicode)
   if (address == NULL)
     return NULL;
 
-  ReadProcessMemory (h, address,  &address_ptr, sizeof (address_ptr), &done);
-
   /* See if we could read the address of a string, and that the
      address isn't null. */
-
-  if (done != sizeof (address_ptr) || !address_ptr)
+  if (!ReadProcessMemory (h, address,  &address_ptr, sizeof (address_ptr), &done)
+      || done != sizeof (address_ptr) || !address_ptr)
     return NULL;
 
   /* Find the length of the string */
-  do
-    {
-      ReadProcessMemory (h, address_ptr + len * size, &b, size, &done);
-      len++;
-    }
-  while ((b[0] != 0 || b[size - 1] != 0) && done == size);
+  while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
+        && (b[0] != 0 || b[size - 1] != 0) && done == size)
+    continue;
 
   if (!unicode)
     ReadProcessMemory (h, address_ptr, buf, len, &done);
@@ -673,191 +737,68 @@ handle_load_dll (void *dummy)
   LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
   char dll_buf[MAX_PATH + 1];
   char *dll_name = NULL;
-  char *p;
 
   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
 
-  if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
+  if (!get_module_name ((DWORD) event->lpBaseOfDll, dll_buf))
     dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
 
   dll_name = dll_buf;
 
   if (*dll_name == '\0')
-    dll_name = get_image_name (current_process_handle, event->lpImageName, event->fUnicode);
+    dll_name = get_image_name (current_process_handle,
+                              event->lpImageName, event->fUnicode);
   if (!dll_name)
     return 1;
 
-  register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000);
+  solib_end->next = win32_make_so (dll_name, (DWORD) event->lpBaseOfDll);
+  solib_end = solib_end->next;
+
+  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at 0x%lx.\n", solib_end->so_name,
+                (DWORD) solib_end->lm_info->load_addr));
 
   return 1;
 }
 
+static void
+win32_free_so (struct so_list *so)
+{
+  if (so->lm_info)
+    xfree (so->lm_info);
+  xfree (so);
+}
+
 static int
 handle_unload_dll (void *dummy)
 {
-  DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000;
-  struct so_stuff *so;
+  DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
+  struct so_list *so;
 
   for (so = &solib_start; so->next != NULL; so = so->next)
-    if (so->next->load_addr == lpBaseOfDll)
+    if (so->next->lm_info->load_addr == lpBaseOfDll)
       {
-       struct so_stuff *sodel = so->next;
+       struct so_list *sodel = so->next;
        so->next = sodel->next;
        if (!so->next)
          solib_end = so;
-       if (sodel->objfile)
-         free_objfile (sodel->objfile);
-       xfree(sodel);
+       DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
+
+       win32_free_so (sodel);
+       solib_add (NULL, 0, NULL, auto_solib_add);
        return 1;
       }
-  error ("Error: dll starting at 0x%lx not found.\n", (DWORD) lpBaseOfDll);
-
-  return 0;
-}
 
-char *
-solib_address (CORE_ADDR address)
-{
-  struct so_stuff *so;
-  for (so = &solib_start; so->next != NULL; so = so->next)
-    if (address >= so->load_addr && address <= so->end_addr)
-      return so->name;
-  return NULL;
-}
+  error (_("Error: dll starting at 0x%lx not found."), (DWORD) lpBaseOfDll);
 
-/* Return name of last loaded DLL. */
-char *
-child_solib_loaded_library_pathname (int pid)
-{
-  return !solib_end || !solib_end->name[0] ? NULL : solib_end->name;
+  return 0;
 }
 
 /* Clear list of loaded DLLs. */
-void
-child_clear_solibs (void)
+static void
+win32_clear_solib (void)
 {
-  struct so_stuff *so, *so1 = solib_start.next;
-
-  while ((so = so1) != NULL)
-    {
-      so1 = so->next;
-      xfree (so);
-    }
-
   solib_start.next = NULL;
-  solib_start.objfile = NULL;
   solib_end = &solib_start;
-  max_dll_name_len = sizeof ("DLL Name") - 1;
-}
-
-/* Get the loaded address of all sections, given that .text was loaded
-   at text_load. Assumes that all sections are subject to the same
-   relocation offset. Returns NULL if problems occur or if the
-   sections were not relocated. */
-
-static struct section_addr_info *
-get_relocated_section_addrs (bfd *abfd, CORE_ADDR text_load)
-{
-  struct section_addr_info *result = NULL;
-  int section_count = bfd_count_sections (abfd);
-  asection *text_section = bfd_get_section_by_name (abfd, ".text");
-  CORE_ADDR text_vma;
-
-  if (!text_section)
-    {
-      /* Couldn't get the .text section. Weird. */
-    }
-
-  else if (text_load == (text_vma = bfd_get_section_vma (abfd, text_section)))
-    {
-      /* DLL wasn't relocated. */
-    }
-
-  else
-    {
-      /* Figure out all sections' loaded addresses. The offset here is
-        such that taking a bfd_get_section_vma() result and adding
-        offset will give the real load address of the section. */
-
-      CORE_ADDR offset = text_load - text_vma;
-
-      struct section_table *table_start = NULL;
-      struct section_table *table_end = NULL;
-      struct section_table *iter = NULL;
-
-      build_section_table (abfd, &table_start, &table_end);
-
-      for (iter = table_start; iter < table_end; ++iter)
-       {
-         /* Relocated addresses. */
-         iter->addr += offset;
-         iter->endaddr += offset;
-       }
-
-      result = build_section_addr_info_from_section_table (table_start,
-                                                          table_end);
-
-      xfree (table_start);
-    }
-
-  return result;
-}
-
-/* Add DLL symbol information. */
-static struct objfile *
-solib_symbols_add (char *name, int from_tty, CORE_ADDR load_addr)
-{
-  struct section_addr_info *section_addrs_ptr = NULL;
-  static struct objfile *result = NULL;
-  bfd *abfd = NULL;
-
-  /* The symbols in a dll are offset by 0x1000, which is the
-     the offset from 0 of the first byte in an image - because
-     of the file header and the section alignment. */
-
-  if (!name || !name[0])
-    return NULL;
-
-  abfd = bfd_openr (name, "pei-i386");
-
-  if (!abfd)
-    {
-      /* pei failed - try pe */
-      abfd = bfd_openr (name, "pe-i386");
-    }
-
-  if (abfd)
-    {
-      if (bfd_check_format (abfd, bfd_object))
-       {
-         section_addrs_ptr = get_relocated_section_addrs (abfd, load_addr);
-       }
-
-      bfd_close (abfd);
-    }
-
-  if (section_addrs_ptr)
-    {
-      result = safe_symbol_file_add (name, from_tty, section_addrs_ptr,
-                                    0, OBJF_SHARED);
-
-      free_section_addr_info (section_addrs_ptr);
-    }
-
-  else
-    {
-      /* Fallback on handling just the .text section. */
-      struct section_addr_info section_addrs;
-
-      memset (&section_addrs, 0, sizeof (section_addrs));
-      section_addrs.other[0].name = ".text";
-      section_addrs.other[0].addr = load_addr;
-
-      result = safe_symbol_file_add (name, from_tty, &section_addrs,
-                                    0, OBJF_SHARED);
-    }
-
-  return result;
 }
 
 /* Load DLL symbol info. */
@@ -868,7 +809,7 @@ dll_symbol_command (char *args, int from_tty)
   dont_repeat ();
 
   if (args == NULL)
-    error ("dll-symbols requires a file name");
+    error (_("dll-symbols requires a file name"));
 
   n = strlen (args);
   if (n > 4 && strcasecmp (args + n - 4, ".dll") != 0)
@@ -882,53 +823,60 @@ dll_symbol_command (char *args, int from_tty)
   safe_symbol_file_add (args, from_tty, NULL, 0, OBJF_SHARED | OBJF_USERLOADED);
 }
 
-/* List currently loaded DLLs. */
-void
-info_dll_command (char *ignore, int from_tty)
-{
-  struct so_stuff *so = &solib_start;
-
-  if (!so->next)
-    return;
-
-  printf_filtered ("%*s  Load Address\n", -max_dll_name_len, "DLL Name");
-  while ((so = so->next) != NULL)
-    printf_filtered ("%*s  %08lx\n", -max_dll_name_len, so->name, so->load_addr);
-
-  return;
-}
-
 /* Handle DEBUG_STRING output from child process.
    Cygwin prepends its messages with a "cygwin:".  Interpret this as
    a Cygwin signal.  Otherwise just print the string as a warning. */
 static int
 handle_output_debug_string (struct target_waitstatus *ourstatus)
 {
-  char *s;
-  int gotasig = FALSE;
+  char *s = NULL;
+  int retval = 0;
 
   if (!target_read_string
-    ((CORE_ADDR) current_event.u.DebugString.lpDebugStringData, &s, 1024, 0)
+       ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
+       &s, 1024, 0)
       || !s || !*s)
-    return gotasig;
-
-  if (strncmp (s, CYGWIN_SIGNAL_STRING, sizeof (CYGWIN_SIGNAL_STRING) - 1) != 0)
+    /* nothing to do */;
+  else if (strncmp (s, _CYGWIN_SIGNAL_STRING, sizeof (_CYGWIN_SIGNAL_STRING) - 1) != 0)
     {
+#ifdef __CYGWIN__
       if (strncmp (s, "cYg", 3) != 0)
-       warning ("%s", s);
+#endif
+       warning (("%s"), s);
     }
+#ifdef __COPY_CONTEXT_SIZE
   else
     {
+      /* Got a cygwin signal marker.  A cygwin signal is followed by the signal number
+        itself and then optionally followed by the thread id and address to saved context
+        within the DLL.  If these are supplied, then the given thread is assumed to have
+        issued the signal and the context from the thread is assumed to be stored at the
+        given address in the inferior.  Tell gdb to treat this like a real signal.  */
       char *p;
-      int sig = strtol (s + sizeof (CYGWIN_SIGNAL_STRING) - 1, &p, 0);
-      gotasig = target_signal_from_host (sig);
+      int sig = strtol (s + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0);
+      int gotasig = target_signal_from_host (sig);
       ourstatus->value.sig = gotasig;
       if (gotasig)
-       ourstatus->kind = TARGET_WAITKIND_STOPPED;
+       {
+         LPCVOID x;
+         DWORD n;
+         ourstatus->kind = TARGET_WAITKIND_STOPPED;
+         retval = strtoul (p, &p, 0);
+         if (!retval)
+           retval = main_thread_id;
+         else if ((x = (LPCVOID) strtoul (p, &p, 0))
+                  && ReadProcessMemory (current_process_handle, x,
+                                        &saved_context, __COPY_CONTEXT_SIZE, &n)
+                  && n == __COPY_CONTEXT_SIZE)
+           have_saved_context = 1;
+         current_event.dwThreadId = retval;
+       }
     }
+#endif
 
-  xfree (s);
-  return gotasig;
+  if (s)
+    xfree (s);
+  return retval;
 }
 
 static int
@@ -949,7 +897,7 @@ display_selector (HANDLE thread, DWORD sel)
             + info.BaseLow;
       limit = (info.HighWord.Bits.LimitHi << 16) + info.LimitLow;
       if (info.HighWord.Bits.Granularity)
-       limit = (limit << 12) | 0xfff;
+       limit = (limit << 12) | 0xfff;
       printf_filtered ("base=0x%08x limit=0x%08x", base, limit);
       if (info.HighWord.Bits.Default_Big)
        puts_filtered(" 32-bit ");
@@ -1071,6 +1019,23 @@ handle_exception (struct target_waitstatus *ourstatus)
     case EXCEPTION_ACCESS_VIOLATION:
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
+#ifdef __CYGWIN__
+      {
+       /* See if the access violation happened within the cygwin DLL itself.  Cygwin uses
+          a kind of exception handling to deal with passed-in invalid addresses. gdb
+          should not treat these as real SEGVs since they will be silently handled by
+          cygwin.  A real SEGV will (theoretically) be caught by cygwin later in the process
+          and will be sent as a cygwin-specific-signal.  So, ignore SEGVs if they show up
+          within the text segment of the DLL itself. */
+       char *fn;
+       bfd_vma addr = (bfd_vma) (uintptr_t) current_event.u.Exception.
+                                            ExceptionRecord.ExceptionAddress;
+       if ((!cygwin_exceptions && (addr >= cygwin_load_start && addr < cygwin_load_end))
+           || (find_pc_partial_function (addr, &fn, NULL, NULL)
+               && strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0))
+         return 0;
+      }
+#endif
       break;
     case STATUS_STACK_OVERFLOW:
       DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
@@ -1145,8 +1110,9 @@ handle_exception (struct target_waitstatus *ourstatus)
       ourstatus->value.sig = TARGET_SIGNAL_ILL;
       break;
     default:
+      /* Treat unhandled first chance exceptions specially. */
       if (current_event.u.Exception.dwFirstChance)
-       return 0;
+       return -1;
       printf_unfiltered ("gdb: unknown target exception 0x%08lx at 0x%08lx\n",
                    current_event.u.Exception.ExceptionRecord.ExceptionCode,
        (DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress);
@@ -1161,7 +1127,7 @@ handle_exception (struct target_waitstatus *ourstatus)
 /* Resume all artificially suspended threads if we are continuing
    execution */
 static BOOL
-child_continue (DWORD continue_status, int id)
+win32_continue (DWORD continue_status, int id)
 {
   int i;
   thread_info *th;
@@ -1171,113 +1137,237 @@ child_continue (DWORD continue_status, int id)
                  current_event.dwProcessId, current_event.dwThreadId,
                  continue_status == DBG_CONTINUE ?
                  "DBG_CONTINUE" : "DBG_EXCEPTION_NOT_HANDLED"));
+
+  for (th = &thread_head; (th = th->next) != NULL;)
+    if ((id == -1 || id == (int) th->id)
+       && th->suspended)
+      {
+       if (debug_registers_changed)
+         {
+           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 = DR6_CLEAR_VALUE;
+           th->context.Dr7 = dr[7];
+         }
+       if (th->context.ContextFlags)
+         {
+           CHECK (SetThreadContext (th->h, &th->context));
+           th->context.ContextFlags = 0;
+         }
+       if (th->suspended > 0)
+         (void) ResumeThread (th->h);
+       th->suspended = 0;
+      }
+
   res = ContinueDebugEvent (current_event.dwProcessId,
                            current_event.dwThreadId,
                            continue_status);
-  continue_status = 0;
-  if (res)
-    for (th = &thread_head; (th = th->next) != NULL;)
-      if (((id == -1) || (id == (int) th->id)) && th->suspend_count)
-       {
-
-         for (i = 0; i < th->suspend_count; i++)
-           (void) ResumeThread (th->h);
-         th->suspend_count = 0;
-         if (debug_registers_changed)
-           {
-             /* Only change the value of the debug reisters */
-             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];
-             CHECK (SetThreadContext (th->h, &th->context));
-             th->context.ContextFlags = 0;
-           }
-       }
 
   debug_registers_changed = 0;
   return res;
 }
 
-/* Get the next event from the child.  Return 1 if the event requires
-   handling by WFI (or whatever).
- */
-static int
-get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
+/* Called in pathological case where Windows fails to send a
+   CREATE_PROCESS_DEBUG_EVENT after an attach.  */
+static DWORD
+fake_create_process (void)
 {
-  BOOL debug_event;
-  DWORD continue_status, event_code;
-  thread_info *th = NULL;
-  static thread_info dummy_thread_info;
-  int retval = 0;
-
-  last_sig = TARGET_SIGNAL_0;
+  current_process_handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE,
+                                       current_event.dwProcessId);
+  if (current_process_handle != NULL)
+    open_process_used = 1;
+  else
+    {
+      error (_("OpenProcess call failed, GetLastError = %lud\n"),
+       GetLastError ());
+      /*  We can not debug anything in that case.  */
+    }
+  main_thread_id = current_event.dwThreadId;
+  current_thread = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                                current_event.dwThreadId),
+                                    current_event.u.CreateThread.hThread);
+  return main_thread_id;
+}
 
-  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
-    goto out;
+static void
+win32_resume (ptid_t ptid, int step, enum target_signal sig)
+{
+  thread_info *th;
+  DWORD continue_status = DBG_CONTINUE;
 
-  event_count++;
-  continue_status = DBG_CONTINUE;
+  /* A specific PTID means `step only this thread id'.  */
+  int resume_all = ptid_equal (ptid, minus_one_ptid);
 
-  event_code = current_event.dwDebugEventCode;
-  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+  /* If we're continuing all threads, it's the current inferior that
+     should be handled specially.  */
+  if (resume_all)
+    ptid = inferior_ptid;
 
-  switch (event_code)
+  if (sig != TARGET_SIGNAL_0)
     {
-    case CREATE_THREAD_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
-                    (unsigned) current_event.dwProcessId,
-                    (unsigned) current_event.dwThreadId,
-                    "CREATE_THREAD_DEBUG_EVENT"));
-      if (saw_create != 1)
-       break;
-      /* Record the existence of this thread */
-      th = child_add_thread (current_event.dwThreadId,
-                            current_event.u.CreateThread.hThread);
-      if (info_verbose)
-       printf_unfiltered ("[New %s]\n",
-                          target_pid_to_str (
-                            pid_to_ptid (current_event.dwThreadId)));
-      retval = current_event.dwThreadId;
-      break;
-
-    case EXIT_THREAD_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                    (unsigned) current_event.dwProcessId,
-                    (unsigned) current_event.dwThreadId,
-                    "EXIT_THREAD_DEBUG_EVENT"));
-      if (saw_create != 1)
-       break;
-      child_delete_thread (current_event.dwThreadId);
-      th = &dummy_thread_info;
-      break;
-
-    case CREATE_PROCESS_DEBUG_EVENT:
-      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                    (unsigned) current_event.dwProcessId,
-                    (unsigned) current_event.dwThreadId,
-                    "CREATE_PROCESS_DEBUG_EVENT"));
-      CloseHandle (current_event.u.CreateProcessInfo.hFile);
-      if (++saw_create != 1)
+      if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
+       {
+         DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
+       }
+      else if (sig == last_sig)
+       continue_status = DBG_EXCEPTION_NOT_HANDLED;
+      else
+#if 0
+/* This code does not seem to work, because
+  the kernel does probably not consider changes in the ExceptionRecord
+  structure when passing the exception to the inferior.
+  Note that this seems possible in the exception handler itself.  */
+       {
+         int i;
+         for (i = 0; xlate[i].them != -1; i++)
+           if (xlate[i].us == sig)
+             {
+               current_event.u.Exception.ExceptionRecord.ExceptionCode =
+                 xlate[i].them;
+               continue_status = DBG_EXCEPTION_NOT_HANDLED;
+               break;
+             }
+         if (continue_status == DBG_CONTINUE)
+           {
+             DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
+           }
+       }
+#endif
+       DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n",
+         last_sig));
+    }
+
+  last_sig = TARGET_SIGNAL_0;
+
+  DEBUG_EXEC (("gdb: win32_resume (pid=%d, tid=%ld, step=%d, sig=%d);\n",
+              ptid_get_pid (ptid), ptid_get_tid (ptid), step, sig));
+
+  /* Get context for currently selected thread */
+  th = thread_rec (ptid_get_tid (inferior_ptid), FALSE);
+  if (th)
+    {
+      if (step)
+       {
+         /* Single step by setting t bit */
+         win32_fetch_inferior_registers (get_current_regcache (),
+                                         gdbarch_ps_regnum (current_gdbarch));
+         th->context.EFlags |= FLAG_TRACE_BIT;
+       }
+
+      if (th->context.ContextFlags)
        {
-         CloseHandle (current_event.u.CreateProcessInfo.hProcess);
+         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 = DR6_CLEAR_VALUE;
+             th->context.Dr7 = dr[7];
+           }
+         CHECK (SetThreadContext (th->h, &th->context));
+         th->context.ContextFlags = 0;
+       }
+    }
+
+  /* Allow continuing with the same signal that interrupted us.
+     Otherwise complain. */
+
+  if (resume_all)
+    win32_continue (continue_status, -1);
+  else
+    win32_continue (continue_status, ptid_get_tid (ptid));
+}
+
+/* Get the next event from the child.  Return 1 if the event requires
+   handling by WFI (or whatever).
+ */
+static int
+get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
+{
+  BOOL debug_event;
+  DWORD continue_status, event_code;
+  thread_info *th;
+  static thread_info dummy_thread_info;
+  int retval = 0;
+
+  last_sig = TARGET_SIGNAL_0;
+
+  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
+    goto out;
+
+  event_count++;
+  continue_status = DBG_CONTINUE;
+
+  event_code = current_event.dwDebugEventCode;
+  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+  th = NULL;
+  have_saved_context = 0;
+
+  switch (event_code)
+    {
+    case CREATE_THREAD_DEBUG_EVENT:
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "CREATE_THREAD_DEBUG_EVENT"));
+      if (saw_create != 1)
+       {
+         struct inferior *inf;
+         inf = find_inferior_pid (current_event.dwProcessId);
+         if (!saw_create && inf->attach_flag)
+           {
+             /* Kludge around a Windows bug where first event is a create
+                thread event.  Caused when attached process does not have
+                a main thread. */
+             retval = fake_create_process ();
+             if (retval)
+               saw_create++;
+           }
          break;
        }
+      /* Record the existence of this thread */
+      retval = current_event.dwThreadId;
+      th = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                        current_event.dwThreadId),
+                            current_event.u.CreateThread.hThread);
+      break;
+
+    case EXIT_THREAD_DEBUG_EVENT:
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "EXIT_THREAD_DEBUG_EVENT"));
+      if (current_event.dwThreadId != main_thread_id)
+       {
+         win32_delete_thread (ptid_build (current_event.dwProcessId, 0,
+                                          current_event.dwThreadId));
+         th = &dummy_thread_info;
+       }
+      break;
+
+    case CREATE_PROCESS_DEBUG_EVENT:
+      DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "CREATE_PROCESS_DEBUG_EVENT"));
+      CloseHandle (current_event.u.CreateProcessInfo.hFile);
+      if (++saw_create != 1)
+       break;
 
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
+      if (main_thread_id)
+       win32_delete_thread (ptid_build (current_event.dwProcessId, 0,
+                                        main_thread_id));
       main_thread_id = current_event.dwThreadId;
       /* Add the main thread */
-#if 0
-      th = child_add_thread (current_event.dwProcessId,
-                            current_event.u.CreateProcessInfo.hProcess);
-#endif
-      th = child_add_thread (main_thread_id,
+      th = win32_add_thread (ptid_build (current_event.dwProcessId, 0,
+                                        current_event.dwThreadId),
                             current_event.u.CreateProcessInfo.hThread);
-      retval = ourstatus->value.related_pid = current_event.dwThreadId;
+      retval = current_event.dwThreadId;
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
@@ -1289,7 +1379,6 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
        break;
       ourstatus->kind = TARGET_WAITKIND_EXITED;
       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
-      CloseHandle (current_process_handle);
       retval = main_thread_id;
       break;
 
@@ -1302,11 +1391,9 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
       if (saw_create != 1)
        break;
       catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
-      registers_changed ();    /* mark all regs invalid */
       ourstatus->kind = TARGET_WAITKIND_LOADED;
       ourstatus->value.integer = 0;
       retval = main_thread_id;
-      re_enable_breakpoints_in_shlibs ();
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
@@ -1317,9 +1404,9 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
       if (saw_create != 1)
        break;
       catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
-      registers_changed ();    /* mark all regs invalid */
-      /* ourstatus->kind = TARGET_WAITKIND_UNLOADED;
-        does not exist yet. */
+      ourstatus->kind = TARGET_WAITKIND_LOADED;
+      ourstatus->value.integer = 0;
+      retval = main_thread_id;
       break;
 
     case EXCEPTION_DEBUG_EVENT:
@@ -1329,8 +1416,19 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
                     "EXCEPTION_DEBUG_EVENT"));
       if (saw_create != 1)
        break;
-      if (handle_exception (ourstatus))
-       retval = current_event.dwThreadId;
+      switch (handle_exception (ourstatus))
+       {
+       case 0:
+         continue_status = DBG_EXCEPTION_NOT_HANDLED;
+         break;
+       case 1:
+         retval = current_event.dwThreadId;
+         break;
+       case -1:
+         last_sig = 1;
+         continue_status = -1;
+         break;
+       }
       break;
 
     case OUTPUT_DEBUG_STRING_EVENT:    /* message from the kernel */
@@ -1340,8 +1438,7 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
                     "OUTPUT_DEBUG_STRING_EVENT"));
       if (saw_create != 1)
        break;
-      if (handle_output_debug_string (ourstatus))
-       retval = main_thread_id;
+      retval = handle_output_debug_string (ourstatus);
       break;
 
     default:
@@ -1356,22 +1453,30 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus)
     }
 
   if (!retval || saw_create != 1)
-    CHECK (child_continue (continue_status, -1));
+    {
+      if (continue_status == -1)
+       win32_resume (minus_one_ptid, 0, 1);
+      else
+       CHECK (win32_continue (continue_status, -1));
+    }
   else
     {
-      current_thread = th ? : thread_rec (current_event.dwThreadId, TRUE);
-      inferior_ptid = pid_to_ptid (retval);
+      inferior_ptid = ptid_build (current_event.dwProcessId, 0,
+                                 retval);
+      current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
     }
 
 out:
   return retval;
 }
 
-/* Wait for interesting events to occur in the target process. */
+/* Wait for interesting events to occur in the target process.  */
 static ptid_t
-child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
+win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 {
-  int pid = PIDGET (ptid);
+  int pid = -1;
+
+  target_terminal_ours ();
 
   /* We loop when we get a non-standard exception rather than return
      with a SPURIOUS because resume can try and step or modify things,
@@ -1381,56 +1486,92 @@ child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
 
   while (1)
     {
-      int retval = get_child_debug_event (pid, ourstatus);
+      int retval;
+      
+      /* Ignore CTRL+C signals while waiting for a debug event.
+         FIXME: brobecker/2008-05-20: When the user presses CTRL+C while
+         the inferior is running, both the inferior and GDB receive the
+         associated signal.  If the inferior receives the signal first
+         and the delay until GDB receives that signal is sufficiently long,
+         GDB can sometimes receive the SIGINT after we have unblocked
+         the CTRL+C handler.  This would lead to the debugger to stop
+         prematurely while handling the new-thread event that comes
+         with the handling of the SIGINT inside the inferior, and then
+         stop again immediately when the user tries to resume the execution
+         in the inferior.  This is a classic race, and it would be nice
+         to find a better solution to that problem.  But in the meantime,
+         the current approach already greatly mitigate this issue.  */
+      SetConsoleCtrlHandler (NULL, TRUE);
+      retval = get_win32_debug_event (pid, ourstatus);
+      SetConsoleCtrlHandler (NULL, FALSE);
+
       if (retval)
-       return pid_to_ptid (retval);
+       return ptid_build (current_event.dwProcessId, 0, retval);
       else
        {
          int detach = 0;
 
-         if (ui_loop_hook != NULL)
-           detach = ui_loop_hook (0);
+         if (deprecated_ui_loop_hook != NULL)
+           detach = deprecated_ui_loop_hook (0);
 
          if (detach)
-           child_kill_inferior ();
+           win32_kill_inferior ();
        }
     }
 }
 
 static void
-do_initial_child_stuff (DWORD pid)
+do_initial_win32_stuff (DWORD pid, int attaching)
 {
   extern int stop_after_trap;
   int i;
+  struct inferior *inf;
+  struct thread_info *tp;
 
   last_sig = TARGET_SIGNAL_0;
   event_count = 0;
   exception_count = 0;
+  open_process_used = 0;
   debug_registers_changed = 0;
   debug_registers_used = 0;
   for (i = 0; i < sizeof (dr) / sizeof (dr[0]); i++)
     dr[i] = 0;
+#ifdef __CYGWIN__
+  cygwin_load_start = cygwin_load_end = 0;
+#endif
   current_event.dwProcessId = pid;
   memset (&current_event, 0, sizeof (current_event));
-  push_target (&child_ops);
-  child_init_thread_list ();
-  disable_breakpoints_in_shlibs (1);
-  child_clear_solibs ();
+  push_target (&win32_ops);
+  disable_breakpoints_in_shlibs ();
+  win32_clear_solib ();
   clear_proceed_status ();
   init_wait_for_inferior ();
 
-  target_terminal_init ();
+  inf = add_inferior (pid);
+  inf->attach_flag = attaching;
+
+  /* Make the new process the current inferior, so terminal handling
+     can rely on it.  When attaching, we don't know about any thread
+     id here, but that's OK --- nothing should be referencing the
+     current thread until we report an event out of win32_wait.  */
+  inferior_ptid = pid_to_ptid (pid);
+
+  terminal_init_inferior_with_pgrp (pid);
   target_terminal_inferior ();
 
+  inf->stop_soon = STOP_QUIETLY;
   while (1)
     {
       stop_after_trap = 1;
-      wait_for_inferior ();
-      if (stop_signal != TARGET_SIGNAL_TRAP)
-       resume (0, stop_signal);
+      wait_for_inferior (0);
+      tp = inferior_thread ();
+      if (tp->stop_signal != TARGET_SIGNAL_TRAP)
+       resume (0, tp->stop_signal);
       else
        break;
     }
+
+  inf->stop_soon = NO_STOP_QUIETLY;
   stop_after_trap = 0;
   return;
 }
@@ -1525,7 +1666,7 @@ set_process_privilege (const char *privilege, BOOL enable)
 #if 0
   /* Disabled, otherwise every `attach' in an unprivileged user session
      would raise the "Failed to get SE_DEBUG_NAME privilege" warning in
-     child_attach(). */
+     win32_attach(). */
   /* AdjustTokenPrivileges returns TRUE even if the privilege could not
      be enabled. GetLastError () returns an correct error code, though. */
   if (enable && GetLastError () == ERROR_NOT_ALL_ASSIGNED)
@@ -1543,13 +1684,13 @@ out:
 
 /* Attach to process PID, then initialize for debugging it.  */
 static void
-child_attach (char *args, int from_tty)
+win32_attach (char *args, int from_tty)
 {
   BOOL ok;
   DWORD pid;
 
   if (!args)
-    error_no_arg ("process-id to attach");
+    error_no_arg (_("process-id to attach"));
 
   if (set_process_privilege (SE_DEBUG_NAME, TRUE) < 0)
     {
@@ -1559,9 +1700,11 @@ child_attach (char *args, int from_tty)
 
   pid = strtoul (args, 0, 0);          /* Windows pid */
 
+  win32_init_thread_list ();
   ok = DebugActiveProcess (pid);
   saw_create = 0;
 
+#ifdef __CYGWIN__
   if (!ok)
     {
       /* Try fall back to Cygwin pid */
@@ -1569,16 +1712,14 @@ child_attach (char *args, int from_tty)
 
       if (pid > 0)
        ok = DebugActiveProcess (pid);
+  }
+#endif
 
-      if (!ok)
-    error ("Can't attach to process.");
-    }
+  if (!ok)
+    error (_("Can't attach to process."));
 
   if (has_detach_ability ())
-    {
-      attach_flag = 1;
-      DebugSetProcessKillOnExit (FALSE);
-    }
+    DebugSetProcessKillOnExit (FALSE);
 
   if (from_tty)
     {
@@ -1594,22 +1735,23 @@ child_attach (char *args, int from_tty)
       gdb_flush (gdb_stdout);
     }
 
-  do_initial_child_stuff (pid);
+  do_initial_win32_stuff (pid, 1);
   target_terminal_ours ();
 }
 
 static void
-child_detach (char *args, int from_tty)
+win32_detach (char *args, int from_tty)
 {
   int detached = 1;
 
   if (has_detach_ability ())
     {
-      delete_command (NULL, 0);
-      child_continue (DBG_CONTINUE, -1);
+      ptid_t ptid = {-1};
+      win32_resume (ptid, 0, TARGET_SIGNAL_0);
+
       if (!DebugActiveProcessStop (current_event.dwProcessId))
        {
-         error ("Can't detach process %lu (error %lu)",
+         error (_("Can't detach process %lu (error %lu)"),
                 current_event.dwProcessId, GetLastError ());
          detached = 0;
        }
@@ -1624,24 +1766,55 @@ child_detach (char *args, int from_tty)
                         current_event.dwProcessId);
       gdb_flush (gdb_stdout);
     }
+
   inferior_ptid = null_ptid;
-  unpush_target (&child_ops);
+  detach_inferior (current_event.dwProcessId);
+
+  unpush_target (&win32_ops);
+}
+
+static char *
+win32_pid_to_exec_file (int pid)
+{
+  static char path[MAX_PATH + 1];
+
+#ifdef __CYGWIN__
+  /* Try to find exe name as symlink target of /proc/<pid>/exe */
+  int nchars;
+  char procexe[sizeof ("/proc/4294967295/exe")];
+  sprintf (procexe, "/proc/%u/exe", pid);
+  nchars = readlink (procexe, path, sizeof(path));
+  if (nchars > 0 && nchars < sizeof (path))
+    {
+      path[nchars] = '\0';     /* Got it */
+      return path;
+    }
+#endif
+
+  /* If we get here then either Cygwin is hosed, this isn't a Cygwin version
+     of gdb, or we're trying to debug a non-Cygwin windows executable. */
+  if (!get_module_name (0, path))
+    path[0] = '\0';
+
+  return path;
 }
 
 /* Print status information about what we're accessing.  */
 
 static void
-child_files_info (struct target_ops *ignore)
+win32_files_info (struct target_ops *ignore)
 {
+  struct inferior *inf = current_inferior ();
+
   printf_unfiltered ("\tUsing the running image of %s %s.\n",
-      attach_flag ? "attached" : "child", target_pid_to_str (inferior_ptid));
+                    inf->attach_flag ? "attached" : "child",
+                    target_pid_to_str (inferior_ptid));
 }
 
-/* ARGSUSED */
 static void
-child_open (char *arg, int from_tty)
+win32_open (char *arg, int from_tty)
 {
-  error ("Use the \"run\" command to start a Unix child process.");
+  error (_("Use the \"run\" command to start a Unix child process."));
 }
 
 /* Start an inferior win32 child process and sets inferior_ptid to its pid.
@@ -1650,12 +1823,9 @@ child_open (char *arg, int from_tty)
    ENV is the environment vector to pass.  Errors reported with error().  */
 
 static void
-child_create_inferior (char *exec_file, char *allargs, char **env)
+win32_create_inferior (char *exec_file, char *allargs, char **in_env,
+                      int from_tty)
 {
-  char *winenv;
-  char *temp;
-  int envlen;
-  int i;
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
   BOOL ret;
@@ -1667,13 +1837,15 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
   const char *sh;
   int tty;
   int ostdin, ostdout, ostderr;
+  const char *inferior_io_terminal = get_inferior_io_terminal ();
 
   if (!exec_file)
-    error ("No executable specified, use `target exec'.\n");
+    error (_("No executable specified, use `target exec'."));
 
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
 
+#ifdef __CYGWIN__
   if (!useshell)
     {
       flags = DEBUG_ONLY_THIS_PROCESS;
@@ -1694,6 +1866,10 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
       toexec = shell;
       flags = DEBUG_PROCESS;
     }
+#else
+  toexec = exec_file;
+  flags = DEBUG_ONLY_THIS_PROCESS;
+#endif
 
   if (new_group)
     flags |= CREATE_NEW_PROCESS_GROUP;
@@ -1706,78 +1882,9 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
   strcat (args, " ");
   strcat (args, allargs);
 
+#ifdef __CYGWIN__
   /* Prepare the environment vars for CreateProcess.  */
-  {
-    /* This code used to assume all env vars were file names and would
-       translate them all to win32 style.  That obviously doesn't work in the
-       general case.  The current rule is that we only translate PATH.
-       We need to handle PATH because we're about to call CreateProcess and
-       it uses PATH to find DLL's.  Fortunately PATH has a well-defined value
-       in both posix and win32 environments.  cygwin.dll will change it back
-       to posix style if necessary.  */
-
-    static const char *conv_path_names[] =
-    {
-      "PATH=",
-      0
-    };
-
-    /* CreateProcess takes the environment list as a null terminated set of
-       strings (i.e. two nulls terminate the list).  */
-
-    /* Get total size for env strings.  */
-    for (envlen = 0, i = 0; env[i] && *env[i]; i++)
-      {
-       int j, len;
-
-       for (j = 0; conv_path_names[j]; j++)
-         {
-           len = strlen (conv_path_names[j]);
-           if (strncmp (conv_path_names[j], env[i], len) == 0)
-             {
-               if (cygwin_posix_path_list_p (env[i] + len))
-                 envlen += len
-                   + cygwin_posix_to_win32_path_list_buf_size (env[i] + len);
-               else
-                 envlen += strlen (env[i]) + 1;
-               break;
-             }
-         }
-       if (conv_path_names[j] == NULL)
-         envlen += strlen (env[i]) + 1;
-      }
-
-    winenv = alloca (envlen + 1);
-
-    /* Copy env strings into new buffer.  */
-    for (temp = winenv, i = 0; env[i] && *env[i]; i++)
-      {
-       int j, len;
-
-       for (j = 0; conv_path_names[j]; j++)
-         {
-           len = strlen (conv_path_names[j]);
-           if (strncmp (conv_path_names[j], env[i], len) == 0)
-             {
-               if (cygwin_posix_path_list_p (env[i] + len))
-                 {
-                   memcpy (temp, env[i], len);
-                   cygwin_posix_to_win32_path_list (env[i] + len, temp + len);
-                 }
-               else
-                 strcpy (temp, env[i]);
-               break;
-             }
-         }
-       if (conv_path_names[j] == NULL)
-         strcpy (temp, env[i]);
-
-       temp += strlen (temp) + 1;
-      }
-
-    /* Final nil string to terminate new env.  */
-    *temp = 0;
-  }
+  cygwin_internal (CW_SYNC_WINENV);
 
   if (!inferior_io_terminal)
     tty = ostdin = ostdout = ostderr = -1;
@@ -1799,17 +1906,21 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
          dup2 (tty, 2);
        }
     }
+#endif
 
+  win32_init_thread_list ();
   ret = CreateProcess (0,
                       args,    /* command line */
                       NULL,    /* Security */
                       NULL,    /* thread */
                       TRUE,    /* inherit handles */
                       flags,   /* start flags */
-                      winenv,
+                      NULL,    /* environment */
                       NULL,    /* current directory */
                       &si,
                       &pi);
+
+#ifdef __CYGWIN__
   if (tty >= 0)
     {
       close (tty);
@@ -1820,9 +1931,11 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
       close (ostdout);
       close (ostderr);
     }
+#endif
 
   if (!ret)
-    error ("Error creating process %s, (error %d)\n", exec_file, (unsigned) GetLastError ());
+    error (_("Error creating process %s, (error %d)."),
+          exec_file, (unsigned) GetLastError ());
 
   CloseHandle (pi.hThread);
   CloseHandle (pi.hProcess);
@@ -1832,18 +1945,22 @@ child_create_inferior (char *exec_file, char *allargs, char **env)
   else
     saw_create = 0;
 
-  do_initial_child_stuff (pi.dwProcessId);
+  do_initial_win32_stuff (pi.dwProcessId, 0);
 
-  /* child_continue (DBG_CONTINUE, -1); */
-  proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
+  /* win32_continue (DBG_CONTINUE, -1); */
 }
 
 static void
-child_mourn_inferior (void)
+win32_mourn_inferior (void)
 {
-  (void) child_continue (DBG_CONTINUE, -1);
+  (void) win32_continue (DBG_CONTINUE, -1);
   i386_cleanup_dregs();
-  unpush_target (&child_ops);
+  if (open_process_used)
+    {
+      CHECK (CloseHandle (current_process_handle));
+      open_process_used = 0;
+    }
+  unpush_target (&win32_ops);
   generic_mourn_inferior ();
 }
 
@@ -1851,45 +1968,50 @@ child_mourn_inferior (void)
    ^C on the controlling terminal. */
 
 static void
-child_stop (void)
+win32_stop (ptid_t ptid)
 {
   DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
   CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
   registers_changed ();                /* refresh register state */
 }
 
-int
-child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
+static int
+win32_xfer_memory (CORE_ADDR memaddr, gdb_byte *our, int len,
                   int write, struct mem_attrib *mem,
                   struct target_ops *target)
 {
-  DWORD done;
+  DWORD done = 0;
   if (write)
     {
       DEBUG_MEM (("gdb: write target memory, %d bytes at 0x%08lx\n",
-                 len, (DWORD) memaddr));
-      WriteProcessMemory (current_process_handle, (LPVOID) memaddr, our,
-                         len, &done);
-      FlushInstructionCache (current_process_handle, (LPCVOID) memaddr, len);
+                 len, (DWORD) (uintptr_t) memaddr));
+      if (!WriteProcessMemory (current_process_handle, 
+                              (LPVOID) (uintptr_t) memaddr, our,
+                              len, &done))
+       done = 0;
+      FlushInstructionCache (current_process_handle, 
+                            (LPCVOID) (uintptr_t) memaddr, len);
     }
   else
     {
       DEBUG_MEM (("gdb: read target memory, %d bytes at 0x%08lx\n",
-                 len, (DWORD) memaddr));
-      ReadProcessMemory (current_process_handle, (LPCVOID) memaddr, our, len,
-                        &done);
+                 len, (DWORD) (uintptr_t) memaddr));
+      if (!ReadProcessMemory (current_process_handle, 
+                             (LPCVOID) (uintptr_t) memaddr, our,
+                             len, &done))
+       done = 0;
     }
   return done;
 }
 
-void
-child_kill_inferior (void)
+static void
+win32_kill_inferior (void)
 {
   CHECK (TerminateProcess (current_process_handle, 0));
 
   for (;;)
     {
-      if (!child_continue (DBG_CONTINUE, -1))
+      if (!win32_continue (DBG_CONTINUE, -1))
        break;
       if (!WaitForDebugEvent (&current_event, INFINITE))
        break;
@@ -1897,154 +2019,153 @@ child_kill_inferior (void)
        break;
     }
 
-  CHECK (CloseHandle (current_process_handle));
+  target_mourn_inferior ();    /* or just win32_mourn_inferior? */
+}
 
-  /* this may fail in an attached process so don't check. */
-  (void) CloseHandle (current_thread->h);
-  target_mourn_inferior ();    /* or just child_mourn_inferior? */
+static void
+win32_prepare_to_store (struct regcache *regcache)
+{
+  /* Do nothing, since we can store individual regs */
 }
 
-void
-child_resume (ptid_t ptid, int step, enum target_signal sig)
+static int
+win32_can_run (void)
 {
-  thread_info *th;
-  DWORD continue_status = DBG_CONTINUE;
+  return 1;
+}
 
-  int pid = PIDGET (ptid);
+static void
+win32_close (int x)
+{
+  DEBUG_EVENTS (("gdb: win32_close, inferior_ptid=%d\n",
+               PIDGET (inferior_ptid)));
+}
 
-  if (sig != TARGET_SIGNAL_0)
+/* Convert pid to printable format. */
+static char *
+win32_pid_to_str (ptid_t ptid)
+{
+  static char buf[80];
+
+  if (ptid_get_tid (ptid) != 0)
     {
-      if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
-       {
-         DEBUG_EXCEPT(("Cannot continue with signal %d here.\n",sig));
-       }
-      else if (sig == last_sig)
-       continue_status = DBG_EXCEPTION_NOT_HANDLED;
-      else
-#if 0
-/* This code does not seem to work, because
-  the kernel does probably not consider changes in the ExceptionRecord
-  structure when passing the exception to the inferior.
-  Note that this seems possible in the exception handler itself.  */
-       {
-         int i;
-         for (i = 0; xlate[i].them != -1; i++)
-           if (xlate[i].us == sig)
-             {
-               current_event.u.Exception.ExceptionRecord.ExceptionCode =
-                 xlate[i].them;
-               continue_status = DBG_EXCEPTION_NOT_HANDLED;
-               break;
-             }
-         if (continue_status == DBG_CONTINUE)
-           {
-             DEBUG_EXCEPT(("Cannot continue with signal %d.\n",sig));
-           }
-       }
-#endif
-       DEBUG_EXCEPT(("Can only continue with recieved signal %d.\n",
-         last_sig));
+      snprintf (buf, sizeof (buf), "Thread %d.0x%lx",
+               ptid_get_pid (ptid), ptid_get_tid (ptid));
+      return buf;
     }
 
-  last_sig = TARGET_SIGNAL_0;
+  return normal_pid_to_str (ptid);
+}
 
-  DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
-              pid, step, sig));
+static LONGEST
+win32_xfer_shared_libraries (struct target_ops *ops,
+                            enum target_object object, const char *annex,
+                            gdb_byte *readbuf, const gdb_byte *writebuf,
+                            ULONGEST offset, LONGEST len)
+{
+  struct obstack obstack;
+  const char *buf;
+  LONGEST len_avail;
+  struct so_list *so;
 
-  /* Get context for currently selected thread */
-  th = thread_rec (current_event.dwThreadId, FALSE);
-  if (th)
-    {
-      if (step)
-       {
-         /* Single step by setting t bit */
-         child_fetch_inferior_registers (PS_REGNUM);
-         th->context.EFlags |= FLAG_TRACE_BIT;
-       }
+  if (writebuf)
+    return -1;
 
-      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];
-       }
-         CHECK (SetThreadContext (th->h, &th->context));
-         th->context.ContextFlags = 0;
-       }
-    }
+  obstack_init (&obstack);
+  obstack_grow_str (&obstack, "<library-list>\n");
+  for (so = solib_start.next; so; so = so->next)
+    win32_xfer_shared_library (so->so_name, so->lm_info->load_addr, &obstack);
+  obstack_grow_str0 (&obstack, "</library-list>\n");
 
-  /* Allow continuing with the same signal that interrupted us.
-     Otherwise complain. */
+  buf = obstack_finish (&obstack);
+  len_avail = strlen (buf);
+  if (offset >= len_avail)
+    return 0;
 
-  child_continue (continue_status, pid);
-}
+  if (len > len_avail - offset)
+    len = len_avail - offset;
+  memcpy (readbuf, buf + offset, len);
 
-static void
-child_prepare_to_store (void)
-{
-  /* Do nothing, since we can store individual regs */
+  obstack_free (&obstack, NULL);
+  return len;
 }
 
-static int
-child_can_run (void)
+static LONGEST
+win32_xfer_partial (struct target_ops *ops, enum target_object object,
+                   const char *annex, gdb_byte *readbuf,
+                   const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
 {
-  return 1;
+  switch (object)
+    {
+    case TARGET_OBJECT_MEMORY:
+      if (readbuf)
+       return (*ops->deprecated_xfer_memory) (offset, readbuf,
+                                              len, 0/*read*/, NULL, ops);
+      if (writebuf)
+       return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
+                                              len, 1/*write*/, NULL, ops);
+      return -1;
+
+    case TARGET_OBJECT_LIBRARIES:
+      return win32_xfer_shared_libraries (ops, object, annex, readbuf,
+                                         writebuf, offset, len);
+
+    default:
+      if (ops->beneath != NULL)
+       return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+                                             readbuf, writebuf, offset, len);
+      return -1;
+    }
 }
 
 static void
-child_close (int x)
-{
-  DEBUG_EVENTS (("gdb: child_close, inferior_ptid=%d\n",
-               PIDGET (inferior_ptid)));
+init_win32_ops (void)
+{
+  win32_ops.to_shortname = "child";
+  win32_ops.to_longname = "Win32 child process";
+  win32_ops.to_doc = "Win32 child process (started by the \"run\" command).";
+  win32_ops.to_open = win32_open;
+  win32_ops.to_close = win32_close;
+  win32_ops.to_attach = win32_attach;
+  win32_ops.to_attach_no_wait = 1;
+  win32_ops.to_detach = win32_detach;
+  win32_ops.to_resume = win32_resume;
+  win32_ops.to_wait = win32_wait;
+  win32_ops.to_fetch_registers = win32_fetch_inferior_registers;
+  win32_ops.to_store_registers = win32_store_inferior_registers;
+  win32_ops.to_prepare_to_store = win32_prepare_to_store;
+  win32_ops.deprecated_xfer_memory = win32_xfer_memory;
+  win32_ops.to_xfer_partial = win32_xfer_partial;
+  win32_ops.to_files_info = win32_files_info;
+  win32_ops.to_insert_breakpoint = memory_insert_breakpoint;
+  win32_ops.to_remove_breakpoint = memory_remove_breakpoint;
+  win32_ops.to_terminal_init = terminal_init_inferior;
+  win32_ops.to_terminal_inferior = terminal_inferior;
+  win32_ops.to_terminal_ours_for_output = terminal_ours_for_output;
+  win32_ops.to_terminal_ours = terminal_ours;
+  win32_ops.to_terminal_save_ours = terminal_save_ours;
+  win32_ops.to_terminal_info = child_terminal_info;
+  win32_ops.to_kill = win32_kill_inferior;
+  win32_ops.to_create_inferior = win32_create_inferior;
+  win32_ops.to_mourn_inferior = win32_mourn_inferior;
+  win32_ops.to_can_run = win32_can_run;
+  win32_ops.to_thread_alive = win32_win32_thread_alive;
+  win32_ops.to_pid_to_str = win32_pid_to_str;
+  win32_ops.to_stop = win32_stop;
+  win32_ops.to_stratum = process_stratum;
+  win32_ops.to_has_all_memory = 1;
+  win32_ops.to_has_memory = 1;
+  win32_ops.to_has_stack = 1;
+  win32_ops.to_has_registers = 1;
+  win32_ops.to_has_execution = 1;
+  win32_ops.to_pid_to_exec_file = win32_pid_to_exec_file;
+  win32_ops.to_magic = OPS_MAGIC;
 }
 
-struct target_ops child_ops;
-
 static void
-init_child_ops (void)
+set_win32_aliases (char *argv0)
 {
-  child_ops.to_shortname = "child";
-  child_ops.to_longname = "Win32 child process";
-  child_ops.to_doc = "Win32 child process (started by the \"run\" command).";
-  child_ops.to_open = child_open;
-  child_ops.to_close = child_close;
-  child_ops.to_attach = child_attach;
-  child_ops.to_detach = child_detach;
-  child_ops.to_resume = child_resume;
-  child_ops.to_wait = child_wait;
-  child_ops.to_fetch_registers = child_fetch_inferior_registers;
-  child_ops.to_store_registers = child_store_inferior_registers;
-  child_ops.to_prepare_to_store = child_prepare_to_store;
-  child_ops.to_xfer_memory = child_xfer_memory;
-  child_ops.to_files_info = child_files_info;
-  child_ops.to_insert_breakpoint = memory_insert_breakpoint;
-  child_ops.to_remove_breakpoint = memory_remove_breakpoint;
-  child_ops.to_terminal_init = terminal_init_inferior;
-  child_ops.to_terminal_inferior = terminal_inferior;
-  child_ops.to_terminal_ours_for_output = terminal_ours_for_output;
-  child_ops.to_terminal_ours = terminal_ours;
-  child_ops.to_terminal_save_ours = terminal_save_ours;
-  child_ops.to_terminal_info = child_terminal_info;
-  child_ops.to_kill = child_kill_inferior;
-  child_ops.to_create_inferior = child_create_inferior;
-  child_ops.to_mourn_inferior = child_mourn_inferior;
-  child_ops.to_can_run = child_can_run;
-  child_ops.to_thread_alive = win32_child_thread_alive;
-  child_ops.to_pid_to_str = cygwin_pid_to_str;
-  child_ops.to_stop = child_stop;
-  child_ops.to_stratum = process_stratum;
-  child_ops.to_has_all_memory = 1;
-  child_ops.to_has_memory = 1;
-  child_ops.to_has_stack = 1;
-  child_ops.to_has_registers = 1;
-  child_ops.to_has_execution = 1;
-  child_ops.to_magic = OPS_MAGIC;
+  add_info_alias ("dll", "sharedlibrary", 1);
 }
 
 void
@@ -2052,81 +2173,95 @@ _initialize_win32_nat (void)
 {
   struct cmd_list_element *c;
 
-  init_child_ops ();
+  init_win32_ops ();
 
   c = add_com ("dll-symbols", class_files, dll_symbol_command,
-              "Load dll library symbols from FILE.");
+              _("Load dll library symbols from FILE."));
   set_cmd_completer (c, filename_completer);
 
   add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
 
-  add_show_from_set (add_set_cmd ("shell", class_support, var_boolean,
-                                 (char *) &useshell,
-                "Set use of shell to start subprocess.",
-                                 &setlist),
-                    &showlist);
-
-  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_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
-                                 (char *) &debug_exec,
-                      "Set whether to display execution in child process.",
-                                 &setlist),
-                    &showlist);
-
-  add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
-                                 (char *) &debug_events,
-                  "Set whether to display kernel events in child process.",
-                                 &setlist),
-                    &showlist);
-
-  add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
-                                 (char *) &debug_memory,
-                "Set whether to display memory accesses in child process.",
-                                 &setlist),
-                    &showlist);
-
-  add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
-                                 (char *) &debug_exceptions,
-              "Set whether to display kernel exceptions in child process.",
-                                 &setlist),
-                    &showlist);
-
-  add_info ("dll", info_dll_command, "Status of loaded DLLs.");
-  add_info_alias ("sharedlibrary", "dll", 1);
+#ifdef __CYGWIN__
+  add_setshow_boolean_cmd ("shell", class_support, &useshell, _("\
+Set use of shell to start subprocess."), _("\
+Show use of shell to start subprocess."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("cygwin-exceptions", class_support, &cygwin_exceptions, _("\
+Break when an exception is detected in the Cygwin DLL itself."), _("\
+Show whether gdb breaks on exceptions in the Cygwin DLL itself."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+#endif
+
+  add_setshow_boolean_cmd ("new-console", class_support, &new_console, _("\
+Set creation of new console when creating child process."), _("\
+Show creation of new console when creating child process."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("new-group", class_support, &new_group, _("\
+Set creation of new group when creating child process."), _("\
+Show creation of new group when creating child process."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("debugexec", class_support, &debug_exec, _("\
+Set whether to display execution in child process."), _("\
+Show whether to display execution in child process."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("debugevents", class_support, &debug_events, _("\
+Set whether to display kernel events in child process."), _("\
+Show whether to display kernel events in child process."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("debugmemory", class_support, &debug_memory, _("\
+Set whether to display memory accesses in child process."), _("\
+Show whether to display memory accesses in child process."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("debugexceptions", class_support,
+                          &debug_exceptions, _("\
+Set whether to display kernel exceptions in child process."), _("\
+Show whether to display kernel exceptions in child process."), NULL,
+                          NULL,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
 
   add_prefix_cmd ("w32", class_info, info_w32_command,
-                 "Print information specific to Win32 debugging.",
+                 _("Print information specific to Win32 debugging."),
                  &info_w32_cmdlist, "info w32 ", 0, &infolist);
 
   add_cmd ("selector", class_info, display_selectors,
-          "Display selectors infos.",
+          _("Display selectors infos."),
           &info_w32_cmdlist);
-
-  add_target (&child_ops);
+  add_target (&win32_ops);
+  deprecated_init_ui_hook = set_win32_aliases;
 }
 
 /* Hardware watchpoint support, adapted from go32-nat.c code.  */
 
 /* Pass the address ADDR to the inferior in the I'th debug register.
    Here we just store the address in dr array, the registers will be
-   actually set up when child_continue is called.  */
+   actually set up when win32_continue is called.  */
 void
 cygwin_set_dr (int i, CORE_ADDR addr)
 {
   if (i < 0 || i > 3)
     internal_error (__FILE__, __LINE__,
-                   "Invalid register %d in cygwin_set_dr.\n", i);
+                   _("Invalid register %d in cygwin_set_dr.\n"), i);
   dr[i] = (unsigned) addr;
   debug_registers_changed = 1;
   debug_registers_used = 1;
@@ -2134,7 +2269,7 @@ cygwin_set_dr (int i, CORE_ADDR addr)
 
 /* Pass the value VAL to the inferior in the DR7 debug control
    register.  Here we just store the address in D_REGS, the watchpoint
-   will be actually set up in child_wait.  */
+   will be actually set up in win32_wait.  */
 void
 cygwin_set_dr7 (unsigned val)
 {
@@ -2152,249 +2287,19 @@ cygwin_get_dr6 (void)
   return dr[6];
 }
 
-
-/* Determine if the thread referenced by "pid" is alive
+/* Determine if the thread referenced by "ptid" is alive
    by "polling" it.  If WaitForSingleObject returns WAIT_OBJECT_0
-   it means that the pid has died.  Otherwise it is assumed to be alive. */
-static int
-win32_child_thread_alive (ptid_t ptid)
-{
-  int pid = PIDGET (ptid);
-
-  return WaitForSingleObject (thread_rec (pid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
-    FALSE : TRUE;
-}
-
-/* Convert pid to printable format. */
-char *
-cygwin_pid_to_str (ptid_t ptid)
-{
-  static char buf[80];
-  int pid = PIDGET (ptid);
-
-  if ((DWORD) pid == current_event.dwProcessId)
-    sprintf (buf, "process %d", pid);
-  else
-    sprintf (buf, "thread %ld.0x%x", current_event.dwProcessId, pid);
-  return buf;
-}
-
-static int
-core_dll_symbols_add (char *dll_name, DWORD base_addr)
-{
-  struct objfile *objfile;
-  char *objfile_basename;
-  const char *dll_basename;
-
-  if (!(dll_basename = strrchr (dll_name, '/')))
-    dll_basename = dll_name;
-  else
-    dll_basename++;
-
-  ALL_OBJFILES (objfile)
-  {
-    objfile_basename = strrchr (objfile->name, '/');
-
-    if (objfile_basename &&
-       strcmp (dll_basename, objfile_basename + 1) == 0)
-      {
-       printf_unfiltered ("%08lx:%s (symbols previously loaded)\n",
-                          base_addr, dll_name);
-       goto out;
-      }
-  }
-
-  register_loaded_dll (dll_name, base_addr + 0x1000);
-  solib_symbols_add (dll_name, 0, (CORE_ADDR) base_addr + 0x1000);
-
-out:
-  return 1;
-}
-
-typedef struct
-{
-  struct target_ops *target;
-  bfd_vma addr;
-}
-map_code_section_args;
-
-static void
-map_single_dll_code_section (bfd * abfd, asection * sect, void *obj)
-{
-  int old;
-  int update_coreops;
-  struct section_table *new_target_sect_ptr;
-
-  map_code_section_args *args = (map_code_section_args *) obj;
-  struct target_ops *target = args->target;
-  if (sect->flags & SEC_CODE)
-    {
-      update_coreops = core_ops.to_sections == target->to_sections;
-
-      if (target->to_sections)
-       {
-         old = target->to_sections_end - target->to_sections;
-         target->to_sections = (struct section_table *)
-           xrealloc ((char *) target->to_sections,
-                     (sizeof (struct section_table)) * (1 + old));
-       }
-      else
-       {
-         old = 0;
-         target->to_sections = (struct section_table *)
-           xmalloc ((sizeof (struct section_table)));
-       }
-      target->to_sections_end = target->to_sections + (1 + old);
-
-      /* Update the to_sections field in the core_ops structure
-        if needed.  */
-      if (update_coreops)
-       {
-         core_ops.to_sections = target->to_sections;
-         core_ops.to_sections_end = target->to_sections_end;
-       }
-      new_target_sect_ptr = target->to_sections + old;
-      new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
-      new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
-       bfd_section_size (abfd, sect);;
-      new_target_sect_ptr->the_bfd_section = sect;
-      new_target_sect_ptr->bfd = abfd;
-    }
-}
-
+   it means that the thread has died.  Otherwise it is assumed to be alive. */
 static int
-dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
-{
-  bfd *dll_bfd;
-  map_code_section_args map_args;
-  asection *lowest_sect;
-  char *name;
-  if (dll_name == NULL || target == NULL)
-    return 0;
-  name = xstrdup (dll_name);
-  dll_bfd = bfd_openr (name, "pei-i386");
-  if (dll_bfd == NULL)
-    return 0;
-
-  if (bfd_check_format (dll_bfd, bfd_object))
-    {
-      lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
-      if (lowest_sect == NULL)
-       return 0;
-      map_args.target = target;
-      map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
-
-      bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
-    }
-
-  return 1;
-}
-
-static void
-core_section_load_dll_symbols (bfd * abfd, asection * sect, void *obj)
-{
-  struct target_ops *target = (struct target_ops *) obj;
-
-  DWORD base_addr;
-
-  int dll_name_size;
-  char *dll_name = NULL;
-  char *buf = NULL;
-  struct win32_pstatus *pstatus;
-  char *p;
-
-  if (strncmp (sect->name, ".module", 7))
-    return;
-
-  buf = (char *) xmalloc (sect->_raw_size + 1);
-  if (!buf)
-    {
-      printf_unfiltered ("memory allocation failed for %s\n", sect->name);
-      goto out;
-    }
-  if (!bfd_get_section_contents (abfd, sect, buf, 0, sect->_raw_size))
-    goto out;
-
-  pstatus = (struct win32_pstatus *) buf;
-
-  memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
-  dll_name_size = pstatus->data.module_info.module_name_size;
-  if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > sect->_raw_size)
-      goto out;
-
-  dll_name = (char *) xmalloc (dll_name_size + 1);
-  if (!dll_name)
-    {
-      printf_unfiltered ("memory allocation failed for %s\n", sect->name);
-      goto out;
-    }
-  strncpy (dll_name, pstatus->data.module_info.module_name, dll_name_size);
-
-  while ((p = strchr (dll_name, '\\')))
-    *p = '/';
-
-  if (!core_dll_symbols_add (dll_name, (DWORD) base_addr))
-    printf_unfiltered ("%s: Failed to load dll symbols.\n", dll_name);
-
-  if (!dll_code_sections_add (dll_name, (DWORD) base_addr + 0x1000, target))
-    printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
-
-out:
-  if (buf)
-    xfree (buf);
-  if (dll_name)
-    xfree (dll_name);
-  return;
-}
-
-void
-child_solib_add (char *filename, int from_tty, struct target_ops *target,
-                int readsyms)
+win32_win32_thread_alive (ptid_t ptid)
 {
-  if (!readsyms)
-    return;
-  if (core_bfd)
-    {
-      child_clear_solibs ();
-      bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols, target);
-    }
-  else
-    {
-      if (solib_end && solib_end->name)
-            solib_end->objfile = solib_symbols_add (solib_end->name, from_tty,
-                                               solib_end->load_addr);
-    }
-}
+  int tid;
 
-static void
-fetch_elf_core_registers (char *core_reg_sect,
-                         unsigned core_reg_size,
-                         int which,
-                         CORE_ADDR reg_addr)
-{
-  int r;
-  if (core_reg_size < sizeof (CONTEXT))
-    {
-      error ("Core file register section too small (%u bytes).", core_reg_size);
-      return;
-    }
-  for (r = 0; r < NUM_REGS; r++)
-    supply_register (r, core_reg_sect + mappings[r]);
-}
+  gdb_assert (ptid_get_tid (ptid) != 0);
+  tid = ptid_get_tid (ptid);
 
-static struct core_fns win32_elf_core_fns =
-{
-  bfd_target_elf_flavour,
-  default_check_format,
-  default_core_sniffer,
-  fetch_elf_core_registers,
-  NULL
-};
-
-void
-_initialize_core_win32 (void)
-{
-  add_core_fns (&win32_elf_core_fns);
+  return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0 ?
+    FALSE : TRUE;
 }
 
 void
@@ -2421,7 +2326,38 @@ _initialize_check_for_gdb_ini (void)
          char *newini = alloca (len + 1);
          sprintf (newini, "%.*s.gdbinit",
            (int) (len - (sizeof ("gdb.ini") - 1)), oldini);
-         warning ("obsolete '%s' found. Rename to '%s'.", oldini, newini);
+         warning (_("obsolete '%s' found. Rename to '%s'."), oldini, newini);
        }
     }
 }
+
+void
+_initialize_psapi (void)
+{
+  /* Load optional functions used for retrieving filename information
+     associated with the currently debugged process or its dlls. */
+  if (!psapi_loaded)
+    {
+      HMODULE psapi_module_handle;
+
+      psapi_loaded = -1;
+
+      psapi_module_handle = LoadLibrary ("psapi.dll");
+      if (psapi_module_handle)
+       {
+         psapi_EnumProcessModules = (void *) GetProcAddress (psapi_module_handle, "EnumProcessModules");
+         psapi_GetModuleInformation = (void *) GetProcAddress (psapi_module_handle, "GetModuleInformation");
+         psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle, "GetModuleFileNameExA");
+
+         if (psapi_EnumProcessModules != NULL
+             && psapi_GetModuleInformation != NULL
+             && psapi_GetModuleFileNameExA != NULL)
+           psapi_loaded = 1;
+       }
+    }
+
+  /* This will probably fail on Windows 9x/Me.  Let the user know that we're
+     missing some functionality. */
+  if (psapi_loaded < 0)
+    warning(_("cannot automatically find executable file or library to read symbols.  Use \"file\" or \"dll\" command to load executable/libraries directly."));
+}
This page took 0.051648 seconds and 4 git commands to generate.