Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* For example only, updated Windows DLL support and gdbserver DLL  support
@ 2007-06-18 15:08 Daniel Jacobowitz
  2007-06-18 21:07 ` Christopher Faylor
  2007-06-19 19:06 ` Ulrich Weigand
  0 siblings, 2 replies; 12+ messages in thread
From: Daniel Jacobowitz @ 2007-06-18 15:08 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ulrich Weigand, Pedro Alves

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;
+}
 \f
 
 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);


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver  DLL  support
  2007-06-18 15:08 For example only, updated Windows DLL support and gdbserver DLL support Daniel Jacobowitz
@ 2007-06-18 21:07 ` Christopher Faylor
  2007-06-18 21:12   ` Daniel Jacobowitz
  2007-06-19 19:06 ` Ulrich Weigand
  1 sibling, 1 reply; 12+ messages in thread
From: Christopher Faylor @ 2007-06-18 21:07 UTC (permalink / raw)
  To: Pedro Alves, Ulrich Weigand, gdb-patches

On Mon, Jun 18, 2007 at 11:08:16AM -0400, Daniel Jacobowitz wrote:
>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.

I have no objections to this with two exceptions:

- You use #ifdef __CYGWIN__ .  That would be the only place in the file
where that is used.  I don't see any reason for this unless your patch
is also going to allow native Windows support.  If that is the case,
then maybe that part should be provided separately.

- You seemed to have gratuitously pulled out the code which deals with
cygwin exceptions into a separate function.  I don't think this has
anything to do with solibs and probably shouldn't be part of any
final patch.

cgf


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver  DLL  support
  2007-06-18 21:07 ` Christopher Faylor
@ 2007-06-18 21:12   ` Daniel Jacobowitz
  2007-06-18 21:54     ` Pedro Alves
  0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2007-06-18 21:12 UTC (permalink / raw)
  To: Pedro Alves, Ulrich Weigand, gdb-patches

On Mon, Jun 18, 2007 at 05:07:28PM -0400, Christopher Faylor wrote:
> I have no objections to this with two exceptions:
> 
> - You use #ifdef __CYGWIN__ .  That would be the only place in the file
> where that is used.  I don't see any reason for this unless your patch
> is also going to allow native Windows support.  If that is the case,
> then maybe that part should be provided separately.
> 
> - You seemed to have gratuitously pulled out the code which deals with
> cygwin exceptions into a separate function.  I don't think this has
> anything to do with solibs and probably shouldn't be part of any
> final patch.

Pedro, what do you remember about these?  At least, I don't _think_ it
was me...

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver   DLL  support
  2007-06-18 21:12   ` Daniel Jacobowitz
@ 2007-06-18 21:54     ` Pedro Alves
  2007-06-18 23:28       ` Christopher Faylor
  0 siblings, 1 reply; 12+ messages in thread
From: Pedro Alves @ 2007-06-18 21:54 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches

Daniel Jacobowitz wrote:
> On Mon, Jun 18, 2007 at 05:07:28PM -0400, Christopher Faylor wrote:
>> I have no objections to this with two exceptions:
>>
>> - You use #ifdef __CYGWIN__ .  That would be the only place in the file
>> where that is used.  I don't see any reason for this unless your patch
>> is also going to allow native Windows support.  If that is the case,
>> then maybe that part should be provided separately.
>>
>> - You seemed to have gratuitously pulled out the code which deals with
>> cygwin exceptions into a separate function.  I don't think this has
>> anything to do with solibs and probably shouldn't be part of any
>> final patch.
> 
> Pedro, what do you remember about these?  At least, I don't _think_ it
> was me...
> 

Guilty as charged.

The __CYGWIN__ came from copy/pasting from the gdbserver side of the
patch, where it is needed.  It can be easily removed.

The gratuitousness is only apparent.  Notice that the
cygwin_load_start/cygwin_load_end calculation moved from the
old solib_symbols_add into that new ignore_access_violation_p
function and now uses the master_so_list () to get at cygwin1.dll.
As I was touching the code,  (and I was finding myself reindenting
that big comment, ) I thought of moving it out of handle_exception
to make it cleaner.

Cheers,
Pedro Alves


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver  DLL  support
  2007-06-18 21:54     ` Pedro Alves
