Share handle_exception
[deliverable/binutils-gdb.git] / gdbserver / win32-low.cc
index a9b1bfb2fd6bb751ae2f2356ee6db4a2b20684c0..7018083746ba479a6179a859b014908b0fa2a2fc 100644 (file)
@@ -36,6 +36,8 @@
 #include "gdbsupport/common-inferior.h"
 #include "gdbsupport/gdb_wait.h"
 
+using namespace windows_nat;
+
 #ifndef USE_WIN32API
 #include <sys/cygwin.h>
 #endif
@@ -72,14 +74,6 @@ int using_threads = 1;
 
 /* Globals.  */
 static int attaching = 0;
-static HANDLE current_process_handle = NULL;
-static DWORD current_process_id = 0;
-static DWORD main_thread_id = 0;
-static EXCEPTION_RECORD siginfo_er;    /* Contents of $_siginfo */
-static enum gdb_signal last_sig = GDB_SIGNAL_0;
-
-/* The current debug event from WaitForDebugEvent.  */
-static DEBUG_EVENT current_event;
 
 /* A status that hasn't been reported to the core yet, and so
    win32_wait should return it next, instead of fetching the next
@@ -103,9 +97,6 @@ typedef BOOL (WINAPI *winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
 typedef BOOL (WINAPI *winapi_DebugBreakProcess) (HANDLE);
 typedef BOOL (WINAPI *winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
 
-static ptid_t win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus,
-                         int options);
-static void win32_resume (struct thread_resume *resume_info, size_t n);
 #ifndef _WIN32_WCE
 static void win32_add_all_dlls (void);
 #endif
@@ -128,7 +119,7 @@ debug_event_ptid (DEBUG_EVENT *event)
 /* Get the thread context of the thread associated with TH.  */
 
 static void
-win32_get_thread_context (win32_thread_info *th)
+win32_get_thread_context (windows_thread_info *th)
 {
   memset (&th->context, 0, sizeof (CONTEXT));
   (*the_low_target.get_thread_context) (th);
@@ -140,7 +131,7 @@ win32_get_thread_context (win32_thread_info *th)
 /* Set the thread context of the thread associated with TH.  */
 
 static void
-win32_set_thread_context (win32_thread_info *th)
+win32_set_thread_context (windows_thread_info *th)
 {
 #ifdef _WIN32_WCE
   /* Calling SuspendThread on a thread that is running kernel code
@@ -161,7 +152,7 @@ win32_set_thread_context (win32_thread_info *th)
 /* Set the thread context of the thread associated with TH.  */
 
 static void
-win32_prepare_to_resume (win32_thread_info *th)
+win32_prepare_to_resume (windows_thread_info *th)
 {
   if (the_low_target.prepare_to_resume != NULL)
     (*the_low_target.prepare_to_resume) (th);
@@ -170,55 +161,41 @@ win32_prepare_to_resume (win32_thread_info *th)
 /* See win32-low.h.  */
 
 void
-win32_require_context (win32_thread_info *th)
+win32_require_context (windows_thread_info *th)
 {
   if (th->context.ContextFlags == 0)
     {
-      if (!th->suspended)
-       {
-         if (SuspendThread (th->h) == (DWORD) -1)
-           {
-             DWORD err = GetLastError ();
-             OUTMSG (("warning: SuspendThread failed in thread_rec, "
-                      "(error %d): %s\n", (int) err, strwinerror (err)));
-           }
-         else
-           th->suspended = 1;
-       }
-
+      th->suspend ();
       win32_get_thread_context (th);
     }
 }
 
-/* Find a thread record given a thread id.  If GET_CONTEXT is set then
-   also retrieve the context for this thread.  */
-static win32_thread_info *
-thread_rec (ptid_t ptid, int get_context)
+/* See nat/windows-nat.h.  */
+
+windows_thread_info *
+windows_nat::thread_rec (ptid_t ptid, thread_disposition_type disposition)
 {
   thread_info *thread = find_thread_ptid (ptid);
   if (thread == NULL)
     return NULL;
 
-  win32_thread_info *th = (win32_thread_info *) thread_target_data (thread);
-  if (get_context)
+  windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
+  if (disposition != DONT_INVALIDATE_CONTEXT)
     win32_require_context (th);
   return th;
 }
 
 /* Add a thread to the thread list.  */
-static win32_thread_info *
+static windows_thread_info *
 child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
 {
-  win32_thread_info *th;
+  windows_thread_info *th;
   ptid_t ptid = ptid_t (pid, tid, 0);
 
-  if ((th = thread_rec (ptid, FALSE)))
+  if ((th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT)))
     return th;
 
-  th = XCNEW (win32_thread_info);
-  th->tid = tid;
-  th->h = h;
-  th->thread_local_base = (CORE_ADDR) (uintptr_t) tlb;
+  th = new windows_thread_info (tid, h, (CORE_ADDR) (uintptr_t) tlb);
 
   add_thread (ptid, th);
 
@@ -232,11 +209,10 @@ child_add_thread (DWORD pid, DWORD tid, HANDLE h, void *tlb)
 static void
 delete_thread_info (thread_info *thread)
 {
-  win32_thread_info *th = (win32_thread_info *) thread_target_data (thread);
+  windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
 
   remove_thread (thread);
-  CloseHandle (th->h);
-  free (th);
+  delete th;
 }
 
 /* Delete a thread from the list of threads.  */
@@ -257,16 +233,16 @@ child_delete_thread (DWORD pid, DWORD tid)
 /* These watchpoint related wrapper functions simply pass on the function call
    if the low target has registered a corresponding function.  */
 
-static int
-win32_supports_z_point_type (char z_type)
+bool
+win32_process_target::supports_z_point_type (char z_type)
 {
   return (the_low_target.supports_z_point_type != NULL
          && the_low_target.supports_z_point_type (z_type));
 }
 
-static int
-win32_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
-                   int size, struct raw_breakpoint *bp)
+int
+win32_process_target::insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+                                   int size, raw_breakpoint *bp)
 {
   if (the_low_target.insert_point != NULL)
     return the_low_target.insert_point (type, addr, size, bp);
@@ -275,9 +251,9 @@ win32_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
     return 1;
 }
 
-static int
-win32_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
-                   int size, struct raw_breakpoint *bp)
+int
+win32_process_target::remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+                                   int size, raw_breakpoint *bp)
 {
   if (the_low_target.remove_point != NULL)
     return the_low_target.remove_point (type, addr, size, bp);
@@ -286,17 +262,17 @@ win32_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
     return 1;
 }
 
