xref: /netbsd-src/external/gpl3/gdb/dist/gdbserver/win32-low.cc (revision 13ed34fa5696ce1ff8e9519eeb5619eee4331db8)
18dffb485Schristos /* Low level interface to Windows debugging, for gdbserver.
2*13ed34faSchristos    Copyright (C) 2006-2024 Free Software Foundation, Inc.
38dffb485Schristos 
48dffb485Schristos    Contributed by Leo Zayas.  Based on "win32-nat.c" from GDB.
58dffb485Schristos 
68dffb485Schristos    This file is part of GDB.
78dffb485Schristos 
88dffb485Schristos    This program is free software; you can redistribute it and/or modify
98dffb485Schristos    it under the terms of the GNU General Public License as published by
108dffb485Schristos    the Free Software Foundation; either version 3 of the License, or
118dffb485Schristos    (at your option) any later version.
128dffb485Schristos 
138dffb485Schristos    This program is distributed in the hope that it will be useful,
148dffb485Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
158dffb485Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
168dffb485Schristos    GNU General Public License for more details.
178dffb485Schristos 
188dffb485Schristos    You should have received a copy of the GNU General Public License
198dffb485Schristos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
208dffb485Schristos 
218dffb485Schristos #include "regcache.h"
224b169a6bSchristos #include "gdbsupport/fileio.h"
238dffb485Schristos #include "mem-break.h"
248dffb485Schristos #include "win32-low.h"
258dffb485Schristos #include "gdbthread.h"
268dffb485Schristos #include "dll.h"
278dffb485Schristos #include "hostio.h"
288dffb485Schristos #include <windows.h>
298dffb485Schristos #include <winnt.h>
308dffb485Schristos #include <imagehlp.h>
318dffb485Schristos #include <tlhelp32.h>
328dffb485Schristos #include <psapi.h>
338dffb485Schristos #include <process.h>
348dffb485Schristos #include "gdbsupport/gdb_tilde_expand.h"
358dffb485Schristos #include "gdbsupport/common-inferior.h"
368dffb485Schristos #include "gdbsupport/gdb_wait.h"
378dffb485Schristos 
388dffb485Schristos using namespace windows_nat;
398dffb485Schristos 
404b169a6bSchristos /* See win32-low.h.  */
414b169a6bSchristos gdbserver_windows_process windows_process;
424b169a6bSchristos 
438dffb485Schristos #ifndef USE_WIN32API
448dffb485Schristos #include <sys/cygwin.h>
458dffb485Schristos #endif
468dffb485Schristos 
478dffb485Schristos #define OUTMSG(X) do { printf X; fflush (stderr); } while (0)
488dffb485Schristos 
498dffb485Schristos #define OUTMSG2(X) \
508dffb485Schristos   do						\
518dffb485Schristos     {						\
528dffb485Schristos       if (debug_threads)			\
538dffb485Schristos 	{					\
548dffb485Schristos 	  printf X;				\
558dffb485Schristos 	  fflush (stderr);			\
568dffb485Schristos 	}					\
578dffb485Schristos     } while (0)
588dffb485Schristos 
598dffb485Schristos #ifndef _T
608dffb485Schristos #define _T(x) TEXT (x)
618dffb485Schristos #endif
628dffb485Schristos 
638dffb485Schristos int using_threads = 1;
648dffb485Schristos 
658dffb485Schristos const struct target_desc *win32_tdesc;
668dffb485Schristos #ifdef __x86_64__
678dffb485Schristos const struct target_desc *wow64_win32_tdesc;
688dffb485Schristos #endif
698dffb485Schristos 
708dffb485Schristos #define NUM_REGS (the_low_target.num_regs ())
718dffb485Schristos 
728dffb485Schristos /* Get the thread ID from the current selected inferior (the current
738dffb485Schristos    thread).  */
748dffb485Schristos static ptid_t
758dffb485Schristos current_thread_ptid (void)
768dffb485Schristos {
778dffb485Schristos   return current_ptid;
788dffb485Schristos }
798dffb485Schristos 
808dffb485Schristos /* The current debug event from WaitForDebugEvent.  */
818dffb485Schristos static ptid_t
828dffb485Schristos debug_event_ptid (DEBUG_EVENT *event)
838dffb485Schristos {
848dffb485Schristos   return ptid_t (event->dwProcessId, event->dwThreadId, 0);
858dffb485Schristos }
868dffb485Schristos 
878dffb485Schristos /* Get the thread context of the thread associated with TH.  */
888dffb485Schristos 
898dffb485Schristos static void
908dffb485Schristos win32_get_thread_context (windows_thread_info *th)
918dffb485Schristos {
928dffb485Schristos #ifdef __x86_64__
934b169a6bSchristos   if (windows_process.wow64_process)
948dffb485Schristos     memset (&th->wow64_context, 0, sizeof (WOW64_CONTEXT));
958dffb485Schristos   else
968dffb485Schristos #endif
978dffb485Schristos     memset (&th->context, 0, sizeof (CONTEXT));
988dffb485Schristos   (*the_low_target.get_thread_context) (th);
998dffb485Schristos }
1008dffb485Schristos 
1018dffb485Schristos /* Set the thread context of the thread associated with TH.  */
1028dffb485Schristos 
1038dffb485Schristos static void
1048dffb485Schristos win32_set_thread_context (windows_thread_info *th)
1058dffb485Schristos {
1068dffb485Schristos #ifdef __x86_64__
1074b169a6bSchristos   if (windows_process.wow64_process)
1084b169a6bSchristos     Wow64SetThreadContext (th->h, &th->wow64_context);
1098dffb485Schristos   else
1108dffb485Schristos #endif
1118dffb485Schristos     SetThreadContext (th->h, &th->context);
1128dffb485Schristos }
1138dffb485Schristos 
1148dffb485Schristos /* Set the thread context of the thread associated with TH.  */
1158dffb485Schristos 
1168dffb485Schristos static void
1178dffb485Schristos win32_prepare_to_resume (windows_thread_info *th)
1188dffb485Schristos {
1198dffb485Schristos   if (the_low_target.prepare_to_resume != NULL)
1208dffb485Schristos     (*the_low_target.prepare_to_resume) (th);
1218dffb485Schristos }
1228dffb485Schristos 
1238dffb485Schristos /* See win32-low.h.  */
1248dffb485Schristos 
1258dffb485Schristos void
1268dffb485Schristos win32_require_context (windows_thread_info *th)
1278dffb485Schristos {
1288dffb485Schristos   DWORD context_flags;
1298dffb485Schristos #ifdef __x86_64__
1304b169a6bSchristos   if (windows_process.wow64_process)
1318dffb485Schristos     context_flags = th->wow64_context.ContextFlags;
1328dffb485Schristos   else
1338dffb485Schristos #endif
1348dffb485Schristos     context_flags = th->context.ContextFlags;
1358dffb485Schristos   if (context_flags == 0)
1368dffb485Schristos     {
1378dffb485Schristos       th->suspend ();
1388dffb485Schristos       win32_get_thread_context (th);
1398dffb485Schristos     }
1408dffb485Schristos }
1418dffb485Schristos 
1428dffb485Schristos /* See nat/windows-nat.h.  */
1438dffb485Schristos 
1448dffb485Schristos windows_thread_info *
1454b169a6bSchristos gdbserver_windows_process::thread_rec
1464b169a6bSchristos      (ptid_t ptid, thread_disposition_type disposition)
1478dffb485Schristos {
1488dffb485Schristos   thread_info *thread = find_thread_ptid (ptid);
1498dffb485Schristos   if (thread == NULL)
1508dffb485Schristos     return NULL;
1518dffb485Schristos 
1528dffb485Schristos   windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
1538dffb485Schristos   if (disposition != DONT_INVALIDATE_CONTEXT)
1548dffb485Schristos     win32_require_context (th);
1558dffb485Schristos   return th;
1568dffb485Schristos }
1578dffb485Schristos 
1588dffb485Schristos /* Add a thread to the thread list.  */
1598dffb485Schristos static windows_thread_info *
1608dffb485Schristos child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
1618dffb485Schristos {
1628dffb485Schristos   windows_thread_info *th;
1638dffb485Schristos   ptid_t ptid = ptid_t (pid, tid, 0);
1648dffb485Schristos 
1654b169a6bSchristos   if ((th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
1668dffb485Schristos     return th;
1678dffb485Schristos 
1688dffb485Schristos   CORE_ADDR base = (CORE_ADDR) (uintptr_t) tlb;
1698dffb485Schristos #ifdef __x86_64__
1708dffb485Schristos   /* For WOW64 processes, this is actually the pointer to the 64bit TIB,
1718dffb485Schristos      and the 32bit TIB is exactly 2 pages after it.  */
1724b169a6bSchristos   if (windows_process.wow64_process)
1738dffb485Schristos     base += 2 * 4096; /* page size = 4096 */
1748dffb485Schristos #endif
1758dffb485Schristos   th = new windows_thread_info (tid, h, base);
1768dffb485Schristos 
1778dffb485Schristos   add_thread (ptid, th);
1788dffb485Schristos 
1798dffb485Schristos   if (the_low_target.thread_added != NULL)
1808dffb485Schristos     (*the_low_target.thread_added) (th);
1818dffb485Schristos 
1828dffb485Schristos   return th;
1838dffb485Schristos }
1848dffb485Schristos 
1858dffb485Schristos /* Delete a thread from the list of threads.  */
1868dffb485Schristos static void
1878dffb485Schristos delete_thread_info (thread_info *thread)
1888dffb485Schristos {
1898dffb485Schristos   windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
1908dffb485Schristos 
1918dffb485Schristos   remove_thread (thread);
1928dffb485Schristos   delete th;
1938dffb485Schristos }
1948dffb485Schristos 
1958dffb485Schristos /* Delete a thread from the list of threads.  */
1968dffb485Schristos static void
1978dffb485Schristos child_delete_thread (DWORD pid, DWORD tid)
1988dffb485Schristos {
1998dffb485Schristos   /* If the last thread is exiting, just return.  */
2008dffb485Schristos   if (all_threads.size () == 1)
2018dffb485Schristos     return;
2028dffb485Schristos 
2038dffb485Schristos   thread_info *thread = find_thread_ptid (ptid_t (pid, tid));
2048dffb485Schristos   if (thread == NULL)
2058dffb485Schristos     return;
2068dffb485Schristos 
2078dffb485Schristos   delete_thread_info (thread);
2088dffb485Schristos }
2098dffb485Schristos 
2108dffb485Schristos /* These watchpoint related wrapper functions simply pass on the function call
2118dffb485Schristos    if the low target has registered a corresponding function.  */
2128dffb485Schristos 
2138dffb485Schristos bool
2148dffb485Schristos win32_process_target::supports_z_point_type (char z_type)
2158dffb485Schristos {
2168dffb485Schristos   return (z_type == Z_PACKET_SW_BP
2178dffb485Schristos 	  || (the_low_target.supports_z_point_type != NULL
2188dffb485Schristos 	      && the_low_target.supports_z_point_type (z_type)));
2198dffb485Schristos }
2208dffb485Schristos 
2218dffb485Schristos int
2228dffb485Schristos win32_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
2238dffb485Schristos 				    int size, raw_breakpoint *bp)
2248dffb485Schristos {
2258dffb485Schristos   if (type == raw_bkpt_type_sw)
2268dffb485Schristos     return insert_memory_breakpoint (bp);
2278dffb485Schristos   else if (the_low_target.insert_point != NULL)
2288dffb485Schristos     return the_low_target.insert_point (type, addr, size, bp);
2298dffb485Schristos   else
2308dffb485Schristos     /* Unsupported (see target.h).  */
2318dffb485Schristos     return 1;
2328dffb485Schristos }
2338dffb485Schristos 
2348dffb485Schristos int
2358dffb485Schristos win32_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
2368dffb485Schristos 				    int size, raw_breakpoint *bp)
2378dffb485Schristos {
2388dffb485Schristos   if (type == raw_bkpt_type_sw)
2398dffb485Schristos     return remove_memory_breakpoint (bp);
2408dffb485Schristos   else if (the_low_target.remove_point != NULL)
2418dffb485Schristos     return the_low_target.remove_point (type, addr, size, bp);
2428dffb485Schristos   else
2438dffb485Schristos     /* Unsupported (see target.h).  */
2448dffb485Schristos     return 1;
2458dffb485Schristos }
2468dffb485Schristos 
2478dffb485Schristos bool
2488dffb485Schristos win32_process_target::stopped_by_watchpoint ()
2498dffb485Schristos {
2508dffb485Schristos   if (the_low_target.stopped_by_watchpoint != NULL)
2518dffb485Schristos     return the_low_target.stopped_by_watchpoint ();
2528dffb485Schristos   else
2538dffb485Schristos     return false;
2548dffb485Schristos }
2558dffb485Schristos 
2568dffb485Schristos CORE_ADDR
2578dffb485Schristos win32_process_target::stopped_data_address ()
2588dffb485Schristos {
2598dffb485Schristos   if (the_low_target.stopped_data_address != NULL)
2608dffb485Schristos     return the_low_target.stopped_data_address ();
2618dffb485Schristos   else
2628dffb485Schristos     return 0;
2638dffb485Schristos }
2648dffb485Schristos 
2658dffb485Schristos 
2668dffb485Schristos /* Transfer memory from/to the debugged process.  */
2678dffb485Schristos static int
2688dffb485Schristos child_xfer_memory (CORE_ADDR memaddr, char *our, int len,
2698dffb485Schristos 		   int write, process_stratum_target *target)
2708dffb485Schristos {
2718dffb485Schristos   BOOL success;
2728dffb485Schristos   SIZE_T done = 0;
2738dffb485Schristos   DWORD lasterror = 0;
2748dffb485Schristos   uintptr_t addr = (uintptr_t) memaddr;
2758dffb485Schristos 
2768dffb485Schristos   if (write)
2778dffb485Schristos     {
2784b169a6bSchristos       success = WriteProcessMemory (windows_process.handle, (LPVOID) addr,
2798dffb485Schristos 				    (LPCVOID) our, len, &done);
2808dffb485Schristos       if (!success)
2818dffb485Schristos 	lasterror = GetLastError ();
2824b169a6bSchristos       FlushInstructionCache (windows_process.handle, (LPCVOID) addr, len);
2838dffb485Schristos     }
2848dffb485Schristos   else
2858dffb485Schristos     {
2864b169a6bSchristos       success = ReadProcessMemory (windows_process.handle, (LPCVOID) addr,
2878dffb485Schristos 				   (LPVOID) our, len, &done);
2888dffb485Schristos       if (!success)
2898dffb485Schristos 	lasterror = GetLastError ();
2908dffb485Schristos     }
2918dffb485Schristos   if (!success && lasterror == ERROR_PARTIAL_COPY && done > 0)
2928dffb485Schristos     return done;
2938dffb485Schristos   else
2948dffb485Schristos     return success ? done : -1;
2958dffb485Schristos }
2968dffb485Schristos 
2978dffb485Schristos /* Clear out any old thread list and reinitialize it to a pristine
2988dffb485Schristos    state. */
2998dffb485Schristos static void
3008dffb485Schristos child_init_thread_list (void)
3018dffb485Schristos {
3028dffb485Schristos   for_each_thread (delete_thread_info);
3038dffb485Schristos }
3048dffb485Schristos 
3058dffb485Schristos static void
3068dffb485Schristos do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
3078dffb485Schristos {
3088dffb485Schristos   struct process_info *proc;
3098dffb485Schristos 
3104b169a6bSchristos   windows_process.last_sig = GDB_SIGNAL_0;
3114b169a6bSchristos   windows_process.handle = proch;
3124b169a6bSchristos   windows_process.main_thread_id = 0;
3138dffb485Schristos 
3144b169a6bSchristos   windows_process.soft_interrupt_requested = 0;
3154b169a6bSchristos   windows_process.faked_breakpoint = 0;
3164b169a6bSchristos   windows_process.open_process_used = true;
3178dffb485Schristos 
3184b169a6bSchristos   memset (&windows_process.current_event, 0,
3194b169a6bSchristos 	  sizeof (windows_process.current_event));
3208dffb485Schristos 
3218dffb485Schristos #ifdef __x86_64__
3228dffb485Schristos   BOOL wow64;
3238dffb485Schristos   if (!IsWow64Process (proch, &wow64))
3248dffb485Schristos     {
3258dffb485Schristos       DWORD err = GetLastError ();
326*13ed34faSchristos       throw_winerror_with_name ("Check if WOW64 process failed", err);
3278dffb485Schristos     }
3284b169a6bSchristos   windows_process.wow64_process = wow64;
3298dffb485Schristos 
3304b169a6bSchristos   if (windows_process.wow64_process
3314b169a6bSchristos       && (Wow64GetThreadContext == nullptr
3324b169a6bSchristos 	  || Wow64SetThreadContext == nullptr))
3338dffb485Schristos     error ("WOW64 debugging is not supported on this system.\n");
3348dffb485Schristos 
3354b169a6bSchristos   windows_process.ignore_first_breakpoint
3364b169a6bSchristos     = !attached && windows_process.wow64_process;
3378dffb485Schristos #endif
3388dffb485Schristos 
3398dffb485Schristos   proc = add_process (pid, attached);
3408dffb485Schristos #ifdef __x86_64__
3414b169a6bSchristos   if (windows_process.wow64_process)
3428dffb485Schristos     proc->tdesc = wow64_win32_tdesc;
3438dffb485Schristos   else
3448dffb485Schristos #endif
3458dffb485Schristos     proc->tdesc = win32_tdesc;
3468dffb485Schristos   child_init_thread_list ();
3474b169a6bSchristos   windows_process.child_initialization_done = 0;
3488dffb485Schristos 
3498dffb485Schristos   if (the_low_target.initial_stuff != NULL)
3508dffb485Schristos     (*the_low_target.initial_stuff) ();
3518dffb485Schristos 
3524b169a6bSchristos   windows_process.cached_status.set_ignore ();
3538dffb485Schristos 
3548dffb485Schristos   /* Flush all currently pending debug events (thread and dll list) up
3558dffb485Schristos      to the initial breakpoint.  */
3568dffb485Schristos   while (1)
3578dffb485Schristos     {
3588dffb485Schristos       struct target_waitstatus status;
3598dffb485Schristos 
3608dffb485Schristos       the_target->wait (minus_one_ptid, &status, 0);
3618dffb485Schristos 
3628dffb485Schristos       /* Note win32_wait doesn't return thread events.  */
3634b169a6bSchristos       if (status.kind () != TARGET_WAITKIND_LOADED)
3648dffb485Schristos 	{
3654b169a6bSchristos 	  windows_process.cached_status = status;
3668dffb485Schristos 	  break;
3678dffb485Schristos 	}
3688dffb485Schristos 
3698dffb485Schristos       {
3708dffb485Schristos 	struct thread_resume resume;
3718dffb485Schristos 
3728dffb485Schristos 	resume.thread = minus_one_ptid;
3738dffb485Schristos 	resume.kind = resume_continue;
3748dffb485Schristos 	resume.sig = 0;
3758dffb485Schristos 
3768dffb485Schristos 	the_target->resume (&resume, 1);
3778dffb485Schristos       }
3788dffb485Schristos     }
3798dffb485Schristos 
3808dffb485Schristos   /* Now that the inferior has been started and all DLLs have been mapped,
3818dffb485Schristos      we can iterate over all DLLs and load them in.
3828dffb485Schristos 
3838dffb485Schristos      We avoid doing it any earlier because, on certain versions of Windows,
3848dffb485Schristos      LOAD_DLL_DEBUG_EVENTs are sometimes not complete.  In particular,
3858dffb485Schristos      we have seen on Windows 8.1 that the ntdll.dll load event does not
3868dffb485Schristos      include the DLL name, preventing us from creating an associated SO.
3878dffb485Schristos      A possible explanation is that ntdll.dll might be mapped before
3888dffb485Schristos      the SO info gets created by the Windows system -- ntdll.dll is
3898dffb485Schristos      the first DLL to be reported via LOAD_DLL_DEBUG_EVENT and other DLLs
3908dffb485Schristos      do not seem to suffer from that problem.
3918dffb485Schristos 
3928dffb485Schristos      Rather than try to work around this sort of issue, it is much
3938dffb485Schristos      simpler to just ignore DLL load/unload events during the startup
3948dffb485Schristos      phase, and then process them all in one batch now.  */
3954b169a6bSchristos   windows_process.add_all_dlls ();
3968dffb485Schristos 
3974b169a6bSchristos   windows_process.child_initialization_done = 1;
3988dffb485Schristos }
3998dffb485Schristos 
4008dffb485Schristos /* Resume all artificially suspended threads if we are continuing
4018dffb485Schristos    execution.  */
4028dffb485Schristos static void
4038dffb485Schristos continue_one_thread (thread_info *thread, int thread_id)
4048dffb485Schristos {
4058dffb485Schristos   windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
4068dffb485Schristos 
4078dffb485Schristos   if (thread_id == -1 || thread_id == th->tid)
4088dffb485Schristos     {
4098dffb485Schristos       win32_prepare_to_resume (th);
4108dffb485Schristos 
4118dffb485Schristos       if (th->suspended)
4128dffb485Schristos 	{
4138dffb485Schristos 	  DWORD *context_flags;
4148dffb485Schristos #ifdef __x86_64__
4154b169a6bSchristos 	  if (windows_process.wow64_process)
4168dffb485Schristos 	    context_flags = &th->wow64_context.ContextFlags;
4178dffb485Schristos 	  else
4188dffb485Schristos #endif
4198dffb485Schristos 	    context_flags = &th->context.ContextFlags;
4208dffb485Schristos 	  if (*context_flags)
4218dffb485Schristos 	    {
4228dffb485Schristos 	      win32_set_thread_context (th);
4238dffb485Schristos 	      *context_flags = 0;
4248dffb485Schristos 	    }
4258dffb485Schristos 
4268dffb485Schristos 	  th->resume ();
4278dffb485Schristos 	}
4288dffb485Schristos     }
4298dffb485Schristos }
4308dffb485Schristos 
4318dffb485Schristos static BOOL
4328dffb485Schristos child_continue (DWORD continue_status, int thread_id)
4338dffb485Schristos {
4344b169a6bSchristos   windows_process.desired_stop_thread_id = thread_id;
4354b169a6bSchristos   if (windows_process.matching_pending_stop (debug_threads))
4368dffb485Schristos     return TRUE;
4378dffb485Schristos 
4388dffb485Schristos   /* The inferior will only continue after the ContinueDebugEvent
4398dffb485Schristos      call.  */
4408dffb485Schristos   for_each_thread ([&] (thread_info *thread)
4418dffb485Schristos     {
4428dffb485Schristos       continue_one_thread (thread, thread_id);
4438dffb485Schristos     });
4444b169a6bSchristos   windows_process.faked_breakpoint = 0;
4458dffb485Schristos 
4468dffb485Schristos   return continue_last_debug_event (continue_status, debug_threads);
4478dffb485Schristos }
4488dffb485Schristos 
4498dffb485Schristos /* Fetch register(s) from the current thread context.  */
4508dffb485Schristos static void
4518dffb485Schristos child_fetch_inferior_registers (struct regcache *regcache, int r)
4528dffb485Schristos {
4538dffb485Schristos   int regno;
4544b169a6bSchristos   windows_thread_info *th
4554b169a6bSchristos     = windows_process.thread_rec (current_thread_ptid (),
4568dffb485Schristos 				  INVALIDATE_CONTEXT);
4578dffb485Schristos   if (r == -1 || r > NUM_REGS)
4588dffb485Schristos     child_fetch_inferior_registers (regcache, NUM_REGS);
4598dffb485Schristos   else
4608dffb485Schristos     for (regno = 0; regno < r; regno++)
4618dffb485Schristos       (*the_low_target.fetch_inferior_register) (regcache, th, regno);
4628dffb485Schristos }
4638dffb485Schristos 
4648dffb485Schristos /* Store a new register value into the current thread context.  We don't
4658dffb485Schristos    change the program's context until later, when we resume it.  */
4668dffb485Schristos static void
4678dffb485Schristos child_store_inferior_registers (struct regcache *regcache, int r)
4688dffb485Schristos {
4698dffb485Schristos   int regno;
4704b169a6bSchristos   windows_thread_info *th
4714b169a6bSchristos     = windows_process.thread_rec (current_thread_ptid (),
4728dffb485Schristos 				  INVALIDATE_CONTEXT);
4738dffb485Schristos   if (r == -1 || r == 0 || r > NUM_REGS)
4748dffb485Schristos     child_store_inferior_registers (regcache, NUM_REGS);
4758dffb485Schristos   else
4768dffb485Schristos     for (regno = 0; regno < r; regno++)
4778dffb485Schristos       (*the_low_target.store_inferior_register) (regcache, th, regno);
4788dffb485Schristos }
4798dffb485Schristos 
4808dffb485Schristos static BOOL
4818dffb485Schristos create_process (const char *program, char *args,
4828dffb485Schristos 		DWORD flags, PROCESS_INFORMATION *pi)
4838dffb485Schristos {
4844b169a6bSchristos   const std::string &inferior_cwd = get_inferior_cwd ();
4858dffb485Schristos   BOOL ret;
4868dffb485Schristos   size_t argslen, proglen;
4878dffb485Schristos 
4888dffb485Schristos   proglen = strlen (program) + 1;
4898dffb485Schristos   argslen = strlen (args) + proglen;
4908dffb485Schristos 
4918dffb485Schristos   STARTUPINFOA si = { sizeof (STARTUPINFOA) };
4928dffb485Schristos   char *program_and_args = (char *) alloca (argslen + 1);
4938dffb485Schristos 
4948dffb485Schristos   strcpy (program_and_args, program);
4958dffb485Schristos   strcat (program_and_args, " ");
4968dffb485Schristos   strcat (program_and_args, args);
4974b169a6bSchristos   ret = create_process (program,           /* image name */
4988dffb485Schristos 			program_and_args,  /* command line */
4998dffb485Schristos 			flags,             /* start flags */
5008dffb485Schristos 			NULL,              /* environment */
5018dffb485Schristos 			/* current directory */
5024b169a6bSchristos 			(inferior_cwd.empty ()
5038dffb485Schristos 			 ? NULL
5044b169a6bSchristos 			 : gdb_tilde_expand (inferior_cwd.c_str ()).c_str()),
5054b169a6bSchristos 			get_client_state ().disable_randomization,
5068dffb485Schristos 			&si,               /* start info */
5078dffb485Schristos 			pi);               /* proc info */
5088dffb485Schristos 
5098dffb485Schristos   return ret;
5108dffb485Schristos }
5118dffb485Schristos 
5128dffb485Schristos /* Start a new process.
5138dffb485Schristos    PROGRAM is the program name.
5148dffb485Schristos    PROGRAM_ARGS is the vector containing the inferior's args.
5158dffb485Schristos    Returns the new PID on success, -1 on failure.  Registers the new
5168dffb485Schristos    process with the process list.  */
5178dffb485Schristos int
5188dffb485Schristos win32_process_target::create_inferior (const char *program,
5198dffb485Schristos 				       const std::vector<char *> &program_args)
5208dffb485Schristos {
5218dffb485Schristos   client_state &cs = get_client_state ();
5228dffb485Schristos #ifndef USE_WIN32API
5238dffb485Schristos   char real_path[PATH_MAX];
5248dffb485Schristos   char *orig_path, *new_path, *path_ptr;
5258dffb485Schristos #endif
5268dffb485Schristos   BOOL ret;
5278dffb485Schristos   DWORD flags;
5288dffb485Schristos   PROCESS_INFORMATION pi;
5298dffb485Schristos   DWORD err;
5308dffb485Schristos   std::string str_program_args = construct_inferior_arguments (program_args);
5318dffb485Schristos   char *args = (char *) str_program_args.c_str ();
5328dffb485Schristos 
5338dffb485Schristos   /* win32_wait needs to know we're not attaching.  */
5344b169a6bSchristos   windows_process.attaching = 0;
5358dffb485Schristos 
5368dffb485Schristos   if (!program)
5378dffb485Schristos     error ("No executable specified, specify executable to debug.\n");
5388dffb485Schristos 
5398dffb485Schristos   flags = DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS;
5408dffb485Schristos 
5418dffb485Schristos #ifndef USE_WIN32API
5428dffb485Schristos   orig_path = NULL;
5438dffb485Schristos   path_ptr = getenv ("PATH");
5448dffb485Schristos   if (path_ptr)
5458dffb485Schristos     {
5468dffb485Schristos       int size = cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, NULL, 0);
5478dffb485Schristos       orig_path = (char *) alloca (strlen (path_ptr) + 1);
5488dffb485Schristos       new_path = (char *) alloca (size);
5498dffb485Schristos       strcpy (orig_path, path_ptr);
5508dffb485Schristos       cygwin_conv_path_list (CCP_POSIX_TO_WIN_A, path_ptr, new_path, size);
5518dffb485Schristos       setenv ("PATH", new_path, 1);
5528dffb485Schristos      }
5538dffb485Schristos   cygwin_conv_path (CCP_POSIX_TO_WIN_A, program, real_path, PATH_MAX);
5548dffb485Schristos   program = real_path;
5558dffb485Schristos #endif
5568dffb485Schristos 
5578dffb485Schristos   OUTMSG2 (("Command line is \"%s %s\"\n", program, args));
5588dffb485Schristos 
5598dffb485Schristos #ifdef CREATE_NEW_PROCESS_GROUP
5608dffb485Schristos   flags |= CREATE_NEW_PROCESS_GROUP;
5618dffb485Schristos #endif
5628dffb485Schristos 
5638dffb485Schristos   ret = create_process (program, args, flags, &pi);
5648dffb485Schristos   err = GetLastError ();
5658dffb485Schristos   if (!ret && err == ERROR_FILE_NOT_FOUND)
5668dffb485Schristos     {
5678dffb485Schristos       char *exename = (char *) alloca (strlen (program) + 5);
5688dffb485Schristos       strcat (strcpy (exename, program), ".exe");
5698dffb485Schristos       ret = create_process (exename, args, flags, &pi);
5708dffb485Schristos       err = GetLastError ();
5718dffb485Schristos     }
5728dffb485Schristos 
5738dffb485Schristos #ifndef USE_WIN32API
5748dffb485Schristos   if (orig_path)
5758dffb485Schristos     setenv ("PATH", orig_path, 1);
5768dffb485Schristos #endif
5778dffb485Schristos 
5788dffb485Schristos   if (!ret)
5798dffb485Schristos     {
580*13ed34faSchristos       std::string msg = string_printf (_("Error creating process \"%s %s\""),
581*13ed34faSchristos 				       program, args);
582*13ed34faSchristos       throw_winerror_with_name (msg.c_str (), err);
5838dffb485Schristos     }
5848dffb485Schristos   else
5858dffb485Schristos     {
5868dffb485Schristos       OUTMSG2 (("Process created: %s %s\n", program, (char *) args));
5878dffb485Schristos     }
5888dffb485Schristos 
5898dffb485Schristos   CloseHandle (pi.hThread);
5908dffb485Schristos 
5918dffb485Schristos   do_initial_child_stuff (pi.hProcess, pi.dwProcessId, 0);
5928dffb485Schristos 
5938dffb485Schristos   /* Wait till we are at 1st instruction in program, return new pid
5948dffb485Schristos      (assuming success).  */
5954b169a6bSchristos   cs.last_ptid = wait (ptid_t (pi.dwProcessId), &cs.last_status, 0);
5968dffb485Schristos 
5978dffb485Schristos   /* Necessary for handle_v_kill.  */
5984b169a6bSchristos   signal_pid = pi.dwProcessId;
5998dffb485Schristos 
6004b169a6bSchristos   return pi.dwProcessId;
6018dffb485Schristos }
6028dffb485Schristos 
6038dffb485Schristos /* Attach to a running process.
6048dffb485Schristos    PID is the process ID to attach to, specified by the user
6058dffb485Schristos    or a higher layer.  */
6068dffb485Schristos int
6078dffb485Schristos win32_process_target::attach (unsigned long pid)
6088dffb485Schristos {
6098dffb485Schristos   HANDLE h;
6108dffb485Schristos   DWORD err;
6118dffb485Schristos 
6128dffb485Schristos   h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
6138dffb485Schristos   if (h != NULL)
6148dffb485Schristos     {
6158dffb485Schristos       if (DebugActiveProcess (pid))
6168dffb485Schristos 	{
6178dffb485Schristos 	  DebugSetProcessKillOnExit (FALSE);
6188dffb485Schristos 
6198dffb485Schristos 	  /* win32_wait needs to know we're attaching.  */
6204b169a6bSchristos 	  windows_process.attaching = 1;
6218dffb485Schristos 	  do_initial_child_stuff (h, pid, 1);
6228dffb485Schristos 	  return 0;
6238dffb485Schristos 	}
6248dffb485Schristos 
6258dffb485Schristos       CloseHandle (h);
6268dffb485Schristos     }
6278dffb485Schristos 
6288dffb485Schristos   err = GetLastError ();
629*13ed34faSchristos   throw_winerror_with_name ("Attach to process failed", err);
6308dffb485Schristos }
6318dffb485Schristos 
6328dffb485Schristos /* See nat/windows-nat.h.  */
6338dffb485Schristos 
6348dffb485Schristos int
6354b169a6bSchristos gdbserver_windows_process::handle_output_debug_string
6364b169a6bSchristos      (struct target_waitstatus *ourstatus)
6378dffb485Schristos {
6388dffb485Schristos #define READ_BUFFER_LEN 1024
6398dffb485Schristos   CORE_ADDR addr;
6408dffb485Schristos   char s[READ_BUFFER_LEN + 1] = { 0 };
6418dffb485Schristos   DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
6428dffb485Schristos 
6438dffb485Schristos   if (nbytes == 0)
6448dffb485Schristos     return 0;
6458dffb485Schristos 
6468dffb485Schristos   if (nbytes > READ_BUFFER_LEN)
6478dffb485Schristos     nbytes = READ_BUFFER_LEN;
6488dffb485Schristos 
6498dffb485Schristos   addr = (CORE_ADDR) (size_t) current_event.u.DebugString.lpDebugStringData;
6508dffb485Schristos 
6518dffb485Schristos   if (current_event.u.DebugString.fUnicode)
6528dffb485Schristos     {
6538dffb485Schristos       /* The event tells us how many bytes, not chars, even
6548dffb485Schristos 	 in Unicode.  */
6558dffb485Schristos       WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
6568dffb485Schristos       if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
6578dffb485Schristos 	return 0;
6588dffb485Schristos       wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
6598dffb485Schristos     }
6608dffb485Schristos   else
6618dffb485Schristos     {
6628dffb485Schristos       if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
6638dffb485Schristos 	return 0;
6648dffb485Schristos     }
6658dffb485Schristos 
6668dffb485Schristos   if (!startswith (s, "cYg"))
6678dffb485Schristos     {
6688dffb485Schristos       if (!server_waiting)
6698dffb485Schristos 	{
6708dffb485Schristos 	  OUTMSG2(("%s", s));
6718dffb485Schristos 	  return 0;
6728dffb485Schristos 	}
6738dffb485Schristos 
6748dffb485Schristos       monitor_output (s);
6758dffb485Schristos     }
6768dffb485Schristos #undef READ_BUFFER_LEN
6778dffb485Schristos 
6788dffb485Schristos   return 0;
6798dffb485Schristos }
6808dffb485Schristos 
6818dffb485Schristos static void
6828dffb485Schristos win32_clear_inferiors (void)
6838dffb485Schristos {
6844b169a6bSchristos   if (windows_process.open_process_used)
6858dffb485Schristos     {
6864b169a6bSchristos       CloseHandle (windows_process.handle);
6874b169a6bSchristos       windows_process.open_process_used = false;
6888dffb485Schristos     }
6898dffb485Schristos 
6908dffb485Schristos   for_each_thread (delete_thread_info);
6914b169a6bSchristos   windows_process.siginfo_er.ExceptionCode = 0;
6928dffb485Schristos   clear_inferiors ();
6938dffb485Schristos }
6948dffb485Schristos 
6958dffb485Schristos /* Implementation of target_ops::kill.  */
6968dffb485Schristos 
6978dffb485Schristos int
6988dffb485Schristos win32_process_target::kill (process_info *process)
6998dffb485Schristos {
7004b169a6bSchristos   TerminateProcess (windows_process.handle, 0);
7018dffb485Schristos   for (;;)
7028dffb485Schristos     {
7038dffb485Schristos       if (!child_continue (DBG_CONTINUE, -1))
7048dffb485Schristos 	break;
7054b169a6bSchristos       if (!wait_for_debug_event (&windows_process.current_event, INFINITE))
7068dffb485Schristos 	break;
7074b169a6bSchristos       if (windows_process.current_event.dwDebugEventCode
7084b169a6bSchristos 	  == EXIT_PROCESS_DEBUG_EVENT)
7098dffb485Schristos 	break;
7104b169a6bSchristos       else if (windows_process.current_event.dwDebugEventCode
7114b169a6bSchristos 	       == OUTPUT_DEBUG_STRING_EVENT)
7124b169a6bSchristos 	windows_process.handle_output_debug_string (nullptr);
7138dffb485Schristos     }
7148dffb485Schristos 
7158dffb485Schristos   win32_clear_inferiors ();
7168dffb485Schristos 
7178dffb485Schristos   remove_process (process);
7188dffb485Schristos   return 0;
7198dffb485Schristos }
7208dffb485Schristos 
7218dffb485Schristos /* Implementation of target_ops::detach.  */
7228dffb485Schristos 
7238dffb485Schristos int
7248dffb485Schristos win32_process_target::detach (process_info *process)
7258dffb485Schristos {
7268dffb485Schristos   struct thread_resume resume;
7278dffb485Schristos   resume.thread = minus_one_ptid;
7288dffb485Schristos   resume.kind = resume_continue;
7298dffb485Schristos   resume.sig = 0;
7308dffb485Schristos   this->resume (&resume, 1);
7318dffb485Schristos 
7324b169a6bSchristos   if (!DebugActiveProcessStop (process->pid))
7338dffb485Schristos     return -1;
7348dffb485Schristos 
7358dffb485Schristos   DebugSetProcessKillOnExit (FALSE);
736*13ed34faSchristos   win32_clear_inferiors ();
7378dffb485Schristos   remove_process (process);
7388dffb485Schristos 
7398dffb485Schristos   return 0;
7408dffb485Schristos }
7418dffb485Schristos 
7428dffb485Schristos void
7438dffb485Schristos win32_process_target::mourn (struct process_info *process)
7448dffb485Schristos {
7458dffb485Schristos   remove_process (process);
7468dffb485Schristos }
7478dffb485Schristos 
7488dffb485Schristos /* Implementation of target_ops::join.  */
7498dffb485Schristos 
7508dffb485Schristos void
7518dffb485Schristos win32_process_target::join (int pid)
7528dffb485Schristos {
7538dffb485Schristos   HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
7548dffb485Schristos   if (h != NULL)
7558dffb485Schristos     {
7568dffb485Schristos       WaitForSingleObject (h, INFINITE);
7578dffb485Schristos       CloseHandle (h);
7588dffb485Schristos     }
7598dffb485Schristos }
7608dffb485Schristos 
7618dffb485Schristos /* Return true iff the thread with thread ID TID is alive.  */
7628dffb485Schristos bool
7638dffb485Schristos win32_process_target::thread_alive (ptid_t ptid)
7648dffb485Schristos {
7658dffb485Schristos   /* Our thread list is reliable; don't bother to poll target
7668dffb485Schristos      threads.  */
7678dffb485Schristos   return find_thread_ptid (ptid) != NULL;
7688dffb485Schristos }
7698dffb485Schristos 
7708dffb485Schristos /* Resume the inferior process.  RESUME_INFO describes how we want
7718dffb485Schristos    to resume.  */
7728dffb485Schristos void
7738dffb485Schristos win32_process_target::resume (thread_resume *resume_info, size_t n)
7748dffb485Schristos {
7758dffb485Schristos   DWORD tid;
7768dffb485Schristos   enum gdb_signal sig;
7778dffb485Schristos   int step;
7788dffb485Schristos   windows_thread_info *th;
7798dffb485Schristos   DWORD continue_status = DBG_CONTINUE;
7808dffb485Schristos   ptid_t ptid;
7818dffb485Schristos 
7828dffb485Schristos   /* This handles the very limited set of resume packets that GDB can
7838dffb485Schristos      currently produce.  */
7848dffb485Schristos 
7858dffb485Schristos   if (n == 1 && resume_info[0].thread == minus_one_ptid)
7868dffb485Schristos     tid = -1;
7878dffb485Schristos   else if (n > 1)
7888dffb485Schristos     tid = -1;
7898dffb485Schristos   else
7908dffb485Schristos     /* Yes, we're ignoring resume_info[0].thread.  It'd be tricky to make
7918dffb485Schristos        the Windows resume code do the right thing for thread switching.  */
7924b169a6bSchristos     tid = windows_process.current_event.dwThreadId;
7938dffb485Schristos 
7948dffb485Schristos   if (resume_info[0].thread != minus_one_ptid)
7958dffb485Schristos     {
7968dffb485Schristos       sig = gdb_signal_from_host (resume_info[0].sig);
7978dffb485Schristos       step = resume_info[0].kind == resume_step;
7988dffb485Schristos     }
7998dffb485Schristos   else
8008dffb485Schristos     {
8018dffb485Schristos       sig = GDB_SIGNAL_0;
8028dffb485Schristos       step = 0;
8038dffb485Schristos     }
8048dffb485Schristos 
8058dffb485Schristos   if (sig != GDB_SIGNAL_0)
8068dffb485Schristos     {
8074b169a6bSchristos       if (windows_process.current_event.dwDebugEventCode
8084b169a6bSchristos 	  != EXCEPTION_DEBUG_EVENT)
8098dffb485Schristos 	{
8108dffb485Schristos 	  OUTMSG (("Cannot continue with signal %s here.\n",
8118dffb485Schristos 		   gdb_signal_to_string (sig)));
8128dffb485Schristos 	}
8134b169a6bSchristos       else if (sig == windows_process.last_sig)
8148dffb485Schristos 	continue_status = DBG_EXCEPTION_NOT_HANDLED;
8158dffb485Schristos       else
8168dffb485Schristos 	OUTMSG (("Can only continue with received signal %s.\n",
8174b169a6bSchristos 		 gdb_signal_to_string (windows_process.last_sig)));
8188dffb485Schristos     }
8198dffb485Schristos 
8204b169a6bSchristos   windows_process.last_sig = GDB_SIGNAL_0;
8218dffb485Schristos 
8228dffb485Schristos   /* Get context for the currently selected thread.  */
8234b169a6bSchristos   ptid = debug_event_ptid (&windows_process.current_event);
8244b169a6bSchristos   th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
8258dffb485Schristos   if (th)
8268dffb485Schristos     {
8278dffb485Schristos       win32_prepare_to_resume (th);
8288dffb485Schristos 
8298dffb485Schristos       DWORD *context_flags;
8308dffb485Schristos #ifdef __x86_64__
8314b169a6bSchristos       if (windows_process.wow64_process)
8328dffb485Schristos 	context_flags = &th->wow64_context.ContextFlags;
8338dffb485Schristos       else
8348dffb485Schristos #endif
8358dffb485Schristos 	context_flags = &th->context.ContextFlags;
8368dffb485Schristos       if (*context_flags)
8378dffb485Schristos 	{
8388dffb485Schristos 	  /* Move register values from the inferior into the thread
8398dffb485Schristos 	     context structure.  */
8408dffb485Schristos 	  regcache_invalidate ();
8418dffb485Schristos 
8428dffb485Schristos 	  if (step)
8438dffb485Schristos 	    {
8448dffb485Schristos 	      if (the_low_target.single_step != NULL)
8458dffb485Schristos 		(*the_low_target.single_step) (th);
8468dffb485Schristos 	      else
8478dffb485Schristos 		error ("Single stepping is not supported "
8488dffb485Schristos 		       "in this configuration.\n");
8498dffb485Schristos 	    }
8508dffb485Schristos 
8518dffb485Schristos 	  win32_set_thread_context (th);
8528dffb485Schristos 	  *context_flags = 0;
8538dffb485Schristos 	}
8548dffb485Schristos     }
8558dffb485Schristos 
8568dffb485Schristos   /* Allow continuing with the same signal that interrupted us.
8578dffb485Schristos      Otherwise complain.  */
8588dffb485Schristos 
8598dffb485Schristos   child_continue (continue_status, tid);
8608dffb485Schristos }
8618dffb485Schristos 
8624b169a6bSchristos /* See nat/windows-nat.h.  */
8634b169a6bSchristos 
8644b169a6bSchristos void
8654b169a6bSchristos gdbserver_windows_process::handle_load_dll (const char *name, LPVOID base)
8668dffb485Schristos {
8674b169a6bSchristos   CORE_ADDR load_addr = (CORE_ADDR) (uintptr_t) base;
8684b169a6bSchristos 
8698dffb485Schristos   char buf[MAX_PATH + 1];
8708dffb485Schristos   char buf2[MAX_PATH + 1];
8718dffb485Schristos 
8728dffb485Schristos   WIN32_FIND_DATAA w32_fd;
8738dffb485Schristos   HANDLE h = FindFirstFileA (name, &w32_fd);
8748dffb485Schristos 
8758dffb485Schristos   /* The symbols in a dll are offset by 0x1000, which is the
8768dffb485Schristos      offset from 0 of the first byte in an image - because
8778dffb485Schristos      of the file header and the section alignment. */
8788dffb485Schristos   load_addr += 0x1000;
8798dffb485Schristos 
8808dffb485Schristos   if (h == INVALID_HANDLE_VALUE)
8818dffb485Schristos     strcpy (buf, name);
8828dffb485Schristos   else
8838dffb485Schristos     {
8848dffb485Schristos       FindClose (h);
8858dffb485Schristos       strcpy (buf, name);
8868dffb485Schristos       {
8878dffb485Schristos 	char cwd[MAX_PATH + 1];
8888dffb485Schristos 	char *p;
8898dffb485Schristos 	if (GetCurrentDirectoryA (MAX_PATH + 1, cwd))
8908dffb485Schristos 	  {
8918dffb485Schristos 	    p = strrchr (buf, '\\');
8928dffb485Schristos 	    if (p)
8938dffb485Schristos 	      p[1] = '\0';
8948dffb485Schristos 	    SetCurrentDirectoryA (buf);
8958dffb485Schristos 	    GetFullPathNameA (w32_fd.cFileName, MAX_PATH, buf, &p);
8968dffb485Schristos 	    SetCurrentDirectoryA (cwd);
8978dffb485Schristos 	  }
8988dffb485Schristos       }
8998dffb485Schristos     }
9008dffb485Schristos 
9018dffb485Schristos   if (strcasecmp (buf, "ntdll.dll") == 0)
9028dffb485Schristos     {
9038dffb485Schristos       GetSystemDirectoryA (buf, sizeof (buf));
9048dffb485Schristos       strcat (buf, "\\ntdll.dll");
9058dffb485Schristos     }
9068dffb485Schristos 
9078dffb485Schristos #ifdef __CYGWIN__
9088dffb485Schristos   cygwin_conv_path (CCP_WIN_A_TO_POSIX, buf, buf2, sizeof (buf2));
9098dffb485Schristos #else
9108dffb485Schristos   strcpy (buf2, buf);
9118dffb485Schristos #endif
9128dffb485Schristos 
9138dffb485Schristos   loaded_dll (buf2, load_addr);
9148dffb485Schristos }
9158dffb485Schristos 
9168dffb485Schristos /* See nat/windows-nat.h.  */
9178dffb485Schristos 
9188dffb485Schristos void
9194b169a6bSchristos gdbserver_windows_process::handle_unload_dll ()
9208dffb485Schristos {
9218dffb485Schristos   CORE_ADDR load_addr =
9228dffb485Schristos 	  (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
9238dffb485Schristos 
9248dffb485Schristos   /* The symbols in a dll are offset by 0x1000, which is the
9258dffb485Schristos      offset from 0 of the first byte in an image - because
9268dffb485Schristos      of the file header and the section alignment. */
9278dffb485Schristos   load_addr += 0x1000;
9288dffb485Schristos   unloaded_dll (NULL, load_addr);
9298dffb485Schristos }
9308dffb485Schristos 
9318dffb485Schristos static void
9328dffb485Schristos suspend_one_thread (thread_info *thread)
9338dffb485Schristos {
9348dffb485Schristos   windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
9358dffb485Schristos 
9368dffb485Schristos   th->suspend ();
9378dffb485Schristos }
9388dffb485Schristos 
9398dffb485Schristos static void
9408dffb485Schristos fake_breakpoint_event (void)
9418dffb485Schristos {
9428dffb485Schristos   OUTMSG2(("fake_breakpoint_event\n"));
9438dffb485Schristos 
9444b169a6bSchristos   windows_process.faked_breakpoint = 1;
9458dffb485Schristos 
9464b169a6bSchristos   memset (&windows_process.current_event, 0,
9474b169a6bSchristos 	  sizeof (windows_process.current_event));
9484b169a6bSchristos   windows_process.current_event.dwThreadId = windows_process.main_thread_id;
9494b169a6bSchristos   windows_process.current_event.dwDebugEventCode = EXCEPTION_DEBUG_EVENT;
9504b169a6bSchristos   windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
9518dffb485Schristos     = EXCEPTION_BREAKPOINT;
9528dffb485Schristos 
9538dffb485Schristos   for_each_thread (suspend_one_thread);
9548dffb485Schristos }
9558dffb485Schristos 
9568dffb485Schristos /* See nat/windows-nat.h.  */
9578dffb485Schristos 
9588dffb485Schristos bool
9594b169a6bSchristos gdbserver_windows_process::handle_access_violation
9604b169a6bSchristos      (const EXCEPTION_RECORD *rec)
9618dffb485Schristos {
9628dffb485Schristos   return false;
9638dffb485Schristos }
9648dffb485Schristos 
9658dffb485Schristos /* A helper function that will, if needed, set
9668dffb485Schristos    'stopped_at_software_breakpoint' on the thread and adjust the
9678dffb485Schristos    PC.  */
9688dffb485Schristos 
9698dffb485Schristos static void
9708dffb485Schristos maybe_adjust_pc ()
9718dffb485Schristos {
9728dffb485Schristos   struct regcache *regcache = get_thread_regcache (current_thread, 1);
9738dffb485Schristos   child_fetch_inferior_registers (regcache, -1);
9748dffb485Schristos 
9754b169a6bSchristos   windows_thread_info *th
9764b169a6bSchristos     = windows_process.thread_rec (current_thread_ptid (),
9778dffb485Schristos 				  DONT_INVALIDATE_CONTEXT);
9788dffb485Schristos   th->stopped_at_software_breakpoint = false;
9798dffb485Schristos 
9804b169a6bSchristos   if (windows_process.current_event.dwDebugEventCode == EXCEPTION_DEBUG_EVENT
9814b169a6bSchristos       && ((windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
9828dffb485Schristos 	   == EXCEPTION_BREAKPOINT)
9834b169a6bSchristos 	  || (windows_process.current_event.u.Exception.ExceptionRecord.ExceptionCode
9848dffb485Schristos 	      == STATUS_WX86_BREAKPOINT))
9854b169a6bSchristos       && windows_process.child_initialization_done)
9868dffb485Schristos     {
9878dffb485Schristos       th->stopped_at_software_breakpoint = true;
9888dffb485Schristos       CORE_ADDR pc = regcache_read_pc (regcache);
9898dffb485Schristos       CORE_ADDR sw_breakpoint_pc = pc - the_low_target.decr_pc_after_break;
9908dffb485Schristos       regcache_write_pc (regcache, sw_breakpoint_pc);
9918dffb485Schristos     }
9928dffb485Schristos }
9938dffb485Schristos 
9948dffb485Schristos /* Get the next event from the child.  */
9958dffb485Schristos 
9968dffb485Schristos static int
9978dffb485Schristos get_child_debug_event (DWORD *continue_status,
9988dffb485Schristos 		       struct target_waitstatus *ourstatus)
9998dffb485Schristos {
10008dffb485Schristos   ptid_t ptid;
10018dffb485Schristos 
10024b169a6bSchristos   windows_process.last_sig = GDB_SIGNAL_0;
10034b169a6bSchristos   ourstatus->set_spurious ();
10048dffb485Schristos   *continue_status = DBG_CONTINUE;
10058dffb485Schristos 
10068dffb485Schristos   /* Check if GDB sent us an interrupt request.  */
10078dffb485Schristos   check_remote_input_interrupt_request ();
10088dffb485Schristos 
10094b169a6bSchristos   DEBUG_EVENT *current_event = &windows_process.current_event;
10104b169a6bSchristos 
10114b169a6bSchristos   if (windows_process.soft_interrupt_requested)
10128dffb485Schristos     {
10134b169a6bSchristos       windows_process.soft_interrupt_requested = 0;
10148dffb485Schristos       fake_breakpoint_event ();
10158dffb485Schristos       goto gotevent;
10168dffb485Schristos     }
10178dffb485Schristos 
10184b169a6bSchristos   windows_process.attaching = 0;
10198dffb485Schristos   {
1020*13ed34faSchristos     std::optional<pending_stop> stop
10214b169a6bSchristos       = windows_process.fetch_pending_stop (debug_threads);
10228dffb485Schristos     if (stop.has_value ())
10238dffb485Schristos       {
10248dffb485Schristos 	*ourstatus = stop->status;
10254b169a6bSchristos 	windows_process.current_event = stop->event;
10264b169a6bSchristos 	ptid = debug_event_ptid (&windows_process.current_event);
10274b169a6bSchristos 	switch_to_thread (find_thread_ptid (ptid));
10288dffb485Schristos 	return 1;
10298dffb485Schristos       }
10308dffb485Schristos 
10318dffb485Schristos     /* Keep the wait time low enough for comfortable remote
10328dffb485Schristos        interruption, but high enough so gdbserver doesn't become a
10338dffb485Schristos        bottleneck.  */
10344b169a6bSchristos     if (!wait_for_debug_event (&windows_process.current_event, 250))
10358dffb485Schristos       {
10368dffb485Schristos 	DWORD e  = GetLastError();
10378dffb485Schristos 
10388dffb485Schristos 	if (e == ERROR_PIPE_NOT_CONNECTED)
10398dffb485Schristos 	  {
1040*13ed34faSchristos 	    /* This will happen if the loader fails to successfully
10418dffb485Schristos 	       load the application, e.g., if the main executable
10428dffb485Schristos 	       tries to pull in a non-existing export from a
10438dffb485Schristos 	       DLL.  */
10444b169a6bSchristos 	    ourstatus->set_exited (1);
10458dffb485Schristos 	    return 1;
10468dffb485Schristos 	  }
10478dffb485Schristos 
10488dffb485Schristos 	return 0;
10498dffb485Schristos       }
10508dffb485Schristos   }
10518dffb485Schristos 
10528dffb485Schristos  gotevent:
10538dffb485Schristos 
10544b169a6bSchristos   switch (current_event->dwDebugEventCode)
10558dffb485Schristos     {
10568dffb485Schristos     case CREATE_THREAD_DEBUG_EVENT:
10578dffb485Schristos       OUTMSG2 (("gdbserver: kernel event CREATE_THREAD_DEBUG_EVENT "
10588dffb485Schristos 		"for pid=%u tid=%x)\n",
10594b169a6bSchristos 		(unsigned) current_event->dwProcessId,
10604b169a6bSchristos 		(unsigned) current_event->dwThreadId));
10618dffb485Schristos 
10628dffb485Schristos       /* Record the existence of this thread.  */
10634b169a6bSchristos       child_add_thread (current_event->dwProcessId,
10644b169a6bSchristos 			current_event->dwThreadId,
10654b169a6bSchristos 			current_event->u.CreateThread.hThread,
10664b169a6bSchristos 			current_event->u.CreateThread.lpThreadLocalBase);
10678dffb485Schristos       break;
10688dffb485Schristos 
10698dffb485Schristos     case EXIT_THREAD_DEBUG_EVENT:
10708dffb485Schristos       OUTMSG2 (("gdbserver: kernel event EXIT_THREAD_DEBUG_EVENT "
10718dffb485Schristos 		"for pid=%u tid=%x\n",
10724b169a6bSchristos 		(unsigned) current_event->dwProcessId,
10734b169a6bSchristos 		(unsigned) current_event->dwThreadId));
10744b169a6bSchristos       child_delete_thread (current_event->dwProcessId,
10754b169a6bSchristos 			   current_event->dwThreadId);
10768dffb485Schristos 
10774b169a6bSchristos       switch_to_thread (get_first_thread ());
10788dffb485Schristos       return 1;
10798dffb485Schristos 
10808dffb485Schristos     case CREATE_PROCESS_DEBUG_EVENT:
10818dffb485Schristos       OUTMSG2 (("gdbserver: kernel event CREATE_PROCESS_DEBUG_EVENT "
10828dffb485Schristos 		"for pid=%u tid=%x\n",
10834b169a6bSchristos 		(unsigned) current_event->dwProcessId,
10844b169a6bSchristos 		(unsigned) current_event->dwThreadId));
10854b169a6bSchristos       CloseHandle (current_event->u.CreateProcessInfo.hFile);
10868dffb485Schristos 
10874b169a6bSchristos       if (windows_process.open_process_used)
10888dffb485Schristos 	{
10894b169a6bSchristos 	  CloseHandle (windows_process.handle);
10904b169a6bSchristos 	  windows_process.open_process_used = false;
10918dffb485Schristos 	}
10928dffb485Schristos 
10934b169a6bSchristos       windows_process.handle = current_event->u.CreateProcessInfo.hProcess;
10944b169a6bSchristos       windows_process.main_thread_id = current_event->dwThreadId;
10958dffb485Schristos 
10968dffb485Schristos       /* Add the main thread.  */
10974b169a6bSchristos       child_add_thread (current_event->dwProcessId,
10984b169a6bSchristos 			windows_process.main_thread_id,
10994b169a6bSchristos 			current_event->u.CreateProcessInfo.hThread,
11004b169a6bSchristos 			current_event->u.CreateProcessInfo.lpThreadLocalBase);
11018dffb485Schristos       break;
11028dffb485Schristos 
11038dffb485Schristos     case EXIT_PROCESS_DEBUG_EVENT:
11048dffb485Schristos       OUTMSG2 (("gdbserver: kernel event EXIT_PROCESS_DEBUG_EVENT "
11058dffb485Schristos 		"for pid=%u tid=%x\n",
11064b169a6bSchristos 		(unsigned) current_event->dwProcessId,
11074b169a6bSchristos 		(unsigned) current_event->dwThreadId));
11088dffb485Schristos       {
11094b169a6bSchristos 	DWORD exit_status = current_event->u.ExitProcess.dwExitCode;
11108dffb485Schristos 	/* If the exit status looks like a fatal exception, but we
11118dffb485Schristos 	   don't recognize the exception's code, make the original
11128dffb485Schristos 	   exit status value available, to avoid losing information.  */
11138dffb485Schristos 	int exit_signal
11148dffb485Schristos 	  = WIFSIGNALED (exit_status) ? WTERMSIG (exit_status) : -1;
11158dffb485Schristos 	if (exit_signal == -1)
11164b169a6bSchristos 	  ourstatus->set_exited (exit_status);
11178dffb485Schristos 	else
11184b169a6bSchristos 	  ourstatus->set_signalled (gdb_signal_from_host (exit_signal));
11198dffb485Schristos       }
11204b169a6bSchristos       child_continue (DBG_CONTINUE, windows_process.desired_stop_thread_id);
11218dffb485Schristos       break;
11228dffb485Schristos 
11238dffb485Schristos     case LOAD_DLL_DEBUG_EVENT:
11248dffb485Schristos       OUTMSG2 (("gdbserver: kernel event LOAD_DLL_DEBUG_EVENT "
11258dffb485Schristos 		"for pid=%u tid=%x\n",
11264b169a6bSchristos 		(unsigned) current_event->dwProcessId,
11274b169a6bSchristos 		(unsigned) current_event->dwThreadId));
11284b169a6bSchristos       CloseHandle (current_event->u.LoadDll.hFile);
11294b169a6bSchristos       if (! windows_process.child_initialization_done)
11308dffb485Schristos 	break;
11314b169a6bSchristos       windows_process.dll_loaded_event ();
11328dffb485Schristos 
11334b169a6bSchristos       ourstatus->set_loaded ();
11348dffb485Schristos       break;
11358dffb485Schristos 
11368dffb485Schristos     case UNLOAD_DLL_DEBUG_EVENT:
11378dffb485Schristos       OUTMSG2 (("gdbserver: kernel event UNLOAD_DLL_DEBUG_EVENT "
11388dffb485Schristos 		"for pid=%u tid=%x\n",
11394b169a6bSchristos 		(unsigned) current_event->dwProcessId,
11404b169a6bSchristos 		(unsigned) current_event->dwThreadId));
11414b169a6bSchristos       if (! windows_process.child_initialization_done)
11428dffb485Schristos 	break;
11434b169a6bSchristos       windows_process.handle_unload_dll ();
11444b169a6bSchristos       ourstatus->set_loaded ();
11458dffb485Schristos       break;
11468dffb485Schristos 
11478dffb485Schristos     case EXCEPTION_DEBUG_EVENT:
11488dffb485Schristos       OUTMSG2 (("gdbserver: kernel event EXCEPTION_DEBUG_EVENT "
11498dffb485Schristos 		"for pid=%u tid=%x\n",
11504b169a6bSchristos 		(unsigned) current_event->dwProcessId,
11514b169a6bSchristos 		(unsigned) current_event->dwThreadId));
11524b169a6bSchristos       if (windows_process.handle_exception (ourstatus, debug_threads)
11538dffb485Schristos 	  == HANDLE_EXCEPTION_UNHANDLED)
11548dffb485Schristos 	*continue_status = DBG_EXCEPTION_NOT_HANDLED;
11558dffb485Schristos       break;
11568dffb485Schristos 
11578dffb485Schristos     case OUTPUT_DEBUG_STRING_EVENT:
11588dffb485Schristos       /* A message from the kernel (or Cygwin).  */
11598dffb485Schristos       OUTMSG2 (("gdbserver: kernel event OUTPUT_DEBUG_STRING_EVENT "
11608dffb485Schristos 		"for pid=%u tid=%x\n",
11614b169a6bSchristos 		(unsigned) current_event->dwProcessId,
11624b169a6bSchristos 		(unsigned) current_event->dwThreadId));
11634b169a6bSchristos       windows_process.handle_output_debug_string (nullptr);
11648dffb485Schristos       break;
11658dffb485Schristos 
11668dffb485Schristos     default:
11678dffb485Schristos       OUTMSG2 (("gdbserver: kernel event unknown "
11688dffb485Schristos 		"for pid=%u tid=%x code=%x\n",
11694b169a6bSchristos 		(unsigned) current_event->dwProcessId,
11704b169a6bSchristos 		(unsigned) current_event->dwThreadId,
11714b169a6bSchristos 		(unsigned) current_event->dwDebugEventCode));
11728dffb485Schristos       break;
11738dffb485Schristos     }
11748dffb485Schristos 
11754b169a6bSchristos   ptid = debug_event_ptid (&windows_process.current_event);
11768dffb485Schristos 
11774b169a6bSchristos   if (windows_process.desired_stop_thread_id != -1
11784b169a6bSchristos       && windows_process.desired_stop_thread_id != ptid.lwp ())
11798dffb485Schristos     {
11808dffb485Schristos       /* Pending stop.  See the comment by the definition of
11818dffb485Schristos 	 "pending_stops" for details on why this is needed.  */
11828dffb485Schristos       OUTMSG2 (("get_windows_debug_event - "
11838dffb485Schristos 		"unexpected stop in 0x%lx (expecting 0x%x)\n",
11844b169a6bSchristos 		ptid.lwp (), windows_process.desired_stop_thread_id));
11858dffb485Schristos       maybe_adjust_pc ();
11864b169a6bSchristos       windows_process.pending_stops.push_back
11874b169a6bSchristos 	({(DWORD) ptid.lwp (), *ourstatus, *current_event});
11884b169a6bSchristos       ourstatus->set_spurious ();
11898dffb485Schristos     }
11908dffb485Schristos   else
11914b169a6bSchristos     switch_to_thread (find_thread_ptid (ptid));
11928dffb485Schristos 
11938dffb485Schristos   return 1;
11948dffb485Schristos }
11958dffb485Schristos 
11968dffb485Schristos /* Wait for the inferior process to change state.
11978dffb485Schristos    STATUS will be filled in with a response code to send to GDB.
11988dffb485Schristos    Returns the signal which caused the process to stop. */
11998dffb485Schristos ptid_t
12008dffb485Schristos win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
12014b169a6bSchristos 			    target_wait_flags options)
12028dffb485Schristos {
12034b169a6bSchristos   if (windows_process.cached_status.kind () != TARGET_WAITKIND_IGNORE)
12048dffb485Schristos     {
12058dffb485Schristos       /* The core always does a wait after creating the inferior, and
12068dffb485Schristos 	 do_initial_child_stuff already ran the inferior to the
12078dffb485Schristos 	 initial breakpoint (or an exit, if creating the process
12088dffb485Schristos 	 fails).  Report it now.  */
12094b169a6bSchristos       *ourstatus = windows_process.cached_status;
12104b169a6bSchristos       windows_process.cached_status.set_ignore ();
12114b169a6bSchristos       return debug_event_ptid (&windows_process.current_event);
12128dffb485Schristos     }
12138dffb485Schristos 
12148dffb485Schristos   while (1)
12158dffb485Schristos     {
12168dffb485Schristos       DWORD continue_status;
12178dffb485Schristos       if (!get_child_debug_event (&continue_status, ourstatus))
12188dffb485Schristos 	continue;
12198dffb485Schristos 
12204b169a6bSchristos       switch (ourstatus->kind ())
12218dffb485Schristos 	{
12228dffb485Schristos 	case TARGET_WAITKIND_EXITED:
12238dffb485Schristos 	  OUTMSG2 (("Child exited with retcode = %x\n",
12244b169a6bSchristos 		    ourstatus->exit_status ()));
12258dffb485Schristos 	  win32_clear_inferiors ();
12264b169a6bSchristos 	  return ptid_t (windows_process.current_event.dwProcessId);
12278dffb485Schristos 	case TARGET_WAITKIND_STOPPED:
12288dffb485Schristos 	case TARGET_WAITKIND_SIGNALLED:
12298dffb485Schristos 	case TARGET_WAITKIND_LOADED:
12308dffb485Schristos 	  {
12318dffb485Schristos 	    OUTMSG2 (("Child Stopped with signal = %d \n",
12324b169a6bSchristos 		      ourstatus->sig ()));
12338dffb485Schristos 	    maybe_adjust_pc ();
12344b169a6bSchristos 	    return debug_event_ptid (&windows_process.current_event);
12358dffb485Schristos 	  }
12368dffb485Schristos 	default:
12374b169a6bSchristos 	  OUTMSG (("Ignoring unknown internal event, %d\n",
12384b169a6bSchristos 		  ourstatus->kind ()));
1239*13ed34faSchristos 	  [[fallthrough]];
12408dffb485Schristos 	case TARGET_WAITKIND_SPURIOUS:
12418dffb485Schristos 	  /* do nothing, just continue */
12424b169a6bSchristos 	  child_continue (continue_status,
12434b169a6bSchristos 			  windows_process.desired_stop_thread_id);
12448dffb485Schristos 	  break;
12458dffb485Schristos 	}
12468dffb485Schristos     }
12478dffb485Schristos }
12488dffb485Schristos 
12498dffb485Schristos /* Fetch registers from the inferior process.
12508dffb485Schristos    If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO.  */
12518dffb485Schristos void
12528dffb485Schristos win32_process_target::fetch_registers (regcache *regcache, int regno)
12538dffb485Schristos {
12548dffb485Schristos   child_fetch_inferior_registers (regcache, regno);
12558dffb485Schristos }
12568dffb485Schristos 
12578dffb485Schristos /* Store registers to the inferior process.
12588dffb485Schristos    If REGNO is -1, store all registers; otherwise, store at least REGNO.  */
12598dffb485Schristos void
12608dffb485Schristos win32_process_target::store_registers (regcache *regcache, int regno)
12618dffb485Schristos {
12628dffb485Schristos   child_store_inferior_registers (regcache, regno);
12638dffb485Schristos }
12648dffb485Schristos 
12658dffb485Schristos /* Read memory from the inferior process.  This should generally be
12668dffb485Schristos    called through read_inferior_memory, which handles breakpoint shadowing.
12678dffb485Schristos    Read LEN bytes at MEMADDR into a buffer at MYADDR.  */
12688dffb485Schristos int
12698dffb485Schristos win32_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr,
12708dffb485Schristos 				   int len)
12718dffb485Schristos {
12728dffb485Schristos   return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
12738dffb485Schristos }
12748dffb485Schristos 
12758dffb485Schristos /* Write memory to the inferior process.  This should generally be
12768dffb485Schristos    called through write_inferior_memory, which handles breakpoint shadowing.
12778dffb485Schristos    Write LEN bytes from the buffer at MYADDR to MEMADDR.
12788dffb485Schristos    Returns 0 on success and errno on failure.  */
12798dffb485Schristos int
12808dffb485Schristos win32_process_target::write_memory (CORE_ADDR memaddr,
12818dffb485Schristos 				    const unsigned char *myaddr, int len)
12828dffb485Schristos {
12838dffb485Schristos   return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
12848dffb485Schristos }
12858dffb485Schristos 
12868dffb485Schristos /* Send an interrupt request to the inferior process. */
12878dffb485Schristos void
12888dffb485Schristos win32_process_target::request_interrupt ()
12898dffb485Schristos {
12904b169a6bSchristos   if (GenerateConsoleCtrlEvent (CTRL_BREAK_EVENT, signal_pid))
12918dffb485Schristos     return;
12928dffb485Schristos 
12938dffb485Schristos   /* GenerateConsoleCtrlEvent can fail if process id being debugged is
12948dffb485Schristos      not a process group id.
12958dffb485Schristos      Fallback to XP/Vista 'DebugBreakProcess', which generates a
12968dffb485Schristos      breakpoint exception in the interior process.  */
12978dffb485Schristos 
12984b169a6bSchristos   if (DebugBreakProcess (windows_process.handle))
12998dffb485Schristos     return;
13008dffb485Schristos 
13018dffb485Schristos   /* Last resort, suspend all threads manually.  */
13024b169a6bSchristos   windows_process.soft_interrupt_requested = 1;
13038dffb485Schristos }
13048dffb485Schristos 
13058dffb485Schristos bool
13068dffb485Schristos win32_process_target::supports_hardware_single_step ()
13078dffb485Schristos {
13088dffb485Schristos   return true;
13098dffb485Schristos }
13108dffb485Schristos 
13118dffb485Schristos bool
13128dffb485Schristos win32_process_target::supports_qxfer_siginfo ()
13138dffb485Schristos {
13148dffb485Schristos   return true;
13158dffb485Schristos }
13168dffb485Schristos 
13178dffb485Schristos /* Write Windows signal info.  */
13188dffb485Schristos 
13198dffb485Schristos int
13208dffb485Schristos win32_process_target::qxfer_siginfo (const char *annex,
13218dffb485Schristos 				     unsigned char *readbuf,
13228dffb485Schristos 				     unsigned const char *writebuf,
13238dffb485Schristos 				     CORE_ADDR offset, int len)
13248dffb485Schristos {
13254b169a6bSchristos   if (windows_process.siginfo_er.ExceptionCode == 0)
13268dffb485Schristos     return -1;
13278dffb485Schristos 
13288dffb485Schristos   if (readbuf == nullptr)
13298dffb485Schristos     return -1;
13308dffb485Schristos 
13314b169a6bSchristos   char *buf = (char *) &windows_process.siginfo_er;
13324b169a6bSchristos   size_t bufsize = sizeof (windows_process.siginfo_er);
13338dffb485Schristos 
13348dffb485Schristos #ifdef __x86_64__
13358dffb485Schristos   EXCEPTION_RECORD32 er32;
13364b169a6bSchristos   if (windows_process.wow64_process)
13378dffb485Schristos     {
13388dffb485Schristos       buf = (char *) &er32;
13398dffb485Schristos       bufsize = sizeof (er32);
13408dffb485Schristos 
13414b169a6bSchristos       er32.ExceptionCode = windows_process.siginfo_er.ExceptionCode;
13424b169a6bSchristos       er32.ExceptionFlags = windows_process.siginfo_er.ExceptionFlags;
13434b169a6bSchristos       er32.ExceptionRecord
13444b169a6bSchristos 	= (uintptr_t) windows_process.siginfo_er.ExceptionRecord;
13454b169a6bSchristos       er32.ExceptionAddress
13464b169a6bSchristos 	= (uintptr_t) windows_process.siginfo_er.ExceptionAddress;
13474b169a6bSchristos       er32.NumberParameters = windows_process.siginfo_er.NumberParameters;
13488dffb485Schristos       int i;
13498dffb485Schristos       for (i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; i++)
13504b169a6bSchristos 	er32.ExceptionInformation[i]
13514b169a6bSchristos 	  = windows_process.siginfo_er.ExceptionInformation[i];
13528dffb485Schristos     }
13538dffb485Schristos #endif
13548dffb485Schristos 
13558dffb485Schristos   if (offset > bufsize)
13568dffb485Schristos     return -1;
13578dffb485Schristos 
13588dffb485Schristos   if (offset + len > bufsize)
13598dffb485Schristos     len = bufsize - offset;
13608dffb485Schristos 
13618dffb485Schristos   memcpy (readbuf, buf + offset, len);
13628dffb485Schristos 
13638dffb485Schristos   return len;
13648dffb485Schristos }
13658dffb485Schristos 
13668dffb485Schristos bool
13678dffb485Schristos win32_process_target::supports_get_tib_address ()
13688dffb485Schristos {
13698dffb485Schristos   return true;
13708dffb485Schristos }
13718dffb485Schristos 
13728dffb485Schristos /* Write Windows OS Thread Information Block address.  */
13738dffb485Schristos 
13748dffb485Schristos int
13758dffb485Schristos win32_process_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
13768dffb485Schristos {
13778dffb485Schristos   windows_thread_info *th;
13784b169a6bSchristos   th = windows_process.thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
13798dffb485Schristos   if (th == NULL)
13808dffb485Schristos     return 0;
13818dffb485Schristos   if (addr != NULL)
13828dffb485Schristos     *addr = th->thread_local_base;
13838dffb485Schristos   return 1;
13848dffb485Schristos }
13858dffb485Schristos 
13868dffb485Schristos /* Implementation of the target_ops method "sw_breakpoint_from_kind".  */
13878dffb485Schristos 
13888dffb485Schristos const gdb_byte *
13898dffb485Schristos win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
13908dffb485Schristos {
13918dffb485Schristos   *size = the_low_target.breakpoint_len;
13928dffb485Schristos   return the_low_target.breakpoint;
13938dffb485Schristos }
13948dffb485Schristos 
13958dffb485Schristos bool
13968dffb485Schristos win32_process_target::stopped_by_sw_breakpoint ()
13978dffb485Schristos {
13984b169a6bSchristos   windows_thread_info *th
13994b169a6bSchristos     = windows_process.thread_rec (current_thread_ptid (),
14008dffb485Schristos 				  DONT_INVALIDATE_CONTEXT);
14018dffb485Schristos   return th == nullptr ? false : th->stopped_at_software_breakpoint;
14028dffb485Schristos }
14038dffb485Schristos 
14048dffb485Schristos bool
14058dffb485Schristos win32_process_target::supports_stopped_by_sw_breakpoint ()
14068dffb485Schristos {
14078dffb485Schristos   return true;
14088dffb485Schristos }
14098dffb485Schristos 
14108dffb485Schristos CORE_ADDR
14118dffb485Schristos win32_process_target::read_pc (struct regcache *regcache)
14128dffb485Schristos {
14138dffb485Schristos   return (*the_low_target.get_pc) (regcache);
14148dffb485Schristos }
14158dffb485Schristos 
14168dffb485Schristos void
14178dffb485Schristos win32_process_target::write_pc (struct regcache *regcache, CORE_ADDR pc)
14188dffb485Schristos {
14198dffb485Schristos   return (*the_low_target.set_pc) (regcache, pc);
14208dffb485Schristos }
14218dffb485Schristos 
14224b169a6bSchristos const char *
14234b169a6bSchristos win32_process_target::thread_name (ptid_t thread)
14244b169a6bSchristos {
14254b169a6bSchristos   windows_thread_info *th
14264b169a6bSchristos     = windows_process.thread_rec (current_thread_ptid (),
14274b169a6bSchristos 				  DONT_INVALIDATE_CONTEXT);
14284b169a6bSchristos   return th->thread_name ();
14294b169a6bSchristos }
14304b169a6bSchristos 
14314b169a6bSchristos const char *
14324b169a6bSchristos win32_process_target::pid_to_exec_file (int pid)
14334b169a6bSchristos {
14344b169a6bSchristos   return windows_process.pid_to_exec_file (pid);
14354b169a6bSchristos }
14364b169a6bSchristos 
14378dffb485Schristos /* The win32 target ops object.  */
14388dffb485Schristos 
14398dffb485Schristos static win32_process_target the_win32_target;
14408dffb485Schristos 
14418dffb485Schristos /* Initialize the Win32 backend.  */
14428dffb485Schristos void
14438dffb485Schristos initialize_low (void)
14448dffb485Schristos {
14458dffb485Schristos   set_target_ops (&the_win32_target);
14468dffb485Schristos   the_low_target.arch_setup ();
14478dffb485Schristos 
14484b169a6bSchristos   initialize_loadable ();
14498dffb485Schristos }
1450