This is the mail archive of the gdb-patches@sourceware.cygnus.com mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

[PATCH] win32-nat.c modernizations


This patch adds some shared library manipulation to the win32 version of
gdb.  It also simplifies the "wait for the first trap" initialization
step after the debugee is first started by using methods similar to
other targets.

cgf

2000-06-03  Christopher Faylor  <cgf@cygnus.com>

	* win32-nat.c (safe_symbol_file_add_cleanup): Ensure that gdb_stderr is
	flushed before deleting and restoring it.
	(safe_symbol_file_add): Ensure that gdb_stderr is flushed before
	reassigning it.
	(handle_load_dll): Split into two functions so that WFI can handle
	shared library events.
	(child_solib_loaded_library_pathname): New function.
	(child_clear_solibs): New function.  Clears shared library list.
	(child_solib_add): New function.  Adds shared library symbols.
	(dll_symbol_command): New function.  Handles "dll-symbol" command.
	(info_dll_command): New function.  Handles info
	"sharedlibrary" command.
	(handle_exceptions): Eliminate 'ignore_trap' argument.
	(get_child_debug_event): Eliminate two arguments.  Return "pid" when
	appropriate.  Break out on most events to allow WFI to handle stuff.
	(child_wait): Accomodate get_child_debug_event changes.
	(child_attach): Clear thread list and list of loaded dlls.
	(child_create_inferior): Clear list of loaded dlls.  Use
	wait_for_inferior in a loop to look for first "trap".
	(child_resume): Avoid accessing a possibly-freed thread pointer.
	(_initialize_inftarg): Add "dll-symbols", "sharedlibrary", and "info
	sharedlibrary" commands.
	* config/i386/tm-cygwin.h: Add some shared library (aka DLL) hooks.

Index: win32-nat.c
===================================================================
RCS file: /cvs/src/src/gdb/win32-nat.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -r1.9 -r1.10
--- win32-nat.c	2000/06/03 05:04:14	1.9
+++ win32-nat.c	2000/06/04 00:28:17	1.10
@@ -58,8 +58,6 @@
 #define CONTEXT_DEBUGGER (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
 #endif
 
-#define FIRST_EXCEPTION 0xffffffff
-
 /* The string sent by cygwin when it processes a signal.
    FIXME: This should be in a cygwin include file. */
 #define CYGWIN_SIGNAL_STRING "cygwin: signal"
@@ -415,6 +413,8 @@
   return 0;
 }
 
+/* Encapsulate the information required in a call to
+   symbol_file_add_args */
 struct safe_symbol_file_add_args
 {
   char *name;
@@ -425,6 +425,8 @@
   struct objfile *ret;
 };
 
+/* Call symbol_file_add with stderr redirected.  We don't care if there
+   are errors. */
 static int
 safe_symbol_file_add_stub (void *argv)
 {
@@ -434,13 +436,16 @@
 #undef p
 }
 
+/* Restore gdb's stderr after calling symbol_file_add */
 static void
 safe_symbol_file_add_cleanup (void *gdb_stderrv)
 {
+  gdb_flush (gdb_stderr);
   ui_file_delete (gdb_stderr);
   gdb_stderr = (struct ui_file *)gdb_stderrv;
 }
 
+/* symbol_file_add wrapper that prevents errors from being displayed. */
 static struct objfile *
 safe_symbol_file_add (char *name, int from_tty,
 		      struct section_addr_info *addrs,
@@ -452,6 +457,7 @@
 
   cleanup = make_cleanup (safe_symbol_file_add_cleanup, gdb_stderr);
 
+  gdb_flush (gdb_stderr);
   gdb_stderr = ui_file_new ();
   p.name = name;
   p.from_tty = from_tty;
@@ -464,9 +470,19 @@
   return p.ret;
 }
 
+/* Maintain a linked list of "so" information. */
+struct so_stuff
+{
+  struct so_stuff *next, **last;
+  DWORD load_addr;
+  char name[0];
+} solib_start, *solib_end;
+
+/* Remember the maximum DLL length for printing in info dll command. */
+int max_dll_name_len;
+
 /* 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 (PTR dummy ATTRIBUTE_UNUSED)
 {
@@ -474,10 +490,12 @@
   DWORD dll_name_ptr;
   DWORD done;
   char dll_buf[MAX_PATH + 1];
-  char *p, *dll_name = NULL;
-  struct section_addr_info section_addrs;
+  struct so_stuff *so, *solast;
+  char *dll_name = NULL;
+  DWORD dll_base = 0;
+  int len;
+  char *p;
 
-  memset (&section_addrs, 0, sizeof (section_addrs));
   dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
 
   if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
@@ -549,16 +567,94 @@
   while ((p = strchr (dll_name, '\\')))
     *p = '/';
 
+  so = (struct so_stuff *) xmalloc (sizeof (struct so_stuff) +  strlen (dll_name) + 8 + 2);
+  so->load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
+  strcpy (so->name, dll_name);
+
+  solib_end->next = so;
+  solib_end = so;
+  so->next = NULL;
+
+  len = strlen (dll_name);
+  if (len > max_dll_name_len)
+    max_dll_name_len = len;
+
+  return 1;
+}
+
+/* Return name of last loaded DLL. */
+char *
+child_solib_loaded_library_pathname (int pid)
+{
+  return !solib_end || !solib_end->name[0]? NULL : solib_end->name;
+}
+
+/* Clear list of loaded DLLs. */
+void
+child_clear_solibs (void)
+{
+  struct so_stuff *so, *so1 = solib_start.next;
+
+  while ((so = so1) != NULL)
+    {
+      so1 = so->next;
+      free (so);
+    }
+
+  solib_start.next = NULL;
+  solib_end = &solib_start;
+  max_dll_name_len = sizeof ("DLL Name") - 1;
+}
+
+/* Add DLL symbol information. */
+void
+child_solib_add (char *filename, int from_tty, struct target_ops *t)
+{
+  struct section_addr_info section_addrs;
+
   /* 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. */
 
+  if (!solib_end || !solib_end->name[0])
+    return;
+
+  memset (&section_addrs, 0, sizeof (section_addrs));
   section_addrs.other[0].name = ".text";
-  section_addrs.other[0].addr = (int) event->lpBaseOfDll + 0x1000;
-  safe_symbol_file_add (dll_name, 0, &section_addrs, 0, OBJF_SHARED);
-  printf_unfiltered ("%lx:%s\n", (DWORD) event->lpBaseOfDll, dll_name);
+  section_addrs.other[0].addr = solib_end->load_addr;
+  safe_symbol_file_add (solib_end->name, 0, &section_addrs, 0, OBJF_SHARED);
 
-  return 1;
+  return;
+}
+
+/* Load DLL symbol info. */
+void
+dll_symbol_command (char *args, int from_tty)
+{
+  struct section_addr_info section_addrs;
+
+  dont_repeat ();
+  
+  if (args == NULL)
+    error ("dll-symbols requires a file name");
+
+  safe_symbol_file_add (args, 0, NULL, 0, OBJF_SHARED);
+} 
+
+/* List currently loaded DLLs. */
+void
+info_dll_command (char *ignore, int from_tty)
+{
+  struct so_stuff *so = &solib_start;
+
+  if (!so->next)
+    return;
+
+  printf ("%*s  Load Address\n", -max_dll_name_len, "DLL Name");
+  while ((so = so->next) != NULL)
+    printf_unfiltered ("%*s  %08lx\n", -max_dll_name_len, so->name, so->load_addr);
+
+  return;
 }
 
 /* Handle DEBUG_STRING output from child process.
@@ -595,14 +691,11 @@
 }
 
 static int
-handle_exception (struct target_waitstatus *ourstatus, int ignore_trap)
+handle_exception (struct target_waitstatus *ourstatus)
 {
   thread_info *th;
   DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
 
-  if (ignore_trap && code == EXCEPTION_BREAKPOINT)
-    return 0;
-
   ourstatus->kind = TARGET_WAITKIND_STOPPED;
 
   /* Record the context of the current thread */
@@ -696,16 +789,15 @@
    handling by WFI (or whatever).
  */
 static int
-get_child_debug_event (int pid ATTRIBUTE_UNUSED, struct target_waitstatus *ourstatus,
-		       DWORD target_event_code, int *retval)
+get_child_debug_event (int pid ATTRIBUTE_UNUSED, struct target_waitstatus *ourstatus)
 {
   int breakout = 0;
   BOOL debug_event;
   DWORD continue_status, event_code;
   thread_info *th = NULL;
   static thread_info dummy_thread_info;
+  int retval = 0;
 
-  *retval = 0;
   if (!(debug_event = WaitForDebugEvent (&current_event, 1000)))
     goto out;
 
@@ -713,7 +805,7 @@
   continue_status = DBG_CONTINUE;
 
   event_code = current_event.dwDebugEventCode;
-  breakout = event_code == target_event_code;
+  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
 
   switch (event_code)
     {
@@ -728,6 +820,7 @@
       if (info_verbose)
 	printf_unfiltered ("[New %s]\n",
 			   target_pid_to_str (current_event.dwThreadId));
+      retval = current_event.dwThreadId;
       break;
 
     case EXIT_THREAD_DEBUG_EVENT:
@@ -748,8 +841,11 @@
 
       main_thread_id = inferior_pid = current_event.dwThreadId;
       /* Add the main thread */
+      th = child_add_thread (current_event.dwProcessId,
+			     current_event.u.CreateProcessInfo.hProcess);
       th = child_add_thread (inferior_pid,
 			     current_event.u.CreateProcessInfo.hThread);
+      retval = ourstatus->value.related_pid = current_event.dwProcessId;
       break;
 
     case EXIT_PROCESS_DEBUG_EVENT:
@@ -760,8 +856,7 @@
       ourstatus->kind = TARGET_WAITKIND_EXITED;
       ourstatus->value.integer = current_event.u.ExitProcess.dwExitCode;
       CloseHandle (current_process_handle);
-      *retval = current_event.dwProcessId;
-      breakout = 1;
+      retval = current_event.dwProcessId;
       break;
 
     case LOAD_DLL_DEBUG_EVENT:
@@ -771,6 +866,9 @@
 		     "LOAD_DLL_DEBUG_EVENT"));
       catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
       registers_changed ();	/* mark all regs invalid */
