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]

Allow section offsets instead of segment offsets (qXfer:libraries:read+)


Hi,

We're working with a target where to access the list of loaded
libraries, we have to use a target side debug API.  Well, that's
what solib-target.c is for, so we can use that.  But in order
to do that, we needed the changes shown in this patch.

Currenly, in the qXfer:libraries:read+ support, GDB expects the
target to pass a list of segment load bases per library.
This target's shared objects are relocatable objects, not
fully linked binaries.  There are no program headers in them,
and no segments to pass along.  Instead, the loader loads
each allocatable section at arbitrary addresses.

This patch adds the support to this kind of target, by enhancing
the library-list xml to enable passing a list of section offsets
instead of segment offsets per library, and adds the solib-target.c
side bits to handle it.

Tested with a native i686-pc-cygwin gdbserver, to ensure the
current support didn't break.

Patch + docs + NEWS entry below.

-- 
Pedro Alves
2008-02-19  Pedro Alves  <pedro@codesourcery.com>

	* features/library-list.dtd: Allow "section" elements as children
	of "library".  Add "section" element and describe its attributes.

	* solib-target.c (struct lm_info): Add section_bases member.
	(library_list_start_segment): Error out if seen a section element.
	(library_list_start_section): New.
	(library_list_end_library): New.
	(solib_target_free_library_list): Free section_bases.
	(section_attributes): New.
	(library_children): Make "segment" optional.  Add "section" child.
	(library_list_children): Register library_list_end_library.
	(solib_target_relocate_section_addresses): Handle section bases.

	* NEWS: Mention new qXfer:libraries:read section offsets support.

doc/
2008-02-19  Pedro Alves  <pedro@codesourcery.com>
	    Sandra Loosemore  <sandra@codesourcery.com>

	* gdb.texinfo (Library List Format): Update to mention the
	possibility to pass section addresses instead of segment
	addresses.

---
 gdb/NEWS                      |    3 
 gdb/doc/gdb.texinfo           |   34 ++++++-
 gdb/features/library-list.dtd |    5 -
 gdb/solib-target.c            |  197 +++++++++++++++++++++++++++++++++---------
 4 files changed, 191 insertions(+), 48 deletions(-)

Index: src/gdb/features/library-list.dtd
===================================================================
--- src.orig/gdb/features/library-list.dtd	2008-01-01 22:53:14.000000000 +0000
+++ src/gdb/features/library-list.dtd	2008-02-26 17:35:52.000000000 +0000
@@ -8,8 +8,11 @@
 <!ELEMENT library-list  (library)*>
 <!ATTLIST library-list  version CDATA   #FIXED  "1.0">
 
-<!ELEMENT library       (segment)*>
+<!ELEMENT library       (segment*, section*)>
 <!ATTLIST library       name    CDATA   #REQUIRED>
 
 <!ELEMENT segment       EMPTY>
 <!ATTLIST segment       address CDATA   #REQUIRED>
+
+<!ELEMENT section       EMPTY>
+<!ATTLIST section       address CDATA   #REQUIRED>
Index: src/gdb/solib-target.c
===================================================================
--- src.orig/gdb/solib-target.c	2008-01-01 22:53:13.000000000 +0000
+++ src/gdb/solib-target.c	2008-02-26 17:40:24.000000000 +0000
@@ -37,12 +37,19 @@ struct lm_info
      so_list; it is only here during XML parsing.  */
   char *name;
 
+  /* The target can either specify segment bases of section bases, not
+     both.  */
+
   /* The base addresses for each independently relocatable segment of
      this shared library.  */
   VEC(CORE_ADDR) *segment_bases;
 
+  /* The base addresses for each independently allocatable,
+     relocatable section of this shared library.  */
+  VEC(CORE_ADDR) *section_bases;
+
   /* The cached offsets for each section of this shared library,
-     determined from SEGMENT_BASES.  */
+     determined from SEGMENT_BASES, or SECTION_BASES.  */
   struct section_offsets *offsets;
 };
 
