This is the mail archive of the gdb-patches@sourceware.org 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]
Other format: [Raw text]

For example only, updated Windows DLL support and gdbserver DLL support


Here's the latest version of my Windows support patch to go with the
previous shared library event support.  Most of this is originally
Pedro's work.  It includes native GDB and remote gdbserver support,
and also fixes a bug in native support where symbols for shared
libraries were not being loaded.

It converts the Windows port to more aggressively fetch the whole list
of libraries from the target.  This is not actually necessary; we
could keep using the load and unload debug messages instead, and
maintain the list separately from solib-target.c.  That wouldn't be
hard.  I haven't decided which would be better yet; this patch is just
as example of the new mechanism.

Ulrich, what do you think - would this work for AIX solib support?

-- 
Daniel Jacobowitz
CodeSourcery

---
 gdb/Makefile.in                   |    9 
 gdb/coff-pe-read.c                |    3 
 gdb/config/i386/cygwin.mh         |    2 
 gdb/config/i386/cygwin.mt         |    3 
 gdb/corelow.c                     |   10 
 gdb/gdb_obstack.h                 |    5 
 gdb/gdbcore.h                     |    9 
 gdb/gdbserver/inferiors.c         |  101 ++++
 gdb/gdbserver/remote-utils.c      |   71 +++
 gdb/gdbserver/server.c            |   73 +++
 gdb/gdbserver/server.h            |   22 -
 gdb/gdbserver/win32-low.c         |  332 +++++++++++++++
 gdb/infcmd.c                      |    8 
 gdb/testsuite/gdb.base/unload.c   |   14 
 gdb/testsuite/gdb.base/unload.exp |   23 -
 gdb/win32-nat.c                   |  802 ++++++++++++++++++--------------------
 gdb/xml-support.c                 |   67 +++
 gdb/xml-support.h                 |   42 +
 libiberty/lbasename.c             |    4 
 19 files changed, 1118 insertions(+), 482 deletions(-)

Index: src/gdb/Makefile.in
===================================================================
--- src.orig/gdb/Makefile.in	2007-06-18 10:22:28.000000000 -0400
+++ src/gdb/Makefile.in	2007-06-18 10:22:35.000000000 -0400
@@ -610,6 +610,7 @@ mep_desc_h =	$(OPCODES_SRC)/mep-desc.h
 mep_opc_h =	$(OPCODES_SRC)/mep-opc.h
 sh_opc_h = 	$(OPCODES_SRC)/sh-opc.h
 gdb_callback_h = $(INCLUDE_DIR)/gdb/callback.h
+gdb_fileio_h = $(INCLUDE_DIR)/gdb/fileio.h
 gdb_sim_arm_h =	$(INCLUDE_DIR)/gdb/sim-arm.h
 gdb_sim_frv_h = $(INCLUDE_DIR)/gdb/sim-frv.h
 gdb_sim_m32c_h = $(INCLUDE_DIR)/gdb/sim-m32c.h
@@ -2403,7 +2404,7 @@ objc-lang.o: objc-lang.c $(defs_h) $(sym
 	$(objfiles_h) $(gdb_string_h) $(target_h) $(gdbcore_h) $(gdbcmd_h) \
 	$(frame_h) $(gdb_regex_h) $(regcache_h) $(block_h) $(infcall_h) \
 	$(valprint_h) $(gdb_assert_h)
-objfiles.o: objfiles.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) \
+objfiles.o: objfiles.c $(defs_h) $(bfd_h) $(symtab_h) $(symfile_h) $(exec_h) \
 	$(objfiles_h) $(gdb_stabs_h) $(target_h) $(bcache_h) $(mdebugread_h) \
 	$(gdb_assert_h) $(gdb_stat_h) $(gdb_obstack_h) $(gdb_string_h) \
 	$(hashtab_h) $(breakpoint_h) $(block_h) $(dictionary_h) $(source_h) \
@@ -2490,7 +2491,8 @@ remote.o: remote.c $(defs_h) $(gdb_strin
 	$(gdb_stabs_h) $(gdbthread_h) $(remote_h) $(regcache_h) $(value_h) \
 	$(gdb_assert_h) $(event_loop_h) $(event_top_h) $(inf_loop_h) \
 	$(serial_h) $(gdbcore_h) $(remote_fileio_h) $(solib_h) $(observer_h) \
-	$(cli_decode_h) $(cli_setshow_h) $(memory_map_h) $(target_descriptions_h)
+	$(cli_decode_h) $(cli_setshow_h) $(memory_map_h) \
+	$(target_descriptions_h) $(solist_h) $(gdb_fileio_h)
 remote-fileio.o: remote-fileio.c $(defs_h) $(gdb_string_h) $(gdbcmd_h) \
 	$(remote_h) $(gdb_fileio_h) $(gdb_wait_h) $(gdb_stat_h) \
 	$(exceptions_h) $(remote_fileio_h)
@@ -2572,7 +2574,7 @@ solib.o: solib.c $(defs_h) $(gdb_string_
 	$(objfiles_h) $(exceptions_h) $(gdbcore_h) $(command_h) $(target_h) \
 	$(frame_h) $(gdb_regex_h) $(inferior_h) $(environ_h) $(language_h) \
 	$(gdbcmd_h) $(completer_h) $(filenames_h) $(exec_h) $(solist_h) \
-	$(observer_h) $(readline_h)
+	$(observer_h) $(readline_h) $(exceptions_h)
 solib-frv.o: solib-frv.c $(defs_h) $(gdb_string_h) $(inferior_h) \
 	$(gdbcore_h) $(solist_h) $(frv_tdep_h) $(objfiles_h) $(symtab_h) \
 	$(language_h) $(command_h) $(gdbcmd_h) $(elf_frv_h) $(solib_h)
@@ -2700,6 +2702,7 @@ stack.o: stack.c $(defs_h) $(value_h) $(
 	$(valprint_h) $(gdb_assert_h) $(gdb_string_h)
 std-regs.o: std-regs.c $(defs_h) $(user_regs_h) $(frame_h) $(gdbtypes_h) \
 	$(value_h) $(gdb_string_h)
+symbian-tdep.o: symbian-tdep.c $(defs_h) $(solib_h)
 symfile.o: symfile.c $(defs_h) $(bfdlink_h) $(symtab_h) $(gdbtypes_h) \
 	$(gdbcore_h) $(frame_h) $(target_h) $(value_h) $(symfile_h) \
 	$(objfiles_h) $(source_h) $(gdbcmd_h) $(breakpoint_h) $(language_h) \
Index: src/gdb/config/i386/cygwin.mh
===================================================================
--- src.orig/gdb/config/i386/cygwin.mh	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/config/i386/cygwin.mh	2007-06-18 10:22:35.000000000 -0400
@@ -1,4 +1,4 @@
 MH_CFLAGS=
-NATDEPFILES= i386-nat.o win32-nat.o corelow.o
+NATDEPFILES= i386-nat.o win32-nat.o
 NAT_FILE=nm-cygwin.h
 XM_CLIBS=
Index: src/gdb/config/i386/cygwin.mt
===================================================================
--- src.orig/gdb/config/i386/cygwin.mt	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/config/i386/cygwin.mt	2007-06-18 10:22:35.000000000 -0400
@@ -1,2 +1,3 @@
 # Target: Intel 386 run win32
-TDEPFILES= i386-tdep.o i386-cygwin-tdep.o i387-tdep.o
+TDEPFILES= i386-tdep.o i386-cygwin-tdep.o i387-tdep.o \
+	   corelow.o solib-target.o
Index: src/gdb/corelow.c
===================================================================
--- src.orig/gdb/corelow.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/corelow.c	2007-06-18 10:22:35.000000000 -0400
@@ -526,8 +526,8 @@ core_xfer_partial (struct target_ops *op
 	return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
 					       0/*write*/, NULL, ops);
       if (writebuf)
-	return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
-					       1/*write*/, NULL, ops);
+	return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
+					       len, 1/*write*/, NULL, ops);
       return -1;
 
     case TARGET_OBJECT_AUXV:
@@ -594,6 +594,12 @@ core_xfer_partial (struct target_ops *op
 	}
       return -1;
 
+    case TARGET_OBJECT_LIBRARIES:
+      if (core_vec->xfer_shared_libraries != NULL)
+	return core_vec->xfer_shared_libraries (ops, object, annex, readbuf,
+					       writebuf, offset, len);
+      /* FALL THROUGH */
+
     default:
       if (ops->beneath != NULL)
 	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
Index: src/gdb/gdbcore.h
===================================================================
--- src.orig/gdb/gdbcore.h	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/gdbcore.h	2007-06-18 10:22:35.000000000 -0400
@@ -29,6 +29,7 @@ struct type;
 struct regcache;
 
 #include "bfd.h"
+#include "target.h"
 
 /* Return the name of the executable file as a string.
    ERR nonzero means get error if there is none specified;
@@ -193,6 +194,14 @@ struct core_fns
 				 unsigned core_reg_size,
 				 int which, CORE_ADDR reg_addr);
 
+    /* Refresh the list of shared libraries.  */
+    LONGEST (*xfer_shared_libraries) (struct target_ops *ops,
+				      enum target_object object,
+				      const char *annex,
+				      gdb_byte *readbuf,
+				      const gdb_byte *writebuf,
+				      ULONGEST offset, LONGEST len);
+
     /* Finds the next struct core_fns.  They are allocated and
        initialized in whatever module implements the functions pointed
        to; an initializer calls deprecated_add_core_fns to add them to
Index: src/gdb/gdbserver/inferiors.c
===================================================================
--- src.orig/gdb/gdbserver/inferiors.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/gdbserver/inferiors.c	2007-06-18 10:22:35.000000000 -0400
@@ -33,10 +33,13 @@ struct thread_info
 };
 
 struct inferior_list all_threads;
+struct inferior_list all_dlls;
+int dlls_changed;
 
 struct thread_info *current_inferior;
 
 #define get_thread(inf) ((struct thread_info *)(inf))
+#define get_dll(inf) ((struct dll_info *)(inf))
 
 void
 add_inferior_to_list (struct inferior_list *list,
@@ -104,15 +107,14 @@ remove_inferior (struct inferior_list *l
 void
 add_thread (unsigned long thread_id, void *target_data, unsigned int gdb_id)
 {
-  struct thread_info *new_thread
-    = (struct thread_info *) malloc (sizeof (*new_thread));
+  struct thread_info *new_thread = malloc (sizeof (*new_thread));
 
   memset (new_thread, 0, sizeof (*new_thread));
 
   new_thread->entry.id = thread_id;
 
   add_inferior_to_list (&all_threads, & new_thread->entry);
-  
+
   if (current_inferior == NULL)
     current_inferior = new_thread;
 
@@ -182,14 +184,6 @@ remove_thread (struct thread_info *threa
   free_one_thread (&thread->entry);
 }
 
-void
-clear_inferiors (void)
-{
-  for_each_inferior (&all_threads, free_one_thread);
-
-  all_threads.head = all_threads.tail = NULL;
-}
-
 struct inferior_list_entry *
 find_inferior (struct inferior_list *list,
 	       int (*func) (struct inferior_list_entry *, void *), void *arg)
@@ -244,3 +238,88 @@ set_inferior_regcache_data (struct threa
 {
   inferior->regcache_data = data;
 }
+
+static struct dll_info *
+make_new_dll (const char *name, CORE_ADDR base_addr)
+{
+  struct dll_info *new_dll = malloc (sizeof (*new_dll));
+  memset (new_dll, 0, sizeof (*new_dll));
+
+  new_dll->entry.id = -1;
+
+  new_dll->name = strdup (name);
+  new_dll->base_addr = base_addr;
+
+  return new_dll;
+}
+
+static void
+free_one_dll (struct inferior_list_entry *inf)
+{
+  struct dll_info *dll = get_dll (inf);
+  if (dll->name != NULL)
+    free (dll->name);
+  free (dll);
+}
+
+static void
+free_dll (struct dll_info *dll)
+{
+  remove_inferior (&all_dlls, &dll->entry);
+  free_one_dll (&dll->entry);
+}
+
+static int
+match_dll (struct inferior_list_entry *inf, void *arg)
+{
+  struct dll_info *iter = (void *) inf;
+  struct dll_info *key = arg;
+
+  if (key->base_addr != ~(CORE_ADDR) 0
+      && iter->base_addr == key->base_addr)
+    return 1;
+  else if (key->name != NULL
+	   && iter->name != NULL
+	   && strcmp (key->name, iter->name) == 0)
+    return 1;
+
+  return 0;
+}
+
+void
+loaded_dll (const char *name, CORE_ADDR base_addr)
+{
+  struct dll_info *dll;
+
+  dll = make_new_dll (name, base_addr);
+  add_inferior_to_list (&all_dlls, &dll->entry);
+  dlls_changed = 1;
+}
+
+void
+unloaded_dll (const char *name, CORE_ADDR base_addr)
+{
+  struct dll_info *dll;
+
+  /* Be careful not to put this dll in any list... */
+  struct dll_info key_dll;
+  key_dll.name = (char *) name;
+  key_dll.base_addr = base_addr;
+
+  dll = (void *) find_inferior (&all_dlls, match_dll, &key_dll);
+  free_dll (dll);
+  dlls_changed = 1;
+}
+
+#define clear_list(LIST) \
+  do { (LIST)->head = (LIST)->tail = NULL; } while (0)
+
+void
+clear_inferiors (void)
+{
+  for_each_inferior (&all_threads, free_one_thread);
+  for_each_inferior (&all_dlls, free_one_dll);
+
+  clear_list (&all_threads);
+  clear_list (&all_dlls);
+}
Index: src/gdb/gdbserver/remote-utils.c
===================================================================
--- src.orig/gdb/gdbserver/remote-utils.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/gdbserver/remote-utils.c	2007-06-18 10:22:35.000000000 -0400
@@ -650,6 +650,7 @@ block_async_io (void)
 {
 #ifndef USE_WIN32API
   sigset_t sigio_set;
+
   sigemptyset (&sigio_set);
   sigaddset (&sigio_set, SIGIO);
   sigprocmask (SIG_BLOCK, &sigio_set, NULL);
@@ -661,6 +662,7 @@ unblock_async_io (void)
 {
 #ifndef USE_WIN32API
   sigset_t sigio_set;
+
   sigemptyset (&sigio_set);
   sigaddset (&sigio_set, SIGIO);
   sigprocmask (SIG_UNBLOCK, &sigio_set, NULL);
@@ -965,6 +967,13 @@ prepare_resume_reply (char *buf, char st
 	      old_thread_from_wait = thread_from_wait;
 	    }
 	}
+
+      if (dlls_changed)
+	{
+	  strcpy (buf, "library:;");
+	  buf += strlen (buf);
+	  dlls_changed = 0;
+	}
     }
   /* For W and X, we're done.  */
   *buf++ = 0;