+      ourstatus->kind = TARGET_WAITKIND_LOADED;
+      ourstatus->value.integer = 0;
+      retval = current_event.dwProcessId;
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
@@ -785,10 +883,8 @@
 		     (unsigned) current_event.dwProcessId,
 		     (unsigned) current_event.dwThreadId,
 		     "EXCEPTION_DEBUG_EVENT"));
-      if (handle_exception (ourstatus, target_event_code == FIRST_EXCEPTION))
-	*retval = current_event.dwThreadId;
-      else
-	breakout = -1;
+      handle_exception (ourstatus);
+      retval = current_event.dwThreadId;
       break;
 
     case OUTPUT_DEBUG_STRING_EVENT:	/* message from the kernel */
@@ -796,7 +892,8 @@
 		     (unsigned) current_event.dwProcessId,
 		     (unsigned) current_event.dwThreadId,
 		     "OUTPUT_DEBUG_STRING_EVENT"));
-      handle_output_debug_string ( ourstatus);
+      if (handle_output_debug_string ( ourstatus))
+	retval = current_event.dwProcessId;
       break;
     default:
       printf_unfiltered ("gdb: kernel event for pid=%ld tid=%ld\n",
@@ -807,21 +904,19 @@
       break;
     }
 
-  if (breakout > 0)
-    current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
-  else if (!breakout)
+  if (!retval)
     CHECK (child_continue (continue_status, -1));
+  else
+    current_thread = th ?: thread_rec (current_event.dwThreadId, TRUE);
 
 out:
-  return breakout;
+  return retval;
 }
 
 /* Wait for interesting events to occur in the target process. */
 static int
 child_wait (int pid, struct target_waitstatus *ourstatus)
 {
-  int retval;
-
   /* We loop when we get a non-standard exception rather than return
      with a SPURIOUS because resume can try and step or modify things,
      which needs a current_thread->h.  But some of these exceptions mark
@@ -829,18 +924,21 @@
      isn't necessarily what you think it is. */
 
   while (1)
-    if (get_child_debug_event (pid, ourstatus, EXCEPTION_DEBUG_EVENT, &retval))
-      return retval;
-    else
-      {
-	int detach = 0;
+    {
+      int retval = get_child_debug_event (pid, ourstatus);
+      if (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.  */
@@ -865,6 +963,9 @@
   exception_count = 0;
   event_count = 0;
 
+  child_init_thread_list ();
+  child_clear_solibs ();
+
   if (from_tty)
     {
       char *exec_file = (char *) get_exec_file (0);
@@ -936,11 +1037,10 @@
   BOOL ret;
   DWORD flags;
   char *args;
+  extern int stop_after_trap;
 
   if (!exec_file)
-    {
-      error ("No executable specified, use `target exec'.\n");
-    }
+    error ("No executable specified, use `target exec'.\n");
 
   memset (&si, 0, sizeof (si));
   si.cb = sizeof (si);
@@ -1057,16 +1157,23 @@
   inferior_pid = current_event.dwThreadId = pi.dwThreadId;
   push_target (&child_ops);
   child_init_thread_list ();
-  init_wait_for_inferior ();
+  child_clear_solibs ();
   clear_proceed_status ();
+  init_wait_for_inferior ();
   target_terminal_init ();
   target_terminal_inferior ();
   last_sig = 0;
 
-  /* Run until process and threads are loaded */
-  while (!get_child_debug_event (inferior_pid, &dummy,
-				 FIRST_EXCEPTION, &ret))
-    continue;
+  while (1)
+    {
+      stop_after_trap = 1;
+      wait_for_inferior ();
+      if (stop_signal != TARGET_SIGNAL_TRAP)
+	resume (0, stop_signal);
+      else
+	break;
+    }
+  stop_after_trap = 0;
 
   /* child_continue (DBG_CONTINUE, -1);*/
   proceed ((CORE_ADDR) - 1, TARGET_SIGNAL_0, 0);
@@ -1150,19 +1257,20 @@
 
   /* Get context for currently selected thread */
   th = thread_rec (current_event.dwThreadId, FALSE);
-  if (step)
+  if (th)
     {
-#ifdef i386
-      /* Single step by setting t bit */
-      child_fetch_inferior_registers (PS_REGNUM);
-      th->context.EFlags |= FLAG_TRACE_BIT;
-#endif
-    }
+      if (step)
+	{
+	  /* Single step by setting t bit */
+	  child_fetch_inferior_registers (PS_REGNUM);
+	  th->context.EFlags |= FLAG_TRACE_BIT;
+	}
 
-  if (th->context.ContextFlags)
-    {
-      CHECK (SetThreadContext (th->h, &th->context));
-      th->context.ContextFlags = 0;
+      if (th->context.ContextFlags)
+	{
+	  CHECK (SetThreadContext (th->h, &th->context));
+	  th->context.ContextFlags = 0;
+	}
     }
 
   /* Allow continuing with the same signal that interrupted us.
@@ -1241,48 +1349,50 @@
 _initialize_inftarg ()
 {
   init_child_ops ();
+
+  add_com ("dll-symbols", class_files, dll_symbol_command,
+           "Load dll library symbols from FILE.");
 
-  add_show_from_set
-    (add_set_cmd ("new-console", class_support, var_boolean,
+  add_com_alias ("sharedlibrary", "dll-symbols", class_alias, 1);
+
+  add_show_from_set (add_set_cmd ("new-console", class_support, var_boolean,
 		  (char *) &new_console,
 		  "Set creation of new console when creating child process.",
 		  &setlist),
      &showlist);
 
-  add_show_from_set
-    (add_set_cmd ("new-group", class_support, var_boolean,
+  add_show_from_set (add_set_cmd ("new-group", class_support, var_boolean,
 		  (char *) &new_group,
 		  "Set creation of new group when creating child process.",
 		  &setlist),
      &showlist);
 
-  add_show_from_set
-    (add_set_cmd ("debugexec", class_support, var_boolean,
+  add_show_from_set (add_set_cmd ("debugexec", class_support, var_boolean,
 		  (char *) &debug_exec,
 		  "Set whether to display execution in child process.",
 		  &setlist),
      &showlist);
 
-  add_show_from_set
-    (add_set_cmd ("debugevents", class_support, var_boolean,
+  add_show_from_set (add_set_cmd ("debugevents", class_support, var_boolean,
 		  (char *) &debug_events,
 		  "Set whether to display kernel events in child process.",
 		  &setlist),
      &showlist);
 
-  add_show_from_set
-    (add_set_cmd ("debugmemory", class_support, var_boolean,
+  add_show_from_set (add_set_cmd ("debugmemory", class_support, var_boolean,
 		  (char *) &debug_memory,
 		  "Set whether to display memory accesses in child process.",
 		  &setlist),
      &showlist);
 
-  add_show_from_set
-    (add_set_cmd ("debugexceptions", class_support, var_boolean,
+  add_show_from_set (add_set_cmd ("debugexceptions", class_support, var_boolean,
 		  (char *) &debug_exceptions,
-	       "Set whether to display kernel exceptions in child process.",
+		  "Set whether to display kernel exceptions in child process.",
 		  &setlist),
      &showlist);
+
+  add_info ("dll", info_dll_command, "Status of loaded DLLs.");
+  add_info_alias ("sharedlibrary", "dll", 1);
 
   add_target (&child_ops);
 }
Index: config/i386/tm-cygwin.h
===================================================================
RCS file: /cvs/src/src/gdb/config/i386/tm-cygwin.h,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- tm-cygwin.h	2000/05/28 01:12:35	1.3
+++ tm-cygwin.h	2000/06/04 00:28:17	1.4
@@ -24,8 +24,20 @@
 
 #include "i386/tm-i386v.h"
 
+#if 0
 #define IN_SOLIB_CALL_TRAMPOLINE(pc, name) skip_trampoline_code (pc, name)
 #define SKIP_TRAMPOLINE_CODE(pc)           skip_trampoline_code (pc, 0)
 extern CORE_ADDR skip_trampoline_code (CORE_ADDR pc, char *name);
+#endif
 
-extern char *cygwin_pid_to_str (int pid);
+#define SOLIB_ADD(filename, from_tty, targ) child_solib_add(filename, from_tty, targ)
+#define SOLIB_LOADED_LIBRARY_PATHNAME(pid) child_solib_loaded_library_pathname(pid)
+#define CLEAR_SOLIB child_clear_solib
+#define ADD_SHARED_SYMBOL_FILES dll_symbol_command
+
+struct target_ops;
+char *cygwin_pid_to_str (int pid);
+void child_solib_add (char *, int, struct target_ops *);
+char *child_solib_loaded_library_pathname(int);
+void child_clear_solib (void);
+void dll_symbol_command (char *, int);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]