@ 2007-06-18 23:28       ` Christopher Faylor
  0 siblings, 0 replies; 12+ messages in thread
From: Christopher Faylor @ 2007-06-18 23:28 UTC (permalink / raw)
  To: Ulrich Weigand, Pedro Alves, gdb-patches

On Mon, Jun 18, 2007 at 10:53:48PM +0100, Pedro Alves wrote:
> Daniel Jacobowitz wrote:
>> On Mon, Jun 18, 2007 at 05:07:28PM -0400, Christopher Faylor wrote:
>>> I have no objections to this with two exceptions:
>>>
>>> - You use #ifdef __CYGWIN__ .  That would be the only place in the file
>>> where that is used.  I don't see any reason for this unless your patch
>>> is also going to allow native Windows support.  If that is the case,
>>> then maybe that part should be provided separately.
>>>
>>> - You seemed to have gratuitously pulled out the code which deals with
>>> cygwin exceptions into a separate function.  I don't think this has
>>> anything to do with solibs and probably shouldn't be part of any
>>> final patch.
>> Pedro, what do you remember about these?  At least, I don't _think_ it
>> was me...
>
> Guilty as charged.
>
> The __CYGWIN__ came from copy/pasting from the gdbserver side of the
> patch, where it is needed.  It can be easily removed.

Ok.

> The gratuitousness is only apparent.  Notice that the
> cygwin_load_start/cygwin_load_end calculation moved from the
> old solib_symbols_add into that new ignore_access_violation_p
> function and now uses the master_so_list () to get at cygwin1.dll.
> As I was touching the code,  (and I was finding myself reindenting
> that big comment, ) I thought of moving it out of handle_exception
> to make it cleaner.

You're right.  I should have looked closer.  It wasn't a gratuitous change
and I agree that moving it into its own function makes sense.

Ship it!

cgf


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver DLL         support
  2007-06-18 15:08 For example only, updated Windows DLL support and gdbserver DLL support Daniel Jacobowitz
  2007-06-18 21:07 ` Christopher Faylor
@ 2007-06-19 19:06 ` Ulrich Weigand
  2007-06-19 19:19   ` Daniel Jacobowitz
  1 sibling, 1 reply; 12+ messages in thread
From: Ulrich Weigand @ 2007-06-19 19:06 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches, Pedro Alves

Daniel Jacobowitz wrote:

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

The general idea looks good to me; in particular I think the segment
relocation approach should be suitable for AIX.

One thing I don't quite like is this:

> +    case TARGET_OBJECT_LIBRARIES:
> +      if (core_vec->xfer_shared_libraries != NULL)
> +	return core_vec->xfer_shared_libraries (ops, object, annex, readbuf,
> +					       writebuf, offset, len);

I had understood the core_fns method of providing a core file target to
be deprecated, and in fact I just recently got rid of it for AIX in favour
of the gdbarch_regset_from_core_section callback ...   I'd prefer this to
be a gdbarch callback (which would also support core file cross-debugging).

The build dependency on libexpat may be a bit annoying on AIX, but I guess
we'll just have to live with that anyway.

The one big unresolved problem (but that was also still unresolved with my
other approach) is the way AIX handles library archives.  It is possible
to use an archive (.a) member as shared library; the operating system
loader will report a pair of file name and member name to identify
the "shared object".

