Use counted_command_line everywhere
[deliverable/binutils-gdb.git] / gdb / windows-nat.c
index c6a809b0b2f54ace8d39dd5859c721ace0aaf772..16ebd176072a6888aa7bfb0a7f15b500e9421b31 100644 (file)
@@ -1,6 +1,6 @@
 /* Target-vector operations for controlling windows child processes, for GDB.
 
-   Copyright (C) 1995-2016 Free Software Foundation, Inc.
+   Copyright (C) 1995-2018 Free Software Foundation, Inc.
 
    Contributed by Cygnus Solutions, A Red Hat Company.
 
@@ -42,6 +42,7 @@
 #include <sys/cygwin.h>
 #include <cygwin/version.h>
 #endif
+#include <algorithm>
 
 #include "buildsym.h"
 #include "filenames.h"
@@ -66,6 +67,7 @@
 #include "x86-nat.h"
 #include "complaints.h"
 #include "inf-child.h"
+#include "gdb_tilde_expand.h"
 
 #define AdjustTokenPrivileges          dyn_AdjustTokenPrivileges
 #define DebugActiveProcessStop         dyn_DebugActiveProcessStop
@@ -199,10 +201,6 @@ typedef enum
 #define DEBUG_MEM(x)   if (debug_memory)       printf_unfiltered x
 #define DEBUG_EXCEPT(x)        if (debug_exceptions)   printf_unfiltered x
 
-static void windows_interrupt (struct target_ops *self, ptid_t);
-static int windows_thread_alive (struct target_ops *, ptid_t);
-static void windows_kill_inferior (struct target_ops *);
-
 static void cygwin_set_dr (int i, CORE_ADDR addr);
 static void cygwin_set_dr7 (unsigned long val);
 static CORE_ADDR cygwin_get_dr (int i);
@@ -300,6 +298,58 @@ static const struct xlate_exception
   {STATUS_FLOAT_DIVIDE_BY_ZERO, GDB_SIGNAL_FPE},
   {-1, GDB_SIGNAL_UNKNOWN}};
 
+
+struct windows_nat_target final : public x86_nat_target<inf_child_target>
+{
+  void close () override;
+
+  void attach (const char *, int) override;
+
+  bool attach_no_wait () override
+  { return true; }
+
+  void detach (inferior *, int) override;
+
+  void resume (ptid_t, int , enum gdb_signal) override;
+
+  ptid_t wait (ptid_t, struct target_waitstatus *, int) override;
+
+  void fetch_registers (struct regcache *, int) override;
+  void store_registers (struct regcache *, int) override;
+
+  enum target_xfer_status xfer_partial (enum target_object object,
+                                       const char *annex,
+                                       gdb_byte *readbuf,
+                                       const gdb_byte *writebuf,
+                                       ULONGEST offset, ULONGEST len,
+                                       ULONGEST *xfered_len) override;
+
+  void files_info () override;
+
+  void kill () override;
+
+  void create_inferior (const char *, const std::string &,
+                       char **, int) override;
+
+  void mourn_inferior () override;
+
+  bool thread_alive (ptid_t ptid) override;
+
+  const char *pid_to_str (ptid_t) override;
+
+  void interrupt () override;
+
+  char *pid_to_exec_file (int pid) override;
+
+  ptid_t get_ada_task_ptid (long lwp, long thread) override;
+
+  bool get_tib_address (ptid_t ptid, CORE_ADDR *addr) override;
+
+  const char *thread_name (struct thread_info *) override;
+};
+
+static windows_nat_target the_windows_nat_target;
+
 /* Set the MAPPINGS static global to OFFSETS.
    See the description of MAPPINGS for more details.  */
 
@@ -409,7 +459,7 @@ windows_add_thread (ptid_t ptid, HANDLE h, void *tlb)
   return th;
 }
 
-/* Clear out any old thread list and reintialize it to a
+/* Clear out any old thread list and reinitialize it to a
    pristine state.  */
 static void
 windows_init_thread_list (void)
@@ -460,18 +510,15 @@ windows_delete_thread (ptid_t ptid, DWORD exit_code)
 }
 
 static void
-do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
+do_windows_fetch_inferior_registers (struct regcache *regcache,
+                                    windows_thread_info *th, int r)
 {
-  char *context_offset = ((char *) &current_thread->context) + mappings[r];
-  struct gdbarch *gdbarch = get_regcache_arch (regcache);
+  char *context_offset = ((char *) &th->context) + mappings[r];
+  struct gdbarch *gdbarch = regcache->arch ();
   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
   long l;
 
-  if (!current_thread)
-    return;    /* Windows sometimes uses a non-existent thread id in its
-                  events.  */
-
-  if (current_thread->reload_context)
+  if (th->reload_context)
     {
 #ifdef __CYGWIN__
       if (have_saved_context)
@@ -480,14 +527,13 @@ do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
             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,
+         memcpy (&th->context, &saved_context,
                  __COPY_CONTEXT_SIZE);
          have_saved_context = 0;
        }
       else
 #endif
        {
-         windows_thread_info *th = current_thread;
          th->context.ContextFlags = CONTEXT_DEBUGGER_DR;
          CHECK (GetThreadContext (th->h, &th->context));
          /* Copy dr values from that thread.
@@ -503,7 +549,7 @@ do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
              dr[7] = th->context.Dr7;
            }
        }
-      current_thread->reload_context = 0;
+      th->reload_context = 0;
     }
 
   if (r == I387_FISEG_REGNUM (tdep))
@@ -529,46 +575,49 @@ do_windows_fetch_inferior_registers (struct regcache *regcache, int r)
   else
     {
       for (r = 0; r < gdbarch_num_regs (gdbarch); r++)
-       do_windows_fetch_inferior_registers (regcache, r);
+       do_windows_fetch_inferior_registers (regcache, th, r);
     }
 }
 
-static void
-windows_fetch_inferior_registers (struct target_ops *ops,
-                                 struct regcache *regcache, int r)
+void
+windows_nat_target::fetch_registers (struct regcache *regcache, int r)
 {
-  current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
-  /* Check if current_thread exists.  Windows sometimes uses a non-existent
+  DWORD pid = ptid_get_tid (regcache_get_ptid (regcache));
+  windows_thread_info *th = thread_rec (pid, TRUE);
+
+  /* Check if TH exists.  Windows sometimes uses a non-existent
      thread id in its events.  */
-  if (current_thread)
-    do_windows_fetch_inferior_registers (regcache, r);
+  if (th != NULL)
+    do_windows_fetch_inferior_registers (regcache, th, r);
 }
 
 static void
-do_windows_store_inferior_registers (const struct regcache *regcache, int r)
+do_windows_store_inferior_registers (const struct regcache *regcache,
+                                    windows_thread_info *th, int r)
 {
-  if (!current_thread)
-    /* Windows sometimes uses a non-existent thread id in its events.  */;
-  else if (r >= 0)
+  if (r >= 0)
     regcache_raw_collect (regcache, r,
-                         ((char *) &current_thread->context) + mappings[r]);
+                         ((char *) &th->context) + mappings[r]);
   else
     {
-      for (r = 0; r < gdbarch_num_regs (get_regcache_arch (regcache)); r++)
-       do_windows_store_inferior_registers (regcache, r);
+      for (r = 0; r < gdbarch_num_regs (regcache->arch ()); r++)
+       do_windows_store_inferior_registers (regcache, th, r);
     }
 }
 
