* win32-nat.c (thread_rec): Be more defensive about suspending already
authorChristopher Faylor <me+cygwin@cgf.cx>
Fri, 21 Apr 2000 02:26:14 +0000 (02:26 +0000)
committerChristopher Faylor <me+cygwin@cgf.cx>
Fri, 21 Apr 2000 02:26:14 +0000 (02:26 +0000)
suspended threads.
(safe_symbol_file_add_stub): New function.
(safe_symbole_file_add_cleanup): New function.
(safe_symbol_file_add): New function.
(handle_load_dll): Use wrapper to add DLL symbol information to avoid bogus
errors from non-stabs DLLs.
(handle_exception): Add work around for detection of first exception breakpoint
which does not seem to occur on W2K.  Detect more "signals" that can be
effectively passed to the debuggee.  Reorganize to eliminate continue_status
global.
(child_continue): Reorganize to eliminate continue_status global.
(child_wait): Ditto.
(child_resume): Ditto.
(get_child_debug_event): Ditto.  Recognize when an a breakpoint exception
should be ignored.  Change method for signalling when an important event has
occured to the caller.
(child_create_inferior): Use new method for noticing when get_child_debug_event
has found something interesting.

gdb/ChangeLog
gdb/win32-nat.c
gdb/windows-nat.c

index 8d59e85e48037bb5fe2f4b2e211800e4b4ed722e..efb8921a22e1f60987f3f18dea90d0efe472c146 100644 (file)
@@ -1,3 +1,25 @@
+2000-04-20  Christopher Faylor  <cgf@cygnus.com>
+
+       * win32-nat.c (thread_rec): Be more defensive about suspending already
+       suspended threads.
+       (safe_symbol_file_add_stub): New function.
+       (safe_symbole_file_add_cleanup): New function.
+       (safe_symbol_file_add): New function.
+       (handle_load_dll): Use wrapper to add DLL symbol information to avoid
+       bogus errors from non-stabs DLLs.
+       (handle_exception): Add work around for detection of first exception
+       breakpoint which does not seem to occur on W2K.  Detect more "signals"
+       that can be effectively passed to the debuggee.  Reorganize to eliminate
+       continue_status global.
+       (child_continue): Reorganize to eliminate continue_status global.
+       (child_wait): Ditto.
+       (child_resume): Ditto.
+       (get_child_debug_event): Ditto.  Recognize when an a breakpoint
+       exception should be ignored.  Change method for signalling when an
+       important event has occured to the caller.
+       (child_create_inferior): Use new method for noticing when
+       get_child_debug_event has found something interesting.
+
 Fri Apr  7 13:44:38 2000  glen mccready  <gkm@pobox.com>
 
         * rs6000-nat.c (xcoff_relocate_symtab): Grow buffer if ptrace()
index 4295d4b52105e7260d96127350c29dc2a01fac5a..0a1c4272cf6feeefb272f82039eec894398b1cb1 100644 (file)
@@ -79,6 +79,9 @@ static void child_stop PARAMS ((void));
 static int win32_child_thread_alive PARAMS ((int));
 void child_kill_inferior PARAMS ((void));
 
+static int last_sig = 0;       /* Set if a signal was received from the
+                                  debugged process */
+
 /* Thread information structure used to track information that is
    not available in gdb's thread structure. */
 typedef struct thread_info_struct
@@ -94,9 +97,6 @@ typedef struct thread_info_struct
 
 static thread_info thread_head = {NULL};
 
-/* The saved state for a continue after breaking back to gdb. */
-static DWORD continue_status;
-
 /* The process and thread handles for the above context. */
 
 static DEBUG_EVENT current_event;      /* The current debug event from
@@ -104,6 +104,8 @@ static DEBUG_EVENT current_event;   /* The current debug event from
 static HANDLE current_process_handle;  /* Currently executing process */
 static thread_info *current_thread;    /* Info on currently selected thread */
 static DWORD main_thread_id;   /* Thread ID of the main thread */
+static int ignore_first_first_chance = 0; /* True if we should ignore the
+                                            first first chance exception that we get. */
 
 /* Counts of things. */
 static int exception_count = 0;