-static int
-win32_stopped_by_watchpoint (void)
+bool
+win32_process_target::stopped_by_watchpoint ()
 {
   if (the_low_target.stopped_by_watchpoint != NULL)
     return the_low_target.stopped_by_watchpoint ();
   else
-    return 0;
+    return false;
 }
 
-static CORE_ADDR
-win32_stopped_data_address (void)
+CORE_ADDR
+win32_process_target::stopped_data_address ()
 {
   if (the_low_target.stopped_data_address != NULL)
     return the_low_target.stopped_data_address ();
@@ -380,7 +356,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
     {
       struct target_waitstatus status;
 
-      win32_wait (minus_one_ptid, &status, 0);
+      the_target->wait (minus_one_ptid, &status, 0);
 
       /* Note win32_wait doesn't return thread events.  */
       if (status.kind != TARGET_WAITKIND_LOADED)
@@ -396,7 +372,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
        resume.kind = resume_continue;
        resume.sig = 0;
 
-       win32_resume (&resume, 1);
+       the_target->resume (&resume, 1);
       }
     }
 
@@ -427,7 +403,7 @@ do_initial_child_stuff (HANDLE proch, DWORD pid, int attached)
 static void
 continue_one_thread (thread_info *thread, int thread_id)
 {
-  win32_thread_info *th = (win32_thread_info *) thread_target_data (thread);
+  windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
 
   if (thread_id == -1 || thread_id == th->tid)
     {
@@ -441,13 +417,7 @@ continue_one_thread (thread_info *thread, int thread_id)
              th->context.ContextFlags = 0;
            }
 
-         if (ResumeThread (th->h) == (DWORD) -1)
-           {
-             DWORD err = GetLastError ();
-             OUTMSG (("warning: ResumeThread failed in continue_one_thread, "
-                      "(error %d): %s\n", (int) err, strwinerror (err)));
-           }
-         th->suspended = 0;
+         th->resume ();
        }
     }
 }