-/* Store a new register value into the current thread context.  */
-static void
-windows_store_inferior_registers (struct target_ops *ops,
-                                 struct regcache *regcache, int r)
+/* Store a new register value into the context of the thread tied to
+   REGCACHE.  */
+
+void
+windows_nat_target::store_registers (struct regcache *regcache, int r)
 {
-  current_thread = thread_rec (ptid_get_tid (inferior_ptid), TRUE);
-  /* Check if current_thread exists.  Windows sometimes uses a non-existent
+  DWORD pid = ptid_get_tid (regcache_get_ptid (regcache));
+  windows_thread_info *th = thread_rec (pid, TRUE);
+
+  /* Check if TH exists.  Windows sometimes uses a non-existent
      thread id in its events.  */
-  if (current_thread)
-    do_windows_store_inferior_registers (regcache, r);
+  if (th != NULL)
+    do_windows_store_inferior_registers (regcache, th, r);
 }
 
 /* Encapsulate the information required in a call to
@@ -577,7 +626,7 @@ struct safe_symbol_file_add_args
 {
   char *name;
   int from_tty;
-  struct section_addr_info *addrs;
+  section_addr_info *addrs;
   int mainline;
   int flags;
   struct ui_file *err, *out;
@@ -585,9 +634,9 @@ struct safe_symbol_file_add_args
 };
 
 /* Maintain a linked list of "so" information.  */
-struct lm_info
+struct lm_info_windows : public lm_info_base
 {
-  LPVOID load_addr;
+  LPVOID load_addr = 0;
 };
 
 static struct so_list solib_start, *solib_end;
@@ -645,8 +694,9 @@ windows_make_so (const char *name, LPVOID load_addr)
     }
 #endif
   so = XCNEW (struct so_list);
-  so->lm_info = XNEW (struct lm_info);
-  so->lm_info->load_addr = load_addr;
+  lm_info_windows *li = new lm_info_windows;
+  so->lm_info = li;
+  li->load_addr = load_addr;
   strcpy (so->so_original_name, name);
 #ifndef __CYGWIN__
   strcpy (so->so_name, buf);
@@ -669,32 +719,27 @@ windows_make_so (const char *name, LPVOID load_addr)
   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 = gdb_bfd_open (so->so_name, "pei-i386", -1);
+      gdb_bfd_ref_ptr abfd (gdb_bfd_open (so->so_name, "pei-i386", -1));
 
-      if (!abfd)
+      if (abfd == NULL)
        return so;
 
-      if (bfd_check_format (abfd, bfd_object))
-       text = bfd_get_section_by_name (abfd, ".text");
+      if (bfd_check_format (abfd.get (), bfd_object))
+       text = bfd_get_section_by_name (abfd.get (), ".text");
 
       if (!text)
-       {
-         gdb_bfd_unref (abfd);
-         return so;
-       }
+       return so;
 
       /* The symbols in a dll are offset by 0x1000, which is the
         offset from 0 of the first byte in an image - because of the
         file header and the section alignment.  */
       cygwin_load_start = (CORE_ADDR) (uintptr_t) ((char *)
                                                   load_addr + 0x1000);
-      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
-
-      gdb_bfd_unref (abfd);
+      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd.get (),
+                                                             text);
     }
 #endif
 
@@ -758,8 +803,8 @@ get_image_name (HANDLE h, void *address, int unicode)
    do_initial_windows_stuff and windows_add_all_dlls for more info
    on how we handle DLL loading during that phase).  */
 
-static int
-handle_load_dll (void *dummy)
+static void
+handle_load_dll ()
 {
   LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
   char *dll_name;
@@ -772,22 +817,23 @@ handle_load_dll (void *dummy)
   dll_name = get_image_name (current_process_handle,
                             event->lpImageName, event->fUnicode);
   if (!dll_name)
-    return 1;
+    return;
 
   solib_end->next = windows_make_so (dll_name, event->lpBaseOfDll);
   solib_end = solib_end->next;
 
-  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
-                host_address_to_string (solib_end->lm_info->load_addr)));
+  lm_info_windows *li = (lm_info_windows *) solib_end->lm_info;
 
-  return 1;
+  DEBUG_EVENTS (("gdb: Loading dll \"%s\" at %s.\n", solib_end->so_name,
+                host_address_to_string (li->load_addr)));
 }
 
 static void
 windows_free_so (struct so_list *so)
 {
-  if (so->lm_info)
-    xfree (so->lm_info);
+  lm_info_windows *li = (lm_info_windows *) so->lm_info;
+
+  delete li;
   xfree (so);
 }
 
@@ -799,25 +845,29 @@ windows_free_so (struct so_list *so)
    do_initial_windows_stuff and windows_add_all_dlls for more info
    on how we handle DLL loading during that phase).  */
 
-static int
-handle_unload_dll (void *dummy)
+static void
+handle_unload_dll ()
 {
   LPVOID lpBaseOfDll = current_event.u.UnloadDll.lpBaseOfDll;
   struct so_list *so;
 
   for (so = &solib_start; so->next != NULL; so = so->next)
-    if (so->next->lm_info->load_addr == lpBaseOfDll)
-      {
-       struct so_list *sodel = so->next;
+    {
+      lm_info_windows *li_next = (lm_info_windows *) so->next->lm_info;
 
-       so->next = sodel->next;
-       if (!so->next)
-         solib_end = so;
-       DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
+      if (li_next->load_addr == lpBaseOfDll)
+       {
+         struct so_list *sodel = so->next;
 
-       windows_free_so (sodel);
-       return 1;
-      }
+         so->next = sodel->next;
+         if (!so->next)
+           solib_end = so;
+         DEBUG_EVENTS (("gdb: Unloading dll \"%s\".\n", sodel->so_name));
+
+         windows_free_so (sodel);
+         return;
+       }
+    }
 
   /* We did not find any DLL that was previously loaded at this address,
      so register a complaint.  We do not report an error, because we have
@@ -828,8 +878,23 @@ handle_unload_dll (void *dummy)
      32bit and 64bit worlds).  */
   complaint (&symfile_complaints, _("dll starting at %s not found."),
             host_address_to_string (lpBaseOfDll));
+}
 