@@ -201,7 +203,7 @@ thread_rec (DWORD id, int get_context)
       {
        if (!th->suspend_count && get_context)
          {
-           if (get_context > 0)
+           if (get_context > 0 && id != current_event.dwThreadId)
              th->suspend_count = SuspendThread (th->h) + 1;
            else if (get_context < 0)
              th->suspend_count = -1;
@@ -418,6 +420,55 @@ failed:
   return 0;
 }
 
+struct safe_symbol_file_add_args
+{
+  char *name;
+  int from_tty;
+  struct section_addr_info *addrs;
+  int mainline;
+  int flags;
+  struct objfile *ret;
+};
+
+static int
+safe_symbol_file_add_stub (void *argv)
+{
+#define p ((struct safe_symbol_file_add_args *)argv)
+  p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
+  return !!p->ret;
+#undef p
+}
+
+static void
+safe_symbol_file_add_cleanup (void *gdb_stderrv)
+{
+  ui_file_delete (gdb_stderr);
+  gdb_stderr = (struct ui_file *)gdb_stderrv;
+}
+
+static struct objfile *
+safe_symbol_file_add (char *name, int from_tty,
+                     struct section_addr_info *addrs,
+                     int mainline, int flags)
+
+{
+  struct safe_symbol_file_add_args p;
+  struct cleanup *cleanup;
+
+  cleanup = make_cleanup (safe_symbol_file_add_cleanup, gdb_stderr);
+
+  gdb_stderr = ui_file_new ();
+  p.name = name;
+  p.from_tty = from_tty;
+  p.addrs = addrs;
+  p.mainline = mainline;
+  p.flags = flags;
+  catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
+
+  do_cleanups (cleanup);
+  return p.ret;
+}
+
 /* Wait for child to do something.  Return pid of child, or -1 in case
    of error; store status through argument pointer OURSTATUS.  */
 
@@ -505,14 +556,11 @@ handle_load_dll (PTR dummy)
 
   /* The symbols in a dll are offset by 0x1000, which is the
      the offset from 0 of the first byte in an image - because
-     of the file header and the section alignment.
-
-     FIXME: Is this the real reason that we need the 0x1000 ? */
+     of the file header and the section alignment. */
 
-  printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
   section_addrs.text_addr = (int) event->lpBaseOfDll + 0x1000;
-  symbol_file_add (dll_name, 0, &section_addrs, 0, OBJF_SHARED);
-  printf_unfiltered ("\n");
+  safe_symbol_file_add (dll_name, 0, &section_addrs, 0, OBJF_SHARED);
+  printf_unfiltered ("%x:%s\n", event->lpBaseOfDll, dll_name);
 
   return 1;
 }
@@ -556,19 +604,24 @@ handle_exception (struct target_waitstatus *ourstatus)
   int i;
   int done = 0;
   thread_info *th;
+  int fc = ignore_first_first_chance;
 
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
+  ignore_first_first_chance = 0;
+
   /* Record the context of the current thread */
   th = thread_rec (current_event.dwThreadId, -1);
 
+  last_sig = 0;
+
   switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
     {
     case EXCEPTION_ACCESS_VIOLATION:
       DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
+      last_sig = SIGSEGV;
       break;
     case STATUS_FLOAT_UNDERFLOW:
     case STATUS_FLOAT_DIVIDE_BY_ZERO:
@@ -577,15 +630,19 @@ handle_exception (struct target_waitstatus *ourstatus)
       DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
     case STATUS_STACK_OVERFLOW:
       DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
     case EXCEPTION_BREAKPOINT:
+      if (fc && current_event.u.Exception.dwFirstChance &&
+         ((DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress & 0xc0000000))
+       {
+         last_sig = -1;
+         return 0;
+       }
       DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
@@ -594,7 +651,7 @@ handle_exception (struct target_waitstatus *ourstatus)
       DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_INT;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
+      last_sig = SIGINT;       /* FIXME - should check pass state */
       break;
     case EXCEPTION_SINGLE_STEP:
       DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
@@ -605,21 +662,13 @@ handle_exception (struct target_waitstatus *ourstatus)
       DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_ILL;
+      last_sig = SIGILL;
       break;
     default:
-      /* This may be a structured exception handling exception.  In
-         that case, we want to let the program try to handle it, and
-         only break if we see the exception a second time.
-      if (current_event.u.Exception.dwFirstChance)
-
-       return 0;
-*/
-
       printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
                    current_event.u.Exception.ExceptionRecord.ExceptionCode,
                current_event.u.Exception.ExceptionRecord.ExceptionAddress);
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
     }
   exception_count++;