@@ -476,7 +446,8 @@ static void
 child_fetch_inferior_registers (struct regcache *regcache, int r)
 {
   int regno;
-  win32_thread_info *th = thread_rec (current_thread_ptid (), TRUE);
+  windows_thread_info *th = thread_rec (current_thread_ptid (),
+                                       INVALIDATE_CONTEXT);
   if (r == -1 || r > NUM_REGS)
     child_fetch_inferior_registers (regcache, NUM_REGS);
   else
@@ -490,7 +461,8 @@ static void
 child_store_inferior_registers (struct regcache *regcache, int r)
 {
   int regno;
-  win32_thread_info *th = thread_rec (current_thread_ptid (), TRUE);
+  windows_thread_info *th = thread_rec (current_thread_ptid (),
+                                       INVALIDATE_CONTEXT);
   if (r == -1 || r == 0 || r > NUM_REGS)
     child_store_inferior_registers (regcache, NUM_REGS);
   else
@@ -715,7 +687,7 @@ 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 = win32_wait (ptid_t (current_process_id), &cs.last_status, 0);
+  cs.last_ptid = wait (ptid_t (current_process_id), &cs.last_status, 0);
 
   /* Necessary for handle_v_kill.  */
   signal_pid = current_process_id;
@@ -726,8 +698,8 @@ win32_process_target::create_inferior (const char *program,
 /* Attach to a running process.
    PID is the process ID to attach to, specified by the user
    or a higher layer.  */
-static int
-win32_attach (unsigned long pid)
+int
+win32_process_target::attach (unsigned long pid)
 {
   HANDLE h;
   winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
@@ -761,9 +733,10 @@ win32_attach (unsigned long pid)
         (int) err, strwinerror (err));
 }
 
-/* Handle OUTPUT_DEBUG_STRING_EVENT from child process.  */
-static void
-handle_output_debug_string (void)
+/* See nat/windows-nat.h.  */
+
+int
+windows_nat::handle_output_debug_string (struct target_waitstatus *ourstatus)
 {
 #define READ_BUFFER_LEN 1024
   CORE_ADDR addr;
@@ -771,7 +744,7 @@ handle_output_debug_string (void)
   DWORD nbytes = current_event.u.DebugString.nDebugStringLength;
 
   if (nbytes == 0)
-    return;
+    return 0;
 
   if (nbytes > READ_BUFFER_LEN)
     nbytes = READ_BUFFER_LEN;
@@ -784,13 +757,13 @@ handle_output_debug_string (void)
         in Unicode.  */
       WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
       if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
-       return;
+       return 0;
       wcstombs (s, buffer, (nbytes + 1) / sizeof (WCHAR));
     }
   else
     {
       if (read_inferior_memory (addr, (unsigned char *) s, nbytes) != 0)
-       return;
+       return 0;
     }
 
   if (!startswith (s, "cYg"))
@@ -798,12 +771,14 @@ handle_output_debug_string (void)
       if (!server_waiting)
        {
          OUTMSG2(("%s", s));
-         return;
+         return 0;
        }
 
       monitor_output (s);
     }
 #undef READ_BUFFER_LEN
+
+  return 0;
 }
 
 static void
@@ -819,8 +794,8 @@ win32_clear_inferiors (void)
 
 /* Implementation of target_ops::kill.  */
 
-static int
-win32_kill (process_info *process)
+int
+win32_process_target::kill (process_info *process)
 {
   TerminateProcess (current_process_handle, 0);
   for (;;)
@@ -832,7 +807,7 @@ win32_kill (process_info *process)
       if (current_event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
        break;
       else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
-       handle_output_debug_string ();
+       handle_output_debug_string (nullptr);
     }
 
   win32_clear_inferiors ();
@@ -843,8 +818,8 @@ win32_kill (process_info *process)
 
 /* Implementation of target_ops::detach.  */
 
-static int
-win32_detach (process_info *process)
+int
+win32_process_target::detach (process_info *process)
 {
   winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
   winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
@@ -865,7 +840,7 @@ win32_detach (process_info *process)
     resume.thread = minus_one_ptid;
     resume.kind = resume_continue;
     resume.sig = 0;
-    win32_resume (&resume, 1);
+    this->resume (&resume, 1);
   }
 
   if (!DebugActiveProcessStop (current_process_id))
@@ -878,16 +853,16 @@ win32_detach (process_info *process)
   return 0;
 }
 
-static void
-win32_mourn (struct process_info *process)
+void
+win32_process_target::mourn (struct process_info *process)
 {
   remove_process (process);
 }
 
 /* Implementation of target_ops::join.  */
 
-static void
-win32_join (int pid)
+void
+win32_process_target::join (int pid)
 {
   HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pid);
   if (h != NULL)
@@ -897,9 +872,9 @@ win32_join (int pid)
     }
 }
 
-/* Return 1 iff the thread with thread ID TID is alive.  */
-static int
-win32_thread_alive (ptid_t ptid)
+/* Return true iff the thread with thread ID TID is alive.  */
+bool
+win32_process_target::thread_alive (ptid_t ptid)
 {
   /* Our thread list is reliable; don't bother to poll target
      threads.  */
@@ -908,13 +883,13 @@ win32_thread_alive (ptid_t ptid)
 
 /* Resume the inferior process.  RESUME_INFO describes how we want
    to resume.  */
-static void
-win32_resume (struct thread_resume *resume_info, size_t n)
+void
+win32_process_target::resume (thread_resume *resume_info, size_t n)
 {
   DWORD tid;
   enum gdb_signal sig;
   int step;
-  win32_thread_info *th;
+  windows_thread_info *th;
   DWORD continue_status = DBG_CONTINUE;
   ptid_t ptid;
 
@@ -959,7 +934,7 @@ win32_resume (struct thread_resume *resume_info, size_t n)
 
   /* Get context for the currently selected thread.  */
   ptid = debug_event_ptid (&current_event);
-  th = thread_rec (ptid, FALSE);
+  th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
   if (th)
     {
       win32_prepare_to_resume (th);
@@ -1051,55 +1026,6 @@ win32_add_one_solib (const char *name, CORE_ADDR load_addr)
   loaded_dll (buf2, load_addr);
 }
 
-static char *
-get_image_name (HANDLE h, void *address, int unicode)
-{
-  static char buf[(2 * MAX_PATH) + 1];
-  DWORD size = unicode ? sizeof (WCHAR) : sizeof (char);
-  char *address_ptr;
-  int len = 0;
-  char b[2];
-  SIZE_T done;
-
-  /* Attempt to read the name of the dll that was detected.
-     This is documented to work only when actively debugging
-     a program.  It will not work for attached processes. */
-  if (address == NULL)
-    return NULL;
-
-#ifdef _WIN32_WCE
-  /* Windows CE reports the address of the image name,
-     instead of an address of a pointer into the image name.  */
-  address_ptr = address;
-#else
-  /* See if we could read the address of a string, and that the
-     address isn't null. */
-  if (!ReadProcessMemory (h, address,  &address_ptr,
-                         sizeof (address_ptr), &done)
-      || done != sizeof (address_ptr)
-      || !address_ptr)
-    return NULL;
-#endif
-
-  /* Find the length of the string */
-  while (ReadProcessMemory (h, address_ptr + len++ * size, &b, size, &done)
-        && (b[0] != 0 || b[size - 1] != 0) && done == size)
-    continue;
-
-  if (!unicode)
-    ReadProcessMemory (h, address_ptr, buf, len, &done);
-  else
-    {
-      WCHAR *unicode_address = XALLOCAVEC (WCHAR, len);
-      ReadProcessMemory (h, address_ptr, unicode_address, len * sizeof (WCHAR),
-                        &done);
-
-      WideCharToMultiByte (CP_ACP, 0, unicode_address, len, buf, len, 0, 0);
-    }
-
-  return buf;
-}
-
 typedef BOOL (WINAPI *winapi_EnumProcessModules) (HANDLE, HMODULE *,
                                                  DWORD, LPDWORD);
 typedef BOOL (WINAPI *winapi_GetModuleInformation) (HANDLE, HMODULE,
@@ -1197,18 +1123,13 @@ typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
 typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
 typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
 
-/* Handle a DLL load event.
-
-   This function assumes that this event did not occur during inferior
-   initialization, where their event info may be incomplete (see
-   do_initial_child_stuff and win32_add_all_dlls for more info on
-   how we handle DLL loading during that phase).  */
+/* See nat/windows-nat.h.  */
 
-static void
-handle_load_dll (void)
+void
+windows_nat::handle_load_dll ()
 {
   LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
-  char *dll_name;
+  const char *dll_name;
 
   dll_name = get_image_name (current_process_handle,
                             event->lpImageName, event->fUnicode);
@@ -1218,15 +1139,10 @@ handle_load_dll (void)
   win32_add_one_solib (dll_name, (CORE_ADDR) (uintptr_t) event->lpBaseOfDll);
 }
 
-/* Handle a DLL unload event.
+/* See nat/windows-nat.h.  */
 
-   This function assumes that this event did not occur during inferior
-   initialization, where their event info may be incomplete (see
-   do_initial_child_stuff and win32_add_one_solib for more info
-   on how we handle DLL loading during that phase).  */
-
-static void
-handle_unload_dll (void)
+void
+windows_nat::handle_unload_dll ()
 {
   CORE_ADDR load_addr =
          (CORE_ADDR) (uintptr_t) current_event.u.UnloadDll.lpBaseOfDll;
@@ -1238,133 +1154,12 @@ handle_unload_dll (void)
   unloaded_dll (NULL, load_addr);
 }
 
-static void
-handle_exception (struct target_waitstatus *ourstatus)
-{
-  DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
-
-  memcpy (&siginfo_er, &current_event.u.Exception.ExceptionRecord,
-         sizeof siginfo_er);
-
-  ourstatus->kind = TARGET_WAITKIND_STOPPED;
-
-  switch (code)
-    {
-    case EXCEPTION_ACCESS_VIOLATION:
-      OUTMSG2 (("EXCEPTION_ACCESS_VIOLATION"));
-      ourstatus->value.sig = GDB_SIGNAL_SEGV;
-      break;
-    case STATUS_STACK_OVERFLOW:
-      OUTMSG2 (("STATUS_STACK_OVERFLOW"));
-      ourstatus->value.sig = GDB_SIGNAL_SEGV;
-      break;
-    case STATUS_FLOAT_DENORMAL_OPERAND:
-      OUTMSG2 (("STATUS_FLOAT_DENORMAL_OPERAND"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
-      OUTMSG2 (("EXCEPTION_ARRAY_BOUNDS_EXCEEDED"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_INEXACT_RESULT:
-      OUTMSG2 (("STATUS_FLOAT_INEXACT_RESULT"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_INVALID_OPERATION:
-      OUTMSG2 (("STATUS_FLOAT_INVALID_OPERATION"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_OVERFLOW:
-      OUTMSG2 (("STATUS_FLOAT_OVERFLOW"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_STACK_CHECK:
-      OUTMSG2 (("STATUS_FLOAT_STACK_CHECK"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_UNDERFLOW:
-      OUTMSG2 (("STATUS_FLOAT_UNDERFLOW"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_FLOAT_DIVIDE_BY_ZERO:
-      OUTMSG2 (("STATUS_FLOAT_DIVIDE_BY_ZERO"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_INTEGER_DIVIDE_BY_ZERO:
-      OUTMSG2 (("STATUS_INTEGER_DIVIDE_BY_ZERO"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case STATUS_INTEGER_OVERFLOW:
-      OUTMSG2 (("STATUS_INTEGER_OVERFLOW"));
-      ourstatus->value.sig = GDB_SIGNAL_FPE;
-      break;
-    case EXCEPTION_BREAKPOINT:
-      OUTMSG2 (("EXCEPTION_BREAKPOINT"));
-      ourstatus->value.sig = GDB_SIGNAL_TRAP;
-#ifdef _WIN32_WCE
-      /* Remove the initial breakpoint.  */
-      check_breakpoints ((CORE_ADDR) (long) current_event
-                        .u.Exception.ExceptionRecord.ExceptionAddress);
-#endif
-      break;
-    case DBG_CONTROL_C:
-      OUTMSG2 (("DBG_CONTROL_C"));
-      ourstatus->value.sig = GDB_SIGNAL_INT;
-      break;
-    case DBG_CONTROL_BREAK:
-      OUTMSG2 (("DBG_CONTROL_BREAK"));
-      ourstatus->value.sig = GDB_SIGNAL_INT;
-      break;
-    case EXCEPTION_SINGLE_STEP:
-      OUTMSG2 (("EXCEPTION_SINGLE_STEP"));
-      ourstatus->value.sig = GDB_SIGNAL_TRAP;
-      break;
-    case EXCEPTION_ILLEGAL_INSTRUCTION:
-      OUTMSG2 (("EXCEPTION_ILLEGAL_INSTRUCTION"));
-      ourstatus->value.sig = GDB_SIGNAL_ILL;
-      break;
-    case EXCEPTION_PRIV_INSTRUCTION:
-      OUTMSG2 (("EXCEPTION_PRIV_INSTRUCTION"));
-      ourstatus->value.sig = GDB_SIGNAL_ILL;
-      break;
-    case EXCEPTION_NONCONTINUABLE_EXCEPTION:
-      OUTMSG2 (("EXCEPTION_NONCONTINUABLE_EXCEPTION"));
-      ourstatus->value.sig = GDB_SIGNAL_ILL;
-      break;
-    default:
-      if (current_event.u.Exception.dwFirstChance)
-       {
-         ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
-         return;
-       }
-      OUTMSG2 (("gdbserver: unknown target exception 0x%08x at 0x%s",
-           (unsigned) current_event.u.Exception.ExceptionRecord.ExceptionCode,
-           phex_nz ((uintptr_t) current_event.u.Exception.ExceptionRecord.
-           ExceptionAddress, sizeof (uintptr_t))));
-      ourstatus->value.sig = GDB_SIGNAL_UNKNOWN;
-      break;
-    }
-  OUTMSG2 (("\n"));
-  last_sig = ourstatus->value.sig;
-}
-
-
 static void
 suspend_one_thread (thread_info *thread)
 {
-  win32_thread_info *th = (win32_thread_info *) thread_target_data (thread);
+  windows_thread_info *th = (windows_thread_info *) thread_target_data (thread);
 
-  if (!th->suspended)
-    {
-      if (SuspendThread (th->h) == (DWORD) -1)
-       {
-         DWORD err = GetLastError ();
-         OUTMSG (("warning: SuspendThread failed in suspend_one_thread, "
-                  "(error %d): %s\n", (int) err, strwinerror (err)));
-       }
-      else
-       th->suspended = 1;
-    }
+  th->suspend ();
 }
 
 static void
@@ -1391,15 +1186,25 @@ auto_delete_breakpoint (CORE_ADDR stop_pc)
 }
 #endif
 
+/* See nat/windows-nat.h.  */
+
+bool
+windows_nat::handle_ms_vc_exception (const EXCEPTION_RECORD *rec)
+{
+  return false;
+}
+
 /* Get the next event from the child.  */
 
 static int
-get_child_debug_event (struct target_waitstatus *ourstatus)
+get_child_debug_event (DWORD *continue_status,
+                      struct target_waitstatus *ourstatus)
 {
   ptid_t ptid;
 
   last_sig = GDB_SIGNAL_0;
   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
+  *continue_status = DBG_CONTINUE;
 
   /* Check if GDB sent us an interrupt request.  */
   check_remote_input_interrupt_request ();
@@ -1582,7 +1387,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
                "for pid=%u tid=%x\n",
                (unsigned) current_event.dwProcessId,
                (unsigned) current_event.dwThreadId));
-      handle_exception (ourstatus);
+      if (handle_exception (ourstatus, debug_threads)
+         == HANDLE_EXCEPTION_UNHANDLED)
+       *continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
 
     case OUTPUT_DEBUG_STRING_EVENT:
@@ -1591,7 +1398,7 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
                "for pid=%u tid=%x\n",
                (unsigned) current_event.dwProcessId,
                (unsigned) current_event.dwThreadId));
-      handle_output_debug_string ();
+      handle_output_debug_string (nullptr);
       break;
 
     default:
@@ -1611,8 +1418,9 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
 /* Wait for the inferior process to change state.
    STATUS will be filled in with a response code to send to GDB.
    Returns the signal which caused the process to stop. */
-static ptid_t
-win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
+ptid_t
+win32_process_target::wait (ptid_t ptid, target_waitstatus *ourstatus,
+                           int options)
 {
   struct regcache *regcache;
 
@@ -1629,7 +1437,8 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 
   while (1)
     {
-      if (!get_child_debug_event (ourstatus))
+      DWORD continue_status;
+      if (!get_child_debug_event (&continue_status, ourstatus))
        continue;
 
       switch (ourstatus->kind)
@@ -1653,7 +1462,7 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
          /* fall-through */
        case TARGET_WAITKIND_SPURIOUS:
          /* do nothing, just continue */
-         child_continue (DBG_CONTINUE, -1);
+         child_continue (continue_status, -1);
          break;
        }
     }
@@ -1661,16 +1470,16 @@ win32_wait (ptid_t ptid, struct target_waitstatus *ourstatus, int options)
 
 /* Fetch registers from the inferior process.
    If REGNO is -1, fetch all registers; otherwise, fetch at least REGNO.  */
-static void
-win32_fetch_inferior_registers (struct regcache *regcache, int regno)
+void
+win32_process_target::fetch_registers (regcache *regcache, int regno)
 {
   child_fetch_inferior_registers (regcache, regno);
 }
 
 /* Store registers to the inferior process.
    If REGNO is -1, store all registers; otherwise, store at least REGNO.  */
-static void
-win32_store_inferior_registers (struct regcache *regcache, int regno)
+void
+win32_process_target::store_registers (regcache *regcache, int regno)
 {
   child_store_inferior_registers (regcache, regno);
 }
@@ -1678,8 +1487,9 @@ win32_store_inferior_registers (struct regcache *regcache, int regno)
 /* Read memory from the inferior process.  This should generally be
    called through read_inferior_memory, which handles breakpoint shadowing.
    Read LEN bytes at MEMADDR into a buffer at MYADDR.  */
-static int
-win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
+int
+win32_process_target::read_memory (CORE_ADDR memaddr, unsigned char *myaddr,
+                                  int len)
 {
   return child_xfer_memory (memaddr, (char *) myaddr, len, 0, 0) != len;
 }
@@ -1688,16 +1498,16 @@ win32_read_inferior_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len)
    called through write_inferior_memory, which handles breakpoint shadowing.
    Write LEN bytes from the buffer at MYADDR to MEMADDR.
    Returns 0 on success and errno on failure.  */
-static int
-win32_write_inferior_memory (CORE_ADDR memaddr, const unsigned char *myaddr,
-                            int len)
+int
+win32_process_target::write_memory (CORE_ADDR memaddr,
+                                   const unsigned char *myaddr, int len)
 {
   return child_xfer_memory (memaddr, (char *) myaddr, len, 1, 0) != len;
 }
 
 /* Send an interrupt request to the inferior process. */
-static void
-win32_request_interrupt (void)
+void
+win32_process_target::request_interrupt ()
 {
   winapi_DebugBreakProcess DebugBreakProcess;
   winapi_GenerateConsoleCtrlEvent GenerateConsoleCtrlEvent;
@@ -1729,6 +1539,12 @@ win32_request_interrupt (void)
   soft_interrupt_requested = 1;
 }
 
+bool
+win32_process_target::supports_hardware_single_step ()
+{
+  return true;
+}
+
 #ifdef _WIN32_WCE
 int
 win32_error_to_fileio_error (DWORD err)
@@ -1779,8 +1595,8 @@ win32_error_to_fileio_error (DWORD err)
   return FILEIO_EUNKNOWN;
 }
 
-static void
-wince_hostio_last_error (char *buf)
+void
+win32_process_target::hostio_last_error (char *buf)
 {
   DWORD winerr = GetLastError ();
   int fileio_err = win32_error_to_fileio_error (winerr);
@@ -1788,11 +1604,19 @@ wince_hostio_last_error (char *buf)
 }
 #endif
 
+bool
+win32_process_target::supports_qxfer_siginfo ()
+{
+  return true;
+}
+
 /* Write Windows signal info.  */
 
-static int
-win32_xfer_siginfo (const char *annex, unsigned char *readbuf,
-                   unsigned const char *writebuf, CORE_ADDR offset, int len)
+int
+win32_process_target::qxfer_siginfo (const char *annex,
+                                    unsigned char *readbuf,
+                                    unsigned const char *writebuf,
+                                    CORE_ADDR offset, int len)
 {
   if (siginfo_er.ExceptionCode == 0)
     return -1;
@@ -1811,13 +1635,19 @@ win32_xfer_siginfo (const char *annex, unsigned char *readbuf,
   return len;
 }
 
+bool
+win32_process_target::supports_get_tib_address ()
+{
+  return true;
+}
+
 /* Write Windows OS Thread Information Block address.  */
 
-static int
-win32_get_tib_address (ptid_t ptid, CORE_ADDR *addr)
+int
+win32_process_target::get_tib_address (ptid_t ptid, CORE_ADDR *addr)
 {
-  win32_thread_info *th;
-  th = thread_rec (ptid, 0);
+  windows_thread_info *th;
+  th = thread_rec (ptid, DONT_INVALIDATE_CONTEXT);
   if (th == NULL)
     return 0;
   if (addr != NULL)
@@ -1827,8 +1657,8 @@ win32_get_tib_address (ptid_t ptid, CORE_ADDR *addr)
 
 /* Implementation of the target_ops method "sw_breakpoint_from_kind".  */
 
-static const gdb_byte *
-win32_sw_breakpoint_from_kind (int kind, int *size)
+const gdb_byte *
+win32_process_target::sw_breakpoint_from_kind (int kind, int *size)
 {
   *size = the_low_target.breakpoint_len;
   return the_low_target.breakpoint;
@@ -1838,93 +1668,10 @@ win32_sw_breakpoint_from_kind (int kind, int *size)
 
 static win32_process_target the_win32_target;
 
-static process_stratum_target win32_target_ops = {
-  win32_attach,
-  win32_kill,
-  win32_detach,
-  win32_mourn,
-  win32_join,
-  win32_thread_alive,
-  win32_resume,
-  win32_wait,
-  win32_fetch_inferior_registers,
-  win32_store_inferior_registers,
-  NULL, /* prepare_to_access_memory */
-  NULL, /* done_accessing_memory */
-  win32_read_inferior_memory,
-  win32_write_inferior_memory,
-  NULL, /* lookup_symbols */
-  win32_request_interrupt,
-  NULL, /* read_auxv */
-  win32_supports_z_point_type,
-  win32_insert_point,
-  win32_remove_point,
-  NULL, /* stopped_by_sw_breakpoint */
-  NULL, /* supports_stopped_by_sw_breakpoint */
-  NULL, /* stopped_by_hw_breakpoint */
-  NULL, /* supports_stopped_by_hw_breakpoint */
-  target_can_do_hardware_single_step,
-  win32_stopped_by_watchpoint,
-  win32_stopped_data_address,
-  NULL, /* read_offsets */
-  NULL, /* get_tls_address */
-#ifdef _WIN32_WCE
-  wince_hostio_last_error,
-#else
-  hostio_last_error_from_errno,
-#endif
-  NULL, /* qxfer_osdata */
-  win32_xfer_siginfo,
-  NULL, /* supports_non_stop */
-  NULL, /* async */
-  NULL, /* start_non_stop */
-  NULL, /* supports_multi_process */
-  NULL, /* supports_fork_events */
-  NULL, /* supports_vfork_events */
-  NULL, /* supports_exec_events */
-  NULL, /* handle_new_gdb_connection */
-  NULL, /* handle_monitor_command */
-  NULL, /* core_of_thread */
-  NULL, /* read_loadmap */
-  NULL, /* process_qsupported */
-  NULL, /* supports_tracepoints */
-  NULL, /* read_pc */
-  NULL, /* write_pc */
-  NULL, /* thread_stopped */
-  win32_get_tib_address,
-  NULL, /* pause_all */
-  NULL, /* unpause_all */
-  NULL, /* stabilize_threads */
-  NULL, /* install_fast_tracepoint_jump_pad */
-  NULL, /* emit_ops */
-  NULL, /* supports_disable_randomization */
-  NULL, /* get_min_fast_tracepoint_insn_len */
-  NULL, /* qxfer_libraries_svr4 */
-  NULL, /* support_agent */
-  NULL, /* enable_btrace */
-  NULL, /* disable_btrace */
-  NULL, /* read_btrace */
-  NULL, /* read_btrace_conf */
-  NULL, /* supports_range_stepping */
-  NULL, /* pid_to_exec_file */
-  NULL, /* multifs_open */
-  NULL, /* multifs_unlink */
-  NULL, /* multifs_readlink */
-  NULL, /* breakpoint_kind_from_pc */
-  win32_sw_breakpoint_from_kind,
-  NULL, /* thread_name */
-  NULL, /* breakpoint_kind_from_current_state */
-  NULL, /* supports_software_single_step */
-  NULL, /* supports_catch_syscall */
-  NULL, /* get_ipa_tdesc_idx */
-  NULL, /* thread_handle */
-  &the_win32_target,
-};
-
 /* Initialize the Win32 backend.  */
 void
 initialize_low (void)
 {
-  set_target_ops (&win32_target_ops);
+  set_target_ops (&the_win32_target);
   the_low_target.arch_setup ();
 }
This page took 0.037114 seconds and 4 git commands to generate.