@@ -1153,3 +1162,65 @@ monitor_output (const char *msg)
   putpkt (buf);
   free (buf);
 }
+
+/* Return a malloc allocated string with special characters from TEXT
+   replaced by entity references.  */
+
+char *
+xml_escape_text (const char *text)
+{
+  char *result;
+  int i, special;
+
+  /* Compute the length of the result.  */
+  for (i = 0, special = 0; text[i] != '\0'; i++)
+    switch (text[i])
+      {
+      case '\'':
+      case '\"':
+	special += 5;
+	break;
+      case '&':
+	special += 4;
+	break;
+      case '<':
+      case '>':
+	special += 3;
+	break;
+      default:
+	break;
+      }
+
+  /* Expand the result.  */
+  result = malloc (i + special + 1);
+  for (i = 0, special = 0; text[i] != '\0'; i++)
+    switch (text[i])
+      {
+      case '\'':
+	strcpy (result + i + special, "&apos;");
+	special += 5;
+	break;
+      case '\"':
+	strcpy (result + i + special, "&quot;");
+	special += 5;
+	break;
+      case '&':
+	strcpy (result + i + special, "&amp;");
+	special += 4;
+	break;
+      case '<':
+	strcpy (result + i + special, "&lt;");
+	special += 3;
+	break;
+      case '>':
+	strcpy (result + i + special, "&gt;");
+	special += 3;
+	break;
+      default:
+	result[i + special] = text[i];
+	break;
+      }
+  result[i + special] = '\0';
+
+  return result;
+}
Index: src/gdb/gdbserver/server.c
===================================================================
--- src.orig/gdb/gdbserver/server.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/gdbserver/server.c	2007-06-18 10:22:35.000000000 -0400
@@ -458,12 +458,74 @@ handle_query (char *own_buf, int packet_
       return;
     }
 
+  if (strncmp ("qXfer:libraries:read:", own_buf, 21) == 0)
+    {
+      CORE_ADDR ofs;
+      unsigned int len, total_len;
+      char *document, *p;
+      struct inferior_list_entry *dll_ptr;
+      char *annex;
+
+      /* Reject any annex; grab the offset and length.  */
+      if (decode_xfer_read (own_buf + 21, &annex, &ofs, &len) < 0
+	  || annex[0] != '\0')
+	{
+	  strcpy (own_buf, "E00");
+	  return;
+	}
+
+      /* FIXME: Handle memory management later.  */
+      document = malloc (4096);
+      strcpy (document, "<library-list>\n");
+      p = document + strlen (document);
+
+      for (dll_ptr = all_dlls.head; dll_ptr != NULL; dll_ptr = dll_ptr->next)
+	{
+	  struct dll_info *dll = (struct dll_info *) dll_ptr;
+	  char *name;
+
+	  strcpy (p, "  <library name=\"");
+	  p = p + strlen (p);
+	  name = xml_escape_text (dll->name);
+	  strcpy (p, name);
+	  free (name);
+	  p = p + strlen (p);
+	  strcpy (p, "\"><segment address=\"");
+	  p = p + strlen (p);
+	  sprintf (p, "0x%lx", (long) dll->base_addr);
+	  p = p + strlen (p);
+	  strcpy (p, "\"/></library>\n");
+	  p = p + strlen (p);
+	}
+
+      strcpy (p, "</library-list>\n");
+
+      total_len = strlen (document);
+      if (len > PBUFSIZ - 2)
+	len = PBUFSIZ - 2;
+
+      if (ofs > total_len)
+	write_enn (own_buf);
+      else if (len < total_len - ofs)
+	*new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
+						  len, 1);
+      else
+	*new_packet_len_p = write_qxfer_response (own_buf, document + ofs,
+						  total_len - ofs, 0);
+
+      return;
+    }
+
   /* Protocol features query.  */
   if (strncmp ("qSupported", own_buf, 10) == 0
       && (own_buf[10] == ':' || own_buf[10] == '\0'))
     {
       sprintf (own_buf, "PacketSize=%x;QPassSignals+", PBUFSIZ - 1);
 
+      /* We do not have any hook to indicate whether the target backend
+	 supports qXfer:libraries:read, so always report it.  */
+      strcat (own_buf, ";qXfer:libraries:read+");
+
       if (the_target->read_auxv != NULL)
 	strcat (own_buf, ";qXfer:auxv:read+");
      
@@ -696,8 +758,7 @@ handle_v_cont (char *own_buf, char *stat
   return;
 
 err:
-  /* No other way to report an error... */
-  strcpy (own_buf, "");
+  write_enn (own_buf);
   free (resume_info);
   return;
 }
@@ -753,7 +814,7 @@ static void
 gdbserver_version (void)
 {
   printf ("GNU gdbserver %s\n"
-	  "Copyright (C) 2006 Free Software Foundation, Inc.\n"
+	  "Copyright (C) 2007 Free Software Foundation, Inc.\n"
 	  "gdbserver is free software, covered by the GNU General Public License.\n"
 	  "This gdbserver was configured as \"%s\"\n",
 	  version, host_name);
@@ -824,7 +885,7 @@ main (int argc, char *argv[])
 
   initialize_low ();
 
-  own_buf = malloc (PBUFSIZ);
+  own_buf = malloc (PBUFSIZ + 1);
   mem_buf = malloc (PBUFSIZ);
 
   if (pid == 0)
@@ -833,6 +894,10 @@ main (int argc, char *argv[])
       signal = start_inferior (&argv[2], &status);
 
       /* We are now stopped at the first instruction of the target process */
+
+      /* Don't report shared library events on the initial connection,
+	 even if some libraries are preloaded.  */
+      dlls_changed = 0;
     }
   else
     {
Index: src/gdb/gdbserver/server.h
===================================================================
--- src.orig/gdb/gdbserver/server.h	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/gdbserver/server.h	2007-06-18 10:22:35.000000000 -0400
@@ -91,6 +91,13 @@ struct inferior_list_entry
 /* Opaque type for user-visible threads.  */
 struct thread_info;
 
+struct dll_info
+{
+  struct inferior_list_entry entry;
+  char *name;
+  CORE_ADDR base_addr;
+};
+
 #include "regcache.h"
 #include "gdb/signals.h"
 
@@ -104,19 +111,24 @@ void initialize_low ();
 /* From inferiors.c.  */
 
 extern struct inferior_list all_threads;
+extern struct inferior_list all_dlls;
+extern int dlls_changed;
+
 void add_inferior_to_list (struct inferior_list *list,
 			   struct inferior_list_entry *new_inferior);
 void for_each_inferior (struct inferior_list *list,
 			void (*action) (struct inferior_list_entry *));
-extern struct thread_info *current_inferior;
 void remove_inferior (struct inferior_list *list,
 		      struct inferior_list_entry *entry);
+
+extern struct thread_info *current_inferior;
 void remove_thread (struct thread_info *thread);
 void add_thread (unsigned long thread_id, void *target_data, unsigned int);
 unsigned int thread_id_to_gdb_id (unsigned long);
 unsigned int thread_to_gdb_id (struct thread_info *);
 unsigned long gdb_id_to_thread_id (unsigned int);
 struct thread_info *gdb_id_to_thread (unsigned int);
+
 void clear_inferiors (void);
 struct inferior_list_entry *find_inferior
      (struct inferior_list *,
@@ -132,6 +144,9 @@ void set_inferior_regcache_data (struct 
 void change_inferior_id (struct inferior_list *list,
 			 unsigned long new_id);
 
+void loaded_dll (const char *name, CORE_ADDR base_addr);
+void unloaded_dll (const char *name, CORE_ADDR base_addr);
+
 /* Public variables in server.c */
 
 extern unsigned long cont_thread;
@@ -145,6 +160,9 @@ extern int pass_signals[];
 
 extern jmp_buf toplevel;
 
+/* Functions from hostio.c.  */
+extern int handle_f_hostio (char *, int, int *);
+
 /* From remote-utils.c */
 
 extern int remote_debug;
@@ -190,6 +208,8 @@ int look_up_one_symbol (const char *name
 
 void monitor_output (const char *msg);
 
+char *xml_escape_text (const char *text);
+
 /* Functions from ``signals.c''.  */
 enum target_signal target_signal_from_host (int hostsig);
 int target_signal_to_host_p (enum target_signal oursig);
Index: src/gdb/gdbserver/win32-low.c
===================================================================
--- src.orig/gdb/gdbserver/win32-low.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/gdbserver/win32-low.c	2007-06-18 10:22:35.000000000 -0400
@@ -29,6 +29,7 @@
 #include <windows.h>
 #include <winnt.h>
 #include <imagehlp.h>
+#include <tlhelp32.h>
 #include <psapi.h>
 #include <sys/param.h>
 #include <malloc.h>
@@ -202,8 +203,8 @@ enum target_waitkind
      value.sig.  */
   TARGET_WAITKIND_STOPPED,
 
-  /* The program is letting us know that it dynamically loaded something
-     (e.g. it called load(2) on AIX).  */
+  /* The program is letting us know that it dynamically loaded
+     or unloaded something.  */
   TARGET_WAITKIND_LOADED,
 
   /* The program has exec'ed a new executable file.  The new file's
@@ -765,6 +766,316 @@ win32_resume (struct thread_resume *resu
 }
 
 static void
+win32_add_one_solib (const char *name, CORE_ADDR load_addr)
+{
+  char buf[MAX_PATH + 1];
+  char buf2[MAX_PATH + 1];
+
+#ifdef _WIN32_WCE
+  WIN32_FIND_DATA w32_fd;
+  WCHAR wname[MAX_PATH + 1];
+  mbstowcs (wname, name, MAX_PATH);
+  HANDLE h = FindFirstFile (wname, &w32_fd);
+#else
+  WIN32_FIND_DATAA w32_fd;
+  HANDLE h = FindFirstFileA (name, &w32_fd);
+#endif
+
+  if (h == INVALID_HANDLE_VALUE)
+    strcpy (buf, name);
+  else
+    {
+      FindClose (h);
+      strcpy (buf, name);
+#ifndef _WIN32_WCE
+      {
+	char cwd[MAX_PATH + 1];
+	char *p;
+	if (GetCurrentDirectoryA (MAX_PATH + 1, cwd))
+	  {
+	    p = strrchr (buf, '\\');
+	    if (p)
+	      p[1] = '\0';
+	    SetCurrentDirectoryA (buf);
+	    GetFullPathNameA (w32_fd.cFileName, MAX_PATH, buf, &p);
+	    SetCurrentDirectoryA (cwd);
+	  }
+      }
+#endif
+    }
+
+#ifdef __CYGWIN__
+  cygwin_conv_to_posix_path (buf, buf2);
+#else
+  strcpy (buf2, buf);
+#endif
+
+  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];
+  DWORD 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 = (WCHAR *) alloca (len * sizeof (WCHAR));
+      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,
+						    LPMODULEINFO, DWORD);
+typedef DWORD (WINAPI *winapi_GetModuleFileNameExA) (HANDLE, HMODULE,
+						     LPSTR, DWORD);
+
+static winapi_EnumProcessModules win32_EnumProcessModules;
+static winapi_GetModuleInformation win32_GetModuleInformation;
+static winapi_GetModuleFileNameExA win32_GetModuleFileNameExA;
+
+static BOOL
+load_psapi (void)
+{
+  static int psapi_loaded = 0;
+  static HMODULE dll = NULL;
+
+  if (!psapi_loaded)
+    {
+      psapi_loaded = 1;
+      dll = LoadLibrary (TEXT("psapi.dll"));
+      if (!dll)
+	return FALSE;
+      win32_EnumProcessModules =
+	      GETPROCADDRESS (dll, EnumProcessModules);
+      win32_GetModuleInformation =
+	      GETPROCADDRESS (dll, GetModuleInformation);
+      win32_GetModuleFileNameExA =
+	      GETPROCADDRESS (dll, GetModuleFileNameExA);
+    }
+
+  return (win32_EnumProcessModules != NULL
+	  && win32_GetModuleInformation != NULL
+	  && win32_GetModuleFileNameExA != NULL);
+}
+
+static int
+psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+{
+  DWORD len;
+  MODULEINFO mi;
+  size_t i;
+  HMODULE dh_buf[1];
+  HMODULE *DllHandle = dh_buf;
+  DWORD cbNeeded;
+  BOOL ok;
+
+  if (!load_psapi ())
+    goto failed;
+
+  cbNeeded = 0;
+  ok = (*win32_EnumProcessModules) (current_process_handle,
+				    DllHandle,
+				    sizeof (HMODULE),
+				    &cbNeeded);
+
+  if (!ok || !cbNeeded)
+    goto failed;
+
+  DllHandle = (HMODULE *) alloca (cbNeeded);
+  if (!DllHandle)
+    goto failed;
+
+  ok = (*win32_EnumProcessModules) (current_process_handle,
+				    DllHandle,
+				    cbNeeded,
+				    &cbNeeded);
+  if (!ok)
+    goto failed;
+
+  for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
+    {
+      if (!(*win32_GetModuleInformation) (current_process_handle,
+					  DllHandle[i],
+					  &mi,
+					  sizeof (mi)))
+	{
+	  DWORD err = GetLastError ();
+	  error ("Can't get module info: (error %d): %s\n",
+		 (int) err, strwinerror (err));
+	}
+
+      if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
+	{
+	  len = (*win32_GetModuleFileNameExA) (current_process_handle,
+					       DllHandle[i],
+					       dll_name_ret,
+					       MAX_PATH);
+	  if (len == 0)
+	    {
+	      DWORD err = GetLastError ();
+	      error ("Error getting dll name: (error %d): %s\n",
+		     (int) err, strwinerror (err));
+	    }
+	  return 1;
+	}
+    }
+
+failed:
+  dll_name_ret[0] = '\0';
+  return 0;
+}
+
+typedef HANDLE (WINAPI *winapi_CreateToolhelp32Snapshot) (DWORD, DWORD);
+typedef BOOL (WINAPI *winapi_Module32First) (HANDLE, LPMODULEENTRY32);
+typedef BOOL (WINAPI *winapi_Module32Next) (HANDLE, LPMODULEENTRY32);
+
+static winapi_CreateToolhelp32Snapshot win32_CreateToolhelp32Snapshot;
+static winapi_Module32First win32_Module32First;
+static winapi_Module32Next win32_Module32Next;
+
+static BOOL
+load_toolhelp (void)
+{
+  static int toolhelp_loaded = 0;
+  static HMODULE dll = NULL;
+
+  if (!toolhelp_loaded)
+    {
+      toolhelp_loaded = 1;
+#ifndef _WIN32_WCE
+      dll = GetModuleHandle (_T("KERNEL32.DLL"));
+#else
+      dll = GetModuleHandle (_T("COREDLL.DLL"));
+#endif
+      if (!dll)
+	return FALSE;
+
+      win32_CreateToolhelp32Snapshot =
+	GETPROCADDRESS (dll, CreateToolhelp32Snapshot);
+      win32_Module32First = GETPROCADDRESS (dll, Module32First);
+      win32_Module32Next = GETPROCADDRESS (dll, Module32Next);
+    }
+
+  return (win32_CreateToolhelp32Snapshot != NULL
+	  && win32_Module32First != NULL
+	  && win32_Module32Next != NULL);
+}
+
+static int
+toolhelp_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
+{
+  HANDLE snapshot_module;
+  MODULEENTRY32 modEntry = { sizeof (MODULEENTRY32) };
+
+  if (!load_toolhelp ())
+    return 0;
+
+  snapshot_module = win32_CreateToolhelp32Snapshot (TH32CS_SNAPMODULE,
+						    current_event.dwProcessId);
+  if (snapshot_module == INVALID_HANDLE_VALUE)
+    return 0;
+
+  /* Ignore the first module, which is the exe.  */
+  if (!win32_Module32First (snapshot_module, &modEntry))
+    goto failed;
+
+  while (win32_Module32Next (snapshot_module, &modEntry))
+    if ((DWORD) modEntry.modBaseAddr == BaseAddress)
+      {
+#ifdef UNICODE
+	wcstombs (dll_name_ret, modEntry.szExePath, MAX_PATH + 1);
+#else
+	strcpy (dll_name_ret, modEntry.szExePath);
+#endif
+	CloseHandle (snapshot_module);
+	return 1;
+      }
+
+failed:
+  CloseHandle (snapshot_module);
+  return 0;
+}
+
+static void
+handle_load_dll (void)
+{
+  LOAD_DLL_DEBUG_INFO *event = &current_event.u.LoadDll;
+  char dll_buf[MAX_PATH + 1];
+  char *dll_name = NULL;
+  DWORD load_addr;
+
+  dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
+
+  if (!psapi_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf)
+      && !toolhelp_get_dll_name ((DWORD) (event->lpBaseOfDll), dll_buf))
+    dll_buf[0] = dll_buf[sizeof (dll_buf) - 1] = '\0';
+
+  dll_name = dll_buf;
+
+  if (*dll_name == '\0')
+    dll_name = get_image_name (current_process_handle,
+			       event->lpImageName, event->fUnicode);
+  if (!dll_name)
+    return;
+
+  /* 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. */
+
+  load_addr = (DWORD) event->lpBaseOfDll + 0x1000;
+  win32_add_one_solib (dll_name, load_addr);
+}
+
+static void
+handle_unload_dll (void)
+{
+  CORE_ADDR load_addr =
+	  (CORE_ADDR) (DWORD) current_event.u.UnloadDll.lpBaseOfDll;
+  load_addr += 0x1000;
+  unloaded_dll (NULL, load_addr);
+}
+
+static void
 handle_exception (struct target_waitstatus *ourstatus)
 {
   DWORD code = current_event.u.Exception.ExceptionRecord.ExceptionCode;
@@ -955,9 +1266,10 @@ get_child_debug_event (struct target_wai
 		(unsigned) current_event.dwProcessId,
 		(unsigned) current_event.dwThreadId));
       CloseHandle (current_event.u.LoadDll.hFile);
+      handle_load_dll ();
 
       ourstatus->kind = TARGET_WAITKIND_LOADED;
-      ourstatus->value.integer = 0;
+      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
@@ -965,6 +1277,9 @@ get_child_debug_event (struct target_wai
 		"for pid=%d tid=%x\n",
 		(unsigned) current_event.dwProcessId,
 		(unsigned) current_event.dwThreadId));
+      handle_unload_dll ();
+      ourstatus->kind = TARGET_WAITKIND_LOADED;
+      ourstatus->value.sig = TARGET_SIGNAL_TRAP;
       break;
 
     case EXCEPTION_DEBUG_EVENT:
@@ -1027,6 +1342,7 @@ win32_wait (char *status)
 
 	  return our_status.value.integer;
 	case TARGET_WAITKIND_STOPPED:
+ 	case TARGET_WAITKIND_LOADED:
 	  OUTMSG2 (("Child Stopped with signal = %d \n",
 		    our_status.value.sig));
 
@@ -1034,12 +1350,20 @@ win32_wait (char *status)
 
 	  child_fetch_inferior_registers (-1);
 
+	  if (our_status.kind == TARGET_WAITKIND_LOADED
+	      && !server_waiting)
+	    {
+	      /* When gdb connects, we want to be stopped at the
+		 initial breakpoint, not in some dll load event.  */
+	      child_continue (DBG_CONTINUE, -1);
+	      break;
+	    }
+
 	  return our_status.value.sig;
  	default:
 	  OUTMSG (("Ignoring unknown internal event, %d\n", our_status.kind));
  	  /* fall-through */
  	case TARGET_WAITKIND_SPURIOUS:
- 	case TARGET_WAITKIND_LOADED:
  	case TARGET_WAITKIND_EXECD:
 	  /* do nothing, just continue */
 	  child_continue (DBG_CONTINUE, -1);
Index: src/gdb/win32-nat.c
===================================================================
--- src.orig/gdb/win32-nat.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/win32-nat.c	2007-06-18 10:22:35.000000000 -0400
@@ -13,7 +13,7 @@
    (at your option) any later version.
 
    This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without eve nthe implied warranty of
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
 
@@ -42,12 +42,16 @@
 #include <stdlib.h>
 #include <windows.h>
 #include <imagehlp.h>
+#include <tlhelp32.h>
+#include <psapi.h>
+#include <sys/procfs.h>
 #include <sys/cygwin.h>
 #include <signal.h>
 
 #include "buildsym.h"
 #include "symfile.h"
 #include "objfiles.h"
+#include "gdb_obstack.h"
 #include "gdb_string.h"
 #include "gdbthread.h"
 #include "gdbcmd.h"
@@ -56,12 +60,12 @@
 #include "exec.h"
 #include "solist.h"
 #include "solib.h"
+#include "xml-support.h"
 
 #include "i386-tdep.h"
 #include "i387-tdep.h"
 
 static struct target_ops win32_ops;
-static struct target_so_ops win32_so_ops;
 
 /* The starting and ending address of the cygwin1.dll text segment. */
 static bfd_vma cygwin_load_start;
@@ -80,8 +84,6 @@ enum
     CONTEXT_DEBUGGER = (CONTEXT_FULL | CONTEXT_FLOATING_POINT)
   };
 #endif
-#include <sys/procfs.h>
-#include <psapi.h>
 
 #define CONTEXT_DEBUGGER_DR CONTEXT_DEBUGGER | CONTEXT_DEBUG_REGISTERS \
 	| CONTEXT_EXTENDED_REGISTERS
@@ -439,46 +441,48 @@ win32_store_inferior_registers (struct r
     do_win32_store_inferior_registers (regcache, r);
 }
 
-static int psapi_loaded = 0;
-static HMODULE psapi_module_handle = NULL;
 static BOOL WINAPI (*psapi_EnumProcessModules) (HANDLE, HMODULE *, DWORD, LPDWORD) = NULL;
 static BOOL WINAPI (*psapi_GetModuleInformation) (HANDLE, HMODULE, LPMODULEINFO, DWORD) = NULL;
 static DWORD WINAPI (*psapi_GetModuleFileNameExA) (HANDLE, HMODULE, LPSTR, DWORD) = NULL;
 
+static BOOL
+load_psapi (void)
+{
+  static int psapi_loaded = 0;
+  static HMODULE psapi_module_handle = NULL;
+
+  if (!psapi_loaded)
+    {
+      psapi_loaded = 1;
+      psapi_module_handle = LoadLibrary ("psapi.dll");
+      if (!psapi_module_handle)
+	return FALSE;
+      psapi_EnumProcessModules = GetProcAddress
+	(psapi_module_handle, "EnumProcessModules");
+      psapi_GetModuleInformation = GetProcAddress
+	(psapi_module_handle, "GetModuleInformation");
+      psapi_GetModuleFileNameExA = (void *) GetProcAddress
+	(psapi_module_handle, "GetModuleFileNameExA");
+    }
+
+  return (psapi_EnumProcessModules != NULL
+	  && psapi_GetModuleInformation != NULL
+	  && psapi_GetModuleFileNameExA != NULL);
+}
+
 static int
 psapi_get_dll_name (DWORD BaseAddress, char *dll_name_ret)
 {
   DWORD len;
   MODULEINFO mi;
-  int i;
+  size_t i;
   HMODULE dh_buf[1];
   HMODULE *DllHandle = dh_buf;
   DWORD cbNeeded;
   BOOL ok;
 
-  if (!psapi_loaded ||
-      psapi_EnumProcessModules == NULL ||
-      psapi_GetModuleInformation == NULL ||
-      psapi_GetModuleFileNameExA == NULL)
-    {
-      if (psapi_loaded)
-	goto failed;
-      psapi_loaded = 1;
-      psapi_module_handle = LoadLibrary ("psapi.dll");
-      if (!psapi_module_handle)
-	{
-	  /* printf_unfiltered ("error loading psapi.dll: %u", GetLastError ()); */
-	  goto failed;
-	}
-      psapi_EnumProcessModules = GetProcAddress (psapi_module_handle, "EnumProcessModules");
-      psapi_GetModuleInformation = GetProcAddress (psapi_module_handle, "GetModuleInformation");
-      psapi_GetModuleFileNameExA = (void *) GetProcAddress (psapi_module_handle,
-						    "GetModuleFileNameExA");
-      if (psapi_EnumProcessModules == NULL ||
-	  psapi_GetModuleInformation == NULL ||
-	  psapi_GetModuleFileNameExA == NULL)
-	goto failed;
-    }
+  if (!load_psapi ())
+    goto failed;
 
   cbNeeded = 0;
   ok = (*psapi_EnumProcessModules) (current_process_handle,
@@ -500,7 +504,7 @@ psapi_get_dll_name (DWORD BaseAddress, c
   if (!ok)
     goto failed;
 
-  for (i = 0; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
+  for (i = 0; i < ((size_t) cbNeeded / sizeof (HMODULE)); i++)
     {
       if (!(*psapi_GetModuleInformation) (current_process_handle,
 					  DllHandle[i],
@@ -508,15 +512,17 @@ psapi_get_dll_name (DWORD BaseAddress, c
 					  sizeof (mi)))
 	error (_("Can't get module info"));
 
-      len = (*psapi_GetModuleFileNameExA) (current_process_handle,
-					   DllHandle[i],
-					   dll_name_ret,
-					   MAX_PATH);
-      if (len == 0)
-	error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
-
       if ((DWORD) (mi.lpBaseOfDll) == BaseAddress)
-	return 1;
+	{
+	  len = (*psapi_GetModuleFileNameExA) (current_process_handle,
+					       DllHandle[i],
+					       dll_name_ret,
+					       MAX_PATH);
+	  if (len == 0)
+	    error (_("Error getting dll name: %u."),
+		   (unsigned) GetLastError ());
+	  return 1;
+	}
     }
 
 failed:
@@ -537,22 +543,12 @@ struct safe_symbol_file_add_args
   struct objfile *ret;
 };
 
-/* Maintain a linked list of "so" information. */
-struct lm_info
-{
-  DWORD load_addr;
-};
-
-static struct so_list solib_start, *solib_end;
-
 /* Call symbol_file_add with stderr redirected.  We don't care if there
    are errors. */
 static int
 safe_symbol_file_add_stub (void *argv)
 {
 #define p ((struct safe_symbol_file_add_args *) argv)
-  struct so_list *so = &solib_start;
-
   p->ret = symbol_file_add (p->name, p->from_tty, p->addrs, p->mainline, p->flags);
   return !!p->ret;
 #undef p
@@ -600,126 +596,15 @@ safe_symbol_file_add (char *name, int fr
   return p.ret;
 }
 
-/* Get the loaded address of all sections, given that .text was loaded
-   at text_load. Assumes that all sections are subject to the same
-   relocation offset. Returns NULL if problems occur or if the
-   sections were not relocated. */
-
-static struct section_addr_info *
-get_relocated_section_addrs (bfd *abfd, CORE_ADDR text_load)
-{
-  struct section_addr_info *result = NULL;
-  int section_count = bfd_count_sections (abfd);
-  asection *text_section = bfd_get_section_by_name (abfd, ".text");
-  CORE_ADDR text_vma;
-
-  if (!text_section)
-    {
-      /* Couldn't get the .text section. Weird. */
-    }
-  else if (text_load == (text_vma = bfd_get_section_vma (abfd, text_section)))
-    {
-      /* DLL wasn't relocated. */
-    }
-  else
-    {
-      /* Figure out all sections' loaded addresses. The offset here is
-	 such that taking a bfd_get_section_vma() result and adding
-	 offset will give the real load address of the section. */
-
-      CORE_ADDR offset = text_load - text_vma;
-
-      struct section_table *table_start = NULL;
-      struct section_table *table_end = NULL;
-      struct section_table *iter = NULL;
-
-      build_section_table (abfd, &table_start, &table_end);
-
-      for (iter = table_start; iter < table_end; ++iter)
-	{
-	  /* Relocated addresses. */
-	  iter->addr += offset;
-	  iter->endaddr += offset;
-	}
-
-      result = build_section_addr_info_from_section_table (table_start,
-							   table_end);
 
-      xfree (table_start);
-    }
 
-  return result;
-}
 
-/* Add DLL symbol information. */
 static void
-solib_symbols_add (struct so_list *so, CORE_ADDR load_addr)
-{
-  struct section_addr_info *addrs = NULL;
-  static struct objfile *result = NULL;
-  char *name = so->so_name;
-  bfd *abfd = NULL;
-  char *p;
-
-  /* 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 (!name || !name[0])
-    return;
-
-  abfd = bfd_openr (name, "pei-i386");
-
-  if (!abfd)
-    {
-      /* pei failed - try pe */
-      abfd = bfd_openr (name, "pe-i386");
-    }
-
-  if (abfd)
-    {
-      if (bfd_check_format (abfd, bfd_object))
-	addrs = get_relocated_section_addrs (abfd, load_addr);
-    }
-
-  if (addrs)
-    {
-      result = safe_symbol_file_add (name, 0, addrs, 0, OBJF_SHARED);
-      free_section_addr_info (addrs);
-    }
-  else
-    {
-      /* Fallback on handling just the .text section. */
-      struct cleanup *my_cleanups;
-
-      addrs = alloc_section_addr_info (1);
-      my_cleanups = make_cleanup (xfree, addrs);
-      addrs->other[0].name = ".text";
-      addrs->other[0].addr = load_addr;
-
-      result = safe_symbol_file_add (name, 0, addrs, 0, OBJF_SHARED);
-      do_cleanups (my_cleanups);
-    }
-
-  p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
-  if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
-    {
-      asection *text = bfd_get_section_by_name (abfd, ".text");
-      cygwin_load_start = bfd_section_vma (abfd, text);
-      cygwin_load_end = cygwin_load_start + bfd_section_size (abfd, text);
-    }
-
-  bfd_close (abfd);
-
-  so->symbols_loaded = !!result;
-  return;
-}
-
-static char *
-register_loaded_dll (const char *name, DWORD load_addr, int readsyms)
+win32_add_one_solib (const char *name, CORE_ADDR load_addr,
+		     struct obstack *obstack)
 {
-  struct so_list *so;
   char buf[MAX_PATH + 1];
+  char buf2[MAX_PATH + 1];
   char cwd[MAX_PATH + 1];
   char *p;
   WIN32_FIND_DATA w32_fd;
@@ -749,19 +634,26 @@ register_loaded_dll (const char *name, D
       GetSystemDirectory (buf, sizeof (buf));
       strcat (buf, "\\ntdll.dll");
     }
-  so = XZALLOC (struct so_list);
-  so->lm_info = (struct lm_info *) xmalloc (sizeof (struct lm_info));
-  so->lm_info->load_addr = load_addr;
-  cygwin_conv_to_posix_path (buf, so->so_name);
-  strcpy (so->so_original_name, so->so_name);
-
-  solib_end->next = so;
-  solib_end = so;
-  len = strlen (so->so_name);
-  if (readsyms)
-    solib_symbols_add (so, (CORE_ADDR) load_addr);
 
-  return so->so_name;
+#ifdef __CYGWIN__
+  cygwin_conv_to_posix_path (buf, buf2);
+#else
+  strcpy (buf2, buf);
+#endif
+
+  /* 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. */
+  load_addr += 0x1000;
+
+  obstack_grow_str (obstack, "<library name=\"");
+  p = xml_escape_text (buf2);
+  obstack_grow_str (obstack, p);
+  xfree (p);
+  obstack_grow_str (obstack, "\"><segment address=\"0x");
+  p = paddr_nz (load_addr);
+  obstack_grow_str (obstack, p);
+  obstack_grow_str (obstack, "\"/></library>");
 }
 
 static char *
@@ -805,8 +697,10 @@ get_image_name (HANDLE h, void *address,
   return buf;
 }
 
-/* Wait for child to do something.  Return pid of child, or -1 in case
-   of error; store status through argument pointer OURSTATUS.  */
+static char last_loaded_dll_name[MAX_PATH + 1];
+static CORE_ADDR last_loaded_dll_base;
+static int last_loaded_dll_valid;
+
 static int
 handle_load_dll (void *dummy)
 {
@@ -826,70 +720,14 @@ handle_load_dll (void *dummy)
   if (!dll_name)
     return 1;
 
-  register_loaded_dll (dll_name, (DWORD) event->lpBaseOfDll + 0x1000, auto_solib_add);
+  last_loaded_dll_name[MAX_PATH] = '\0';
+  strncpy (last_loaded_dll_name, dll_name, MAX_PATH);
+  last_loaded_dll_base = (DWORD) event->lpBaseOfDll;
+  last_loaded_dll_valid = 1;
 
   return 1;
 }
 
-static void
-win32_free_so (struct so_list *so)
-{
-  if (so->lm_info)
-    xfree (so->lm_info);
-}
-
-static void
-win32_relocate_section_addresses (struct so_list *so,
-				  struct section_table *sec)
-{
-  /* FIXME */
-  return;
-}
-
-static void
-win32_solib_create_inferior_hook (void)
-{
-  solib_add (NULL, 0, NULL, auto_solib_add);
-  return;
-}
-
-static int
-handle_unload_dll (void *dummy)
-{
-  DWORD lpBaseOfDll = (DWORD) current_event.u.UnloadDll.lpBaseOfDll + 0x1000;
-  struct so_list *so;
-
-  for (so = &solib_start; so->next != NULL; so = so->next)
-    if (so->next->lm_info->load_addr == lpBaseOfDll)
-      {
-	struct so_list *sodel = so->next;
-	so->next = sodel->next;
-	if (!so->next)
-	  solib_end = so;
-	free_so (sodel);
-	solib_add (NULL, 0, NULL, auto_solib_add);
-	return 1;
-      }
-
-  error (_("Error: dll starting at 0x%lx not found."), (DWORD) lpBaseOfDll);
-
-  return 0;
-}
-
-/* Clear list of loaded DLLs. */
-static void
-win32_clear_solib (void)
-{
-  solib_start.next = NULL;
-  solib_end = &solib_start;
-}
-
-static void
-win32_special_symbol_handling (void)
-{
-  return;
-}
-
 /* Load DLL symbol info. */
 void
 dll_symbol_command (char *args, int from_tty)
@@ -1084,6 +922,58 @@ info_w32_command (char *args, int from_t
   help_list (info_w32_cmdlist, "info w32 ", class_info, gdb_stdout);
 }
 
+static int
+ignore_access_violation_p (PVOID exception_addr)
+{
+  bfd_vma addr = (bfd_vma) exception_addr;
+
+  if (!cygwin_exceptions)
+    {
+      /* See if the access violation happened within the cygwin DLL itself.
+	 Cygwin uses a kind of exception handling to deal with passed-in invalid
+	 addresses. gdb should not treat these as real SEGVs since they will be
+	 silently handled by cygwin.  A real SEGV will (theoretically) be caught
+	 by cygwin later in the process and will be sent as a
+	 cygwin-specific-signal.  So, ignore SEGVs if they show up within the
+	 text segment of the DLL itself. */
+
+      if (cygwin_load_start == 0 && cygwin_load_end == 0)
+	{
+	  struct so_list *so;
+
+	  for (so = master_so_list (); so; so = so->next)
+	    {
+	      char *p;
+	      p = strchr (so->so_name, '\0') - (sizeof ("/cygwin1.dll") - 1);
+	      if (p >= so->so_name && strcasecmp (p, "/cygwin1.dll") == 0)
+		{
+		  asection *text = bfd_get_section_by_name (so->abfd, ".text");
+		  if (text)
+		    {
+		      cygwin_load_start = bfd_section_vma (so->abfd, text);
+		      cygwin_load_end = cygwin_load_start +
+			bfd_section_size (so->abfd, text);
+		    }
+		  break;
+		}
+	    }
+	}
+
+      if (cygwin_load_start <= addr && addr < cygwin_load_end)
+	return 1;
+    }
+
+  {
+    /* The IsBadXxxPtr family of Win32 functions triggers an access
+       violation by design.  */
+    char *fn;
+    if (find_pc_partial_function (addr, &fn, NULL, NULL)
+	&& strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0)
+      return 1;
+  }
+
+  return 0;
+}
 
 #define DEBUG_EXCEPTION_SIMPLE(x)       if (debug_exceptions) \
   printf_unfiltered ("gdb: Target exception %s at 0x%08lx\n", x, \
@@ -1105,20 +995,9 @@ handle_exception (struct target_waitstat
     case EXCEPTION_ACCESS_VIOLATION:
       DEBUG_EXCEPTION_SIMPLE ("EXCEPTION_ACCESS_VIOLATION");
       ourstatus->value.sig = TARGET_SIGNAL_SEGV;
-      {
-	/* See if the access violation happened within the cygwin DLL itself.  Cygwin uses
-	   a kind of exception handling to deal with passed-in invalid addresses. gdb
-	   should not treat these as real SEGVs since they will be silently handled by
-	   cygwin.  A real SEGV will (theoretically) be caught by cygwin later in the process
-	   and will be sent as a cygwin-specific-signal.  So, ignore SEGVs if they show up
-	   within the text segment of the DLL itself. */
-	char *fn;
-	bfd_vma addr = (bfd_vma) current_event.u.Exception.ExceptionRecord.ExceptionAddress;
-	if ((!cygwin_exceptions && (addr >= cygwin_load_start && addr < cygwin_load_end))
-	    || (find_pc_partial_function (addr, &fn, NULL, NULL)
-		&& strncmp (fn, "KERNEL32!IsBad", strlen ("KERNEL32!IsBad")) == 0))
-	  return 0;
-      }
+      if (ignore_access_violation_p
+	  (current_event.u.Exception.ExceptionRecord.ExceptionAddress))
+	return 0;
       break;
     case STATUS_STACK_OVERFLOW:
       DEBUG_EXCEPTION_SIMPLE ("STATUS_STACK_OVERFLOW");
@@ -1351,6 +1230,7 @@ win32_resume (ptid_t ptid, int step, enu
 static int
 get_win32_debug_event (int pid, struct target_waitstatus *ourstatus)
 {
+  extern int stop_after_trap;
   BOOL debug_event;
   DWORD continue_status, event_code;
   thread_info *th;
@@ -1370,6 +1250,7 @@ get_win32_debug_event (int pid, struct t
   ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
   th = NULL;
   have_saved_context = 0;
+  last_loaded_dll_valid = 0;
 
   switch (event_code)
     {
@@ -1455,12 +1336,17 @@ get_win32_debug_event (int pid, struct t
       CloseHandle (current_event.u.LoadDll.hFile);
       if (saw_create != 1)
 	break;
-      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;
+
+      /* Only report DLL load events after the initial startup.  We will
+	 poll the list of DLLs once the program is started.  */
+      if (stop_after_trap == 0)
+	{
+	  catch_errors (handle_load_dll, NULL, (char *) "", RETURN_MASK_ALL);
+	  ourstatus->kind = TARGET_WAITKIND_LOADED;
+	  ourstatus->value.integer = 0;
+	}
+
       retval = main_thread_id;
-      re_enable_breakpoints_in_shlibs ();
       break;
 
     case UNLOAD_DLL_DEBUG_EVENT:
@@ -1470,10 +1356,10 @@ get_win32_debug_event (int pid, struct t
 		     "UNLOAD_DLL_DEBUG_EVENT"));
       if (saw_create != 1)
 	break;
-      catch_errors (handle_unload_dll, NULL, (char *) "", RETURN_MASK_ALL);
-      registers_changed ();	/* mark all regs invalid */
-      /* ourstatus->kind = TARGET_WAITKIND_UNLOADED;
-	 does not exist yet. */
+
+      ourstatus->kind = TARGET_WAITKIND_LOADED;
+      ourstatus->value.integer = 0;
+      retval = main_thread_id;
       break;
 
     case EXCEPTION_DEBUG_EVENT:
@@ -1585,7 +1471,6 @@ do_initial_win32_stuff (DWORD pid)
   memset (&current_event, 0, sizeof (current_event));
   push_target (&win32_ops);
   disable_breakpoints_in_shlibs (1);
-  win32_clear_solib ();
   clear_proceed_status ();
   init_wait_for_inferior ();
 
@@ -1972,6 +1857,7 @@ win32_create_inferior (char *exec_file, 
 static void
 win32_mourn_inferior (void)
 {
+  last_loaded_dll_valid = 0;
   (void) win32_continue (DBG_CONTINUE, -1);
   i386_cleanup_dregs();
   unpush_target (&win32_ops);
@@ -2071,140 +1957,189 @@ cygwin_pid_to_str (ptid_t ptid)
   return buf;
 }
 
-typedef struct
-{
-  struct target_ops *target;
-  bfd_vma addr;
-} map_code_section_args;
+typedef HANDLE (WINAPI *win32_CREATETOOLHELP32SNAPSHOT) (DWORD, DWORD);
+typedef BOOL (WINAPI *win32_MODULE32FIRST) (HANDLE, LPMODULEENTRY32);
+typedef BOOL (WINAPI *win32_MODULE32NEXT) (HANDLE, LPMODULEENTRY32);
+
+static win32_CREATETOOLHELP32SNAPSHOT pCreateToolhelp32Snapshot;
+static win32_MODULE32FIRST pModule32First;
+static win32_MODULE32NEXT pModule32Next;
 
-static void
-map_single_dll_code_section (bfd *abfd, asection *sect, void *obj)
+static BOOL
+win32_get_shared_libraries_ToolHelp32 (struct target_ops *ops,
+				       struct obstack *obstack)
 {
-  int old;
-  int update_coreops;
-  struct section_table *new_target_sect_ptr;
+  BOOL cont;
+  HMODULE kernel32;
+  HANDLE snapshot_module;
+  MODULEENTRY32 modEntry = { sizeof (MODULEENTRY32) };
+
+  kernel32 = GetModuleHandle ("KERNEL32.DLL");
+
+  pCreateToolhelp32Snapshot = (win32_CREATETOOLHELP32SNAPSHOT)
+    GetProcAddress (kernel32, "CreateToolhelp32Snapshot");
+
+  pModule32First = (win32_MODULE32FIRST)
+    GetProcAddress (kernel32, "Module32First");
+
+  pModule32Next = (win32_MODULE32NEXT)
+    GetProcAddress (kernel32, "Module32Next");
 
-  map_code_section_args *args = (map_code_section_args *) obj;
-  struct target_ops *target = args->target;
-  if (sect->flags & SEC_CODE)
+  if (!pCreateToolhelp32Snapshot
+      || !pModule32First
+      || !pModule32Next)
+    return FALSE;
+
+  snapshot_module = pCreateToolhelp32Snapshot (TH32CS_SNAPMODULE,
+					       current_event.dwProcessId);
+  if (snapshot_module == INVALID_HANDLE_VALUE)
+    return FALSE;
+
+  /* Ignore the first module, which is the exe.  */
+  if (!pModule32First (snapshot_module, &modEntry))
     {
-      update_coreops = core_ops.to_sections == target->to_sections;
+      CloseHandle (snapshot_module);
+      return FALSE;
+    }
 
-      if (target->to_sections)
-	{
-	  old = target->to_sections_end - target->to_sections;
-	  target->to_sections = (struct section_table *)
-	    xrealloc ((char *) target->to_sections,
-		      (sizeof (struct section_table)) * (1 + old));
-	}
-      else
-	{
-	  old = 0;
-	  target->to_sections = (struct section_table *)
-	    xmalloc ((sizeof (struct section_table)));
-	}
-      target->to_sections_end = target->to_sections + (1 + old);
-
-      /* Update the to_sections field in the core_ops structure
-	 if needed.  */
-      if (update_coreops)
-	{
-	  core_ops.to_sections = target->to_sections;
-	  core_ops.to_sections_end = target->to_sections_end;
-	}
-      new_target_sect_ptr = target->to_sections + old;
-      new_target_sect_ptr->addr = args->addr + bfd_section_vma (abfd, sect);
-      new_target_sect_ptr->endaddr = args->addr + bfd_section_vma (abfd, sect) +
-	bfd_section_size (abfd, sect);;
-      new_target_sect_ptr->the_bfd_section = sect;
-      new_target_sect_ptr->bfd = abfd;
+  while (pModule32Next (snapshot_module, &modEntry))
+    {
+      win32_add_one_solib (modEntry.szExePath, (CORE_ADDR) modEntry.hModule,
+			   obstack);
+      /* If it's already on the list, do not add it again.  */
+      if (last_loaded_dll_valid
+	  && (CORE_ADDR) modEntry.hModule == last_loaded_dll_base
+	  && strcmp (modEntry.szExePath, last_loaded_dll_name) == 0)
+	last_loaded_dll_valid = 0;
     }
+
+  CloseHandle (snapshot_module);
+  fflush (stdout);
+
+  return TRUE;
 }
 
-static int
-dll_code_sections_add (const char *dll_name, int base_addr, struct target_ops *target)
+static BOOL
+win32_get_shared_libraries_PSAPI (struct target_ops *ops,
+				  struct obstack *obstack)
 {
-  bfd *dll_bfd;
-  map_code_section_args map_args;
-  asection *lowest_sect;
-  char *name;
-  if (dll_name == NULL || target == NULL)
-    return 0;
-  name = xstrdup (dll_name);
-  dll_bfd = bfd_openr (name, "pei-i386");
-  if (dll_bfd == NULL)
-    return 0;
+  DWORD len;
+  MODULEINFO mi;
+  int i;
+  HMODULE dh_buf[1];
+  HMODULE *DllHandle = dh_buf;
+  DWORD cbNeeded;
+  BOOL ok;
+
+  if (!load_psapi ())
+    goto failed;
+
+  cbNeeded = 0;
+  ok = (*psapi_EnumProcessModules) (current_process_handle,
+				    DllHandle,
+				    sizeof (HMODULE),
+				    &cbNeeded);
+
+  if (!ok || !cbNeeded)
+    goto failed;
+
+  DllHandle = (HMODULE *) alloca (cbNeeded);
+  if (!DllHandle)
+    goto failed;
 
-  if (bfd_check_format (dll_bfd, bfd_object))
+  ok = (*psapi_EnumProcessModules) (current_process_handle,
+				    DllHandle,
+				    cbNeeded,
+				    &cbNeeded);
+  if (!ok)
+    goto failed;
+
+  /* Ignore the first module, which is the exe.  */
+  for (i = 1; i < (int) (cbNeeded / sizeof (HMODULE)); i++)
     {
-      lowest_sect = bfd_get_section_by_name (dll_bfd, ".text");
-      if (lowest_sect == NULL)
-	return 0;
-      map_args.target = target;
-      map_args.addr = base_addr - bfd_section_vma (dll_bfd, lowest_sect);
+      char buf[MAX_PATH + 1];
+
+      if (!(*psapi_GetModuleInformation) (current_process_handle,
+					  DllHandle[i],
+					  &mi,
+					  sizeof (mi)))
+	error (_("Can't get module info"));
 
-      bfd_map_over_sections (dll_bfd, &map_single_dll_code_section, (void *) (&map_args));
+      len = (*psapi_GetModuleFileNameExA) (current_process_handle,
+					   DllHandle[i],
+					   buf,
+					   MAX_PATH + 1);
+      if (len == 0)
+	error (_("Error getting dll name: %u."), (unsigned) GetLastError ());
+
+      win32_add_one_solib (buf, (CORE_ADDR) mi.lpBaseOfDll, obstack);
+
+      /* If it's already on the list, do not add it again.  */
+      if (last_loaded_dll_valid
+	  && (CORE_ADDR) mi.lpBaseOfDll == last_loaded_dll_base
+	  && strcmp (buf, last_loaded_dll_name) == 0)
+	last_loaded_dll_valid = 0;
     }
 
   return 1;
+
+failed:
+  return 0;
 }
 
+struct cs_get_sos_data
+{
+  struct target_ops *target;
+  int module_count;
+  struct obstack obstack;
+};
+
 static void
-core_section_load_dll_symbols (bfd *abfd, asection *sect, void *obj)
+core_section_look_for_modules (bfd *abfd, asection *sect, void *obj)
 {
-  struct target_ops *target = (struct target_ops *) obj;
+  struct cs_get_sos_data *data = obj;
 
+  struct win32_pstatus *pstatus;
+  char *module_name;
+  int module_name_offset;
+  int module_name_size;
   DWORD base_addr;
 
-  int dll_name_size;
-  struct win32_pstatus *pstatus;
-  struct so_list *so;
-  char *dll_name;
   char *buf = NULL;
-  char *p;
-  struct objfile *objfile;
-  const char *dll_basename;
 
   if (strncmp (sect->name, ".module", 7) != 0)
     return;
 
-  buf = (char *) xmalloc (bfd_get_section_size (sect) + 1);
+  buf = xmalloc (bfd_get_section_size (sect) + 1);
   if (!buf)
     {
       printf_unfiltered ("memory allocation failed for %s\n", sect->name);
       goto out;
     }
-  if (!bfd_get_section_contents (abfd, sect, buf, 0, bfd_get_section_size (sect)))
+  if (!bfd_get_section_contents (abfd, sect,
+				 buf, 0, bfd_get_section_size (sect)))
     goto out;
 
   pstatus = (struct win32_pstatus *) buf;
 
-  memmove (&base_addr, &(pstatus->data.module_info.base_address), sizeof (base_addr));
-  dll_name_size = pstatus->data.module_info.module_name_size;
-  if (offsetof (struct win32_pstatus, data.module_info.module_name) + dll_name_size > bfd_get_section_size (sect))
-      goto out;
-
-  dll_name = pstatus->data.module_info.module_name;
-
-  if (!(dll_basename = strrchr (dll_name, '/')))
-    dll_basename = dll_name;
-  else
-    dll_basename++;
-
-  ALL_OBJFILES (objfile)
-  {
-    char *objfile_basename = strrchr (objfile->name, '/');
+  memcpy (&base_addr, &pstatus->data.module_info.base_address,
+	  sizeof (base_addr));
 
-    if (objfile_basename &&
-	strcasecmp (dll_basename, objfile_basename + 1) == 0)
+  module_name_size = pstatus->data.module_info.module_name_size;
+  module_name = pstatus->data.module_info.module_name;
+  if (module_name - buf + module_name_size > bfd_get_section_size (sect))
       goto out;
-  }
-
-  base_addr += 0x1000;
-  dll_name = register_loaded_dll (dll_name, base_addr, 1);
 
-  if (!dll_code_sections_add (dll_name, (DWORD) base_addr, target))
-    printf_unfiltered ("%s: Failed to map dll code sections.\n", dll_name);
+  data->module_count++;
+  /* ### TODO: What if the user supplied exec and/or symbol
+     files on the command line?  */
+  if (data->module_count == 1)
+    {
+      /* The first module is the .exe itself.  */
+      symbol_file_add_main (module_name, 0);
+    }
+  else
+    win32_add_one_solib (module_name, base_addr, &data->obstack);
 
 out:
   if (buf)
@@ -2212,39 +2147,112 @@ out:
   return;
 }
 
-static struct so_list *
-win32_current_sos (void)
-{
-  struct so_list *sop;
-  struct so_list *start = NULL;
-  struct so_list *last = NULL;
+static LONGEST
+win32_core_xfer_shared_libraries (struct target_ops *ops,
+				  enum target_object object, const char *annex,
+				  gdb_byte *readbuf, const gdb_byte *writebuf,
+				  ULONGEST offset, LONGEST len)
+{
+  struct obstack obstack;
+  const char *buf;
+  LONGEST len_avail;
+  struct cs_get_sos_data data = { ops, 0 };
+
+  if (writebuf)
+    return -1;
+
+  obstack_init (&obstack);
+  obstack_grow_str (&obstack, "<library-list>\n");
+  bfd_map_over_sections (core_bfd,
+			 &core_section_look_for_modules,
+			 &data);
+  obstack_grow_str0 (&obstack, "</library-list>\n");
+
+  buf = obstack_finish (&obstack);
+  len_avail = strlen (buf);
+  if (offset >= len_avail)
+    return 0;
 
-  if (!solib_start.next && core_bfd)
-    {
-      win32_clear_solib ();
-      bfd_map_over_sections (core_bfd, &core_section_load_dll_symbols,
-			     &win32_ops);
-    }
+  if (len > len_avail - offset)
+    len = len_avail - offset;
+  memcpy (readbuf, buf + offset, len);
+
+  obstack_free (&obstack, NULL);
+  return len;
+}
+
+static LONGEST
+win32_xfer_shared_libraries (struct target_ops *ops,
+			     enum target_object object, const char *annex,
+			     gdb_byte *readbuf, const gdb_byte *writebuf,
+			     ULONGEST offset, LONGEST len)
+{
+  struct obstack obstack;
+  const char *buf;
+  LONGEST len_avail;
+
+  if (writebuf)
+    return -1;
+
+  obstack_init (&obstack);
+  obstack_grow_str (&obstack, "<library-list>\n");
+  if (!win32_get_shared_libraries_ToolHelp32 (ops, &obstack))
+    win32_get_shared_libraries_PSAPI (ops, &obstack);
+
+  /* If we are stopped at a DLL load event, and the DLL was
+     automatically loaded by the operating system, then that DLL may
+     not be on the list yet.  We may not be able to read the (empty)
+     list if this is the first loaded DLL, either.  But we have to
+     check, because DLLs loaded using LoadLibrary do seem to appear on
+     the list.  */
+  if (last_loaded_dll_valid)
+    win32_add_one_solib (last_loaded_dll_name, last_loaded_dll_base, &obstack);
+
+  obstack_grow_str0 (&obstack, "</library-list>\n");
+
+  buf = obstack_finish (&obstack);
+  len_avail = strlen (buf);
+  if (offset >= len_avail)
+    return 0;
 
-  for (sop = solib_start.next; sop; sop = sop->next)
-    {
-      struct so_list *new = XZALLOC (struct so_list);
-      strcpy (new->so_name, sop->so_name);
-      strcpy (new->so_original_name, sop->so_original_name);
-      if (!start)
-	last = start = new;
-      else
-	{
-	  last->next = new;
-	  last = new;
-	}
-    }
+  if (len > len_avail - offset)
+    len = len_avail - offset;
+  memcpy (readbuf, buf + offset, len);
+
+  obstack_free (&obstack, NULL);
+  return len;
+}
+
+static LONGEST
+win32_xfer_partial (struct target_ops *ops, enum target_object object,
+		    const char *annex, gdb_byte *readbuf,
+		    const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
+{
+  switch (object)
+    {
+    case TARGET_OBJECT_MEMORY:
+      if (readbuf)
+	return (*ops->deprecated_xfer_memory) (offset, readbuf, len,
+					       0/*write*/, NULL, ops);
+      if (writebuf)
+	return (*ops->deprecated_xfer_memory) (offset, (gdb_byte *) writebuf,
+					       len, 1/*write*/, NULL, ops);
+      return -1;
+
+    case TARGET_OBJECT_LIBRARIES:
+      return win32_xfer_shared_libraries (ops, object, annex, readbuf,
+					  writebuf, offset, len);
 
-  return start;
+    default:
+      if (ops->beneath != NULL)
+	return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
+					      readbuf, writebuf, offset, len);
+      return -1;
+    }
 }
 
 static void
-fetch_elf_core_registers (struct regcache *regcache,
+win32_fetch_elf_core_registers (struct regcache *regcache,
 			  char *core_reg_sect,
 			  unsigned core_reg_size,
 			  int which,
@@ -2260,18 +2268,6 @@ fetch_elf_core_registers (struct regcach
     regcache_raw_supply (regcache, r, core_reg_sect + mappings[r]);
 }
 
-static int
-open_symbol_file_object (void *from_ttyp)
-{
-  return 0;
-}
-
-static int
-in_dynsym_resolve_code (CORE_ADDR pc)
-{
-  return 0;
-}
-
 static void
 init_win32_ops (void)
 {
@@ -2288,6 +2284,7 @@ init_win32_ops (void)
   win32_ops.to_store_registers = win32_store_inferior_registers;
   win32_ops.to_prepare_to_store = win32_prepare_to_store;
   win32_ops.deprecated_xfer_memory = win32_xfer_memory;
+  win32_ops.to_xfer_partial = win32_xfer_partial;
   win32_ops.to_files_info = win32_files_info;
   win32_ops.to_insert_breakpoint = memory_insert_breakpoint;
   win32_ops.to_remove_breakpoint = memory_remove_breakpoint;
@@ -2312,18 +2309,6 @@ init_win32_ops (void)
   win32_ops.to_has_execution = 1;
   win32_ops.to_magic = OPS_MAGIC;
   win32_ops.to_pid_to_exec_file = win32_pid_to_exec_file;
-
-  win32_so_ops.relocate_section_addresses = win32_relocate_section_addresses;
-  win32_so_ops.free_so = win32_free_so;
-  win32_so_ops.clear_solib = win32_clear_solib;
-  win32_so_ops.solib_create_inferior_hook = win32_solib_create_inferior_hook;
-  win32_so_ops.special_symbol_handling = win32_special_symbol_handling;
-  win32_so_ops.current_sos = win32_current_sos;
-  win32_so_ops.open_symbol_file_object = open_symbol_file_object;
-  win32_so_ops.in_dynsym_resolve_code = in_dynsym_resolve_code;
-
-  /* FIXME: Don't do this here.  *_gdbarch_init() should set so_ops. */
-  current_target_so_ops = &win32_so_ops;
 }
 
 static void
@@ -2466,7 +2451,8 @@ static struct core_fns win32_elf_core_fn
   bfd_target_elf_flavour,
   default_check_format,
   default_core_sniffer,
-  fetch_elf_core_registers,
+  win32_fetch_elf_core_registers,
+  win32_core_xfer_shared_libraries,
   NULL
 };
 
Index: src/libiberty/lbasename.c
===================================================================
--- src.orig/libiberty/lbasename.c	2007-06-18 10:21:44.000000000 -0400
+++ src/libiberty/lbasename.c	2007-06-18 10:22:35.000000000 -0400
@@ -50,14 +50,14 @@ lbasename (const char *name)
 {
   const char *base;
 
-#if defined (HAVE_DOS_BASED_FILE_SYSTEM)
+#if 1 || defined (HAVE_DOS_BASED_FILE_SYSTEM)
   /* Skip over a possible disk name.  */
   if (ISALPHA (name[0]) && name[1] == ':') 
     name += 2;
 #endif
 
   for (base = name; *name; name++)
-    if (IS_DIR_SEPARATOR (*name))
+    if (*name == '\\' || IS_DIR_SEPARATOR (*name))
       base = name + 1;
 
   return base;
Index: src/gdb/gdb_obstack.h
===================================================================
--- src.orig/gdb/gdb_obstack.h	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/gdb_obstack.h	2007-06-18 10:22:35.000000000 -0400
@@ -42,4 +42,9 @@
 #define obstack_chunk_alloc xmalloc
 #define obstack_chunk_free xfree
 
+#define obstack_grow_str(OBSTACK,STRING) \
+  obstack_grow (OBSTACK, STRING, strlen (STRING))
+#define obstack_grow_str0(OBSTACK,STRING) \
+  obstack_grow0 (OBSTACK, STRING, strlen (STRING))
+
 #endif
Index: src/gdb/xml-support.c
===================================================================
--- src.orig/gdb/xml-support.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/xml-support.c	2007-06-18 10:22:35.000000000 -0400
@@ -546,6 +546,8 @@ gdb_xml_parse (struct gdb_xml_parser *pa
   enum XML_Status status;
   const char *error_string;
 
+  gdb_xml_debug (parser, _("Starting:\n%s"), buffer);
+
   status = XML_Parse (parser->expat_parser, buffer, strlen (buffer), 1);
 
   if (status == XML_STATUS_OK && parser->error.reason == 0)
@@ -871,8 +873,7 @@ xml_process_xincludes (const char *name,
       result = xstrdup (obstack_finish (&data->obstack));
 
       if (depth == 0)
-	gdb_xml_debug (parser, _("XInclude processing succeeded:\n%s"),
-		       result);
+	gdb_xml_debug (parser, _("XInclude processing succeeded."));
     }
   else
     result = NULL;
@@ -927,6 +928,68 @@ xml_builtin_xfer_partial (const char *fi
   memcpy (readbuf, buf + offset, len);
   return len;
 }
+
+/* Return a malloc allocated string with special characters from TEXT
+   replaced by entity references.  */
+
+char *
+xml_escape_text (const char *text)
+{
+  char *result;
+  int i, special;
+
+  /* Compute the length of the result.  */
+  for (i = 0, special = 0; text[i] != '\0'; i++)
+    switch (text[i])
+      {
+      case '\'':
+      case '\"':
+	special += 5;
+	break;
+      case '&':
+	special += 4;
+	break;
+      case '<':
+      case '>':
+	special += 3;
+	break;
+      default:
+	break;
+      }
+
+  /* Expand the result.  */
+  result = xmalloc (i + special + 1);
+  for (i = 0, special = 0; text[i] != '\0'; i++)
+    switch (text[i])
+      {
+      case '\'':
+	strcpy (result + i + special, "&apos;");
+	special += 5;
+	break;
+      case '\"':
+	strcpy (result + i + special, "&quot;");
+	special += 5;
+	break;
+      case '&':
+	strcpy (result + i + special, "&amp;");
+	special += 4;
+	break;
+      case '<':
+	strcpy (result + i + special, "&lt;");
+	special += 3;
+	break;
+      case '>':
+	strcpy (result + i + special, "&gt;");
+	special += 3;
+	break;
+      default:
+	result[i + special] = text[i];
+	break;
+      }
+  result[i + special] = '\0';
+
+  return result;
+}
 
 
 static void
Index: src/gdb/xml-support.h
===================================================================
--- src.orig/gdb/xml-support.h	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/xml-support.h	2007-06-18 10:22:35.000000000 -0400
@@ -30,24 +30,6 @@ struct gdb_xml_parser;
 struct gdb_xml_element;
 struct gdb_xml_attribute;
 
-/* Support for XInclude.  */
-
-/* Callback to fetch a new XML file, based on the provided HREF.  */
-
-typedef char *(*xml_fetch_another) (const char *href, void *baton);
-
-/* Return a new string which is the expansion of TEXT after processing
-   <xi:include> tags.  FETCHER will be called (with FETCHER_BATON) to
-   retrieve any new files.  DEPTH should be zero on the initial call.
-
-   On failure, this function uses NAME in a warning and returns NULL.
-   It may throw an exception, but does not for XML parsing
-   problems.  */
-
-char *xml_process_xincludes (const char *name, const char *text,
-			     xml_fetch_another fetcher, void *fetcher_baton,
-			     int depth);
-
 /* Return an XML document which was compiled into GDB, from
    the given FILENAME, or NULL if the file was not compiled in.  */
 
@@ -64,8 +46,32 @@ LONGEST xml_builtin_xfer_partial (const 
 
 /* The text of compiled-in XML documents, from xml-builtin.c
    (generated).  */
+
 extern const char *xml_builtin[][2];
 
+/* Return a malloc allocated string with special characters from TEXT
+   replaced by entity references.  */
+
+char *xml_escape_text (const char *text);
+
+/* Support for XInclude.  */
+
+/* Callback to fetch a new XML file, based on the provided HREF.  */
+
+typedef char *(*xml_fetch_another) (const char *href, void *baton);
+
+/* Return a new string which is the expansion of TEXT after processing
+   <xi:include> tags.  FETCHER will be called (with FETCHER_BATON) to
+   retrieve any new files.  DEPTH should be zero on the initial call.
+
+   On failure, this function uses NAME in a warning and returns NULL.
+   It may throw an exception, but does not for XML parsing
+   problems.  */
+
+char *xml_process_xincludes (const char *name, const char *text,
+			     xml_fetch_another fetcher, void *fetcher_baton,
+			     int depth);
+
 /* Simplified XML parser infrastructure.  */
 
 /* A name and value pair, used to record parsed attributes.  */
Index: src/gdb/coff-pe-read.c
===================================================================
--- src.orig/gdb/coff-pe-read.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/coff-pe-read.c	2007-06-18 10:22:35.000000000 -0400
@@ -309,9 +309,6 @@ read_pe_exported_syms (struct objfile *o
 	+= ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
     }
 
-  printf_filtered (_("Minimal symbols from %s..."), dll_name);
-  wrap_here ("");
-
   /* Truncate name at first dot. Should maybe also convert to all
      lower case for convenience on Windows. */
   read_pe_truncate_name (dll_name);
Index: src/gdb/testsuite/gdb.base/unload.c
===================================================================
--- src.orig/gdb/testsuite/gdb.base/unload.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/testsuite/gdb.base/unload.c	2007-06-18 10:37:40.000000000 -0400
@@ -18,12 +18,19 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+
+#ifdef __WIN32__
+#include <windows.h>
+#define dlopen(name, mode) LoadLibrary (name)
+#define dlsym(handle, func) GetProcAddress (handle, func)
+#define dlclose(handle) FreeLibrary (handle)
+#define dlerror() "error %d occurred", GetLastError ()
+#else
 #include <dlfcn.h>
+#endif
 
 int k = 0;
 
-#define SHLIB_NAME SHLIB_DIR "/unloadshr.sl"
-
 int main()
 {
   void *handle;
@@ -32,11 +39,10 @@ int main()
   const char *msg;
 
   handle = dlopen (SHLIB_NAME, RTLD_LAZY);
-  msg = dlerror ();
   
   if (!handle)
     {
-      fprintf (stderr, msg);
+      fprintf (stderr, dlerror ());
       exit (1);
     }
 
Index: src/gdb/testsuite/gdb.base/unload.exp
===================================================================
--- src.orig/gdb/testsuite/gdb.base/unload.exp	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/testsuite/gdb.base/unload.exp	2007-06-18 10:38:59.000000000 -0400
@@ -30,37 +30,28 @@ if {[skip_shlib_tests]} {
     return 0
 }
 
-# TODO: Use LoadLibrary on these targets instead of dlopen.
-if {([istarget arm*-*-symbianelf*]
-     || [istarget *-*-mingw*]
-     || [istarget *-*-cygwin*]
-     || [istarget *-*-pe*])} {
+# TODO: Use LoadLibrary on this target instead of dlopen.
+if {[istarget arm*-*-symbianelf*]} {
     return 0
 }
 
 set testfile "unload"
 set libfile "unloadshr"
+set libname "${libfile}.sl"
 set libsrcfile ${libfile}.c
 set srcfile $srcdir/$subdir/$testfile.c
 set binfile $objdir/$subdir/$testfile
 set shlibdir ${objdir}/${subdir}
 set libsrc  $srcdir/$subdir/$libfile.c
-set lib_sl  $objdir/$subdir/$libfile.sl
-
-set lib_opts debug
-set exec_opts [list debug additional_flags=-DSHLIB_DIR\=\"${shlibdir}\"]
-
-switch -glob [istarget] {
-    "hppa*-hp-hpux*" { }
-    "*-*-linux*"     { lappend exec_opts "libs=-ldl" }
-    "*-*-solaris*"   { lappend exec_opts "libs=-ldl" }
-    default          { }
-}
+set lib_sl  $objdir/$subdir/$libname
 
 if [get_compiler_info ${binfile}] {
     return -1
 }
 
+set lib_opts debug
+set exec_opts [list debug shlib_load additional_flags=-DSHLIB_NAME\=\"${libname}\"]
+
 if { [gdb_compile_shlib $libsrc $lib_sl $lib_opts] != ""
      || [gdb_compile $srcfile $binfile executable $exec_opts] != ""} {
     untested "Couldn't compile $libsrc or $srcfile."
Index: src/gdb/infcmd.c
===================================================================
--- src.orig/gdb/infcmd.c	2007-06-18 10:21:44.000000000 -0400
+++ src/gdb/infcmd.c	2007-06-18 10:22:35.000000000 -0400
@@ -419,7 +419,9 @@ post_create_inferior (struct target_ops 
     {
       /* Sometimes the platform-specific hook loads initial shared
 	 libraries, and sometimes it doesn't.  Try to do so first, so
-	 that we can add them with the correct value for FROM_TTY.  */
+	 that we can add them with the correct value for FROM_TTY.
+	 If we made all the inferior hook methods consistent,
+	 this call could be removed.  */
 #ifdef SOLIB_ADD
       SOLIB_ADD (NULL, from_tty, target, auto_solib_add);
 #else
@@ -560,7 +562,9 @@ run_command_1 (char *args, int from_tty,
   target_create_inferior (exec_file, get_inferior_args (),
 			  environ_vector (inferior_environ), from_tty);
 
-  post_create_inferior (&current_target, from_tty);
+  /* Pass zero for FROM_TTY, because at this point the "run" command
+     has done its thing; now we are setting up the running program.  */
+  post_create_inferior (&current_target, 0);
 
   /* Start the target running.  */
   proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);


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