@@ -629,7 +678,7 @@ handle_exception (struct target_waitstatus *ourstatus)
 /* Resume all artificially suspended threads if we are continuing
    execution */
 static BOOL
-child_continue (int id)
+child_continue (DWORD continue_status, int id)
 {
   int i;
   thread_info *th;
@@ -653,16 +702,22 @@ child_continue (int id)
   return res;
 }
 
+/* Get the next event from the child.  Return 1 if the event requires
+   handling by WFI (or whatever).
+ */
 static int
 get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
-                      DWORD *event_code, int *retval)
+                      DWORD target_event_code, int *retval)
 {
+  int breakout = 0;
   BOOL debug_event;
-  int breakout = 1;
+  DWORD continue_status, event_code;
+  thread_info *th = NULL;
+  static thread_info dummy_thread_info;
 
-  if (!(debug_event = WaitForDebugEvent (&current_event, 20)))
+  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
     {
-      breakout = *retval = *event_code = 0;
+      *retval = 0;
       goto out;
     }
 
@@ -670,91 +725,95 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
   continue_status = DBG_CONTINUE;
   *retval = 0;
 
-  switch (*event_code = current_event.dwDebugEventCode)
+  event_code = current_event.dwDebugEventCode;
+  breakout = event_code == target_event_code;
+
+  switch (event_code)
     {
     case CREATE_THREAD_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "CREATE_THREAD_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "CREATE_THREAD_DEBUG_EVENT"));
       /* Record the existence of this thread */
-      child_add_thread (current_event.dwThreadId,
-                       current_event.u.CreateThread.hThread);
+      th = child_add_thread (current_event.dwThreadId,
+                            current_event.u.CreateThread.hThread);
       if (info_verbose)
        printf_unfiltered ("[New %s]\n",
-                     target_pid_to_str (current_event.dwThreadId));
+                          target_pid_to_str (current_event.dwThreadId));
       break;
 
     case EXIT_THREAD_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "EXIT_THREAD_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "EXIT_THREAD_DEBUG_EVENT"));
       child_delete_thread (current_event.dwThreadId);
+      th = &dummy_thread_info;
       break;
 
     case CREATE_PROCESS_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "CREATE_PROCESS_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "CREATE_PROCESS_DEBUG_EVENT"));
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
 
       main_thread_id = inferior_pid = current_event.dwThreadId;
       /* Add the main thread */
-      current_thread = child_add_thread (inferior_pid,
-                        current_event.u.CreateProcessInfo.hThread);
+      th = child_add_thread (inferior_pid,
+                            current_event.u.CreateProcessInfo.hThread);
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "EXIT_PROCESS_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "EXIT_PROCESS_DEBUG_EVENT"));
       ourstatus->kind = TARGET_WAITKIND_EXITED;
       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
       CloseHandle (current_process_handle);
       *retval = current_event.dwProcessId;
-      goto out;
+      breakout = 1;
+      break;
 
     case LOAD_DLL_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "LOAD_DLL_DEBUG_EVENT"));
-      catch_errors (handle_load_dll, NULL, "", RETURN_MASK_ALL);
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "LOAD_DLL_DEBUG_EVENT"));
+      catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
       registers_changed ();    /* mark all regs invalid */
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "UNLOAD_DLL_DEBUG_EVENT"));
-      break;           /* FIXME: don't know what to do here */
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "UNLOAD_DLL_DEBUG_EVENT"));
+      break;                   /* FIXME: don't know what to do here */
 
     case EXCEPTION_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "EXCEPTION_DEBUG_EVENT"));
-      if (handle_exception (ourstatus))        /* sets continue_status */
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "EXCEPTION_DEBUG_EVENT"));
+      if (handle_exception (ourstatus))
+       *retval = current_event.dwThreadId;
+      else
        {
-         *retval = current_event.dwThreadId;
-         goto out;
+         if (last_sig >= 0)
+           continue_status = DBG_EXCEPTION_NOT_HANDLED;
+         breakout = 0;
        }
       break;
 
-    case OUTPUT_DEBUG_STRING_EVENT:
+    case OUTPUT_DEBUG_STRING_EVENT:    /* message from the kernel */
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "OUTPUT_DEBUG_STRING_EVENT"));
-      if (handle_output_debug_string (ourstatus))
-       {
-         *retval = main_thread_id;
-         goto out;
-       }
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "OUTPUT_DEBUG_STRING_EVENT"));
+      handle_output_debug_string ( ourstatus);
       break;
     default:
       printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
@@ -765,15 +824,15 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
       break;
     }
 
-  breakout = 0;
-  CHECK (child_continue (-1));
-  continue_status = 0;
+  if (breakout)
+    current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
+  else
+    CHECK (child_continue (continue_status, -1));
 
 out:
   return breakout;
 }
 
-
 /* Wait for interesting events to occur in the target process. */
 static int
 child_wait (int pid, struct target_waitstatus *ourstatus)
@@ -788,22 +847,18 @@ child_wait (int pid, struct target_waitstatus *ourstatus)
      isn't necessarily what you think it is. */
 
   while (1)
-    {
-      if (continue_status != 0)
-       CHECK (child_continue (-1));
-      if (get_child_debug_event (pid, ourstatus, &event_code, &retval))
-       return retval;
-      else
-       {
-         int detach = 0;
+    if (get_child_debug_event (pid, ourstatus, EXCEPTION_DEBUG_EVENT, &retval))
+      return retval;
+    else
+      {
+       int detach = 0;
 
-         if (ui_loop_hook != NULL)
-           detach = ui_loop_hook (0);
+       if (ui_loop_hook != NULL)
+         detach = ui_loop_hook (0);
 
-         if (detach)
-           child_kill_inferior ();
-       }
-    }
+       if (detach)
+         child_kill_inferior ();
+      }
 }
 
 /* Attach to process PID, then initialize for debugging it.  */
@@ -1031,22 +1086,21 @@ child_create_inferior (exec_file, allargs, env)
   target_terminal_init ();
   target_terminal_inferior ();
 
-  /* Run until process and threads are loaded */
-  do
-    get_child_debug_event (inferior_pid, &dummy, &event_code, &ret);
-  while (event_code != EXCEPTION_DEBUG_EVENT);
+  ignore_first_first_chance = 1;
 
-  SymSetOptions (SYMOPT_DEFERRED_LOADS);
-  SymInitialize (current_process_handle, NULL, TRUE);
+  /* Run until process and threads are loaded */
+  while (!get_child_debug_event (inferior_pid, &dummy,
+                                CREATE_PROCESS_DEBUG_EVENT, &ret))
+    continue;
 
+  /* child_continue (DBG_CONTINUE, -1);*/
   proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
 }
 
 static void
 child_mourn_inferior ()
 {
-  continue_status = DBG_CONTINUE;
-  (void) child_continue (-1);
+  (void) child_continue (DBG_CONTINUE, -1);
   unpush_target (&child_ops);
   generic_mourn_inferior ();
 }
@@ -1092,8 +1146,7 @@ child_kill_inferior (void)
 
   for (;;)
     {
-      continue_status = DBG_CONTINUE;
-      if (!child_continue (-1))
+      if (!child_continue (DBG_CONTINUE, -1))
        break;
       if (!WaitForDebugEvent (&current_event, INFINITE))
        break;
@@ -1111,8 +1164,11 @@ child_kill_inferior (void)
 void
 child_resume (int pid, int step, enum target_signal sig)
 {
-  int i;
   thread_info *th;
+  DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
+                         DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
+
+  last_sig = 0;
 
   DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
               pid, step, sig));
