]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blobdiff - gdbserver/win32-low.cc
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdbserver / win32-low.cc
index 1f4967320bcdf847ac1ad760408447fd044d2d8d..756507709d81971ef59fcaddc9768a37679ca1d4 100644 (file)
@@ -1,5 +1,5 @@
 /* Low level interface to Windows debugging, for gdbserver.
-   Copyright (C) 2006-2021 Free Software Foundation, Inc.
+   Copyright (C) 2006-2023 Free Software Foundation, Inc.
 
    Contributed by Leo Zayas.  Based on "win32-nat.c" from GDB.
 
@@ -20,7 +20,7 @@
 
 #include "server.h"
 #include "regcache.h"
-#include "gdb/fileio.h"
+#include "gdbsupport/fileio.h"
 #include "mem-break.h"
 #include "win32-low.h"
 #include "gdbthread.h"
@@ -38,6 +38,9 @@
 
 using namespace windows_nat;
 
+/* See win32-low.h.  */
+gdbserver_windows_process windows_process;
+
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>
 #endif
@@ -58,34 +61,8 @@ using namespace windows_nat;
 #define _T(x) TEXT (x)
 #endif
 
-#ifndef COUNTOF
-#define COUNTOF(STR) (sizeof (STR) / sizeof ((STR)[0]))
-#endif
-
-#define GETPROCADDRESS(DLL, PROC) \
-  ((winapi_ ## PROC) GetProcAddress (DLL, #PROC))
-
 int using_threads = 1;
 
-/* Globals.  */
-static int attaching = 0;
-
-/* A status that hasn't been reported to the core yet, and so
-   win32_wait should return it next, instead of fetching the next
-   debug event off the win32 API.  */
-static struct target_waitstatus cached_status;
-
-/* Non zero if an interrupt request is to be satisfied by suspending
-   all threads.  */
-static int soft_interrupt_requested = 0;
-
-/* Non zero if the inferior is stopped in a simulated breakpoint done
-   by suspending all the threads.  */
-static int faked_breakpoint = 0;
-
-/* True if current_process_handle needs to be closed.  */
-static bool open_process_used = false;
-
 const struct target_desc *win32_tdesc;
 #ifdef __x86_64__
 const struct target_desc *wow64_win32_tdesc;
@@ -93,21 +70,6 @@ const struct target_desc *wow64_win32_tdesc;
 
 #define NUM_REGS (the_low_target.num_regs ())
 
-typedef BOOL (WINAPI *winapi_DebugActiveProcessStop) (DWORD dwProcessId);
-typedef BOOL (WINAPI *winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
-typedef BOOL (WINAPI *winapi_DebugBreakProcess) (HANDLE);
-typedef BOOL (WINAPI *winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
-
-#ifdef __x86_64__
-typedef BOOL (WINAPI *winapi_Wow64SetThreadContext) (HANDLE,
-                                                    const WOW64_CONTEXT *);
-
-winapi_Wow64GetThreadContext win32_Wow64GetThreadContext;
-static winapi_Wow64SetThreadContext win32_Wow64SetThreadContext;
-#endif
-
-static void win32_add_all_dlls (void);
-
 /* Get the thread ID from the current selected inferior (the current
    thread).  */
 static ptid_t
@@ -129,7 +91,7 @@ static void
 win32_get_thread_context (windows_thread_info *th)
 {
 #ifdef __x86_64__
-  if (wow64_process)
+  if (windows_process.wow64_process)
     memset (&th->wow64_context, 0, sizeof (WOW64_CONTEXT));
   else
 #endif
@@ -143,8 +105,8 @@ static void
 win32_set_thread_context (windows_thread_info *th)
 {
 #ifdef __x86_64__
-  if (wow64_process)
-    win32_Wow64SetThreadContext (th->h, &th->wow64_context);
+  if (windows_process.wow64_process)
+    Wow64SetThreadContext (th->h, &th->wow64_context);
   else
 #endif
     SetThreadContext (th->h, &th->context);
@@ -166,7 +128,7 @@ win32_require_context (windows_thread_info *th)
 {
   DWORD context_flags;
 #ifdef __x86_64__
-  if (wow64_process)
+  if (windows_process.wow64_process)
     context_flags = th->wow64_context.ContextFlags;
   else
 #endif
@@ -181,7 +143,8 @@ win32_require_context (windows_thread_info *th)
 /* See nat/windows-nat.h.  */
 
 windows_thread_info *
-windows_nat::thread_rec (ptid_t ptid, thread_disposition_type disposition)
+gdbserver_windows_process::thread_rec
+     (ptid_t ptid, thread_disposition_type disposition)
 {
   thread_info *thread = find_thread_ptid (ptid);
   if (thread == NULL)
@@ -200,14 +163,14 @@ child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
   windows_thread_info *th;
   ptid_t ptid = ptid_t (pid, tid, 0);
 
-  if ((th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
+  if ((th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
     return th;
 
   CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
 #ifdef __x86_64__
   /* For WOW64 processes, this is actually the pointer to the 64bit TIB,
      and the 32bit TIB is exactly 2 pages after it.  */
-  if (wow64_process)
+  if (windows_process.wow64_process)
     base += 2 * 4096; /* page size = 4096 */
 #endif
   th = new windows_thread_info (tid, h, base);
@@ -313,15 +276,15 @@ child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
 
   if (write)
     {
-      success = WriteProcessMemory (current_process_handle, (LPVOID) addr,
+      success = WriteProcessMemory (windows_process.handle, (LPVOID) addr,
                                    (LPCVOID) our, len, &done);
       if (!success)
        lasterror = GetLastError ();
-      FlushInstructionCache (current_process_handle, (LPCVOID) addr, len);
+      FlushInstructionCache (windows_process.handle, (LPCVOID) addr, len);
     }
   else
     {
-      success = ReadProcessMemory (current_process_handle, (LPCVOID) addr,
+      success = ReadProcessMemory (windows_process.handle, (LPCVOID) addr,
                                   (LPVOID) our, len, &done);
       if (!success)
        lasterror = GetLastError ();
@@ -340,26 +303,21 @@ child_init_thread_list (void)
   for_each_thread (delete_thread_info);
 }
 
-/* Zero during the child initialization phase, and nonzero otherwise.  */
-
-static int child_initialization_done = 0;
-
 static void
 do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
 {
   struct process_info *proc;
 
-  last_sig = GDB_SIGNAL_0;
-
-  current_process_handle = proch;
-  current_process_id = pid;
-  main_thread_id = 0;
+  windows_process.last_sig = GDB_SIGNAL_0;
+  windows_process.handle = proch;
+  windows_process.main_thread_id = 0;
 
-  soft_interrupt_requested = 0;
-  faked_breakpoint = 0;
-  open_process_used = true;
+  windows_process.soft_interrupt_requested = 0;
+  windows_process.faked_breakpoint = 0;
+  windows_process.open_process_used = true;
 
-  memset (&current_event, 0, sizeof (current_event));
+  memset (&windows_process.current_event, 0,
+         sizeof (windows_process.current_event));
 
 #ifdef __x86_64__
   BOOL wow64;
@@ -369,30 +327,31 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
       error ("Check if WOW64 process failed (error %d): %s\n",
             (int) err, strwinerror (err));
     }
-  wow64_process = wow64;
+  windows_process.wow64_process = wow64;
 
-  if (wow64_process
-      && (win32_Wow64GetThreadContext == nullptr
-         || win32_Wow64SetThreadContext == nullptr))
+  if (windows_process.wow64_process
+      && (Wow64GetThreadContext == nullptr
+         || Wow64SetThreadContext == nullptr))
     error ("WOW64 debugging is not supported on this system.\n");
 
-  ignore_first_breakpoint = !attached && wow64_process;
+  windows_process.ignore_first_breakpoint
+    = !attached && windows_process.wow64_process;
 #endif
 
   proc = add_process (pid, attached);
 #ifdef __x86_64__
-  if (wow64_process)
+  if (windows_process.wow64_process)
     proc->tdesc = wow64_win32_tdesc;
   else
 #endif
     proc->tdesc = win32_tdesc;
   child_init_thread_list ();
-  child_initialization_done = 0;
+  windows_process.child_initialization_done = 0;
 
   if (the_low_target.initial_stuff != NULL)
     (*the_low_target.initial_stuff) ();
 
-  cached_status.kind = TARGET_WAITKIND_IGNORE;
+  windows_process.cached_status.set_ignore ();
 
   /* Flush all currently pending debug events (thread and dll list) up
      to the initial breakpoint.  */
@@ -403,9 +362,9 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
       the_target->wait (minus_one_ptid, &status, 0);
 
       /* Note win32_wait doesn't return thread events.  */
-      if (status.kind != TARGET_WAITKIND_LOADED)
+      if (status.kind () != TARGET_WAITKIND_LOADED)
        {
-         cached_status = status;
+         windows_process.cached_status = status;
          break;
        }
 
@@ -435,9 +394,9 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
      Rather than try to work around this sort of issue, it is much
      simpler to just ignore DLL load/unload events during the startup
      phase, and then process them all in one batch now.  */
-  win32_add_all_dlls ();
+  windows_process.add_all_dlls ();
 
-  child_initialization_done = 1;
+  windows_process.child_initialization_done = 1;
 }
 
 /* Resume all artificially suspended threads if we are continuing
@@ -455,7 +414,7 @@ continue_one_thread (thread_info *thread, int thread_id)
        {
          DWORD *context_flags;
 #ifdef __x86_64__
-         if (wow64_process)
+         if (windows_process.wow64_process)
            context_flags = &th->wow64_context.ContextFlags;
          else
 #endif
@@ -474,8 +433,8 @@ continue_one_thread (thread_info *thread, int thread_id)
 static BOOL
 child_continue (DWORD continue_status, int thread_id)
 {
-  desired_stop_thread_id = thread_id;
-  if (matching_pending_stop (debug_threads))
+  windows_process.desired_stop_thread_id = thread_id;
+  if (windows_process.matching_pending_stop (debug_threads))
     return TRUE;
 
   /* The inferior will only continue after the ContinueDebugEvent
@@ -484,7 +443,7 @@ child_continue (DWORD continue_status, int thread_id)
     {
       continue_one_thread (thread, thread_id);
     });
-  faked_breakpoint = 0;
+  windows_process.faked_breakpoint = 0;
 
   return continue_last_debug_event (continue_status, debug_threads);
 }
@@ -494,8 +453,9 @@ static void
 child_fetch_inferior_registers (struct regcache *regcache, int r)
 {
   int regno;
-  windows_thread_info *th = thread_rec (current_thread_ptid (),
-                                       INVALIDATE_CONTEXT);
+  windows_thread_info *th
+    = windows_process.thread_rec (current_thread_ptid (),
+                                 INVALIDATE_CONTEXT);
   if (r == -1 || r > NUM_REGS)
     child_fetch_inferior_registers (regcache, NUM_REGS);
   else
@@ -509,8 +469,9 @@ static void
 child_store_inferior_registers (struct regcache *regcache, int r)
 {
   int regno;
-  windows_thread_info *th = thread_rec (current_thread_ptid (),
-                                       INVALIDATE_CONTEXT);
+  windows_thread_info *th
+    = windows_process.thread_rec (current_thread_ptid (),
+                                 INVALIDATE_CONTEXT);
   if (r == -1 || r == 0 || r > NUM_REGS)
     child_store_inferior_registers (regcache, NUM_REGS);
   else
@@ -518,66 +479,11 @@ child_store_inferior_registers (struct regcache *regcache, int r)
       (*the_low_target.store_inferior_register) (regcache, th, regno);
 }
 
-/* Map the Windows error number in ERROR to a locale-dependent error
-   message string and return a pointer to it.  Typically, the values
-   for ERROR come from GetLastError.
-
-   The string pointed to shall not be modified by the application,
-   but may be overwritten by a subsequent call to strwinerror
-
-   The strwinerror function does not change the current setting
-   of GetLastError.  */
-
-char *
-strwinerror (DWORD error)
-{
-  static char buf[1024];
-  TCHAR *msgbuf;
-  DWORD lasterr = GetLastError ();
-  DWORD chars = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM
-                              | FORMAT_MESSAGE_ALLOCATE_BUFFER,
-                              NULL,
-                              error,
-                              0, /* Default language */
-                              (LPTSTR) &msgbuf,
-                              0,
-                              NULL);
-  if (chars != 0)
-    {
-      /* If there is an \r\n appended, zap it.  */
-      if (chars >= 2
-         && msgbuf[chars - 2] == '\r'
-         && msgbuf[chars - 1] == '\n')
-       {
-         chars -= 2;
-         msgbuf[chars] = 0;
-       }
-
-      if (chars > ((COUNTOF (buf)) - 1))
-       {
-         chars = COUNTOF (buf) - 1;
-         msgbuf [chars] = 0;
-       }
-
-#ifdef UNICODE
-      wcstombs (buf, msgbuf, chars + 1);
-#else
-      strncpy (buf, msgbuf, chars + 1);
-#endif
-      LocalFree (msgbuf);
-    }
-  else
-    sprintf (buf, "unknown win32 error (%u)", (unsigned) error);
-
-  SetLastError (lasterr);
-  return buf;
-}
-
 static BOOL
 create_process (const char *program, char *args,
                DWORD flags, PROCESS_INFORMATION *pi)
 {
-  const char *inferior_cwd = get_inferior_cwd ();
+  const std::string &inferior_cwd = get_inferior_cwd ();
   BOOL ret;
   size_t argslen, proglen;
 
@@ -590,17 +496,15 @@ create_process (const char *program, char *args,
   strcpy (program_and_args, program);
   strcat (program_and_args, " ");
   strcat (program_and_args, args);
-  ret = CreateProcessA (program,           /* image name */
+  ret = create_process (program,           /* image name */
                        program_and_args,  /* command line */
-                       NULL,              /* security */
-                       NULL,              /* thread */
-                       TRUE,              /* inherit handles */
                        flags,             /* start flags */
                        NULL,              /* environment */
                        /* current directory */
-                       (inferior_cwd == NULL
+                       (inferior_cwd.empty ()
                         ? NULL
-                        : gdb_tilde_expand (inferior_cwd).c_str()),
+                        : gdb_tilde_expand (inferior_cwd.c_str ()).c_str()),
+                       get_client_state ().disable_randomization,
                        &si,               /* start info */
                        pi);               /* proc info */
 
@@ -629,7 +533,7 @@ win32_process_target::create_inferior (const char *program,
   char *args = (char *) str_program_args.c_str ();
 
   /* win32_wait needs to know we're not attaching.  */
-  attaching = 0;
+  windows_process.attaching = 0;
 
   if (!program)
     error ("No executable specified, specify executable to debug.\n");
@@ -689,12 +593,12 @@ win32_process_target::create_inferior (const char *program,
 
   /* Wait till we are at 1st instruction in program, return new pid
      (assuming success).  */
-  cs.last_ptid = wait (ptid_t (current_process_id), &cs.last_status, 0);
+  cs.last_ptid = wait (ptid_t (pi.dwProcessId), &cs.last_status, 0);
 
   /* Necessary for handle_v_kill.  */
-  signal_pid = current_process_id;
+  signal_pid = pi.dwProcessId;
 
-  return current_process_id;
+  return pi.dwProcessId;
 }
 
 /* Attach to a running process.
@@ -704,21 +608,17 @@ int
 win32_process_target::attach (unsigned long pid)
 {
   HANDLE h;
-  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
   DWORD err;
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
 
   h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
   if (h != NULL)
     {
       if (DebugActiveProcess (pid))
        {
-         if (DebugSetProcessKillOnExit != NULL)
-           DebugSetProcessKillOnExit (FALSE);
+         DebugSetProcessKillOnExit (FALSE);
 
          /* win32_wait needs to know we're attaching.  */
-         attaching = 1;
+         windows_process.attaching = 1;
          do_initial_child_stuff (h, pid, 1);
          return 0;
        }
@@ -734,7 +634,8 @@ win32_process_target::attach (unsigned long pid)
 /* See nat/windows-nat.h.  */
 
 int
-windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
+gdbserver_windows_process::handle_output_debug_string
+     (struct target_waitstatus *ourstatus)
 {
 #define READ_BUFFER_LEN 1024
   CORE_ADDR addr;
@@ -782,14 +683,14 @@ windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
 static void
 win32_clear_inferiors (void)
 {
-  if (open_process_used)
+  if (windows_process.open_process_used)
     {
-      CloseHandle (current_process_handle);
-      open_process_used = false;
+      CloseHandle (windows_process.handle);
+      windows_process.open_process_used = false;
     }
 
   for_each_thread (delete_thread_info);
-  siginfo_er.ExceptionCode = 0;
+  windows_process.siginfo_er.ExceptionCode = 0;
   clear_inferiors ();
 }
 
@@ -798,17 +699,19 @@ win32_clear_inferiors (void)
 int
 win32_process_target::kill (process_info *process)
 {
-  TerminateProcess (current_process_handle, 0);
+  TerminateProcess (windows_process.handle, 0);
   for (;;)
     {
       if (!child_continue (DBG_CONTINUE, -1))
        break;
-      if (!wait_for_debug_event (&current_event, INFINITE))
+      if (!wait_for_debug_event (&windows_process.current_event, INFINITE))
        break;
-      if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
+      if (windows_process.current_event.dwDebugEventCode
+         == EXIT_PROCESS_DEBUG_EVENT)
        break;
-      else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
-       handle_output_debug_string (nullptr);
+      else if (windows_process.current_event.dwDebugEventCode
+              == OUTPUT_DEBUG_STRING_EVENT)
+       windows_process.handle_output_debug_string (nullptr);
     }
 
   win32_clear_inferiors ();
@@ -822,25 +725,13 @@ win32_process_target::kill (process_info *process)
 int
 win32_process_target::detach (process_info *process)
 {
-  winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
-  winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-  DebugActiveProcessStop = GETPROCADDRESS (dll, DebugActiveProcessStop);
-  DebugSetProcessKillOnExit = GETPROCADDRESS (dll, DebugSetProcessKillOnExit);
-
-  if (DebugSetProcessKillOnExit == NULL
-      || DebugActiveProcessStop == NULL)
-    return -1;
+  struct thread_resume resume;
+  resume.thread = minus_one_ptid;
+  resume.kind = resume_continue;
+  resume.sig = 0;
+  this->resume (&resume, 1);
 
-  {
-    struct thread_resume resume;
-    resume.thread = minus_one_ptid;
-    resume.kind = resume_continue;
-    resume.sig = 0;
-    this->resume (&resume, 1);
-  }
-
-  if (!DebugActiveProcessStop (current_process_id))
+  if (!DebugActiveProcessStop (process->pid))
     return -1;
 
   DebugSetProcessKillOnExit (FALSE);
@@ -900,7 +791,7 @@ win32_process_target::resume (thread_resume *resume_info, size_t n)
   else
     /* Yes, we're ignoring resume_info[0].thread.  It'd be tricky to make
        the Windows resume code do the right thing for thread switching.  */
-    tid = current_event.dwThreadId;
+    tid = windows_process.current_event.dwThreadId;
 
   if (resume_info[0].thread != minus_one_ptid)
     {
@@ -915,30 +806,31 @@ win32_process_target::resume (thread_resume *resume_info, size_t n)
 
   if (sig != GDB_SIGNAL_0)
     {
-      if (current_event.dwDebugEventCode != EXCEPTION_DEBUG_EVENT)
+      if (windows_process.current_event.dwDebugEventCode
+         != EXCEPTION_DEBUG_EVENT)
        {
          OUTMSG (("Cannot continue with signal %s here.\n",
                   gdb_signal_to_string (sig)));
        }
-      else if (sig == last_sig)
+      else if (sig == windows_process.last_sig)
        continue_status = DBG_EXCEPTION_NOT_HANDLED;
       else
        OUTMSG (("Can only continue with received signal %s.\n",
-                gdb_signal_to_string (last_sig)));
+                gdb_signal_to_string (windows_process.last_sig)));
     }
 
-  last_sig = GDB_SIGNAL_0;
+  windows_process.last_sig = GDB_SIGNAL_0;
 
   /* Get context for the currently selected thread.  */
-  ptid = debug_event_ptid (&current_event);
-  th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
+  ptid = debug_event_ptid (&windows_process.current_event);
+  th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
   if (th)
     {
       win32_prepare_to_resume (th);
 
       DWORD *context_flags;
 #ifdef __x86_64__
-      if (wow64_process)
+      if (windows_process.wow64_process)
        context_flags = &th->wow64_context.ContextFlags;
       else
 #endif
@@ -969,9 +861,13 @@ win32_process_target::resume (thread_resume *resume_info, size_t n)
   child_continue (continue_status, tid);
 }
 
-static void
-win32_add_one_solib (const char *name, CORE_ADDR load_addr)
+/* See nat/windows-nat.h.  */
+
+void
+gdbserver_windows_process::handle_load_dll (const char *name, LPVOID base)
 {
+  CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) base;
+
   char buf[MAX_PATH + 1];
   char buf2[MAX_PATH + 1];
 
@@ -1019,227 +915,10 @@ win32_add_one_solib (const char *name, CORE_ADDR load_addr)
   loaded_dll (buf2, load_addr);
 }
 
-typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
-                                                 DWORD, LPDWORD);
-#ifdef __x86_64__
-typedef BOOL (WINAPI *winapi_EnumProcessModulesEx) (HANDLE, HMODULE *, DWORD,
-                                                   LPDWORD, DWORD);
-#endif
-typedef BOOL (WINAPI *winapi_GetModuleInformation) (HANDLE, HMODULE,
-                                                   LPMODULEINFO, DWORD);
-typedef DWORD (WINAPI *winapi_GetModuleFileNameExA) (HANDLE, HMODULE,
-                                                    LPSTR, DWORD);
-
-static winapi_EnumProcessModules win32_EnumProcessModules;
-#ifdef __x86_64__
-static winapi_EnumProcessModulesEx win32_EnumProcessModulesEx;
-#endif
-static winapi_GetModuleInformation win32_GetModuleInformation;
-static winapi_GetModuleFileNameExA win32_GetModuleFileNameExA;
-
-static BOOL
-load_psapi (void)
-{
-  static int psapi_loaded = 0;
-  static HMODULE dll = NULL;
-
-  if (!psapi_loaded)
-    {
-      psapi_loaded = 1;
-      dll = LoadLibrary (TEXT("psapi.dll"));
-      if (!dll)
-       return FALSE;
-      win32_EnumProcessModules =
-             GETPROCADDRESS (dll, EnumProcessModules);
-#ifdef __x86_64__
-      win32_EnumProcessModulesEx =
-             GETPROCADDRESS (dll, EnumProcessModulesEx);
-#endif
-      win32_GetModuleInformation =
-             GETPROCADDRESS (dll, GetModuleInformation);
-      win32_GetModuleFileNameExA =
-             GETPROCADDRESS (dll, GetModuleFileNameExA);
-    }
-
-#ifdef __x86_64__
-  if (wow64_process && win32_EnumProcessModulesEx == nullptr)
-    return FALSE;
-#endif
-
-  return (win32_EnumProcessModules != NULL
-         && win32_GetModuleInformation != NULL
-         && win32_GetModuleFileNameExA != NULL);
-}
-
-/* Iterate over all DLLs currently mapped by our inferior, looking for
-   a DLL loaded at LOAD_ADDR; if found, return its file name,
-   otherwise return NULL.  If LOAD_ADDR is NULL, add all mapped DLLs
-   to our list of solibs.  */
-
-static char *
-win32_add_dll (LPVOID load_addr)
-{
-  size_t i;
-  HMODULE dh_buf[1];
-  HMODULE *DllHandle = dh_buf;
-  DWORD cbNeeded;
-  BOOL ok;
-
-  if (!load_psapi ())
-    return NULL;
-
-  cbNeeded = 0;
-#ifdef __x86_64__
-  if (wow64_process)
-    ok = (*win32_EnumProcessModulesEx) (current_process_handle,
-                                       DllHandle,
-                                       sizeof (HMODULE),
-                                       &cbNeeded,
-                                       LIST_MODULES_32BIT);
-  else
-#endif
-    ok = (*win32_EnumProcessModules) (current_process_handle,
-                                     DllHandle,
-                                     sizeof (HMODULE),
-                                     &cbNeeded);
-
-  if (!ok || !cbNeeded)
-    return NULL;
-
-  DllHandle = (HMODULE *) alloca (cbNeeded);
-  if (!DllHandle)
-    return NULL;
-
-#ifdef __x86_64__
-  if (wow64_process)
-    ok = (*win32_EnumProcessModulesEx) (current_process_handle,
-                                       DllHandle,
-                                       cbNeeded,
-                                       &cbNeeded,
-                                       LIST_MODULES_32BIT);
-  else
-#endif
-    ok = (*win32_EnumProcessModules) (current_process_handle,
-                                     DllHandle,
-                                     cbNeeded,
-                                     &cbNeeded);
-  if (!ok)
-    return NULL;
-
-  char system_dir[MAX_PATH];
-  char syswow_dir[MAX_PATH];
-  size_t system_dir_len = 0;
-  bool convert_syswow_dir = false;
-#ifdef __x86_64__
-  if (wow64_process)
-#endif
-    {
-      /* This fails on 32bit Windows because it has no SysWOW64 directory,
-        and in this case a path conversion isn't necessary.  */
-      UINT len = GetSystemWow64DirectoryA (syswow_dir, sizeof (syswow_dir));
-      if (len > 0)
-       {
-         /* Check that we have passed a large enough buffer.  */
-         gdb_assert (len < sizeof (syswow_dir));
-
-         len = GetSystemDirectoryA (system_dir, sizeof (system_dir));
-         /* Error check.  */
-         gdb_assert (len != 0);
-         /* Check that we have passed a large enough buffer.  */
-         gdb_assert (len < sizeof (system_dir));
-
-         strcat (system_dir, "\\");
-         strcat (syswow_dir, "\\");
-         system_dir_len = strlen (system_dir);
-
-         convert_syswow_dir = true;
-       }
-
-    }
-
-  for (i = 1; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
-    {
-      MODULEINFO mi;
-      static char dll_name[MAX_PATH];
-
-      if (!(*win32_GetModuleInformation) (current_process_handle,
-                                         DllHandle[i],
-                                         &mi,
-                                         sizeof (mi)))
-       continue;
-      if ((*win32_GetModuleFileNameExA) (current_process_handle,
-                                        DllHandle[i],
-                                        dll_name,
-                                        MAX_PATH) == 0)
-       continue;
-
-      if (load_addr != nullptr && mi.lpBaseOfDll != load_addr)
-       continue;
-
-      const char *name = dll_name;
-      /* Convert the DLL path of 32bit processes returned by
-        GetModuleFileNameEx from the 64bit system directory to the
-        32bit syswow64 directory if necessary.  */
-      std::string syswow_dll_path;
-      if (convert_syswow_dir
-         && strncasecmp (dll_name, system_dir, system_dir_len) == 0
-         && strchr (dll_name + system_dir_len, '\\') == nullptr)
-       {
-         syswow_dll_path = syswow_dir;
-         syswow_dll_path += dll_name + system_dir_len;
-         name = syswow_dll_path.c_str();
-       }
-
-      if (load_addr != nullptr)
-       {
-         if (name != dll_name)
-           strcpy (dll_name, name);
-         return dll_name;
-       }
-      else
-       win32_add_one_solib (name, (CORE_ADDR) (uintptr_t) mi.lpBaseOfDll);
-    }
-  return NULL;
-}
-
-/* Iterate over all DLLs currently mapped by our inferior, and
-   add them to our list of solibs.  */
-
-static void
-win32_add_all_dlls (void)
-{
-  win32_add_dll (NULL);
-}
-
-typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
-typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
-typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
-
 /* See nat/windows-nat.h.  */
 
 void
-windows_nat::handle_load_dll ()
-{
-  LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
-  const char *dll_name;
-
-  dll_name = get_image_name (current_process_handle,
-                            event->lpImageName, event->fUnicode);
-#ifndef _WIN32_WCE
-  if (dll_name == nullptr
-      && event->lpBaseOfDll != nullptr)
-    dll_name = win32_add_dll (event->lpBaseOfDll);
-#endif
-  if (dll_name == nullptr)
-    return;
-
-  win32_add_one_solib (dll_name, (CORE_ADDR) (uintptr_t) event->lpBaseOfDll);
-}
-
-/* See nat/windows-nat.h.  */
-
-void
-windows_nat::handle_unload_dll ()
+gdbserver_windows_process::handle_unload_dll ()
 {
   CORE_ADDR load_addr =
          (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
@@ -1264,12 +943,13 @@ fake_breakpoint_event (void)
 {
   OUTMSG2(("fake_breakpoint_event\n"));
 
-  faked_breakpoint = 1;
+  windows_process.faked_breakpoint = 1;
 
-  memset (&current_event, 0, sizeof (current_event));
-  current_event.dwThreadId = main_thread_id;
-  current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
-  current_event.u.Exception.ExceptionRecord.ExceptionCode
+  memset (&windows_process.current_event, 0,
+         sizeof (windows_process.current_event));
+  windows_process.current_event.dwThreadId = windows_process.main_thread_id;
+  windows_process.current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
+  windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
     = EXCEPTION_BREAKPOINT;
 
   for_each_thread (suspend_one_thread);
@@ -1278,15 +958,8 @@ fake_breakpoint_event (void)
 /* See nat/windows-nat.h.  */
 
 bool
-windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
-{
-  return false;
-}
-
-/* See nat/windows-nat.h.  */
-
-bool
-windows_nat::handle_access_violation (const EXCEPTION_RECORD *rec)
+gdbserver_windows_process::handle_access_violation
+     (const EXCEPTION_RECORD *rec)
 {
   return false;
 }
@@ -1301,16 +974,17 @@ maybe_adjust_pc ()
   struct regcache *regcache = get_thread_regcache (current_thread, 1);
   child_fetch_inferior_registers (regcache, -1);
 
-  windows_thread_info *th = thread_rec (current_thread_ptid (),
-                                       DONT_INVALIDATE_CONTEXT);
+  windows_thread_info *th
+    = windows_process.thread_rec (current_thread_ptid (),
+                                 DONT_INVALIDATE_CONTEXT);
   th->stopped_at_software_breakpoint = false;
 
-  if (current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
-      && ((current_event.u.Exception.ExceptionRecord.ExceptionCode
+  if (windows_process.current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
+      && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
           == EXCEPTION_BREAKPOINT)
-         || (current_event.u.Exception.ExceptionRecord.ExceptionCode
+         || (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
              == STATUS_WX86_BREAKPOINT))
-      && child_initialization_done)
+      && windows_process.child_initialization_done)
     {
       th->stopped_at_software_breakpoint = true;
       CORE_ADDR pc = regcache_read_pc (regcache);
@@ -1327,36 +1001,39 @@ get_child_debug_event (DWORD *continue_status,
 {
   ptid_t ptid;
 
-  last_sig = GDB_SIGNAL_0;
-  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+  windows_process.last_sig = GDB_SIGNAL_0;
+  ourstatus->set_spurious ();
   *continue_status = DBG_CONTINUE;
 
   /* Check if GDB sent us an interrupt request.  */
   check_remote_input_interrupt_request ();
 
-  if (soft_interrupt_requested)
+  DEBUG_EVENT *current_event = &windows_process.current_event;
+
+  if (windows_process.soft_interrupt_requested)
     {
-      soft_interrupt_requested = 0;
+      windows_process.soft_interrupt_requested = 0;
       fake_breakpoint_event ();
       goto gotevent;
     }
 
-  attaching = 0;
+  windows_process.attaching = 0;
   {
-    gdb::optional<pending_stop> stop = fetch_pending_stop (debug_threads);
+    gdb::optional<pending_stop> stop
+      = windows_process.fetch_pending_stop (debug_threads);
     if (stop.has_value ())
       {
        *ourstatus = stop->status;
-       current_event = stop->event;
-       ptid = debug_event_ptid (&current_event);
-       current_thread = find_thread_ptid (ptid);
+       windows_process.current_event = stop->event;
+       ptid = debug_event_ptid (&windows_process.current_event);
+       switch_to_thread (find_thread_ptid (ptid));
        return 1;
       }
 
     /* Keep the wait time low enough for comfortable remote
        interruption, but high enough so gdbserver doesn't become a
        bottleneck.  */
-    if (!wait_for_debug_event (&current_event, 250))
+    if (!wait_for_debug_event (&windows_process.current_event, 250))
       {
        DWORD e  = GetLastError();
 
@@ -1366,8 +1043,7 @@ get_child_debug_event (DWORD *continue_status,
               load the application, e.g., if the main executable
               tries to pull in a non-existing export from a
               DLL.  */
-           ourstatus->kind = TARGET_WAITKIND_EXITED;
-           ourstatus->value.integer = 1;
+           ourstatus->set_exited (1);
            return 1;
          }
 
@@ -1377,113 +1053,105 @@ get_child_debug_event (DWORD *continue_status,
 
  gotevent:
 
-  switch (current_event.dwDebugEventCode)
+  switch (current_event->dwDebugEventCode)
     {
     case CREATE_THREAD_DEBUG_EVENT:
       OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
                "for pid=%u tid=%x)\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
 
       /* Record the existence of this thread.  */
-      child_add_thread (current_event.dwProcessId,
-                       current_event.dwThreadId,
-                       current_event.u.CreateThread.hThread,
-                       current_event.u.CreateThread.lpThreadLocalBase);
+      child_add_thread (current_event->dwProcessId,
+                       current_event->dwThreadId,
+                       current_event->u.CreateThread.hThread,
+                       current_event->u.CreateThread.lpThreadLocalBase);
       break;
 
     case EXIT_THREAD_DEBUG_EVENT:
       OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
                "for pid=%u tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      child_delete_thread (current_event.dwProcessId,
-                          current_event.dwThreadId);
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
+      child_delete_thread (current_event->dwProcessId,
+                          current_event->dwThreadId);
 
-      current_thread = get_first_thread ();
+      switch_to_thread (get_first_thread ());
       return 1;
 
     case CREATE_PROCESS_DEBUG_EVENT:
       OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
                "for pid=%u tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      CloseHandle (current_event.u.CreateProcessInfo.hFile);
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
+      CloseHandle (current_event->u.CreateProcessInfo.hFile);
 
-      if (open_process_used)
+      if (windows_process.open_process_used)
        {
-         CloseHandle (current_process_handle);
-         open_process_used = false;
+         CloseHandle (windows_process.handle);
+         windows_process.open_process_used = false;
        }
 
-      current_process_handle = current_event.u.CreateProcessInfo.hProcess;
-      main_thread_id = current_event.dwThreadId;
+      windows_process.handle = current_event->u.CreateProcessInfo.hProcess;
+      windows_process.main_thread_id = current_event->dwThreadId;
 
       /* Add the main thread.  */
-      child_add_thread (current_event.dwProcessId,
-                       main_thread_id,
-                       current_event.u.CreateProcessInfo.hThread,
-                       current_event.u.CreateProcessInfo.lpThreadLocalBase);
+      child_add_thread (current_event->dwProcessId,
+                       windows_process.main_thread_id,
+                       current_event->u.CreateProcessInfo.hThread,
+                       current_event->u.CreateProcessInfo.lpThreadLocalBase);
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
       OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
                "for pid=%u tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
       {
-       DWORD exit_status = current_event.u.ExitProcess.dwExitCode;
+       DWORD exit_status = current_event->u.ExitProcess.dwExitCode;
        /* If the exit status looks like a fatal exception, but we
           don't recognize the exception's code, make the original
           exit status value available, to avoid losing information.  */
        int exit_signal
          = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
        if (exit_signal == -1)
-         {
-           ourstatus->kind = TARGET_WAITKIND_EXITED;
-           ourstatus->value.integer = exit_status;
-         }
+         ourstatus->set_exited (exit_status);
        else
-         {
-           ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
-           ourstatus->value.sig = gdb_signal_from_host (exit_signal);
-         }
+         ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
       }
-      child_continue (DBG_CONTINUE, desired_stop_thread_id);
+      child_continue (DBG_CONTINUE, windows_process.desired_stop_thread_id);
       break;
 
     case LOAD_DLL_DEBUG_EVENT:
       OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
                "for pid=%u tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      CloseHandle (current_event.u.LoadDll.hFile);
-      if (! child_initialization_done)
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
+      CloseHandle (current_event->u.LoadDll.hFile);
+      if (! windows_process.child_initialization_done)
        break;
-      handle_load_dll ();
+      windows_process.dll_loaded_event ();
 
-      ourstatus->kind = TARGET_WAITKIND_LOADED;
-      ourstatus->value.sig = GDB_SIGNAL_TRAP;
+      ourstatus->set_loaded ();
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
       OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
                "for pid=%u tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      if (! child_initialization_done)
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
+      if (! windows_process.child_initialization_done)
        break;
-      handle_unload_dll ();
-      ourstatus->kind = TARGET_WAITKIND_LOADED;
-      ourstatus->value.sig = GDB_SIGNAL_TRAP;
+      windows_process.handle_unload_dll ();
+      ourstatus->set_loaded ();
       break;
 
     case EXCEPTION_DEBUG_EVENT:
       OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
                "for pid=%u tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      if (handle_exception (ourstatus, debug_threads)
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
+      if (windows_process.handle_exception (ourstatus, debug_threads)
          == HANDLE_EXCEPTION_UNHANDLED)
        *continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
@@ -1492,35 +1160,37 @@ get_child_debug_event (DWORD *continue_status,
       /* A message from the kernel (or Cygwin).  */
       OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
                "for pid=%u tid=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId));
-      handle_output_debug_string (nullptr);
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId));
+      windows_process.handle_output_debug_string (nullptr);
       break;
 
     default:
       OUTMSG2 (("gdbserver: kernel event unknown "
                "for pid=%u tid=%x code=%x\n",
-               (unsigned) current_event.dwProcessId,
-               (unsigned) current_event.dwThreadId,
-               (unsigned) current_event.dwDebugEventCode));
+               (unsigned) current_event->dwProcessId,
+               (unsigned) current_event->dwThreadId,
+               (unsigned) current_event->dwDebugEventCode));
       break;
     }
 
-  ptid = debug_event_ptid (&current_event);
+  ptid = debug_event_ptid (&windows_process.current_event);
 
-  if (desired_stop_thread_id != -1 && desired_stop_thread_id != ptid.lwp ())
+  if (windows_process.desired_stop_thread_id != -1
+      && windows_process.desired_stop_thread_id != ptid.lwp ())
     {
       /* Pending stop.  See the comment by the definition of
         "pending_stops" for details on why this is needed.  */
       OUTMSG2 (("get_windows_debug_event - "
                "unexpected stop in 0x%lx (expecting 0x%x)\n",
-               ptid.lwp (), desired_stop_thread_id));
+               ptid.lwp (), windows_process.desired_stop_thread_id));
       maybe_adjust_pc ();
-      pending_stops.push_back ({(DWORD) ptid.lwp (), *ourstatus, current_event});
-      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+      windows_process.pending_stops.push_back
+       ({(DWORD) ptid.lwp (), *ourstatus, *current_event});
+      ourstatus->set_spurious ();
     }
   else
-    current_thread = find_thread_ptid (ptid);
+    switch_to_thread (find_thread_ptid (ptid));
 
   return 1;
 }
@@ -1532,15 +1202,15 @@ ptid_t
 win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
                            target_wait_flags options)
 {
-  if (cached_status.kind != TARGET_WAITKIND_IGNORE)
+  if (windows_process.cached_status.kind () != TARGET_WAITKIND_IGNORE)
     {
       /* The core always does a wait after creating the inferior, and
         do_initial_child_stuff already ran the inferior to the
         initial breakpoint (or an exit, if creating the process
         fails).  Report it now.  */
-      *ourstatus = cached_status;
-      cached_status.kind = TARGET_WAITKIND_IGNORE;
-      return debug_event_ptid (&current_event);
+      *ourstatus = windows_process.cached_status;
+      windows_process.cached_status.set_ignore ();
+      return debug_event_ptid (&windows_process.current_event);
     }
 
   while (1)
@@ -1549,28 +1219,30 @@ win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
       if (!get_child_debug_event (&continue_status, ourstatus))
        continue;
 
-      switch (ourstatus->kind)
+      switch (ourstatus->kind ())
        {
        case TARGET_WAITKIND_EXITED:
          OUTMSG2 (("Child exited with retcode = %x\n",
-                   ourstatus->value.integer));
+                   ourstatus->exit_status ()));
          win32_clear_inferiors ();
-         return ptid_t (current_event.dwProcessId);
+         return ptid_t (windows_process.current_event.dwProcessId);
        case TARGET_WAITKIND_STOPPED:
        case TARGET_WAITKIND_SIGNALLED:
        case TARGET_WAITKIND_LOADED:
          {
            OUTMSG2 (("Child Stopped with signal = %d \n",
-                     ourstatus->value.sig));
+                     ourstatus->sig ()));
            maybe_adjust_pc ();
-           return debug_event_ptid (&current_event);
+           return debug_event_ptid (&windows_process.current_event);
          }
        default:
-         OUTMSG (("Ignoring unknown internal event, %d\n", ourstatus->kind));
+         OUTMSG (("Ignoring unknown internal event, %d\n",
+                 ourstatus->kind ()));
          /* fall-through */
        case TARGET_WAITKIND_SPURIOUS:
          /* do nothing, just continue */
-         child_continue (continue_status, desired_stop_thread_id);
+         child_continue (continue_status,
+                         windows_process.desired_stop_thread_id);
          break;
        }
     }
@@ -1617,15 +1289,7 @@ win32_process_target::write_memory (CORE_ADDR memaddr,
 void
 win32_process_target::request_interrupt ()
 {
-  winapi_DebugBreakProcess DebugBreakProcess;
-  winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
-
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-
-  GenerateConsoleCtrlEvent = GETPROCADDRESS (dll, GenerateConsoleCtrlEvent);
-
-  if (GenerateConsoleCtrlEvent != NULL
-      && GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, current_process_id))
+  if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, signal_pid))
     return;
 
   /* GenerateConsoleCtrlEvent can fail if process id being debugged is
@@ -1633,14 +1297,11 @@ win32_process_target::request_interrupt ()
      Fallback to XP/Vista 'DebugBreakProcess', which generates a
      breakpoint exception in the interior process.  */
 
-  DebugBreakProcess = GETPROCADDRESS (dll, DebugBreakProcess);
-
-  if (DebugBreakProcess != NULL
-      && DebugBreakProcess (current_process_handle))
+  if (DebugBreakProcess (windows_process.handle))
     return;
 
   /* Last resort, suspend all threads manually.  */
-  soft_interrupt_requested = 1;
+  windows_process.soft_interrupt_requested = 1;
 }
 
 bool
@@ -1663,30 +1324,33 @@ win32_process_target::qxfer_siginfo (const char *annex,
                                     unsigned const char *writebuf,
                                     CORE_ADDR offset, int len)
 {
-  if (siginfo_er.ExceptionCode == 0)
+  if (windows_process.siginfo_er.ExceptionCode == 0)
     return -1;
 
   if (readbuf == nullptr)
     return -1;
 
-  char *buf = (char *) &siginfo_er;
-  size_t bufsize = sizeof (siginfo_er);
+  char *buf = (char *) &windows_process.siginfo_er;
+  size_t bufsize = sizeof (windows_process.siginfo_er);
 
 #ifdef __x86_64__
   EXCEPTION_RECORD32 er32;
-  if (wow64_process)
+  if (windows_process.wow64_process)
     {
       buf = (char *) &er32;
       bufsize = sizeof (er32);
 
-      er32.ExceptionCode = siginfo_er.ExceptionCode;
-      er32.ExceptionFlags = siginfo_er.ExceptionFlags;
-      er32.ExceptionRecord = (uintptr_t) siginfo_er.ExceptionRecord;
-      er32.ExceptionAddress = (uintptr_t) siginfo_er.ExceptionAddress;
-      er32.NumberParameters = siginfo_er.NumberParameters;
+      er32.ExceptionCode = windows_process.siginfo_er.ExceptionCode;
+      er32.ExceptionFlags = windows_process.siginfo_er.ExceptionFlags;
+      er32.ExceptionRecord
+       = (uintptr_t) windows_process.siginfo_er.ExceptionRecord;
+      er32.ExceptionAddress
+       = (uintptr_t) windows_process.siginfo_er.ExceptionAddress;
+      er32.NumberParameters = windows_process.siginfo_er.NumberParameters;
       int i;
       for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
-       er32.ExceptionInformation[i] = siginfo_er.ExceptionInformation[i];
+       er32.ExceptionInformation[i]
+         = windows_process.siginfo_er.ExceptionInformation[i];
     }
 #endif
 
@@ -1713,7 +1377,7 @@ int
 win32_process_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
 {
   windows_thread_info *th;
-  th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
+  th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
   if (th == NULL)
     return 0;
   if (addr != NULL)
@@ -1733,8 +1397,9 @@ win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
 bool
 win32_process_target::stopped_by_sw_breakpoint ()
 {
-  windows_thread_info *th = thread_rec (current_thread_ptid (),
-                                       DONT_INVALIDATE_CONTEXT);
+  windows_thread_info *th
+    = windows_process.thread_rec (current_thread_ptid (),
+                                 DONT_INVALIDATE_CONTEXT);
   return th == nullptr ? false : th->stopped_at_software_breakpoint;
 }
 
@@ -1756,6 +1421,21 @@ win32_process_target::write_pc (struct regcache *regcache, CORE_ADDR pc)
   return (*the_low_target.set_pc) (regcache, pc);
 }
 
+const char *
+win32_process_target::thread_name (ptid_t thread)
+{
+  windows_thread_info *th
+    = windows_process.thread_rec (current_thread_ptid (),
+                                 DONT_INVALIDATE_CONTEXT);
+  return th->thread_name ();
+}
+
+const char *
+win32_process_target::pid_to_exec_file (int pid)
+{
+  return windows_process.pid_to_exec_file (pid);
+}
+
 /* The win32 target ops object.  */
 
 static win32_process_target the_win32_target;
@@ -1767,11 +1447,5 @@ initialize_low (void)
   set_target_ops (&the_win32_target);
   the_low_target.arch_setup ();
 
-#ifdef __x86_64__
-  /* These functions are loaded dynamically, because they are not available
-     on Windows XP.  */
-  HMODULE dll = GetModuleHandle (_T("KERNEL32.DLL"));
-  win32_Wow64GetThreadContext = GETPROCADDRESS (dll, Wow64GetThreadContext);
-  win32_Wow64SetThreadContext = GETPROCADDRESS (dll, Wow64SetThreadContext);
-#endif
+  initialize_loadable ();
 }