-  return 0;
+/* Call FUNC wrapped in a TRY/CATCH that swallows all GDB
+   exceptions.  */
+
+static void
+catch_errors (void (*func) ())
+{
+  TRY
+    {
+      func ();
+    }
+  CATCH (ex, RETURN_MASK_ALL)
+    {
+      exception_print (gdb_stderr, ex);
+    }
+  END_CATCH
 }
 
 /* Clear list of loaded DLLs.  */
@@ -841,7 +906,7 @@ windows_clear_solib (void)
 }
 
 static void
-signal_event_command (char *args, int from_tty)
+signal_event_command (const char *args, int from_tty)
 {
   uintptr_t event_id = 0;
   char *endargs = NULL;
@@ -865,25 +930,25 @@ signal_event_command (char *args, int from_tty)
 static int
 handle_output_debug_string (struct target_waitstatus *ourstatus)
 {
-  char *s = NULL;
+  gdb::unique_xmalloc_ptr<char> s;
   int retval = 0;
 
   if (!target_read_string
        ((CORE_ADDR) (uintptr_t) current_event.u.DebugString.lpDebugStringData,
-       &s, 1024, 0)
-      || !s || !*s)
+        &s, 1024, 0)
+      || !s || !*(s.get ()))
     /* nothing to do */;
-  else if (!startswith (s, _CYGWIN_SIGNAL_STRING))
+  else if (!startswith (s.get (), _CYGWIN_SIGNAL_STRING))
     {
 #ifdef __CYGWIN__
-      if (!startswith (s, "cYg"))
+      if (!startswith (s.get (), "cYg"))
 #endif
        {
-         char *p = strchr (s, '\0');
+         char *p = strchr (s.get (), '\0');
 
-         if (p > s && *--p == '\n')
+         if (p > s.get () && *--p == '\n')
            *p = '\0';
-         warning (("%s"), s);
+         warning (("%s"), s.get ());
        }
     }
 #ifdef __CYGWIN__
@@ -897,7 +962,7 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
         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);
+      int sig = strtol (s.get () + sizeof (_CYGWIN_SIGNAL_STRING) - 1, &p, 0);
       gdb_signal gotasig = gdb_signal_from_host (sig);
 
       ourstatus->value.sig = gotasig;
@@ -920,8 +985,6 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
     }
 #endif
 
-  if (s)
-    xfree (s);
   return retval;
 }
 
@@ -1002,7 +1065,7 @@ display_selector (HANDLE thread, DWORD sel)
 }
 
 static void
-display_selectors (char * args, int from_tty)
+display_selectors (const char * args, int from_tty)
 {
   if (!current_thread)
     {
@@ -1175,18 +1238,16 @@ handle_exception (struct target_waitstatus *ourstatus)
          if (named_thread != NULL)
            {
              int thread_name_len;
-             char *thread_name;
+             gdb::unique_xmalloc_ptr<char> thread_name;
 
              thread_name_len = target_read_string (thread_name_target,
                                                    &thread_name, 1025, NULL);
              if (thread_name_len > 0)
                {
-                 thread_name[thread_name_len - 1] = '\0';
+                 thread_name.get ()[thread_name_len - 1] = '\0';
                  xfree (named_thread->name);
-                 named_thread->name = thread_name;
+                 named_thread->name = thread_name.release ();
                }
-             else
-               xfree (thread_name);
            }
          ourstatus->value.sig = GDB_SIGNAL_TRAP;
          result = HANDLE_EXCEPTION_IGNORED;
@@ -1296,9 +1357,8 @@ fake_create_process (void)
   return main_thread_id;
 }
 
-static void
-windows_resume (struct target_ops *ops,
-               ptid_t ptid, int step, enum gdb_signal sig)
+void
+windows_nat_target::resume (ptid_t ptid, int step, enum gdb_signal sig)
 {
   windows_thread_info *th;
   DWORD continue_status = DBG_CONTINUE;
@@ -1358,9 +1418,8 @@ windows_resume (struct target_ops *ops,
        {
          /* Single step by setting t bit.  */
          struct regcache *regcache = get_current_regcache ();
-         struct gdbarch *gdbarch = get_regcache_arch (regcache);
-         windows_fetch_inferior_registers (ops, regcache,
-                                           gdbarch_ps_regnum (gdbarch));
+         struct gdbarch *gdbarch = regcache->arch ();
+         fetch_registers (regcache, gdbarch_ps_regnum (gdbarch));
          th->context.EFlags |= FLAG_TRACE_BIT;
        }
 
@@ -1516,7 +1575,7 @@ get_windows_debug_event (struct target_ops *ops,
                     "EXIT_PROCESS_DEBUG_EVENT"));
       if (!windows_initialization_done)
        {
-         target_terminal_ours ();
+         target_terminal::ours ();
          target_mourn_inferior (inferior_ptid);
          error (_("During startup program exited with code 0x%x."),
                 (unsigned int) current_event.u.ExitProcess.dwExitCode);
@@ -1537,7 +1596,7 @@ get_windows_debug_event (struct target_ops *ops,
       CloseHandle (current_event.u.LoadDll.hFile);
       if (saw_create != 1 || ! windows_initialization_done)
        break;
-      catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
+      catch_errors (handle_load_dll);
       ourstatus->kind = TARGET_WAITKIND_LOADED;
       ourstatus->value.integer = 0;
       thread_id = main_thread_id;
@@ -1550,7 +1609,7 @@ get_windows_debug_event (struct target_ops *ops,
                     "UNLOAD_DLL_DEBUG_EVENT"));
       if (saw_create != 1 || ! windows_initialization_done)
        break;
-      catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
+      catch_errors (handle_unload_dll);
       ourstatus->kind = TARGET_WAITKIND_LOADED;
       ourstatus->value.integer = 0;
       thread_id = main_thread_id;
@@ -1617,13 +1676,13 @@ out:
 }
 
 /* Wait for interesting events to occur in the target process.  */
-static ptid_t
-windows_wait (struct target_ops *ops,
-             ptid_t ptid, struct target_waitstatus *ourstatus, int options)
+ptid_t
+windows_nat_target::wait (ptid_t ptid, struct target_waitstatus *ourstatus,
+                         int options)
 {
   int pid = -1;
 
-  target_terminal_ours ();
+  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,
@@ -1662,7 +1721,7 @@ windows_wait (struct target_ops *ops,
             the user tries to resume the execution in the inferior.
             This is a classic race that we should try to fix one day.  */
       SetConsoleCtrlHandler (&ctrl_c_handler, TRUE);
-      retval = get_windows_debug_event (ops, pid, ourstatus);
+      retval = get_windows_debug_event (this, pid, ourstatus);
       SetConsoleCtrlHandler (&ctrl_c_handler, FALSE);
 
       if (retval)
@@ -1675,7 +1734,7 @@ windows_wait (struct target_ops *ops,
            detach = deprecated_ui_loop_hook (0);
 
          if (detach)
-           windows_kill_inferior (ops);
+           kill ();
        }
     }
 }
@@ -1768,8 +1827,8 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
      current thread until we report an event out of windows_wait.  */
   inferior_ptid = pid_to_ptid (pid);
 
-  target_terminal_init ();
-  target_terminal_inferior ();
+  target_terminal::init ();
+  target_terminal::inferior ();
 
   windows_initialization_done = 0;
 
@@ -1777,7 +1836,7 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
     {
       struct target_waitstatus status;
 
-      windows_wait (ops, minus_one_ptid, &status, 0);
+      ops->wait (minus_one_ptid, &status, 0);
 
       /* Note windows_wait returns TARGET_WAITKIND_SPURIOUS for thread
         events.  */
@@ -1785,7 +1844,7 @@ do_initial_windows_stuff (struct target_ops *ops, DWORD pid, int attaching)
          && status.kind != TARGET_WAITKIND_SPURIOUS)
        break;
 
-      windows_resume (ops, minus_one_ptid, 0, GDB_SIGNAL_0);
+      ops->resume (minus_one_ptid, 0, GDB_SIGNAL_0);
     }
 
   /* Now that the inferior has been started and all DLLs have been mapped,
@@ -1859,8 +1918,9 @@ out:
 }
 
 /* Attach to process PID, then initialize for debugging it.  */
-static void
-windows_attach (struct target_ops *ops, const char *args, int from_tty)
+
+void
+windows_nat_target::attach (const char *args, int from_tty)
 {
   BOOL ok;
   DWORD pid;
@@ -1908,17 +1968,17 @@ windows_attach (struct target_ops *ops, const char *args, int from_tty)
       gdb_flush (gdb_stdout);
     }
 
-  do_initial_windows_stuff (ops, pid, 1);
-  target_terminal_ours ();
+  do_initial_windows_stuff (this, pid, 1);
+  target_terminal::ours ();
 }
 