@@ -1137,7 +1193,7 @@ child_resume (int pid, int step, enum target_signal sig)
   /* Allow continuing with the same signal that interrupted us.
      Otherwise complain. */
 
-  child_continue (pid);
+  child_continue (continue_status, pid);
 }
 
 static void
@@ -1209,7 +1265,6 @@ init_child_ops (void)
 void
 _initialize_inftarg ()
 {
-  struct cmd_list_element *c;
   init_child_ops ();
 
   add_show_from_set
index 4295d4b52105e7260d96127350c29dc2a01fac5a..0a1c4272cf6feeefb272f82039eec894398b1cb1 100644 (file)
@@ -79,6 +79,9 @@ static void child_stop PARAMS ((void));
 static int win32_child_thread_alive PARAMS ((int));
 void child_kill_inferior PARAMS ((void));
 
+static int last_sig = 0;       /* Set if a signal was received from the
+                                  debugged process */
+
 /* Thread information structure used to track information that is
    not available in gdb's thread structure. */
 typedef struct thread_info_struct
@@ -94,9 +97,6 @@ typedef struct thread_info_struct
 
 static thread_info thread_head = {NULL};
 
-/* The saved state for a continue after breaking back to gdb. */
-static DWORD continue_status;
-
 /* The process and thread handles for the above context. */
 
 static DEBUG_EVENT current_event;      /* The current debug event from
@@ -104,6 +104,8 @@ static DEBUG_EVENT current_event;   /* The current debug event from
 static HANDLE current_process_handle;  /* Currently executing process */
 static thread_info *current_thread;    /* Info on currently selected thread */
 static DWORD main_thread_id;   /* Thread ID of the main thread */
+static int ignore_first_first_chance = 0; /* True if we should ignore the
+                                            first first chance exception that we get. */
 
 /* Counts of things. */
 static int exception_count = 0;
@@ -201,7 +203,7 @@ thread_rec (DWORD id, int get_context)
       {
        if (!th->suspend_count && get_context)
          {
-           if (get_context > 0)
+           if (get_context > 0 && id != current_event.dwThreadId)
              th->suspend_count = SuspendThread (th->h) + 1;
            else if (get_context < 0)
              th->suspend_count = -1;
@@ -418,6 +420,55 @@ failed:
   return 0;
 }
 
+struct safe_symbol_file_add_args
+{
+  char *name;
+  int from_tty;
+  struct section_addr_info *addrs;
+  int mainline;
+  int flags;
+  struct objfile *ret;
+};
+
+static int
+safe_symbol_file_add_stub (void *argv)
+{
+#define p ((struct safe_symbol_file_add_args *)argv)
+  p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
+  return !!p->ret;
+#undef p
+}
+
+static void
+safe_symbol_file_add_cleanup (void *gdb_stderrv)
+{
+  ui_file_delete (gdb_stderr);
+  gdb_stderr = (struct ui_file *)gdb_stderrv;
+}
+
+static struct objfile *
+safe_symbol_file_add (char *name, int from_tty,
+                     struct section_addr_info *addrs,
+                     int mainline, int flags)
+
+{
+  struct safe_symbol_file_add_args p;
+  struct cleanup *cleanup;
+
+  cleanup = make_cleanup (safe_symbol_file_add_cleanup, gdb_stderr);
+
+  gdb_stderr = ui_file_new ();
+  p.name = name;
+  p.from_tty = from_tty;
+  p.addrs = addrs;
+  p.mainline = mainline;
+  p.flags = flags;
+  catch_errors (safe_symbol_file_add_stub, &p, "", RETURN_MASK_ERROR);
+
+  do_cleanups (cleanup);
+  return p.ret;
+}
+
 /* Wait for child to do something.  Return pid of child, or -1 in case
    of error; store status through argument pointer OURSTATUS.  */
 
@@ -505,14 +556,11 @@ handle_load_dll (PTR dummy)
 
   /* The symbols in a dll are offset by 0x1000, which is the
      the offset from 0 of the first byte in an image - because
-     of the file header and the section alignment.
-
-     FIXME: Is this the real reason that we need the 0x1000 ? */
+     of the file header and the section alignment. */
 
-  printf_unfiltered ("%x:%s", event->lpBaseOfDll, dll_name);
   section_addrs.text_addr = (int) event->lpBaseOfDll + 0x1000;
-  symbol_file_add (dll_name, 0, &section_addrs, 0, OBJF_SHARED);
-  printf_unfiltered ("\n");
+  safe_symbol_file_add (dll_name, 0, &section_addrs, 0, OBJF_SHARED);
+  printf_unfiltered ("%x:%s\n", event->lpBaseOfDll, dll_name);
 
   return 1;
 }
@@ -556,19 +604,24 @@ handle_exception (struct target_waitstatus *ourstatus)
   int i;
   int done = 0;
   thread_info *th;
+  int fc = ignore_first_first_chance;
 
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
+  ignore_first_first_chance = 0;
+
   /* Record the context of the current thread */
   th = thread_rec (current_event.dwThreadId, -1);
 
+  last_sig = 0;
+
   switch (current_event.u.Exception.ExceptionRecord.ExceptionCode)
     {
     case EXCEPTION_ACCESS_VIOLATION:
       DEBUG_EXCEPT (("gdb: Target exception ACCESS_VIOLATION at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
+      last_sig = SIGSEGV;
       break;
     case STATUS_FLOAT_UNDERFLOW:
     case STATUS_FLOAT_DIVIDE_BY_ZERO:
@@ -577,15 +630,19 @@ handle_exception (struct target_waitstatus *ourstatus)
       DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_FPE;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
     case STATUS_STACK_OVERFLOW:
       DEBUG_EXCEPT (("gdb: Target exception STACK_OVERFLOW at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
     case EXCEPTION_BREAKPOINT:
+      if (fc && current_event.u.Exception.dwFirstChance &&
+         ((DWORD) current_event.u.Exception.ExceptionRecord.ExceptionAddress & 0xc0000000))
+       {
+         last_sig = -1;
+         return 0;
+       }
       DEBUG_EXCEPT (("gdb: Target exception BREAKPOINT at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
@@ -594,7 +651,7 @@ handle_exception (struct target_waitstatus *ourstatus)
       DEBUG_EXCEPT (("gdb: Target exception CONTROL_C at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_INT;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
+      last_sig = SIGINT;       /* FIXME - should check pass state */
       break;
     case EXCEPTION_SINGLE_STEP:
       DEBUG_EXCEPT (("gdb: Target exception SINGLE_STEP at 0x%08x\n",
@@ -605,21 +662,13 @@ handle_exception (struct target_waitstatus *ourstatus)
       DEBUG_EXCEPT (("gdb: Target exception SINGLE_ILL at 0x%08x\n",
               current_event.u.Exception.ExceptionRecord.ExceptionAddress));
       ourstatus->value.sig = TARGET_SIGNAL_ILL;
+      last_sig = SIGILL;
       break;
     default:
-      /* This may be a structured exception handling exception.  In
-         that case, we want to let the program try to handle it, and
-         only break if we see the exception a second time.
-      if (current_event.u.Exception.dwFirstChance)
-
-       return 0;
-*/
-
       printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
                    current_event.u.Exception.ExceptionRecord.ExceptionCode,
                current_event.u.Exception.ExceptionRecord.ExceptionAddress);
       ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
-      continue_status = DBG_EXCEPTION_NOT_HANDLED;
       break;
     }
   exception_count++;
@@ -629,7 +678,7 @@ handle_exception (struct target_waitstatus *ourstatus)
 /* Resume all artificially suspended threads if we are continuing
    execution */
 static BOOL
-child_continue (int id)
+child_continue (DWORD continue_status, int id)
 {
   int i;
   thread_info *th;
@@ -653,16 +702,22 @@ child_continue (int id)
   return res;
 }
 
+/* Get the next event from the child.  Return 1 if the event requires
+   handling by WFI (or whatever).
+ */
 static int
 get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
-                      DWORD *event_code, int *retval)
+                      DWORD target_event_code, int *retval)
 {
+  int breakout = 0;
   BOOL debug_event;
-  int breakout = 1;
+  DWORD continue_status, event_code;
+  thread_info *th = NULL;
+  static thread_info dummy_thread_info;
 
-  if (!(debug_event = WaitForDebugEvent (&current_event, 20)))
+  if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
     {
-      breakout = *retval = *event_code = 0;
+      *retval = 0;
       goto out;
     }
 
@@ -670,91 +725,95 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
   continue_status = DBG_CONTINUE;
   *retval = 0;
 
-  switch (*event_code = current_event.dwDebugEventCode)
+  event_code = current_event.dwDebugEventCode;
+  breakout = event_code == target_event_code;
+
+  switch (event_code)
     {
     case CREATE_THREAD_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%x code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "CREATE_THREAD_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "CREATE_THREAD_DEBUG_EVENT"));
       /* Record the existence of this thread */
-      child_add_thread (current_event.dwThreadId,
-                       current_event.u.CreateThread.hThread);
+      th = child_add_thread (current_event.dwThreadId,
+                            current_event.u.CreateThread.hThread);
       if (info_verbose)
        printf_unfiltered ("[New %s]\n",
-                     target_pid_to_str (current_event.dwThreadId));
+                          target_pid_to_str (current_event.dwThreadId));
       break;
 
     case EXIT_THREAD_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "EXIT_THREAD_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "EXIT_THREAD_DEBUG_EVENT"));
       child_delete_thread (current_event.dwThreadId);
+      th = &dummy_thread_info;
       break;
 
     case CREATE_PROCESS_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "CREATE_PROCESS_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "CREATE_PROCESS_DEBUG_EVENT"));
       current_process_handle = current_event.u.CreateProcessInfo.hProcess;
 
       main_thread_id = inferior_pid = current_event.dwThreadId;
       /* Add the main thread */
-      current_thread = child_add_thread (inferior_pid,
-                        current_event.u.CreateProcessInfo.hThread);
+      th = child_add_thread (inferior_pid,
+                            current_event.u.CreateProcessInfo.hThread);
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "EXIT_PROCESS_DEBUG_EVENT"));
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "EXIT_PROCESS_DEBUG_EVENT"));
       ourstatus->kind = TARGET_WAITKIND_EXITED;
       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
       CloseHandle (current_process_handle);
       *retval = current_event.dwProcessId;
-      goto out;
+      breakout = 1;
+      break;
 
     case LOAD_DLL_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "LOAD_DLL_DEBUG_EVENT"));
-      catch_errors (handle_load_dll, NULL, "", RETURN_MASK_ALL);
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "LOAD_DLL_DEBUG_EVENT"));
+      catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
       registers_changed ();    /* mark all regs invalid */
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "UNLOAD_DLL_DEBUG_EVENT"));
-      break;           /* FIXME: don't know what to do here */
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "UNLOAD_DLL_DEBUG_EVENT"));
+      break;                   /* FIXME: don't know what to do here */
 
     case EXCEPTION_DEBUG_EVENT:
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "EXCEPTION_DEBUG_EVENT"));
-      if (handle_exception (ourstatus))        /* sets continue_status */
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "EXCEPTION_DEBUG_EVENT"));
+      if (handle_exception (ourstatus))
+       *retval = current_event.dwThreadId;
+      else
        {
-         *retval = current_event.dwThreadId;
-         goto out;
+         if (last_sig >= 0)
+           continue_status = DBG_EXCEPTION_NOT_HANDLED;
+         breakout = 0;
        }
       break;
 
-    case OUTPUT_DEBUG_STRING_EVENT:
+    case OUTPUT_DEBUG_STRING_EVENT:    /* message from the kernel */
       DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
-                   (unsigned) current_event.dwProcessId,
-                   (unsigned) current_event.dwThreadId,
-                   "OUTPUT_DEBUG_STRING_EVENT"));
-      if (handle_output_debug_string (ourstatus))
-       {
-         *retval = main_thread_id;
-         goto out;
-       }
+                    (unsigned) current_event.dwProcessId,
+                    (unsigned) current_event.dwThreadId,
+                    "OUTPUT_DEBUG_STRING_EVENT"));
+      handle_output_debug_string ( ourstatus);
       break;
     default:
       printf_unfiltered ("gdb: kernel event for pid=%d tid=%d\n",
@@ -765,15 +824,15 @@ get_child_debug_event (int pid, struct target_waitstatus *ourstatus,
       break;
     }
 
-  breakout = 0;
-  CHECK (child_continue (-1));
-  continue_status = 0;
+  if (breakout)
+    current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
+  else
+    CHECK (child_continue (continue_status, -1));
 
 out:
   return breakout;
 }
 
-
 /* Wait for interesting events to occur in the target process. */
 static int
 child_wait (int pid, struct target_waitstatus *ourstatus)