@@ -82,9 +89,30 @@ library_list_start_segment (struct gdb_x
   ULONGEST *address_p = VEC_index (gdb_xml_value_s, attributes, 0)->value;
   CORE_ADDR address = (CORE_ADDR) *address_p;
 
+  if (last->section_bases != NULL)
+    gdb_xml_error (parser,
+		   _("Library list with both segments and sections"));
+
   VEC_safe_push (CORE_ADDR, last->segment_bases, &address);
 }
 
+static void
+library_list_start_section (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;
+  CORE_ADDR address = (CORE_ADDR) *address_p;
+
+  if (last->segment_bases != NULL)
+    gdb_xml_error (parser,
+		   _("Library list with both segments and sections"));
+
+  VEC_safe_push (CORE_ADDR, last->section_bases, &address);
+}
+
 /* Handle the start of a <library> element.  */
 
 static void
@@ -100,6 +128,20 @@ library_list_start_library (struct gdb_x
   VEC_safe_push (lm_info_p, *list, item);
 }
 
+static void
+library_list_end_library (struct gdb_xml_parser *parser,
+			  const struct gdb_xml_element *element,
+			  void *user_data, const char *body_text)
+{
+  VEC(lm_info_p) **list = user_data;
+  struct lm_info *lm_info = VEC_last (lm_info_p, *list);
+  if (lm_info->segment_bases == NULL
+      && lm_info->section_bases == NULL)
+    gdb_xml_error (parser,
+		   _("No segment or section bases defined"));
+}
+
+
 /* Handle the start of a <library-list> element.  */
 
 static void
@@ -128,6 +170,7 @@ solib_target_free_library_list (void *p)
     {
       xfree (info->name);
       VEC_free (CORE_ADDR, info->segment_bases);
+      VEC_free (CORE_ADDR, info->section_bases);
       xfree (info);
     }
   VEC_free (lm_info_p, *result);
@@ -142,9 +185,18 @@ const struct gdb_xml_attribute segment_a
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
+const struct gdb_xml_attribute section_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,
+  { "segment", segment_attributes, NULL,
+    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
     library_list_start_segment, NULL },
+  { "section", section_attributes, NULL,
+    GDB_XML_EF_REPEATABLE | GDB_XML_EF_OPTIONAL,
+    library_list_start_section, NULL },
   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
 };
 
@@ -156,7 +208,7 @@ const struct gdb_xml_attribute library_a
 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 },
+    library_list_start_library, library_list_end_library },
   { NULL, NULL, NULL, GDB_XML_EF_NONE, NULL, NULL }
 };
 
@@ -285,55 +337,116 @@ solib_target_relocate_section_addresses 
      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
+      if (so->lm_info->section_bases)
 	{
-	  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"),
+	  asection *sect;
+	  int num_section_bases
+	    = VEC_length (CORE_ADDR, so->lm_info->section_bases);
+	  int num_alloc_sections = 0;
+
+	  for (i = 0, sect = so->abfd->sections;
+	       sect != NULL;
+	       i++, sect = sect->next)
+	    if ((bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
+	      num_alloc_sections++;
+
+	  if (num_alloc_sections != num_section_bases)
+	    warning (_("\
+Could not relocate shared library \"%s\": wrong number of ALLOC sections"),
 		     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++)
+	  else
 	    {
-	      /* 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;
+	      int bases_index = 0;
+	      int found_range = 0;
+	      CORE_ADDR *section_bases;
+	      section_bases = VEC_address (CORE_ADDR,
+					   so->lm_info->section_bases);
+
+	      so->addr_low = ~(CORE_ADDR) 0;
+	      so->addr_high = 0;
+	      for (i = 0, sect = so->abfd->sections;
+		   sect != NULL;
+		   i++, sect = sect->next)
+		{
+		  if (!(bfd_get_section_flags (so->abfd, sect) & SEC_ALLOC))
+		    continue;
+		  if (bfd_section_size (so->abfd, sect) > 0)
+		    {
+		      CORE_ADDR low, high;
+		      low = section_bases[i];
+		      high = low + bfd_section_size (so->abfd, sect) - 1;
+
+		      if (low < so->addr_low)
+			so->addr_low = low;
+		      if (high > so->addr_high)
+			so->addr_high = high;
+		      gdb_assert (so->addr_low <= so->addr_high);
+		      found_range = 1;
+		    }
+		  so->lm_info->offsets->offsets[i] = section_bases[bases_index];
+		  bases_index++;
+		}
+	      if (!found_range)
+		so->addr_low = so->addr_high = 0;
+	      gdb_assert (so->addr_low <= so->addr_high);
 	    }
+	}
+      else if (so->lm_info->segment_bases)
+	{
+	  struct symfile_segment_data *data;
+	  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;
+	      CORE_ADDR *segment_bases;
+
+	      num_bases = VEC_length (CORE_ADDR, so->lm_info->segment_bases);
+	      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]
+			       + orig_delta);
+	      gdb_assert (so->addr_low <= so->addr_high);
 
-	  so->addr_low = segment_bases[0];
-	  so->addr_high = (data->segment_bases[i - 1]
-			   + data->segment_sizes[i - 1]
-			   + orig_delta);
-	  gdb_assert (so->addr_low <= so->addr_high);
-
-	  free_symfile_segment_data (data);
+	      free_symfile_segment_data (data);
+	    }
 	}
     }
 
Index: src/gdb/doc/gdb.texinfo
===================================================================
--- src.orig/gdb/doc/gdb.texinfo	2008-02-21 15:07:37.000000000 +0000
+++ src/gdb/doc/gdb.texinfo	2008-02-26 17:35:52.000000000 +0000
@@ -26264,10 +26264,15 @@ 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.
+associated name and one or more segment or section base addresses,
+which report where the library was loaded in memory.
+
+For the common case of libraries that are fully linked binaries, the
+library should have a list of segments.  If the target supports
+dynamic linking of a relocatable object file, its library XML element
+should instead include a list of allocated sections.  The segment or
+section bases are start addresses, not relocation offsets; they do not
+depend on the library's link-time base addresses.
 
 @value{GDBN} must be linked with the Expat library to support XML
 library lists.  @xref{Expat}.
@@ -26283,18 +26288,37 @@ offset, looks like this:
 </library-list>
 @end smallexample
 
+Another simple memory map, with one loaded library with three
+allocated sections (.text, .data, .bss), looks like this:
+
+@smallexample
+<library-list>
+  <library name="sharedlib.o">
+    <section address="0x10000000"/>
+    <section address="0x20000000"/>
+    <section address="0x30000000"/>
+  </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)*>
+<!ELEMENT library       (segment*, section*)>
 <!ATTLIST library       name    CDATA   #REQUIRED>
 <!ELEMENT segment       EMPTY>
 <!ATTLIST segment       address CDATA   #REQUIRED>
+<!ELEMENT section       EMPTY>
+<!ATTLIST section       address CDATA   #REQUIRED>
 @end smallexample
 
+In addition, segments and section descriptors cannot be mixed within a
+single library element, and you must supply at least one segment or
+section for each library.
+
 @node Memory Map Format
 @section Memory Map Format
 @cindex memory map format
Index: src/gdb/NEWS
===================================================================
--- src.orig/gdb/NEWS	2008-02-26 18:48:48.000000000 +0000
+++ src/gdb/NEWS	2008-02-26 18:56:06.000000000 +0000
@@ -13,6 +13,9 @@ Xtensa GNU/Linux		xtensa*-*-linux*
 NetBSD/hppa			hppa*-*-netbsd*
 Xtensa GNU/Lunux		xtensa*-*-linux*
 
+* The qXfer:libraries:read remote procotol packet now allows passing a
+  list of section offsets.
+
 * Change in command line behavior -- corefiles vs. process ids.
 
   When the '-p NUMBER' or '--pid NUMBER' options are used, and

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