-static void
-windows_detach (struct target_ops *ops, const char *args, int from_tty)
+void
+windows_nat_target::detach (inferior *inf, int from_tty)
 {
   int detached = 1;
 
-  ptid_t ptid = {-1};
-  windows_resume (ops, ptid, 0, GDB_SIGNAL_0);
+  ptid_t ptid = minus_one_ptid;
+  resume (ptid, 0, GDB_SIGNAL_0);
 
   if (!DebugActiveProcessStop (current_event.dwProcessId))
     {
@@ -1930,7 +1990,7 @@ windows_detach (struct target_ops *ops, const char *args, int from_tty)
 
   if (detached && from_tty)
     {
-      char *exec_file = get_exec_file (0);
+      const char *exec_file = get_exec_file (0);
       if (exec_file == 0)
        exec_file = "";
       printf_unfiltered ("Detaching from program: %s, Pid %u\n", exec_file,
@@ -1942,7 +2002,7 @@ windows_detach (struct target_ops *ops, const char *args, int from_tty)
   inferior_ptid = null_ptid;
   detach_inferior (current_event.dwProcessId);
 
-  inf_child_maybe_unpush_target (ops);
+  maybe_unpush_target ();
 }
 
 /* Try to determine the executable filename.
@@ -1999,8 +2059,8 @@ windows_get_exec_module_filename (char *exe_name_ret, size_t exe_name_max_len)
 
 /* The pid_to_exec_file target_ops method for this platform.  */
 
-static char *
-windows_pid_to_exec_file (struct target_ops *self, int pid)
+char *
+windows_nat_target::pid_to_exec_file (int pid)
 {
   static char path[__PMAX];
 #ifdef __CYGWIN__
@@ -2027,8 +2087,8 @@ windows_pid_to_exec_file (struct target_ops *self, int pid)
 
 /* Print status information about what we're accessing.  */
 
-static void
-windows_files_info (struct target_ops *ignore)
+void
+windows_nat_target::files_info ()
 {
   struct inferior *inf = current_inferior ();
 
@@ -2116,19 +2176,316 @@ clear_win32_environment (char **env)
 }
 #endif
 
+#ifndef __CYGWIN__
+
+/* Redirection of inferior I/O streams for native MS-Windows programs.
+   Unlike on Unix, where this is handled by invoking the inferior via
+   the shell, on MS-Windows we need to emulate the cmd.exe shell.
+
+   The official documentation of the cmd.exe redirection features is here:
+
+     http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx
+
+   (That page talks about Windows XP, but there's no newer
+   documentation, so we assume later versions of cmd.exe didn't change
+   anything.)
+
+   Caveat: the documentation on that page seems to include a few lies.
+   For example, it describes strange constructs 1<&2 and 2<&1, which
+   seem to work only when 1>&2 resp. 2>&1 would make sense, and so I
+   think the cmd.exe parser of the redirection symbols simply doesn't
+   care about the < vs > distinction in these cases.  Therefore, the
+   supported features are explicitly documented below.
+
+   The emulation below aims at supporting all the valid use cases
+   supported by cmd.exe, which include:
+
+     < FILE    redirect standard input from FILE
+     0< FILE   redirect standard input from FILE
+     <&N       redirect standard input from file descriptor N
+     0<&N      redirect standard input from file descriptor N
+     > FILE    redirect standard output to FILE
+     >> FILE   append standard output to FILE
+     1>> FILE  append standard output to FILE
+     >&N       redirect standard output to file descriptor N
+     1>&N      redirect standard output to file descriptor N
+     >>&N      append standard output to file descriptor N
+     1>>&N     append standard output to file descriptor N
+     2> FILE   redirect standard error to FILE
+     2>> FILE  append standard error to FILE
+     2>&N      redirect standard error to file descriptor N
+     2>>&N     append standard error to file descriptor N
+
+     Note that using N > 2 in the above construct is supported, but
+     requires that the corresponding file descriptor be open by some
+     means elsewhere or outside GDB.  Also note that using ">&0" or
+     "<&2" will generally fail, because the file descriptor redirected
+     from is normally open in an incompatible mode (e.g., FD 0 is open
+     for reading only).  IOW, use of such tricks is not recommended;
+     you are on your own.
+
+     We do NOT support redirection of file descriptors above 2, as in
+     "3>SOME-FILE", because MinGW compiled programs don't (supporting
+     that needs special handling in the startup code that MinGW
+     doesn't have).  Pipes are also not supported.
+
+     As for invalid use cases, where the redirection contains some
+     error, the emulation below will detect that and produce some
+     error and/or failure.  But the behavior in those cases is not
+     bug-for-bug compatible with what cmd.exe does in those cases.
+     That's because what cmd.exe does then is not well defined, and
+     seems to be a side effect of the cmd.exe parsing of the command
+     line more than anything else.  For example, try redirecting to an
+     invalid file name, as in "> foo:bar".
+
+     There are also minor syntactic deviations from what cmd.exe does
+     in some corner cases.  For example, it doesn't support the likes
+     of "> &foo" to mean redirect to file named literally "&foo"; we
+     do support that here, because that, too, sounds like some issue
+     with the cmd.exe parser.  Another nicety is that we support
+     redirection targets that use file names with forward slashes,
+     something cmd.exe doesn't -- this comes in handy since GDB
+     file-name completion can be used when typing the command line for
+     the inferior.  */
+
+/* Support routines for redirecting standard handles of the inferior.  */
+
+/* Parse a single redirection spec, open/duplicate the specified
+   file/fd, and assign the appropriate value to one of the 3 standard
+   file descriptors. */
+static int
+redir_open (const char *redir_string, int *inp, int *out, int *err)
+{
+  int *fd, ref_fd = -2;
+  int mode;
+  const char *fname = redir_string + 1;
+  int rc = *redir_string;
+
+  switch (rc)
+    {
+    case '0':
+      fname++;
+      /* FALLTHROUGH */
+    case '<':
+      fd = inp;
+      mode = O_RDONLY;
+      break;
+    case '1': case '2':
+      fname++;
+      /* FALLTHROUGH */
+    case '>':
+      fd = (rc == '2') ? err : out;
+      mode = O_WRONLY | O_CREAT;
+      if (*fname == '>')
+       {
+         fname++;
+         mode |= O_APPEND;
+       }
+      else
+       mode |= O_TRUNC;
+      break;
+    default:
+      return -1;
+    }
+
+  if (*fname == '&' && '0' <= fname[1] && fname[1] <= '9')
+    {
+      /* A reference to a file descriptor.  */
+      char *fdtail;
+      ref_fd = (int) strtol (fname + 1, &fdtail, 10);
+      if (fdtail > fname + 1 && *fdtail == '\0')
+       {
+         /* Don't allow redirection when open modes are incompatible.  */
+         if ((ref_fd == 0 && (fd == out || fd == err))
+             || ((ref_fd == 1 || ref_fd == 2) && fd == inp))
+           {
+             errno = EPERM;
+             return -1;
+           }
+         if (ref_fd == 0)
+           ref_fd = *inp;
+         else if (ref_fd == 1)
+           ref_fd = *out;
+         else if (ref_fd == 2)
+           ref_fd = *err;
+       }
+      else
+       {
+         errno = EBADF;
+         return -1;
+       }
+    }
+  else
+    fname++;   /* skip the separator space */
+  /* If the descriptor is already open, close it.  This allows
+     multiple specs of redirections for the same stream, which is
+     somewhat nonsensical, but still valid and supported by cmd.exe.
+     (But cmd.exe only opens a single file in this case, the one
+     specified by the last redirection spec on the command line.)  */
+  if (*fd >= 0)
+    _close (*fd);
+  if (ref_fd == -2)
+    {
+      *fd = _open (fname, mode, _S_IREAD | _S_IWRITE);
+      if (*fd < 0)
+       return -1;
+    }
+  else if (ref_fd == -1)
+    *fd = -1;  /* reset to default destination */
+  else
+    {
+      *fd = _dup (ref_fd);
+      if (*fd < 0)
+       return -1;
+    }
+  /* _open just sets a flag for O_APPEND, which won't be passed to the
+     inferior, so we need to actually move the file pointer.  */
+  if ((mode & O_APPEND) != 0)
+    _lseek (*fd, 0L, SEEK_END);
+  return 0;
+}
+
+/* Canonicalize a single redirection spec and set up the corresponding
+   file descriptor as specified.  */
+static int
+redir_set_redirection (const char *s, int *inp, int *out, int *err)
+{
+  char buf[__PMAX + 2 + 5]; /* extra space for quotes & redirection string */
+  char *d = buf;
+  const char *start = s;
+  int quote = 0;
+
+  *d++ = *s++; /* copy the 1st character, < or > or a digit */
+  if ((*start == '>' || *start == '1' || *start == '2')
+      && *s == '>')
+    {
+      *d++ = *s++;
+      if (*s == '>' && *start != '>')
+       *d++ = *s++;
+    }
+  else if (*start == '0' && *s == '<')
+    *d++ = *s++;
+  /* cmd.exe recognizes "&N" only immediately after the redirection symbol.  */
+  if (*s != '&')
+    {
+      while (isspace (*s))  /* skip whitespace before file name */
+       s++;
+      *d++ = ' ';          /* separate file name with a single space */
+    }
+
+  /* Copy the file name.  */
+  while (*s)
+    {
+      /* Remove quoting characters from the file name in buf[].  */
+      if (*s == '"')   /* could support '..' quoting here */
+       {
+         if (!quote)
+           quote = *s++;
+         else if (*s == quote)
+           {
+             quote = 0;
+             s++;
+           }
+         else
+           *d++ = *s++;
+       }
+      else if (*s == '\\')
+       {
+         if (s[1] == '"')      /* could support '..' here */
+           s++;
+         *d++ = *s++;
+       }
+      else if (isspace (*s) && !quote)
+       break;
+      else
+       *d++ = *s++;
+      if (d - buf >= sizeof (buf) - 1)
+       {
+         errno = ENAMETOOLONG;
+         return 0;
+       }
+    }
+  *d = '\0';
+
+  /* Windows doesn't allow redirection characters in file names, so we
+     can bail out early if they use them, or if there's no target file
+     name after the redirection symbol.  */
+  if (d[-1] == '>' || d[-1] == '<')
+    {
+      errno = ENOENT;
+      return 0;
+    }
+  if (redir_open (buf, inp, out, err) == 0)
+    return s - start;
+  return 0;
+}
+
+/* Parse the command line for redirection specs and prepare the file
+   descriptors for the 3 standard streams accordingly.  */
+static bool
+redirect_inferior_handles (const char *cmd_orig, char *cmd,
+                          int *inp, int *out, int *err)
+{
+  const char *s = cmd_orig;
+  char *d = cmd;
+  int quote = 0;
+  bool retval = false;
+
+  while (isspace (*s))
+    *d++ = *s++;
+
+  while (*s)
+    {
+      if (*s == '"')   /* could also support '..' quoting here */
+       {
+         if (!quote)
+           quote = *s;
+         else if (*s == quote)
+           quote = 0;
+       }
+      else if (*s == '\\')
+       {
+         if (s[1] == '"')      /* escaped quote char */
+           s++;
+       }
+      else if (!quote)
+       {
+         /* Process a single redirection candidate.  */
+         if (*s == '<' || *s == '>'
+             || ((*s == '1' || *s == '2') && s[1] == '>')
+             || (*s == '0' && s[1] == '<'))
+           {
+             int skip = redir_set_redirection (s, inp, out, err);
+
+             if (skip <= 0)
+               return false;
+             retval = true;
+             s += skip;
+           }
+       }
+      if (*s)
+       *d++ = *s++;
+    }
+  *d = '\0';
+  return retval;
+}
+#endif /* !__CYGWIN__ */
+
 /* Start an inferior windows child process and sets inferior_ptid to its pid.
    EXEC_FILE is the file to run.
    ALLARGS is a string containing the arguments to the program.
    ENV is the environment vector to pass.  Errors reported with error().  */
 
-static void
-windows_create_inferior (struct target_ops *ops, char *exec_file,
-                      char *allargs, char **in_env, int from_tty)
+void
+windows_nat_target::create_inferior (const char *exec_file,
+                                    const std::string &origallargs,
+                                    char **in_env, int from_tty)
 {
   STARTUPINFO si;
 #ifdef __CYGWIN__
   cygwin_buf_t real_path[__PMAX];
   cygwin_buf_t shell[__PMAX]; /* Path to shell */
+  cygwin_buf_t infcwd[__PMAX];
   const char *sh;
   cygwin_buf_t *toexec;
   cygwin_buf_t *cygallargs;
@@ -2138,20 +2495,26 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
   size_t len;
   int tty;
   int ostdin, ostdout, ostderr;
-#else
+#else  /* !__CYGWIN__ */
   char real_path[__PMAX];
   char shell[__PMAX]; /* Path to shell */
-  char *toexec;
-  char *args;
-  size_t args_len;
-  HANDLE tty;
+  const char *toexec;
+  char *args, *allargs_copy;
+  size_t args_len, allargs_len;
+  int fd_inp = -1, fd_out = -1, fd_err = -1;
+  HANDLE tty = INVALID_HANDLE_VALUE;
+  HANDLE inf_stdin = INVALID_HANDLE_VALUE;
+  HANDLE inf_stdout = INVALID_HANDLE_VALUE;
+  HANDLE inf_stderr = INVALID_HANDLE_VALUE;
+  bool redirected = false;
   char *w32env;
   char *temp;
   size_t envlen;
   int i;
   size_t envsize;
   char **env;
-#endif
+#endif /* !__CYGWIN__ */
+  const char *allargs = origallargs.c_str ();
   PROCESS_INFORMATION pi;
   BOOL ret;
   DWORD flags = 0;
@@ -2160,6 +2523,17 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
   if (!exec_file)
     error (_("No executable specified, use `target exec'."));
 
+  const char *inferior_cwd = get_inferior_cwd ();
+  std::string expanded_infcwd;
+  if (inferior_cwd != NULL)
+    {
+      expanded_infcwd = gdb_tilde_expand (inferior_cwd);
+      /* Mirror slashes on inferior's cwd.  */
+      std::replace (expanded_infcwd.begin (), expanded_infcwd.end (),
+                   '/', '\\');
+      inferior_cwd = expanded_infcwd.c_str ();
+    }
+
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
 
@@ -2183,7 +2557,7 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
        error (_("Error starting executable: %d"), errno);
       cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
       mbstowcs (cygallargs, allargs, len);
-#else
+#else  /* !__USEWIDE */
       cygallargs = allargs;
 #endif
     }
@@ -2199,28 +2573,33 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
            + mbstowcs (NULL, allargs, 0) + 2;
       cygallargs = (wchar_t *) alloca (len * sizeof (wchar_t));
       swprintf (cygallargs, len, L" -c 'exec %s %s'", exec_file, allargs);
-#else
+#else  /* !__USEWIDE */
       len = (sizeof (" -c 'exec  '") + strlen (exec_file)
             + strlen (allargs) + 2);
       cygallargs = (char *) alloca (len);
       xsnprintf (cygallargs, len, " -c 'exec %s %s'", exec_file, allargs);
-#endif
+#endif /* __USEWIDE */
       toexec = shell;
       flags |= DEBUG_PROCESS;
     }
 
+  if (inferior_cwd != NULL
+      && cygwin_conv_path (CCP_POSIX_TO_WIN_W, inferior_cwd,
+                          infcwd, strlen (inferior_cwd)) < 0)
+    error (_("Error converting inferior cwd: %d"), errno);
+
 #ifdef __USEWIDE
   args = (cygwin_buf_t *) alloca ((wcslen (toexec) + wcslen (cygallargs) + 2)
                                  * sizeof (wchar_t));
   wcscpy (args, toexec);
   wcscat (args, L" ");
   wcscat (args, cygallargs);
-#else
+#else  /* !__USEWIDE */
   args = (cygwin_buf_t *) alloca (strlen (toexec) + strlen (cygallargs) + 2);
   strcpy (args, toexec);
   strcat (args, " ");
   strcat (args, cygallargs);
-#endif
+#endif /* !__USEWIDE */
 
 #ifdef CW_CVT_ENV_TO_WINENV
   /* First try to create a direct Win32 copy of the POSIX environment. */
@@ -2229,7 +2608,7 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
     flags |= CREATE_UNICODE_ENVIRONMENT;
   else
     /* If that fails, fall back to old method tweaking GDB's environment. */
-#endif
+#endif /* CW_CVT_ENV_TO_WINENV */
     {
       /* Reset all Win32 environment variables to avoid leftover on next run. */
       clear_win32_environment (environ);
@@ -2269,7 +2648,8 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
                       TRUE,    /* inherit handles */
                       flags,   /* start flags */
                       w32_env, /* environment */
-                      NULL,    /* current directory */
+                      inferior_cwd != NULL ? infcwd : NULL, /* current
+                                                               directory */
                       &si,
                       &pi);
   if (w32_env)
@@ -2294,21 +2674,26 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
       close (ostdout);
       close (ostderr);
     }
-#else
-  toexec = exec_file;
-  /* Build the command line, a space-separated list of tokens where
-     the first token is the name of the module to be executed.
-     To avoid ambiguities introduced by spaces in the module name,
-     we quote it.  */
-  args_len = strlen (toexec) + 2 /* quotes */ + strlen (allargs) + 2;
-  args = (char *) alloca (args_len);
-  xsnprintf (args, args_len, "\"%s\" %s", toexec, allargs);
-
-  flags |= DEBUG_ONLY_THIS_PROCESS;
-
-  if (!inferior_io_terminal)
-    tty = INVALID_HANDLE_VALUE;
-  else
+#else  /* !__CYGWIN__ */
+  allargs_len = strlen (allargs);
+  allargs_copy = strcpy ((char *) alloca (allargs_len + 1), allargs);
+  if (strpbrk (allargs_copy, "<>") != NULL)
+    {
+      int e = errno;
+      errno = 0;
+      redirected =
+       redirect_inferior_handles (allargs, allargs_copy,
+                                  &fd_inp, &fd_out, &fd_err);
+      if (errno)
+       warning (_("Error in redirection: %s."), strerror (errno));
+      else
+       errno = e;
+      allargs_len = strlen (allargs_copy);
+    }
+  /* If not all the standard streams are redirected by the command
+     line, use inferior_io_terminal for those which aren't.  */
+  if (inferior_io_terminal
+      && !(fd_inp >= 0 && fd_out >= 0 && fd_err >= 0))
     {
       SECURITY_ATTRIBUTES sa;
       sa.nLength = sizeof(sa);
@@ -2319,15 +2704,41 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
       if (tty == INVALID_HANDLE_VALUE)
        warning (_("Warning: Failed to open TTY %s, error %#x."),
                 inferior_io_terminal, (unsigned) GetLastError ());
+    }
+  if (redirected || tty != INVALID_HANDLE_VALUE)
+    {
+      if (fd_inp >= 0)
+       si.hStdInput = (HANDLE) _get_osfhandle (fd_inp);
+      else if (tty != INVALID_HANDLE_VALUE)
+       si.hStdInput = tty;
       else
-       {
-         si.hStdInput = tty;
-         si.hStdOutput = tty;
-         si.hStdError = tty;
-         si.dwFlags |= STARTF_USESTDHANDLES;
-       }
+       si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
+      if (fd_out >= 0)
+       si.hStdOutput = (HANDLE) _get_osfhandle (fd_out);
+      else if (tty != INVALID_HANDLE_VALUE)
+       si.hStdOutput = tty;
+      else
+       si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
+      if (fd_err >= 0)
+       si.hStdError = (HANDLE) _get_osfhandle (fd_err);
+      else if (tty != INVALID_HANDLE_VALUE)
+       si.hStdError = tty;
+      else
+       si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
+      si.dwFlags |= STARTF_USESTDHANDLES;
     }
 
+  toexec = exec_file;
+  /* Build the command line, a space-separated list of tokens where
+     the first token is the name of the module to be executed.
+     To avoid ambiguities introduced by spaces in the module name,
+     we quote it.  */
+  args_len = strlen (toexec) + 2 /* quotes */ + allargs_len + 2;
+  args = (char *) alloca (args_len);
+  xsnprintf (args, args_len, "\"%s\" %s", toexec, allargs_copy);
+
+  flags |= DEBUG_ONLY_THIS_PROCESS;
+
   /* CreateProcess takes the environment list as a null terminated set of
      strings (i.e. two nulls terminate the list).  */
 
@@ -2361,12 +2772,18 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
                        TRUE,   /* inherit handles */
                        flags,  /* start flags */
                        w32env, /* environment */
-                       NULL,   /* current directory */
+                       inferior_cwd, /* current directory */
                        &si,
                        &pi);
   if (tty != INVALID_HANDLE_VALUE)
     CloseHandle (tty);
-#endif
+  if (fd_inp >= 0)
+    _close (fd_inp);
+  if (fd_out >= 0)
+    _close (fd_out);
+  if (fd_err >= 0)
+    _close (fd_err);
+#endif /* !__CYGWIN__ */
 
   if (!ret)
     error (_("Error creating process %s, (error %u)."),
@@ -2380,13 +2797,13 @@ windows_create_inferior (struct target_ops *ops, char *exec_file,
   else
     saw_create = 0;
 
-  do_initial_windows_stuff (ops, pi.dwProcessId, 0);
+  do_initial_windows_stuff (this, pi.dwProcessId, 0);
 
   /* windows_continue (DBG_CONTINUE, -1, 0); */
 }
 
-static void
-windows_mourn_inferior (struct target_ops *ops)
+void
+windows_nat_target::mourn_inferior ()
 {
   (void) windows_continue (DBG_CONTINUE, -1, 0);
   x86_cleanup_dregs();
@@ -2395,14 +2812,14 @@ windows_mourn_inferior (struct target_ops *ops)
       CHECK (CloseHandle (current_process_handle));
       open_process_used = 0;
     }
-  inf_child_mourn_inferior (ops);
+  inf_child_target::mourn_inferior ();
 }
 
 /* Send a SIGINT to the process group.  This acts just like the user typed a
    ^C on the controlling terminal.  */
 
-static void
-windows_interrupt (struct target_ops *self, ptid_t ptid)
+void
+windows_nat_target::interrupt ()
 {
   DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
   CHECK (GenerateConsoleCtrlEvent (CTRL_C_EVENT, current_event.dwProcessId));
@@ -2449,8 +2866,8 @@ windows_xfer_memory (gdb_byte *readbuf, const gdb_byte *writebuf,
     return success ? TARGET_XFER_OK : TARGET_XFER_E_IO;
 }
 
-static void
-windows_kill_inferior (struct target_ops *ops)
+void
+windows_nat_target::kill ()
 {
   CHECK (TerminateProcess (current_process_handle, 0));
 
@@ -2467,16 +2884,16 @@ windows_kill_inferior (struct target_ops *ops)
   target_mourn_inferior (inferior_ptid);       /* Or just windows_mourn_inferior?  */
 }
 
-static void
-windows_close (struct target_ops *self)
+void
+windows_nat_target::close ()
 {
   DEBUG_EVENTS (("gdb: windows_close, inferior_ptid=%d\n",
                ptid_get_pid (inferior_ptid)));
 }
 
 /* Convert pid to printable format.  */
-static char *
-windows_pid_to_str (struct target_ops *ops, ptid_t ptid)
+const char *
+windows_nat_target::pid_to_str (ptid_t ptid)
 {
   static char buf[80];
 
@@ -2508,9 +2925,13 @@ windows_xfer_shared_libraries (struct target_ops *ops,
   obstack_init (&obstack);
   obstack_grow_str (&obstack, "<library-list>\n");
   for (so = solib_start.next; so; so = so->next)
-    windows_xfer_shared_library (so->so_name, (CORE_ADDR)
-                                (uintptr_t) so->lm_info->load_addr,
-                                target_gdbarch (), &obstack);
+    {
+      lm_info_windows *li = (lm_info_windows *) so->lm_info;
+
+      windows_xfer_shared_library (so->so_name, (CORE_ADDR)
+                                  (uintptr_t) li->load_addr,
+                                  target_gdbarch (), &obstack);
+    }
   obstack_grow_str0 (&obstack, "</library-list>\n");
 
   buf = (const char *) obstack_finish (&obstack);
@@ -2529,11 +2950,11 @@ windows_xfer_shared_libraries (struct target_ops *ops,
   return len != 0 ? TARGET_XFER_OK : TARGET_XFER_EOF;
 }
 
-static enum target_xfer_status
-windows_xfer_partial (struct target_ops *ops, enum target_object object,
-                     const char *annex, gdb_byte *readbuf,
-                     const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
-                     ULONGEST *xfered_len)
+enum target_xfer_status
+windows_nat_target::xfer_partial (enum target_object object,
+                                 const char *annex, gdb_byte *readbuf,
+                                 const gdb_byte *writebuf, ULONGEST offset, ULONGEST len,
+                                 ULONGEST *xfered_len)
 {
   switch (object)
     {
@@ -2541,90 +2962,52 @@ windows_xfer_partial (struct target_ops *ops, enum target_object object,
       return windows_xfer_memory (readbuf, writebuf, offset, len, xfered_len);
 
     case TARGET_OBJECT_LIBRARIES:
-      return windows_xfer_shared_libraries (ops, object, annex, readbuf,
+      return windows_xfer_shared_libraries (this, object, annex, readbuf,
                                            writebuf, offset, len, xfered_len);
 
     default:
-      return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
-                                           readbuf, writebuf, offset, len,
-                                           xfered_len);
+      return beneath->xfer_partial (object, annex,
+                                   readbuf, writebuf, offset, len,
+                                   xfered_len);
     }
 }
 
 /* Provide thread local base, i.e. Thread Information Block address.
    Returns 1 if ptid is found and sets *ADDR to thread_local_base.  */
 
-static int
-windows_get_tib_address (struct target_ops *self,
-                        ptid_t ptid, CORE_ADDR *addr)
+bool
+windows_nat_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
 {
   windows_thread_info *th;
 
   th = thread_rec (ptid_get_tid (ptid), 0);
   if (th == NULL)
-    return 0;
+    return false;
 
   if (addr != NULL)
     *addr = th->thread_local_base;
 
-  return 1;
+  return true;
 }
 
-static ptid_t
-windows_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
+ptid_t
+windows_nat_target::get_ada_task_ptid (long lwp, long thread)
 {
   return ptid_build (ptid_get_pid (inferior_ptid), 0, lwp);
 }
 
 /* Implementation of the to_thread_name method.  */
 
-static const char *
-windows_thread_name (struct target_ops *self, struct thread_info *thr)
+const char *
+windows_nat_target::thread_name (struct thread_info *thr)
 {
   return thread_rec (ptid_get_tid (thr->ptid), 0)->name;
 }
 
-static struct target_ops *
-windows_target (void)
-{
-  struct target_ops *t = inf_child_target ();
-
-  t->to_close = windows_close;
-  t->to_attach = windows_attach;
-  t->to_attach_no_wait = 1;
-  t->to_detach = windows_detach;
-  t->to_resume = windows_resume;
-  t->to_wait = windows_wait;
-  t->to_fetch_registers = windows_fetch_inferior_registers;
-  t->to_store_registers = windows_store_inferior_registers;
-  t->to_xfer_partial = windows_xfer_partial;
-  t->to_files_info = windows_files_info;
-  t->to_kill = windows_kill_inferior;
-  t->to_create_inferior = windows_create_inferior;
-  t->to_mourn_inferior = windows_mourn_inferior;
-  t->to_thread_alive = windows_thread_alive;
-  t->to_pid_to_str = windows_pid_to_str;
-  t->to_interrupt = windows_interrupt;
-  t->to_pid_to_exec_file = windows_pid_to_exec_file;
-  t->to_get_ada_task_ptid = windows_get_ada_task_ptid;
-  t->to_get_tib_address = windows_get_tib_address;
-  t->to_thread_name = windows_thread_name;
-
-  return t;
-}
-
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_windows_nat;
 
 void
 _initialize_windows_nat (void)
 {
-  struct target_ops *t;
-
-  t = windows_target ();
-
-  x86_use_watchpoints (t);
-
   x86_dr_low.set_control = cygwin_set_dr7;
   x86_dr_low.set_addr = cygwin_set_dr;
   x86_dr_low.get_addr = cygwin_get_dr;
@@ -2635,7 +3018,7 @@ _initialize_windows_nat (void)
      calling x86_set_debug_register_length function
      in processor windows specific native file.  */
 
-  add_target (t);
+  add_inf_child_target (&the_windows_nat_target);
 
 #ifdef __CYGWIN__
   cygwin_internal (CW_SET_DOS_FILE_WARNING, 0);
@@ -2772,21 +3155,18 @@ cygwin_get_dr7 (void)
 /* Determine if the thread referenced by "ptid" is alive
    by "polling" it.  If WaitForSingleObject returns WAIT_OBJECT_0
    it means that the thread has died.  Otherwise it is assumed to be alive.  */
-static int
-windows_thread_alive (struct target_ops *ops, ptid_t ptid)
+
+bool
+windows_nat_target::thread_alive (ptid_t ptid)
 {
   int tid;
 
   gdb_assert (ptid_get_tid (ptid) != 0);
   tid = ptid_get_tid (ptid);
 
-  return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) == WAIT_OBJECT_0
-    ? FALSE : TRUE;
+  return WaitForSingleObject (thread_rec (tid, FALSE)->h, 0) != WAIT_OBJECT_0;
 }
 
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_check_for_gdb_ini;
-
 void
 _initialize_check_for_gdb_ini (void)
 {
@@ -2881,9 +3261,6 @@ bad_GetConsoleFontSize (HANDLE w, DWORD nFont)
   return size;
 }
  
-/* -Wmissing-prototypes */
-extern initialize_file_ftype _initialize_loadable;
-
 /* Load any functions which may not be available in ancient versions
    of Windows.  */
 
This page took 0.043282 seconds and 4 git commands to generate.