@@ -788,22 +847,18 @@ child_wait (int pid, struct target_waitstatus *ourstatus)
      isn't necessarily what you think it is. */
 
   while (1)
-    {
-      if (continue_status != 0)
-       CHECK (child_continue (-1));
-      if (get_child_debug_event (pid, ourstatus, &event_code, &retval))
-       return retval;
-      else
-       {
-         int detach = 0;
+    if (get_child_debug_event (pid, ourstatus, EXCEPTION_DEBUG_EVENT, &retval))
+      return retval;
+    else
+      {
+       int detach = 0;
 
-         if (ui_loop_hook != NULL)
-           detach = ui_loop_hook (0);
+       if (ui_loop_hook != NULL)
+         detach = ui_loop_hook (0);
 
-         if (detach)
-           child_kill_inferior ();
-       }
-    }
+       if (detach)
+         child_kill_inferior ();
+      }
 }
 
 /* Attach to process PID, then initialize for debugging it.  */
@@ -1031,22 +1086,21 @@ child_create_inferior (exec_file, allargs, env)
   target_terminal_init ();
   target_terminal_inferior ();
 
-  /* Run until process and threads are loaded */
-  do
-    get_child_debug_event (inferior_pid, &dummy, &event_code, &ret);
-  while (event_code != EXCEPTION_DEBUG_EVENT);
+  ignore_first_first_chance = 1;
 
-  SymSetOptions (SYMOPT_DEFERRED_LOADS);
-  SymInitialize (current_process_handle, NULL, TRUE);
+  /* Run until process and threads are loaded */
+  while (!get_child_debug_event (inferior_pid, &dummy,
+                                CREATE_PROCESS_DEBUG_EVENT, &ret))
+    continue;
 
+  /* child_continue (DBG_CONTINUE, -1);*/
   proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
 }
 
 static void
 child_mourn_inferior ()
 {
-  continue_status = DBG_CONTINUE;
-  (void) child_continue (-1);
+  (void) child_continue (DBG_CONTINUE, -1);
   unpush_target (&child_ops);
   generic_mourn_inferior ();
 }
@@ -1092,8 +1146,7 @@ child_kill_inferior (void)
 
   for (;;)
     {
-      continue_status = DBG_CONTINUE;
-      if (!child_continue (-1))
+      if (!child_continue (DBG_CONTINUE, -1))
        break;
       if (!WaitForDebugEvent (&current_event, INFINITE))
        break;
@@ -1111,8 +1164,11 @@ child_kill_inferior (void)
 void
 child_resume (int pid, int step, enum target_signal sig)
 {
-  int i;
   thread_info *th;
+  DWORD continue_status = last_sig > 0 && last_sig < NSIG ?
+                         DBG_EXCEPTION_NOT_HANDLED : DBG_CONTINUE;
+
+  last_sig = 0;
 
   DEBUG_EXEC (("gdb: child_resume (pid=%d, step=%d, sig=%d);\n",
               pid, step, sig));
@@ -1137,7 +1193,7 @@ child_resume (int pid, int step, enum target_signal sig)
   /* Allow continuing with the same signal that interrupted us.
      Otherwise complain. */
 
-  child_continue (pid);
+  child_continue (continue_status, pid);
 }
 
 static void
@@ -1209,7 +1265,6 @@ init_child_ops (void)
 void
 _initialize_inftarg ()
 {
-  struct cmd_list_element *c;
   init_child_ops ();
 
   add_show_from_set
This page took 0.056355 seconds and 4 git commands to generate.