Thu May 21 13:14:25 1998 John Metzler <jmetzler@cygnus.com>
[deliverable/binutils-gdb.git] / gdb / win32-nat.c
index dd11b338490e70469f33040948db1aed47d48e0d..d6c6e1f04c00252dc986e36d05dc80cd21530bd2 100644 (file)
@@ -1,5 +1,5 @@
 /* Target-vector operations for controlling win32 child processes, for GDB.
-   Copyright 1995, 1996 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
    Contributed by Cygnus Support.
 
    This file is part of GDB.
@@ -16,7 +16,8 @@
 
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
-   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
 
 /* by Steve Chamberlain, sac@cygnus.com */
 
 #include <signal.h>
 #include <sys/types.h>
 #include <fcntl.h>
+#include <stdlib.h>
+
+#ifdef _MSC_VER
+#include "windefs.h"
+#else /* other WIN32 compiler */
 #include <windows.h>
+#endif
+
 #include "buildsym.h"
 #include "symfile.h"
 #include "objfiles.h"
@@ -51,6 +59,8 @@
 /* Forward declaration */
 extern struct target_ops child_ops;
 
+static void child_stop PARAMS ((void));
+
 /* The most recently read context. Inspect ContextFlags to see what 
    bits are valid. */
 
@@ -94,7 +104,6 @@ struct regmappings
     int mask;
   };
 
-
 static const struct regmappings  mappings[] =
 {
 #ifdef __PPC__
@@ -170,7 +179,6 @@ static const struct regmappings  mappings[] =
   {(char *) &context.Fpr30, CONTEXT_FLOATING_POINT},
   {(char *) &context.Fpr31, CONTEXT_FLOATING_POINT},
 
-
   {(char *) &context.Iar, CONTEXT_CONTROL},
   {(char *) &context.Msr, CONTEXT_CONTROL},
   {(char *) &context.Cr,  CONTEXT_INTEGER},
@@ -207,7 +215,6 @@ static const struct regmappings  mappings[] =
 #endif
 };
 
-
 /* This vector maps the target's idea of an exception (extracted
    from the DEBUG_EVENT structure) to GDB's idea. */
 
@@ -217,7 +224,6 @@ struct xlate_exception
     enum target_signal us;
   };
 
-
 static const struct xlate_exception
   xlate[] =
 {
@@ -228,7 +234,6 @@ static const struct xlate_exception
   {EXCEPTION_SINGLE_STEP, TARGET_SIGNAL_TRAP},
   {-1, -1}};
 
-
 static void 
 check (BOOL ok, const char *file, int line)
 {
@@ -268,7 +273,6 @@ child_store_inferior_registers (int r)
 /* Wait for child to do something.  Return pid of child, or -1 in case
    of error; store status through argument pointer OURSTATUS.  */
 
-
 static int
 handle_load_dll (char *eventp)
 {
@@ -350,7 +354,6 @@ handle_load_dll (char *eventp)
              return 1;
            }
        }
 
       context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
       GetThreadContext (current_thread, &context);
@@ -372,7 +375,7 @@ handle_load_dll (char *eventp)
 }
 
 
-static void
+static int
 handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
 {
   int i;
@@ -408,6 +411,12 @@ handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
       ourstatus->value.sig = TARGET_SIGNAL_TRAP;
       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 (event->u.Exception.dwFirstChance)
+       return 0;
+
       printf_unfiltered ("gdb: unknown target exception 0x%08x at 0x%08x\n",
                         event->u.Exception.ExceptionRecord.ExceptionCode,
                         event->u.Exception.ExceptionRecord.ExceptionAddress);
@@ -417,6 +426,7 @@ handle_exception (DEBUG_EVENT * event, struct target_waitstatus *ourstatus)
   context.ContextFlags = CONTEXT_FULL | CONTEXT_FLOATING_POINT;
   GetThreadContext (current_thread, &context);
   exception_count++;
+  return 1;
 }
 
 static int
@@ -433,12 +443,15 @@ child_wait (int pid, struct target_waitstatus *ourstatus)
       DEBUG_EVENT event;
       BOOL t = WaitForDebugEvent (&event, INFINITE);
       char *p;
+      DWORD continue_status;
 
       event_count++;
 
       current_thread_id = event.dwThreadId;
       current_process_id = event.dwProcessId;
 
+      continue_status = DBG_CONTINUE;
+
       switch (event.dwDebugEventCode)
        {
        case CREATE_THREAD_DEBUG_EVENT:
@@ -487,8 +500,10 @@ child_wait (int pid, struct target_waitstatus *ourstatus)
          DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
                        event.dwProcessId, event.dwThreadId,
                        "EXCEPTION_DEBUG_EVENT"));
-         handle_exception (&event, ourstatus);
-         return current_process_id;
+         if (handle_exception (&event, ourstatus))
+           return current_process_id;
+         continue_status = DBG_EXCEPTION_NOT_HANDLED;
+         break;
 
        case OUTPUT_DEBUG_STRING_EVENT: /* message from the kernel */
          DEBUG_EVENTS (("gdb: kernel event for pid=%d tid=%d code=%s)\n",
@@ -513,11 +528,10 @@ child_wait (int pid, struct target_waitstatus *ourstatus)
                     current_process_id, current_thread_id));
       CHECK (ContinueDebugEvent (current_process_id,
                                 current_thread_id,
-                                DBG_CONTINUE));
+                                continue_status));
     }
 }
 
-
 /* Attach to process PID, then initialize for debugging it.  */
 
 static void
@@ -537,7 +551,6 @@ child_attach (args, from_tty)
   if (!ok)
     error ("Can't attach to process.");
 
-
   exception_count = 0;
   event_count = 0;
 
@@ -559,7 +572,6 @@ child_attach (args, from_tty)
   push_target (&child_ops);
 }
 
-
 static void
 child_detach (args, from_tty)
      char *args;
@@ -578,7 +590,6 @@ child_detach (args, from_tty)
   unpush_target (&child_ops);
 }
 
-
 /* Print status information about what we're accessing.  */
 
 static void
@@ -757,15 +768,17 @@ child_create_inferior (exec_file, allargs, env)
 static void
 child_mourn_inferior ()
 {
+  (void) ContinueDebugEvent (current_process_id,
+                            current_thread_id,
+                            DBG_CONTINUE);
   unpush_target (&child_ops);
   generic_mourn_inferior ();
 }
 
-
 /* Send a SIGINT to the process group.  This acts just like the user typed a
    ^C on the controlling terminal. */
 
-void
+static void
 child_stop ()
 {
   DEBUG_EVENTS (("gdb: GenerateConsoleCtrlEvent (CTRLC_EVENT, 0)\n"));
@@ -798,6 +811,22 @@ void
 child_kill_inferior (void)
 {
   CHECK (TerminateProcess (current_process, 0));
+  
+  for (;;)
+    {
+      DEBUG_EVENT event;
+      if (!ContinueDebugEvent (current_process_id,
+                              current_thread_id,
+                              DBG_CONTINUE))
+       break;
+      if (!WaitForDebugEvent (&event, INFINITE))
+       break;
+      current_thread_id = event.dwThreadId;
+      current_process_id = event.dwProcessId;
+      if (event.dwDebugEventCode == EXIT_PROCESS_DEBUG_EVENT)
+       break;
+    }
+
   CHECK (CloseHandle (current_process));
   CHECK (CloseHandle (current_thread));
   target_mourn_inferior();     /* or just child_mourn_inferior? */
@@ -857,54 +886,57 @@ child_close ()
   DEBUG_EVENTS (("gdb: child_close, inferior_pid=%d\n", inferior_pid));
 }
 
-struct target_ops child_ops =
+struct target_ops child_ops ;
+
+static void init_child_ops(void)
 {
-  "child",                     /* to_shortname */
-  "Win32 child process",       /* to_longname */
-  "Win32 child process (started by the \"run\" command).",     /* to_doc */
-  child_open,                  /* to_open */
-  child_close,                 /* to_close */
-  child_attach,                        /* to_attach */
-  child_detach,                        /* to_detach */
-  child_resume,                        /* to_resume */
-  child_wait,                  /* to_wait */
-  child_fetch_inferior_registers,/* to_fetch_registers */
-  child_store_inferior_registers,/* to_store_registers */
-  child_prepare_to_store,      /* to_child_prepare_to_store */
-  child_xfer_memory,           /* to_xfer_memory */
-  child_files_info,            /* to_files_info */
-  memory_insert_breakpoint,    /* to_insert_breakpoint */
-  memory_remove_breakpoint,    /* to_remove_breakpoint */
-  terminal_init_inferior,      /* to_terminal_init */
-  terminal_inferior,           /* to_terminal_inferior */
-  terminal_ours_for_output,    /* to_terminal_ours_for_output */
-  terminal_ours,               /* to_terminal_ours */
-  child_terminal_info,         /* to_terminal_info */
-  child_kill_inferior,         /* to_kill */
-  0,                           /* to_load */
-  0,                           /* to_lookup_symbol */
-  child_create_inferior,       /* to_create_inferior */
-  child_mourn_inferior,                /* to_mourn_inferior */
-  child_can_run,               /* to_can_run */
-  0,                           /* to_notice_signals */
-  0,                           /* to_thread_alive */
-  child_stop,                  /* to_stop */
-  process_stratum,             /* to_stratum */
-  0,                           /* to_next */
-  1,                           /* to_has_all_memory */
-  1,                           /* to_has_memory */
-  1,                           /* to_has_stack */
-  1,                           /* to_has_registers */
-  1,                           /* to_has_execution */
-  0,                           /* to_sections */
-  0,                           /* to_sections_end */
-  OPS_MAGIC                    /* to_magic */
-};
+  child_ops.to_shortname =   "child";                  
+  child_ops.to_longname =   "Win32 child process";
+  child_ops.to_doc =   "Win32 child process (started by the \"run\" command).";        
+  child_ops.to_open =   child_open;            
+  child_ops.to_close =   child_close;          
+  child_ops.to_attach =   child_attach;                
+  child_ops.to_detach =   child_detach;                
+  child_ops.to_resume =   child_resume;                
+  child_ops.to_wait  =   child_wait;           
+  child_ops.to_fetch_registers  =   child_fetch_inferior_registers;
+  child_ops.to_store_registers  =   child_store_inferior_registers;
+  child_ops.to_prepare_to_store =   child_prepare_to_store;    
+  child_ops.to_xfer_memory  =   child_xfer_memory;             
+  child_ops.to_files_info  =   child_files_info;               
+  child_ops.to_insert_breakpoint =   memory_insert_breakpoint;
+  child_ops.to_remove_breakpoint =   memory_remove_breakpoint;
+  child_ops.to_terminal_init  =   terminal_init_inferior;
+  child_ops.to_terminal_inferior =   terminal_inferior;        
+  child_ops.to_terminal_ours_for_output =   terminal_ours_for_output;
+  child_ops.to_terminal_ours  =   terminal_ours;       
+  child_ops.to_terminal_info  =   child_terminal_info; 
+  child_ops.to_kill  =   child_kill_inferior;  
+  child_ops.to_load  =   0;                    
+  child_ops.to_lookup_symbol =   0;                            
+  child_ops.to_create_inferior =   child_create_inferior;
+  child_ops.to_mourn_inferior =   child_mourn_inferior;        
+  child_ops.to_can_run  =   child_can_run;     
+  child_ops.to_notice_signals =   0;           
+  child_ops.to_thread_alive  =   0;            
+  child_ops.to_stop  =   child_stop;           
+  child_ops.to_stratum =   process_stratum;
+  child_ops.DONT_USE =   0;            
+  child_ops.to_has_all_memory =   1;   
+  child_ops.to_has_memory =   1;       
+  child_ops.to_has_stack =   1;                
+  child_ops.to_has_registers =   1;    
+  child_ops.to_has_execution =   1;    
+  child_ops.to_sections =   0;         
+  child_ops.to_sections_end =   0;     
+  child_ops.to_magic =   OPS_MAGIC;
+}
 
 void
 _initialize_inftarg ()
 {
   struct cmd_list_element *c;
+  init_child_ops() ;
 
   add_show_from_set
     (add_set_cmd ("new-console", class_support, var_boolean,
This page took 0.028455 seconds and 4 git commands to generate.