The current rs6000-nat.c code uses this to open such an object:

  /* make sure we have an object file */

  if (bfd_check_format (abfd, bfd_object))
    vp = map_vmap (abfd, 0);

  else if (bfd_check_format (abfd, bfd_archive))
    {
      last = 0;
      /* FIXME??? am I tossing BFDs?  bfd? */
      while ((last = bfd_openr_next_archived_file (abfd, last)))
        if (DEPRECATED_STREQ (mem, last->filename))
          break;

      if (!last)
        {
          warning (_("\"%s\": member \"%s\" missing."), objname, mem);
          bfd_close (abfd);
          return NULL;
        }

      if (!bfd_check_format (last, bfd_object))
        {
          warning (_("\"%s\": member \"%s\" not in executable format: %s."),
                   objname, mem, bfd_errmsg (bfd_get_error ()));
          bfd_close (last);
          bfd_close (abfd);
          return NULL;
        }

It looks like the only way to get this to work within the regular solib
framework would be to actually teach solib.c itself about this form of
archive members.


Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver  DLL         support
  2007-06-19 19:06 ` Ulrich Weigand
@ 2007-06-19 19:19   ` Daniel Jacobowitz
  2007-06-19 20:00     ` Ulrich Weigand
  0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2007-06-19 19:19 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches, Pedro Alves

On Tue, Jun 19, 2007 at 09:05:51PM +0200, Ulrich Weigand wrote:
> One thing I don't quite like is this:
> 
> > +    case TARGET_OBJECT_LIBRARIES:
> > +      if (core_vec->xfer_shared_libraries != NULL)
> > +	return core_vec->xfer_shared_libraries (ops, object, annex, readbuf,
> > +					       writebuf, offset, len);
> 
> I had understood the core_fns method of providing a core file target to
> be deprecated, and in fact I just recently got rid of it for AIX in favour
> of the gdbarch_regset_from_core_section callback ...   I'd prefer this to
> be a gdbarch callback (which would also support core file cross-debugging).

I hadn't even thought about it.  Yes, you're right.

> It looks like the only way to get this to work within the regular solib
> framework would be to actually teach solib.c itself about this form of
> archive members.

Yes, I think you're right.  How about we add an optional member=""
attribute to <library>, and make the common solib.c code open it?
We'd also have to allow .o files.

I'm not sure how much trouble you'll have reporting the correct
relocations for an object file.  Do you get something based on
sections, or do AIX object files have a fixed number of segments?

One thing I've thought of doing is having <section name="blah"
address="blah"/> tags, as an alternative to segment; or they could
have id="N" instead of using section name, or whatever else was
necessary.  So far I haven't needed it, but it would work for
e.g. Linux KGDB which also loads .o files.  Though that's just an
example; actually, for KGDB I'd rather have a bit of Python
distributed with GDB or with the kernel that knows how to list
additional "libraries" :-)

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver         DLL         support
  2007-06-19 19:19   ` Daniel Jacobowitz
@ 2007-06-19 20:00     ` Ulrich Weigand
  2007-06-19 20:12       ` Daniel Jacobowitz
  0 siblings, 1 reply; 12+ messages in thread
From: Ulrich Weigand @ 2007-06-19 20:00 UTC (permalink / raw)
  To: Daniel Jacobowitz; +Cc: gdb-patches, Pedro Alves

Dan Jacobowitz wrote:

> > It looks like the only way to get this to work within the regular solib
> > framework would be to actually teach solib.c itself about this form of
> > archive members.
> 
> Yes, I think you're right.  How about we add an optional member=""
> attribute to <library>, and make the common solib.c code open it?
> We'd also have to allow .o files.

That sounds reasonable.  The member name would presumably also
have to be added to so_list ...

> I'm not sure how much trouble you'll have reporting the correct
> relocations for an object file.  Do you get something based on
> sections, or do AIX object files have a fixed number of segments?

XCOFF seems to be a bit limited in that respect, I understand there
is just "Text" and "Data".  The AIX ldinfo structure provides:

ldinfo_textorg
    Effective address of the loaded program image, including the XCOFF headers. 

ldinfo_textsize
    Length of loaded program image. 

ldinfo_dataorg
    Effective address of the start of data. 

ldinfo_datasize
    Size of data, including the .bss section. 

For more details, see:
http://publib.boulder.ibm.com/infocenter/pseries/v5r3/index.jsp?topic=/com.ibm.aix.files/doc/aixfiles/ldr.h.htm


Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver  DLL         support
  2007-06-19 20:00     ` Ulrich Weigand
@ 2007-06-19 20:12       ` Daniel Jacobowitz
  2007-06-19 22:43         ` Pedro Alves
  0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2007-06-19 20:12 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches, Pedro Alves

On Tue, Jun 19, 2007 at 10:00:35PM +0200, Ulrich Weigand wrote:
> That sounds reasonable.  The member name would presumably also
> have to be added to so_list ...

Yeah.

> > I'm not sure how much trouble you'll have reporting the correct
> > relocations for an object file.  Do you get something based on
> > sections, or do AIX object files have a fixed number of segments?
> 
> XCOFF seems to be a bit limited in that respect, I understand there
> is just "Text" and "Data".  The AIX ldinfo structure provides:

Perfect.  Then GDB's xcoff reader can report that the object file has
two "segments", one text and one data.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver   DLL         support
  2007-06-19 20:12       ` Daniel Jacobowitz
@ 2007-06-19 22:43         ` Pedro Alves
  2007-06-19 23:34           ` Daniel Jacobowitz
  0 siblings, 1 reply; 12+ messages in thread
From: Pedro Alves @ 2007-06-19 22:43 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ulrich Weigand

Daniel Jacobowitz wrote:
> Ulrich Weigand wrote:
>>> I'm not sure how much trouble you'll have reporting the correct
>>> relocations for an object file.  Do you get something based on
>>> sections, or do AIX object files have a fixed number of segments?
>> XCOFF seems to be a bit limited in that respect, I understand there
>> is just "Text" and "Data".  The AIX ldinfo structure provides:
> 
> Perfect.  Then GDB's xcoff reader can report that the object file has
> two "segments", one text and one data.
> 

Are .text and .data really loaded as one segment like on windows,
or can AIX load them separately at arbitrary addresses irrespective
of the order that they have on the file?  The bfd view of the order
of the sections may be different from what the target would report.
One might need to take that into account.

Eg:

On file:
sect1, .text 0x000001000 (seg0)
sect2, .data 0x000100000 (seg1)

On load:
.text 0x010000000 (seg0)
.data 0x001100000 (seg1)

report .text as seg0 and .data as seg1,

relocate 0x000001000 to 0x010000000
relocate 0x000100000 to 0x001100000

OK.

---

Eg2:

On file:
sect1, .data 0x000002000 (seg0)
sect2, .text 0x000200000 (seg1)

On load:
.text 0x020000000 (seg0)
.data 0x002200000 (seg1)

report .text as seg0 and .data as seg1, (bad)

relocate 0x000002000 to 0x020000000 (bad)
relocate 0x000200000 to 0x002200000 (bad)

NOK.

Cheers,
Pedro Alves


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver  DLL         support
  2007-06-19 22:43         ` Pedro Alves
@ 2007-06-19 23:34           ` Daniel Jacobowitz
  2007-06-19 23:58             ` Pedro Alves
  0 siblings, 1 reply; 12+ messages in thread
From: Daniel Jacobowitz @ 2007-06-19 23:34 UTC (permalink / raw)
  To: Pedro Alves; +Cc: gdb-patches, Ulrich Weigand

On Tue, Jun 19, 2007 at 11:43:21PM +0100, Pedro Alves wrote:
> Are .text and .data really loaded as one segment like on windows,
> or can AIX load them separately at arbitrary addresses irrespective
> of the order that they have on the file?  The bfd view of the order
> of the sections may be different from what the target would report.
> One might need to take that into account.

They're two separate sections, but they're named - i.e. it's clear
which one is text and which one is data.  Since this is all internal
to GDB, we can just define text to be the first segment.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: For example only, updated Windows DLL support and gdbserver DLL          support
  2007-06-19 23:34           ` Daniel Jacobowitz
@ 2007-06-19 23:58             ` Pedro Alves
  0 siblings, 0 replies; 12+ messages in thread
From: Pedro Alves @ 2007-06-19 23:58 UTC (permalink / raw)
  To: Pedro Alves, gdb-patches, Ulrich Weigand

Daniel Jacobowitz wrote:
> On Tue, Jun 19, 2007 at 11:43:21PM +0100, Pedro Alves wrote:
>> Are .text and .data really loaded as one segment like on windows,
>> or can AIX load them separately at arbitrary addresses irrespective
>> of the order that they have on the file?  The bfd view of the order
>> of the sections may be different from what the target would report.
>> One might need to take that into account.
> 
> They're two separate sections, but they're named - i.e. it's clear
> which one is text and which one is data.  Since this is all internal
> to GDB, we can just define text to be the first segment.
> 

Ah right, implement an xcoffread.c:xcoff_symfile_segments that takes that
into account, and allow *_symfile_segments override per target if needed
later.

Cheers,
Pedro Alves


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2007-06-19 23:58 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-06-18 15:08 For example only, updated Windows DLL support and gdbserver DLL support Daniel Jacobowitz
2007-06-18 21:07 ` Christopher Faylor
2007-06-18 21:12   ` Daniel Jacobowitz
2007-06-18 21:54     ` Pedro Alves
2007-06-18 23:28       ` Christopher Faylor
2007-06-19 19:06 ` Ulrich Weigand
2007-06-19 19:19   ` Daniel Jacobowitz
2007-06-19 20:00     ` Ulrich Weigand
2007-06-19 20:12       ` Daniel Jacobowitz
2007-06-19 22:43         ` Pedro Alves
2007-06-19 23:34           ` Daniel Jacobowitz
2007-06-19 23:58             ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox