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]

Re: [rfc] Shared libraries over the remote protocol, take two


On Mon, Jun 18, 2007 at 11:02:11AM -0400, Daniel Jacobowitz wrote:
> Here is a new attempt at remote shared library events.  The major
> protocol changes since last time are the elimination of load/unload
> events (just query the whole list again), the use of target objects
> (so that this can be used more easily for other targets, like AIX)
> , and the use XML (because I had to both escape the entire message
> and then the library name - my rule of thumb is that when I need to
> invent a new way to escape special characters, I should probably use
> XML, since it offers a standard way to do that "for free").

I checked this in.

-- 
Daniel Jacobowitz
CodeSourcery

2007-07-02  Daniel Jacobowitz  <dan@codesourcery.com>

	* Makefile.in (XMLFILES): Add library-list.dtd.
	(ALLDEPFILES): Add solib-target.o.
	(solib-target.o): New rule.
	* remote.c (PACKET_qXfer_libraries): New constant.
	(remote_protocol_features): Add qXfer:libraries:read.
	(remote_wait): Recognize library stop replies.
	(remote_async_wait): Likewise.  Fix typo.
	(remote_xfer_partial): Handle TARGET_OBJECT_LIBRARIES.
	(init_remote_async_ops): Fix typo.
	(_initialize_remote): Register "set remote library-info-packet".
	* solib-som.c (som_current_sos): Set addr_low and addr_high.
	* solib-target.c: New file.
	* solib.c (solib_map_sections): Use addr_low and addr_high instead
	of textsection.
	(info_sharedlibrary_command): Likewise.
	(solib_add_library, solib_remove_library): New.
	* solist.h (struct so_list): Replace textsection with addr_low and
	addr_high.
	* target.h (enum target_object): Add TARGET_OBJECT_LIBRARIES.
	* NEWS: Describe new qXfer:libraries:read and shared library
	event support.
	* features/library-list.dtd: New.

2007-07-02  Daniel Jacobowitz  <dan@codesourcery.com>

	* gdb.texinfo (Remote Configuration): Document library-info-packet.
	Add other missing entries.  Adjust the table size to fit.
	(Stop Reply Packets): Use @itemize instead of @enumerate.  Document
	stop reasons including the new "library" event.
	(General Query Packets): Adjust table widths for qSupported.  Mention
	qXfer:libraries:read reply to qSupported and document the new packet.
	(Library List Format): New section.

---
 gdb/Makefile.in               |    5 
 gdb/NEWS                      |   12 +
 gdb/doc/gdb.texinfo           |  153 ++++++++++++++--
 gdb/features/library-list.dtd |   15 +
 gdb/remote.c                  |   59 +++++-
 gdb/solib-som.c               |    3 
 gdb/solib-target.c            |  384 ++++++++++++++++++++++++++++++++++++++++++
 gdb/solib.c                   |   18 +
 gdb/solist.h                  |    6 
 gdb/target.h                  |    4 
 10 files changed, 622 insertions(+), 37 deletions(-)

Index: gdb/Makefile.in
===================================================================
--- gdb/Makefile.in.orig	2007-07-02 14:56:41.000000000 -0400
+++ gdb/Makefile.in	2007-07-02 15:16:42.000000000 -0400
@@ -403,6 +403,7 @@ RUNTESTFLAGS=
 
 # XML files to build in to GDB.
 XMLFILES = $(srcdir)/features/gdb-target.dtd $(srcdir)/features/xinclude.dtd \
+	$(srcdir)/features/library-list.dtd \
 	$(TDEP_XML)
 
 # This is ser-unix.o for any system which supports a v7/BSD/SYSV/POSIX
@@ -1471,6 +1472,7 @@ ALLDEPFILES = \
 	mips64obsd-nat.c mips64obsd-tdep.c \
 	nbsd-nat.c nbsd-tdep.c obsd-tdep.c \
 	solib-osf.c \
+	solib-target.c \
 	somread.c solib-som.c \
 	posix-hdep.c \
 	ppc-sysv-tdep.c ppc-linux-nat.c ppc-linux-tdep.c \
@@ -2596,6 +2598,9 @@ solib-svr4.o: solib-svr4.c $(defs_h) $(e
 	$(gdbcore_h) $(target_h) $(inferior_h) $(gdb_assert_h) \
 	$(solist_h) $(solib_h) $(solib_svr4_h) $(bfd_target_h) $(elf_bfd_h) \
 	$(exec_h)
+solib-target.o: solib-target.c $(defs_h) $(objfiles_h) $(solist_h) \
+	$(symtab_h) $(symfile_h) $(target_h) $(vec_h) $(xml_support_h) \
+	$(gdb_string_h)
 sol-thread.o: sol-thread.c $(defs_h) $(gdbthread_h) $(target_h) \
 	$(inferior_h) $(gdb_stat_h) $(gdbcmd_h) $(gdbcore_h) $(regcache_h) \
 	$(solib_h) $(symfile_h) $(observer_h) $(gdb_string_h) $(gregset_h)
Index: gdb/remote.c
===================================================================
--- gdb/remote.c.orig	2007-07-02 14:56:51.000000000 -0400
+++ gdb/remote.c	2007-07-02 14:58:13.000000000 -0400
@@ -905,6 +905,7 @@ enum {
   PACKET_Z4,
   PACKET_qXfer_auxv,
   PACKET_qXfer_features,
+  PACKET_qXfer_libraries,
   PACKET_qXfer_memory_map,
   PACKET_qXfer_spu_read,
   PACKET_qXfer_spu_write,
@@ -2376,6 +2377,8 @@ static struct protocol_feature remote_pr
     PACKET_qXfer_auxv },
   { "qXfer:features:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_features },
+  { "qXfer:libraries:read", PACKET_DISABLE, remote_supported_packet,
+    PACKET_qXfer_libraries },
   { "qXfer:memory-map:read", PACKET_DISABLE, remote_supported_packet,
     PACKET_qXfer_memory_map },
   { "qXfer:spu:read", PACKET_DISABLE, remote_supported_packet,
@@ -3181,6 +3184,7 @@ remote_wait (ptid_t ptid, struct target_
   struct remote_arch_state *rsa = get_remote_arch_state ();
   ULONGEST thread_num = -1;
   ULONGEST addr;
+  int solibs_changed = 0;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3266,6 +3270,16 @@ Packet: '%s'\n"),
 			p = unpack_varlen_hex (++p1, &addr);
 			remote_watch_data_address = (CORE_ADDR)addr;
 		      }
+		    else if (strncmp (p, "library", p1 - p) == 0)
+		      {
+			p1++;
+			p_temp = p1;
+			while (*p_temp && *p_temp != ';')
+			  p_temp++;
+
+			solibs_changed = 1;
+			p = p_temp;
+		      }
 		    else
  		      {
  			/* Silently skip unknown optional info.  */
@@ -3307,9 +3321,14 @@ Packet: '%s'\n"),
 	  }
 	  /* fall through */
 	case 'S':		/* Old style status, just signal only.  */
-	  status->kind = TARGET_WAITKIND_STOPPED;
-	  status->value.sig = (enum target_signal)
-	    (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+	  if (solibs_changed)
+	    status->kind = TARGET_WAITKIND_LOADED;
+	  else
+	    {
+	      status->kind = TARGET_WAITKIND_STOPPED;
+	      status->value.sig = (enum target_signal)
+		(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+	    }
 
 	  if (buf[3] == 'p')
 	    {
@@ -3372,6 +3391,7 @@ remote_async_wait (ptid_t ptid, struct t
   struct remote_arch_state *rsa = get_remote_arch_state ();
   ULONGEST thread_num = -1;
   ULONGEST addr;
+  int solibs_changed = 0;
 
   status->kind = TARGET_WAITKIND_EXITED;
   status->value.integer = 0;
@@ -3433,7 +3453,7 @@ remote_async_wait (ptid_t ptid, struct t
 		/* If this packet is an awatch packet, don't parse the 'a'
 		   as a register number.  */
 
-		if (!strncmp (p, "awatch", strlen ("awatch")) != 0)
+		if (strncmp (p, "awatch", strlen("awatch")) != 0)
 		  {
 		    /* Read the register number.  */
 		    pnum = strtol (p, &p_temp, 16);
@@ -3463,6 +3483,16 @@ Packet: '%s'\n"),
 			p = unpack_varlen_hex (++p1, &addr);
 			remote_watch_data_address = (CORE_ADDR)addr;
 		      }
+		    else if (strncmp (p, "library", p1 - p) == 0)
+		      {
+			p1++;
+			p_temp = p1;
+			while (*p_temp && *p_temp != ';')
+			  p_temp++;
+
+			solibs_changed = 1;
+			p = p_temp;
+		      }
 		    else
  		      {
  			/* Silently skip unknown optional info.  */
@@ -3504,9 +3534,14 @@ Packet: '%s'\n"),
 	  }
 	  /* fall through */
 	case 'S':		/* Old style status, just signal only.  */
-	  status->kind = TARGET_WAITKIND_STOPPED;
-	  status->value.sig = (enum target_signal)
-	    (((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+	  if (solibs_changed)
+	    status->kind = TARGET_WAITKIND_LOADED;
+	  else
+	    {
+	      status->kind = TARGET_WAITKIND_STOPPED;
+	      status->value.sig = (enum target_signal)
+		(((fromhex (buf[1])) << 4) + (fromhex (buf[2])));
+	    }
 
 	  if (buf[3] == 'p')
 	    {
@@ -5799,6 +5834,11 @@ remote_xfer_partial (struct target_ops *
 	(ops, "features", annex, readbuf, offset, len,
 	 &remote_protocol_packets[PACKET_qXfer_features]);
 
+    case TARGET_OBJECT_LIBRARIES:
+      return remote_read_qxfer
+	(ops, "libraries", annex, readbuf, offset, len,
+	 &remote_protocol_packets[PACKET_qXfer_libraries]);
+
     case TARGET_OBJECT_MEMORY_MAP:
       gdb_assert (annex == NULL);
       return remote_read_qxfer (ops, "memory-map", annex, readbuf, offset, len,
@@ -6416,7 +6456,7 @@ Specify the serial device it is connecte
   remote_async_ops.to_memory_map = remote_memory_map;
   remote_async_ops.to_flash_erase = remote_flash_erase;
   remote_async_ops.to_flash_done = remote_flash_done;
-  remote_ops.to_read_description = remote_read_description;
+  remote_async_ops.to_read_description = remote_read_description;
 }
 
 /* Set up the async extended remote vector by making a copy of the standard
@@ -6656,6 +6696,9 @@ Show the maximum size of the address (in
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_features],
 			 "qXfer:features:read", "target-features", 0);
 
+  add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_libraries],
+			 "qXfer:libraries:read", "library-info", 0);
+
   add_packet_config_cmd (&remote_protocol_packets[PACKET_qXfer_memory_map],
 			 "qXfer:memory-map:read", "memory-map", 0);
 
Index: gdb/solib-som.c
===================================================================
--- gdb/solib-som.c.orig	2007-07-02 14:56:17.000000000 -0400
+++ gdb/solib-som.c	2007-07-02 14:58:13.000000000 -0400
@@ -623,6 +623,9 @@ som_current_sos (void)
 	    	    paddr_nz (new->lm_info->tsd_start_addr));
 #endif
 
+	    new->addr_low = lmi->text_addr;
+	    new->addr_high = lmi->text_end;
+
 	    /* Link the new object onto the list.  */
 	    new->next = NULL;
 	    *link_ptr = new;
Index: gdb/solib-target.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/solib-target.c	2007-07-02 15:17:02.000000000 -0400
@@ -0,0 +1,384 @@
+/* Definitions for targets which report shared library events.
+
+   Copyright (C) 2007
+   Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   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.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.  */
+
+#include "defs.h"
+#include "objfiles.h"
+#include "solist.h"
+#include "symtab.h"
+#include "symfile.h"
+#include "target.h"
+#include "vec.h"
+
+#include "gdb_string.h"
+
+DEF_VEC_O(CORE_ADDR);
+
+/* Private data for each loaded library.  */
+struct lm_info
+{
+  /* The library's name.  The name is normally kept in the struct
+     so_list; it is only here during XML parsing.  */
+  char *name;
+
+  /* The base addresses for each independently relocatable segment of
+     this shared library.  */
+  VEC(CORE_ADDR) *segment_bases;
+
+  /* The cached offsets for each section of this shared library,
+     determined from SEGMENT_BASES.  */
+  struct section_offsets *offsets;
+};
+
+typedef struct lm_info *lm_info_p;
+DEF_VEC_P(lm_info_p);
+
+#if !defined(HAVE_LIBEXPAT)
+
+static VEC(lm_info_p)
+solib_target_parse_libraries (const char *library)
+{
+  static int have_warned;
+
+  if (!have_warned)
+    {
+      have_warned = 1;
+      warning (_("Can not parse XML library list; XML support was disabled "
+		 "at compile time"));
+    }
+
+  return NULL;
+}
+
+#else /* HAVE_LIBEXPAT */
+
+#include "xml-support.h"
+
+/* Handle the start of a <segment> element.  */
+
+static void
+library_list_start_segment (struct gdb_xml_parser *parser,
+			    const struct gdb_xml_element *element,
+			    void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+  VEC(lm_info_p) **list = user_data;
+  struct lm_info *last = VEC_last (lm_info_p, *list);
+  ULONGEST *address_p = VEC_index (gdb_xml_value_s, attributes, 0)->value;
+
+  VEC_safe_push (CORE_ADDR, last->segment_bases, address_p);
+}
+
+/* Handle the start of a <library> element.  */
+
+static void
+library_list_start_library (struct gdb_xml_parser *parser,
+			    const struct gdb_xml_element *element,
+			    void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+  VEC(lm_info_p) **list = user_data;
+  struct lm_info *item = XZALLOC (struct lm_info);
+  const char *name = VEC_index (gdb_xml_value_s, attributes, 0)->value;
+
+  item->name = xstrdup (name);
+  VEC_safe_push (lm_info_p, *list, item);
+}
+
+/* Handle the start of a <library-list> element.  */
+
+static void
+library_list_start_list (struct gdb_xml_parser *parser,
+			 const struct gdb_xml_element *element,
+			 void *user_data, VEC(gdb_xml_value_s) *attributes)
+{
+  char *version = VEC_index (gdb_xml_value_s, attributes, 0)->value;
+
+  if (strcmp (version, "1.0") != 0)
+    gdb_xml_error (parser,
+		   _("Library list has unsupported version \"%s\""),
+		   version);
+}
+
+/* Discard the constructed library list.  */
+
+static void
+solib_target_free_library_list (void *p)
+{
+  VEC(lm_info_p) **result = p;
+  struct lm_info *info;
+  int ix;
+
+  for (ix = 0; VEC_iterate (lm_info_p, *result, ix, info); ix++)
+    {
+      xfree (info->name);
+      VEC_free (CORE_ADDR, info->segment_bases);
+      xfree (info);
+    }
+  VEC_free (lm_info_p, *result);
+  *result = NULL;
+}
+
+/* The allowed elements and attributes for an XML library list.
+   The root element is a <library-list>.  */
+
+const struct gdb_xml_attribute segment_attributes[] = {
+  { "address", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element library_children[] = {
+  { "segment", segment_attributes, NULL, GDB_XML_EF_REPEATABLE,
+    library_list_start_segment, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_attribute library_attributes[] = {
+  { "name", GDB_XML_AF_NONE, NULL, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element library_list_children[] = {
+  { "library", library_attributes, library_children,
+    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+    library_list_start_library, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_attribute library_list_attributes[] = {
+  { "version", GDB_XML_AF_NONE, NULL, NULL },
+  { NULL, GDB_XML_AF_NONE, NULL, NULL }
+};
+
+const struct gdb_xml_element library_list_elements[] = {
+  { "library-list", library_list_attributes, library_list_children,
+    GDB_XML_EF_NONE, library_list_start_list, NULL },
+  { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
+};
+
+static VEC(lm_info_p) *
+solib_target_parse_libraries (const char *library)
+{
+  struct gdb_xml_parser *parser;
+  VEC(lm_info_p) *result = NULL;
+  struct cleanup *before_deleting_result, *back_to;
+
+  back_to = make_cleanup (null_cleanup, NULL);
+  parser = gdb_xml_create_parser_and_cleanup (_("target library list"),
+					      library_list_elements, &result);
+  gdb_xml_use_dtd (parser, "library-list.dtd");
+
+  before_deleting_result = make_cleanup (solib_target_free_library_list,
+					 &result);
+
+  if (gdb_xml_parse (parser, library) == 0)
+    /* Parsed successfully, don't need to delete the result.  */
+    discard_cleanups (before_deleting_result);
+
+  do_cleanups (back_to);
+  return result;
+}
+#endif
+
+static struct so_list *
+solib_target_current_sos (void)
+{
+  struct so_list *new_solib, *start = NULL, *last = NULL;
+  const char *library_document;
+  VEC(lm_info_p) *library_list;
+  struct lm_info *info;
+  int ix;
+
+  /* Fetch the list of shared libraries.  */
+  library_document = target_read_stralloc (&current_target,
+					   TARGET_OBJECT_LIBRARIES,
+					   NULL);
+  if (library_document == NULL)
+    return NULL;
+
+  /* Parse the list.  */
+  library_list = solib_target_parse_libraries (library_document);
+  if (library_list == NULL)
+    return NULL;
+
+  /* Build a struct so_list for each entry on the list.  */
+  for (ix = 0; VEC_iterate (lm_info_p, library_list, ix, info); ix++)
+    {
+      new_solib = XZALLOC (struct so_list);
+      strncpy (new_solib->so_name, info->name, SO_NAME_MAX_PATH_SIZE - 1);
+      new_solib->so_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+      strncpy (new_solib->so_original_name, info->name,
+	       SO_NAME_MAX_PATH_SIZE - 1);
+      new_solib->so_original_name[SO_NAME_MAX_PATH_SIZE - 1] = '\0';
+      new_solib->lm_info = info;
+
+      /* We no longer need this copy of the name.  */
+      xfree (info->name);
+      info->name = NULL;
+
+      /* Add it to the list.  */
+      if (!start)
+	last = start = new_solib;
+      else
+	{
+	  last->next = new_solib;
+	  last = new_solib;
+	}
+    }
+
+  /* Free the library list, but not its members.  */
+  VEC_free (lm_info_p, library_list);
+
+  return start;
+}
+
+static void
+solib_target_special_symbol_handling (void)
+{
+  /* Nothing needed.  */
+}
+
+static void
+solib_target_solib_create_inferior_hook (void)
+{
+  /* Nothing needed.  */
+}
+
+static void
+solib_target_clear_solib (void)
+{
+  /* Nothing needed.  */
+}
+
+static void
+solib_target_free_so (struct so_list *so)
+{
+  gdb_assert (so->lm_info->name == NULL);
+  xfree (so->lm_info->offsets);
+  VEC_free (CORE_ADDR, so->lm_info->segment_bases);
+  xfree (so->lm_info);
+}
+
+static void
+solib_target_relocate_section_addresses (struct so_list *so,
+					 struct section_table *sec)
+{
+  int flags = bfd_get_section_flags (sec->bfd, sec->the_bfd_section);
+  CORE_ADDR offset;
+
+  /* Build the offset table only once per object file.  We can not do
+     it any earlier, since we need to open the file first.  */
+  if (so->lm_info->offsets == NULL)
+    {
+      struct symfile_segment_data *data;
+      int num_sections = bfd_count_sections (so->abfd);
+
+      so->lm_info->offsets = xzalloc (SIZEOF_N_SECTION_OFFSETS (num_sections));
+
+      data = get_symfile_segment_data (so->abfd);
+      if (data == NULL)
+	warning (_("Could not relocate shared library \"%s\": no segments"),
+		 so->so_name);
+      else
+	{
+	  ULONGEST orig_delta;
+	  int i;
+	  int num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
+	  CORE_ADDR *segment_bases = VEC_address (CORE_ADDR,
+						  so->lm_info->segment_bases);
+
+	  if (!symfile_map_offsets_to_segments (so->abfd, data,
+						so->lm_info->offsets,
+						num_bases, segment_bases))
+	    warning (_("Could not relocate shared library \"%s\": bad offsets"),
+		     so->so_name);
+
+	  /* Find the range of addresses to report for this library in
+	     "info sharedlibrary".  Report any consecutive segments
+	     which were relocated as a single unit.  */
+	  gdb_assert (num_bases > 0);
+	  orig_delta = segment_bases[0] - data->segment_bases[0];
+
+	  for (i = 1; i < data->num_segments; i++)
+	    {
+	      /* If we have run out of offsets, assume all remaining segments
+		 have the same offset.  */
+	      if (i >= num_bases)
+		continue;
+
+	      /* If this segment does not have the same offset, do not include
+		 it in the library's range.  */
+	      if (segment_bases[i] - data->segment_bases[i] != orig_delta)
+		break;
+	    }
+
+	  so->addr_low = segment_bases[0];
+	  so->addr_high = (data->segment_bases[i - 1]
+			   + data->segment_sizes[i - 1]
+			   /* FIXME this must be needed! + orig_delta */);
+
+	  free_symfile_segment_data (data);
+	}
+    }
+
+  offset = so->lm_info->offsets->offsets[sec->the_bfd_section->index];
+  sec->addr += offset;
+  sec->endaddr += offset;
+}
+
+static int
+solib_target_open_symbol_file_object (void *from_ttyp)
+{
+  /* We can't locate the main symbol file based on the target's
+     knowledge; the user has to specify it.  */
+  return 0;
+}
+
+static int
+solib_target_in_dynsym_resolve_code (CORE_ADDR pc)
+{
+  /* We don't have a range of addresses for the dynamic linker; there
+     may not be one in the program's address space.  So only report
+     PLT entries (which may be import stubs).  */
+  return in_plt_section (pc, NULL);
+}
+
+static struct target_so_ops solib_target_so_ops;
+
+extern initialize_file_ftype _initialize_solib_target; /* -Wmissing-prototypes */
+
+void
+_initialize_solib_target (void)
+{
+  solib_target_so_ops.relocate_section_addresses
+    = solib_target_relocate_section_addresses;
+  solib_target_so_ops.free_so = solib_target_free_so;
+  solib_target_so_ops.clear_solib = solib_target_clear_solib;
+  solib_target_so_ops.solib_create_inferior_hook
+    = solib_target_solib_create_inferior_hook;
+  solib_target_so_ops.special_symbol_handling
+    = solib_target_special_symbol_handling;
+  solib_target_so_ops.current_sos = solib_target_current_sos;
+  solib_target_so_ops.open_symbol_file_object
+    = solib_target_open_symbol_file_object;
+  solib_target_so_ops.in_dynsym_resolve_code
+    = solib_target_in_dynsym_resolve_code;
+
+  current_target_so_ops = &solib_target_so_ops;
+}
Index: gdb/solib.c
===================================================================
--- gdb/solib.c.orig	2007-07-02 14:56:52.000000000 -0400
+++ gdb/solib.c	2007-07-02 14:58:13.000000000 -0400
@@ -316,9 +316,15 @@ solib_map_sections (void *arg)
          object's file by the base address to which the object was actually
          mapped. */
       ops->relocate_section_addresses (so, p);
-      if (strcmp (p->the_bfd_section->name, ".text") == 0)
+
+      /* If the target didn't provide information about the address
+	 range of the shared object, assume we want the location of
+	 the .text section.  */
+      if (so->addr_low == 0 && so->addr_high == 0
+	  && strcmp (p->the_bfd_section->name, ".text") == 0)
 	{
-	  so->textsection = p;
+	  so->addr_low = p->addr;
+	  so->addr_high = p->endaddr;
 	}
     }
 
@@ -742,15 +748,15 @@ info_sharedlibrary_command (char *ignore
 	    }
 
 	  printf_unfiltered ("%-*s", addr_width,
-			     so->textsection != NULL 
+			     so->addr_high != 0
 			       ? hex_string_custom (
-			           (LONGEST) so->textsection->addr,
+			           (LONGEST) so->addr_low,
 	                           addr_width - 4)
 			       : "");
 	  printf_unfiltered ("%-*s", addr_width,
-			     so->textsection != NULL 
+			     so->addr_high != 0
 			       ? hex_string_custom (
-			           (LONGEST) so->textsection->endaddr,
+			           (LONGEST) so->addr_high,
 	                           addr_width - 4)
 			       : "");
 	  printf_unfiltered ("%-12s", so->symbols_loaded ? "Yes" : "No");
Index: gdb/solist.h
===================================================================
--- gdb/solist.h.orig	2007-07-02 14:56:17.000000000 -0400
+++ gdb/solist.h	2007-07-02 14:58:13.000000000 -0400
@@ -64,7 +64,11 @@ struct so_list
     struct objfile *objfile;	/* objfile for loaded lib */
     struct section_table *sections;
     struct section_table *sections_end;
-    struct section_table *textsection;
+
+    /* Record the range of addresses belonging to this shared library.
+       There may not be just one (e.g. if two segments are relocated
+       differently); but this is only used for "info sharedlibrary".  */
+    CORE_ADDR addr_low, addr_high;
   };
 
 struct target_so_ops
Index: gdb/target.h
===================================================================
--- gdb/target.h.orig	2007-07-02 14:56:17.000000000 -0400
+++ gdb/target.h	2007-07-02 14:58:13.000000000 -0400
@@ -212,7 +212,9 @@ enum target_object
   TARGET_OBJECT_FLASH,
   /* Available target-specific features, e.g. registers and coprocessors.
      See "target-descriptions.c".  ANNEX should never be empty.  */
-  TARGET_OBJECT_AVAILABLE_FEATURES
+  TARGET_OBJECT_AVAILABLE_FEATURES,
+  /* Currently loaded libraries, in XML format.  */
+  TARGET_OBJECT_LIBRARIES
   /* Possible future objects: TARGET_OBJECT_FILE, TARGET_OBJECT_PROC, ... */
 };
 
Index: gdb/NEWS
===================================================================
--- gdb/NEWS.orig	2007-07-02 14:56:41.000000000 -0400
+++ gdb/NEWS	2007-07-02 14:58:13.000000000 -0400
@@ -44,6 +44,12 @@ segment base addresses (rather than offs
 * The /i format now outputs any trailing branch delay slot instructions 
 immediately following the last instruction within the count specified.
 
+* The GDB remote protocol "T" stop reply packet now supports a
+"library" response.  Combined with the new "qXfer:libraries:read"
+packet, this response allows GDB to debug shared libraries on targets
+where the operating system manages the list of loaded libraries (e.g.
+Windows and SymbianOS).
+
 * New commands
 
 set remoteflow
@@ -117,6 +123,12 @@ qXfer:spu:write:
   Read or write contents of an spufs file on the target system.  These
   packets are available only on the Cell/B.E. SPU architecture.
 
+qXfer:libraries:read:
+  Report the loaded shared libraries.  Combined with new "T" packet
+  response, this packet allows GDB to debug shared libraries on
+  targets where the operating system manages the list of loaded
+  libraries (e.g. Windows and SymbianOS).
+
 * Removed targets
 
 Support for these obsolete configurations has been removed.
Index: gdb/doc/gdb.texinfo
===================================================================
--- gdb/doc/gdb.texinfo.orig	2007-07-02 14:56:56.000000000 -0400
+++ gdb/doc/gdb.texinfo	2007-07-02 15:01:59.000000000 -0400
@@ -12859,58 +12859,80 @@ If you do, that may be a bug in your rem
 in @value{GDBN}.  You may want to report the problem to the
 @value{GDBN} developers.
 
-The available settings are:
+For each packet @var{name}, the command to enable or disable the
+packet is @code{set remote @var{name}-packet}.  The available settings
+are:
 
-@multitable @columnfractions 0.3 0.2 0.35
+@multitable @columnfractions 0.28 0.32 0.25
 @item Command Name
 @tab Remote Packet
 @tab Related Features
 
-@item @code{fetch-register-packet}
+@item @code{fetch-register}
 @tab @code{p}
 @tab @code{info registers}
 
-@item @code{set-register-packet}
+@item @code{set-register}
 @tab @code{P}
 @tab @code{set}
 
-@item @code{binary-download-packet}
+@item @code{binary-download}
 @tab @code{X}
 @tab @code{load}, @code{set}
 
-@item @code{read-aux-vector-packet}
+@item @code{read-aux-vector}
 @tab @code{qXfer:auxv:read}
 @tab @code{info auxv}
 
-@item @code{symbol-lookup-packet}
+@item @code{symbol-lookup}
 @tab @code{qSymbol}
 @tab Detecting multiple threads
 
-@item @code{verbose-resume-packet}
+@item @code{verbose-resume}
 @tab @code{vCont}
 @tab Stepping or resuming multiple threads
 
-@item @code{software-breakpoint-packet}
+@item @code{software-breakpoint}
 @tab @code{Z0}
 @tab @code{break}
 
-@item @code{hardware-breakpoint-packet}
+@item @code{hardware-breakpoint}
 @tab @code{Z1}
 @tab @code{hbreak}
 
-@item @code{write-watchpoint-packet}
+@item @code{write-watchpoint}
 @tab @code{Z2}
 @tab @code{watch}
 
-@item @code{read-watchpoint-packet}
+@item @code{read-watchpoint}
 @tab @code{Z3}
 @tab @code{rwatch}
 
-@item @code{access-watchpoint-packet}
+@item @code{access-watchpoint}
 @tab @code{Z4}
 @tab @code{awatch}
 
-@item @code{get-thread-local-storage-address-packet}
+@item @code{target-features}
+@tab @code{qXfer:features:read}
+@tab @code{set architecture}
+
+@item @code{library-info}
+@tab @code{qXfer:libraries:read}
+@tab @code{info sharedlibrary}
+
+@item @code{memory-map}
+@tab @code{qXfer:memory-map:read}
+@tab @code{info mem}
+
+@item @code{read-spu-object}
+@tab @code{qXfer:spu:read}
+@tab @code{info spu}
+
+@item @code{write-spu-object}
+@tab @code{qXfer:spu:write}
+@tab @code{info spu}
+
+@item @code{get-thread-local-@*storage-address}
 @tab @code{qGetTLSAddr}
 @tab Displaying @code{__thread} variables
 
@@ -12918,7 +12940,7 @@ The available settings are:
 @tab @code{qSupported}
 @tab Remote communications parameters
 
-@item @code{pass-signals-packet}
+@item @code{pass-signals}
 @tab @code{QPassSignals}
 @tab @code{handle @var{signal}}
 
@@ -22506,6 +22528,7 @@ Show the current setting of the target w
 * Interrupts::
 * Examples::
 * File-I/O Remote Protocol Extension::
+* Library List Format::
 * Memory Map Format::
 @end menu
 
@@ -23223,24 +23246,45 @@ number).  This is equivalent to an @samp
 and other information directly in the stop reply packet, reducing
 round-trip latency.  Single-step and breakpoint traps are reported
 this way.  Each @samp{@var{n}:@var{r}} pair is interpreted as follows:
-@enumerate
+
+@itemize @bullet
 @item
 If @var{n} is a hexadecimal number, it is a register number, and the
 corresponding @var{r} gives that register's value.  @var{r} is a
 series of bytes in target byte order, with each byte given by a
 two-digit hex number.
+
 @item
 If @var{n} is @samp{thread}, then @var{r} is the thread process ID, in
 hex.
+
 @item
-If @var{n} is @samp{watch}, @samp{rwatch}, or @samp{awatch}, then the
-packet indicates a watchpoint hit, and @var{r} is the data address, in
-hex.
+If @var{n} is a recognized @dfn{stop reason}, it describes a more
+specific event that stopped the target.  The currently defined stop
+reasons are listed below.  @var{aa} should be @samp{05}, the trap
+signal.  At most one stop reason should be present.
+
 @item
 Otherwise, @value{GDBN} should ignore this @samp{@var{n}:@var{r}} pair
 and go on to the next; this allows us to extend the protocol in the
 future.
-@end enumerate
+@end itemize
+
+The currently defined stop reasons are:
+
+@table @samp
+@item watch
+@itemx rwatch
+@itemx awatch
+The packet indicates a watchpoint hit, and @var{r} is the data address, in
+hex.
+
+@cindex shared library events, remote reply
+@item library
+The packet indicates that the loaded libraries have changed.
+@value{GDBN} should use @samp{qXfer:libraries:read} to fetch a new
+list of loaded libraries.  @var{r} is ignored.
+@end table
 
 @item W @var{AA}
 The process exited, and @var{AA} is the exit status.  This is only
@@ -23626,7 +23670,7 @@ stubs which may be configured for multip
 
 These are the currently defined stub features and their properties:
 
-@multitable @columnfractions 0.25 0.2 0.2 0.2
+@multitable @columnfractions 0.35 0.2 0.12 0.2
 @c NOTE: The first row should be @headitem, but we do not yet require
 @c a new enough version of Texinfo (4.7) to use @headitem.
 @item Feature Name
@@ -23649,6 +23693,11 @@ These are the currently defined stub fea
 @tab @samp{-}
 @tab Yes
 
+@item @samp{qXfer:libraries:read}
+@tab No
+@tab @samp{-}
+@tab Yes
+
 @item @samp{qXfer:memory-map:read}
 @tab No
 @tab @samp{-}
@@ -23693,6 +23742,10 @@ The remote stub understands the @samp{qX
 The remote stub understands the @samp{qXfer:features:read} packet
 (@pxref{qXfer target description read}).
 
+@item qXfer:libraries:read
+The remote stub understands the @samp{qXfer:libraries:read} packet
+(@pxref{qXfer library list read}).
+
 @item qXfer:memory-map:read
 The remote stub understands the @samp{qXfer:memory-map:read} packet
 (@pxref{qXfer memory map read}).
@@ -23815,6 +23868,19 @@ always loaded from the @samp{target.xml}
 This packet is not probed by default; the remote stub must request it,
 by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
 
+@item qXfer:libraries:read:@var{annex}:@var{offset},@var{length}
+@anchor{qXfer library list read}
+Access the target's list of loaded libraries.  @xref{Library List Format}.
+The annex part of the generic @samp{qXfer} packet must be empty
+(@pxref{qXfer read}).
+
+Targets which maintain a list of libraries in the program's memory do
+not need to implement this packet; it is designed for platforms where
+the operating system manages the list of loaded libraries.
+
+This packet is not probed by default; the remote stub must request it,
+by supplying an appropriate @samp{qSupported} response (@pxref{qSupported}).
+
 @item qXfer:memory-map:read::@var{offset},@var{length}
 @anchor{qXfer memory map read}
 Access the target's @dfn{memory-map}.  @xref{Memory Map Format}.  The
@@ -25331,6 +25397,51 @@ host is called:
 <- @code{T02}
 @end smallexample
 
+@node Library List Format
+@section Library List Format
+@cindex library list format, remote protocol
+
+On some platforms, a dynamic loader (e.g.@: @file{ld.so}) runs in the
+same process as your application to manage libraries.  In this case,
+@value{GDBN} can use the loader's symbol table and normal memory
+operations to maintain a list of shared libraries.  On other
+platforms, the operating system manages loaded libraries.
+@value{GDBN} can not retrieve the list of currently loaded libraries
+through memory operations, so it uses the @samp{qXfer:libraries:read}
+packet (@pxref{qXfer library list read}) instead.  The remote stub
+queries the target's operating system and reports which libraries
+are loaded.
+
+The @samp{qXfer:libraries:read} packet returns an XML document which
+lists loaded libraries and their offsets.  Each library has an
+associated name and one or more segment base addresses, which report
+where the library was loaded in memory.  The segment bases are start
+addresses, not relocation offsets; they do not depend on the library's
+link-time base addresses.
+
+A simple memory map, with one loaded library relocated by a single
+offset, looks like this:
+
+@smallexample
+<library-list>
+  <library name="/lib/libc.so.6">
+    <segment address="0x10000000"/>
+  </library>
+</library-list>
+@end smallexample
+
+The format of a library list is described by this DTD:
+
+@smallexample
+<!-- library-list: Root element with versioning -->
+<!ELEMENT library-list  (library)*>
+<!ATTLIST library-list  version CDATA   #FIXED  "1.0">
+<!ELEMENT library       (segment)*>
+<!ATTLIST library       name    CDATA   #REQUIRED>
+<!ELEMENT segment       EMPTY>
+<!ATTLIST segment       address CDATA   #REQUIRED>
+@end smallexample
+
 @node Memory Map Format
 @section Memory Map Format
 @cindex memory map format
Index: gdb/features/library-list.dtd
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ gdb/features/library-list.dtd	2007-07-02 14:58:13.000000000 -0400
@@ -0,0 +1,15 @@
+<!-- Copyright (C) 2007 Free Software Foundation, Inc.
+
+     Copying and distribution of this file, with or without modification,
+     are permitted in any medium without royalty provided the copyright
+     notice and this notice are preserved.  -->
+
+<!-- library-list: Root element with versioning -->
+<!ELEMENT library-list  (library)*>
+<!ATTLIST library-list  version CDATA   #FIXED  "1.0">
+
+<!ELEMENT library       (segment)*>
+<!ATTLIST library       name    CDATA   #REQUIRED>
+
+<!ELEMENT segment       EMPTY>
+<!ATTLIST segment       address CDATA   #REQUIRED>


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