* target.h (struct thread_resume): Delete leave_stopped member.
[deliverable/binutils-gdb.git] / gdb / gdbserver / win32-low.c
index 141403d81f1aa8a5167ae3661f134f7a58fcd545..7c63ff44e8eb7e565529f9e6e7c9fe51404b4dc1 100644 (file)
@@ -1,5 +1,5 @@
 /* Low level interface to Windows debugging, for gdbserver.
-   Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
+   Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 
    Contributed by Leo Zayas.  Based on "win32-nat.c" from GDB.
 
@@ -69,6 +69,7 @@ int using_threads = 1;
 static int attaching = 0;
 static HANDLE current_process_handle = NULL;
 static DWORD current_process_id = 0;
+static DWORD main_thread_id = 0;
 static enum target_signal last_sig = TARGET_SIGNAL_0;
 
 /* The current debug event from WaitForDebugEvent.  */
@@ -89,9 +90,7 @@ typedef BOOL WINAPI (*winapi_DebugSetProcessKillOnExit) (BOOL KillOnExit);
 typedef BOOL WINAPI (*winapi_DebugBreakProcess) (HANDLE);
 typedef BOOL WINAPI (*winapi_GenerateConsoleCtrlEvent) (DWORD, DWORD);
 
-static DWORD main_thread_id = 0;
-
-static void win32_resume (struct thread_resume *resume_info);
+static void win32_resume (struct thread_resume *resume_info, size_t n);
 
 /* Get the thread ID from the current selected inferior (the current
    thread).  */
@@ -177,7 +176,7 @@ child_add_thread (DWORD tid, HANDLE h)
   if ((th = thread_rec (tid, FALSE)))
     return th;
 
-  th = calloc (1, sizeof (*th));
+  th = xcalloc (1, sizeof (*th));
   th->tid = tid;
   th->h = h;
 
@@ -290,10 +289,17 @@ child_init_thread_list (void)
 }
 
 static void
-do_initial_child_stuff (DWORD pid)
+do_initial_child_stuff (HANDLE proch, DWORD pid)
 {
   last_sig = TARGET_SIGNAL_0;
 
+  current_process_handle = proch;
+  current_process_id = pid;
+  main_thread_id = 0;
+
+  soft_interrupt_requested = 0;
+  faked_breakpoint = 0;
+
   memset (&current_event, 0, sizeof (current_event));
 
   child_init_thread_list ();
@@ -452,15 +458,15 @@ create_process (const char *program, char *args,
   mbstowcs (wargs, args, argslen + 1);
 
   ret = CreateProcessW (wprogram, /* image name */
-                        wargs,    /* command line */
-                        NULL,     /* security, not supported */
-                        NULL,     /* thread, not supported */
-                        FALSE,    /* inherit handles, not supported */
-                        flags,    /* start flags */
-                        NULL,     /* environment, not supported */
-                        NULL,     /* current directory, not supported */
-                        NULL,     /* start info, not supported */
-                        pi);      /* proc info */
+                       wargs,    /* command line */
+                       NULL,     /* security, not supported */
+                       NULL,     /* thread, not supported */
+                       FALSE,    /* inherit handles, not supported */
+                       flags,    /* start flags */
+                       NULL,     /* environment, not supported */
+                       NULL,     /* current directory, not supported */
+                       NULL,     /* start info, not supported */
+                       pi);      /* proc info */
 #else
   STARTUPINFOA si = { sizeof (STARTUPINFOA) };
 
@@ -531,7 +537,7 @@ win32_create_inferior (char *program, char **program_args)
   for (argc = 1; program_args[argc]; argc++)
     {
       /* FIXME: Can we do better about quoting?  How does Cygwin
-         handle this?  */
+        handle this?  */
       strcat (args, " ");
       strcat (args, program_args[argc]);
     }
@@ -573,10 +579,7 @@ win32_create_inferior (char *program, char **program_args)
   CloseHandle (pi.hThread);
 #endif
 
-  current_process_handle = pi.hProcess;
-  current_process_id = pi.dwProcessId;
-
-  do_initial_child_stuff (current_process_id);
+  do_initial_child_stuff (pi.hProcess, pi.dwProcessId);
 
   return current_process_id;
 }
@@ -606,10 +609,8 @@ win32_attach (unsigned long pid)
            DebugSetProcessKillOnExit (FALSE);
 
          /* win32_wait needs to know we're attaching.  */
-         attaching = 1;
-         current_process_handle = h;
-         current_process_id = pid;
-         do_initial_child_stuff (pid);
+         attaching = 1;
+         do_initial_child_stuff (h, pid);
          return 0;
        }
 
@@ -641,7 +642,7 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
   if (current_event.u.DebugString.fUnicode)
     {
       /* The event tells us how many bytes, not chars, even
-         in Unicode.  */
+        in Unicode.  */
       WCHAR buffer[(READ_BUFFER_LEN + 1) / sizeof (WCHAR)] = { 0 };
       if (read_inferior_memory (addr, (unsigned char *) buffer, nbytes) != 0)
        return;
@@ -666,12 +667,20 @@ handle_output_debug_string (struct target_waitstatus *ourstatus)
 #undef READ_BUFFER_LEN
 }
 
+static void
+win32_clear_inferiors (void)
+{
+  if (current_process_handle != NULL)
+    CloseHandle (current_process_handle);
+
+  for_each_inferior (&all_threads, delete_thread_info);
+  clear_inferiors ();
+}
+
 /* Kill all inferiors.  */
 static void
 win32_kill (void)
 {
-  win32_thread_info *current_thread;
-
   if (current_process_handle == NULL)
     return;
 
@@ -686,27 +695,18 @@ win32_kill (void)
        break;
       else if (current_event.dwDebugEventCode == OUTPUT_DEBUG_STRING_EVENT)
        {
-         struct target_waitstatus our_status = { 0 };
+         struct target_waitstatus our_status = { 0 };
          handle_output_debug_string (&our_status);
-       }
+       }
     }
 
-  CloseHandle (current_process_handle);
-
-  current_thread = inferior_target_data (current_inferior);
-  if (current_thread && current_thread->h)
-    {
-      /* This may fail in an attached process, so don't check.  */
-      (void) CloseHandle (current_thread->h);
-    }
+  win32_clear_inferiors ();
 }
 
 /* Detach from all inferiors.  */
 static int
 win32_detach (void)
 {
-  HANDLE h;
-
   winapi_DebugActiveProcessStop DebugActiveProcessStop = NULL;
   winapi_DebugSetProcessKillOnExit DebugSetProcessKillOnExit = NULL;
 #ifdef _WIN32_WCE
@@ -721,33 +721,20 @@ win32_detach (void)
       || DebugActiveProcessStop == NULL)
     return -1;
 
-  /* We need a new handle, since DebugActiveProcessStop
-     closes all the ones that came through the events.  */
-  if ((h = OpenProcess (PROCESS_ALL_ACCESS,
-                       FALSE,
-                       current_process_id)) == NULL)
-    {
-      /* The process died.  */
-      return -1;
-    }
-
   {
     struct thread_resume resume;
     resume.thread = -1;
     resume.step = 0;
     resume.sig = 0;
-    resume.leave_stopped = 0;
-    win32_resume (&resume);
+    win32_resume (&resume, 1);
   }
 
   if (!DebugActiveProcessStop (current_process_id))
-    {
-      CloseHandle (h);
-      return -1;
-    }
+    return -1;
+
   DebugSetProcessKillOnExit (FALSE);
 
-  current_process_handle = h;
+  win32_clear_inferiors ();
   return 0;
 }
 
@@ -755,15 +742,14 @@ win32_detach (void)
 static void
 win32_join (void)
 {
-  if (current_process_id == 0
-      || current_process_handle == NULL)
-    return;
+  extern unsigned long signal_pid;
 
-  WaitForSingleObject (current_process_handle, INFINITE);
-  CloseHandle (current_process_handle);
-
-  current_process_handle = NULL;
-  current_process_id = 0;
+  HANDLE h = OpenProcess (PROCESS_ALL_ACCESS, FALSE, signal_pid);
+  if (h != NULL)
+    {
+      WaitForSingleObject (h, INFINITE);
+      CloseHandle (h);
+    }
 }
 
 /* Return 1 iff the thread with thread ID TID is alive.  */
@@ -784,7 +770,7 @@ win32_thread_alive (unsigned long tid)
 /* Resume the inferior process.  RESUME_INFO describes how we want
    to resume.  */
 static void
-win32_resume (struct thread_resume *resume_info)
+win32_resume (struct thread_resume *resume_info, size_t n)
 {
   DWORD tid;
   enum target_signal sig;
@@ -795,9 +781,9 @@ win32_resume (struct thread_resume *resume_info)
   /* This handles the very limited set of resume packets that GDB can
      currently produce.  */
 
-  if (resume_info[0].thread == -1)
+  if (n == 1 && resume_info[0].thread == -1)
     tid = -1;
-  else if (resume_info[1].thread == -1 && !resume_info[1].leave_stopped)
+  else if (n > 1)
     tid = -1;
   else
     /* Yes, we're ignoring resume_info[0].thread.  It'd be tricky to make
@@ -1255,7 +1241,7 @@ handle_exception (struct target_waitstatus *ourstatus)
 #ifdef _WIN32_WCE
       /* Remove the initial breakpoint.  */
       check_breakpoints ((CORE_ADDR) (long) current_event
-                         .u.Exception.ExceptionRecord.ExceptionAddress);
+                        .u.Exception.ExceptionRecord.ExceptionAddress);
 #endif
       break;
     case DBG_CONTROL_C:
@@ -1367,37 +1353,37 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
   if (attaching)
     {
       /* WinCE doesn't set an initial breakpoint automatically.  To
-        stop the inferior, we flush all currently pending debug
-        events -- the thread list and the dll list are always
-        reported immediatelly without delay, then, we suspend all
-        threads and pretend we saw a trap at the current PC of the
-        main thread.
-
-        Contrary to desktop Windows, Windows CE *does* report the dll
-        names on LOAD_DLL_DEBUG_EVENTs resulting from a
-        DebugActiveProcess call.  This limits the way we can detect
-        if all the dlls have already been reported.  If we get a real
-        debug event before leaving attaching, the worst that will
-        happen is the user will see a spurious breakpoint.  */
+        stop the inferior, we flush all currently pending debug
+        events -- the thread list and the dll list are always
+        reported immediatelly without delay, then, we suspend all
+        threads and pretend we saw a trap at the current PC of the
+        main thread.
+
+        Contrary to desktop Windows, Windows CE *does* report the dll
+        names on LOAD_DLL_DEBUG_EVENTs resulting from a
+        DebugActiveProcess call.  This limits the way we can detect
+        if all the dlls have already been reported.  If we get a real
+        debug event before leaving attaching, the worst that will
+        happen is the user will see a spurious breakpoint.  */
 
       current_event.dwDebugEventCode = 0;
       if (!WaitForDebugEvent (&current_event, 0))
-       {
-         OUTMSG2(("no attach events left\n"));
-         fake_breakpoint_event ();
-         attaching = 0;
-       }
+       {
+         OUTMSG2(("no attach events left\n"));
+         fake_breakpoint_event ();
+         attaching = 0;
+       }
       else
-       OUTMSG2(("got attach event\n"));
+       OUTMSG2(("got attach event\n"));
     }
   else
 #endif
     {
       /* Keep the wait time low enough for confortable remote
-        interruption, but high enough so gdbserver doesn't become a
-        bottleneck.  */
+        interruption, but high enough so gdbserver doesn't become a
+        bottleneck.  */
       if (!WaitForDebugEvent (&current_event, 250))
-       return 0;
+       return 0;
     }
 
  gotevent:
@@ -1466,6 +1452,7 @@ get_child_debug_event (struct target_waitstatus *ourstatus)
                (unsigned) current_event.dwThreadId));
       ourstatus->kind = TARGET_WAITKIND_EXITED;
       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
+      child_continue (DBG_CONTINUE, -1);
       CloseHandle (current_process_handle);
       current_process_handle = NULL;
       break;
@@ -1546,9 +1533,10 @@ win32_wait (char *status)
                    our_status.value.integer));
 
          *status = 'W';
+         win32_clear_inferiors ();
          return our_status.value.integer;
        case TARGET_WAITKIND_STOPPED:
-       case TARGET_WAITKIND_LOADED:
+       case TARGET_WAITKIND_LOADED:
          OUTMSG2 (("Child Stopped with signal = %d \n",
                    our_status.value.sig));
 
@@ -1566,11 +1554,11 @@ win32_wait (char *status)
            }
 
          return our_status.value.sig;
-       default:
+       default:
          OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
-         /* fall-through */
-       case TARGET_WAITKIND_SPURIOUS:
-       case TARGET_WAITKIND_EXECD:
+         /* fall-through */
+       case TARGET_WAITKIND_SPURIOUS:
+       case TARGET_WAITKIND_EXECD:
          /* do nothing, just continue */
          child_continue (DBG_CONTINUE, -1);
          break;
@@ -1648,12 +1636,6 @@ win32_request_interrupt (void)
   soft_interrupt_requested = 1;
 }
 
-static const char *
-win32_arch_string (void)
-{
-  return the_low_target.arch_string;
-}
-
 #ifdef _WIN32_WCE
 int
 win32_error_to_fileio_error (DWORD err)
@@ -1735,7 +1717,6 @@ static struct target_ops win32_target_ops = {
   NULL,
   NULL,
   NULL,
-  win32_arch_string,
   NULL,
 #ifdef _WIN32_WCE
   wince_hostio_last_error,
@@ -1752,5 +1733,5 @@ initialize_low (void)
   if (the_low_target.breakpoint != NULL)
     set_breakpoint_data (the_low_target.breakpoint,
                         the_low_target.breakpoint_len);
-  init_registers ();
+  the_low_target.arch_setup ();
 }
This page took 0.031054 seconds and 4 git commands to generate.