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 / remote protocol] ELF segment based qOffsets


On Wed, May 09, 2007 at 03:12:15PM -0400, Daniel Jacobowitz wrote:
> 2007-05-09  Daniel Jacobowitz  <dan@codesourcery.com>
> 
> 	* coffread.c (coff_sym_fns): Add default_symfile_segments.
> 	* dbxread.c (aout_sym_fns): Likewise.
> 	* elfread.c (elf_symfile_segments): New.
> 	(elf_sym_fns): Add elf_symfile_segments.
> 	* mipsread.c (ecoff_sym_fns): Add default_symfile_segments.
> 	* remote.c (get_offsets): Use symfile_map_offsets_to_segments.
> 	Skip if there is no symfile_objfile.  Handle TextSeg and DataSeg.
> 	* somread.c (som_sym_fns): Use default_symfile_segments.
> 	* symfile.c (find_sym_fns): Take a BFD and return the sym_fns.
> 	(init_objfile_sect_indices): Call symfile_find_segment_sections.
> 	(default_symfile_segments): New function.
> 	(syms_from_objfile): Update call to find_sym_fns.
> 	(symfile_get_segment_data, free_symfile_segment_data): New.
> 	(symfile_map_offsets_to_segments): New.
> 	(symfile_find_segment_sections): New.
> 	* symfile.h (struct symfile_segment_data): New.
> 	(struct sym_fns): Add sym_segments.
> 	(default_symfile_segments, symfile_get_segment_data)
> 	(free_symfile_segment_data): New prototypes.
> 	(symfile_map_offsets_to_segments): Likewise.
> 	* xcoffread.c (xcoff_sym_fns): Add default_symfile_segments.
> 	* Makefile.in (elf_internal_h): New.
> 	(elfread.o): Update.
> 	* NEWS: Mention qOffsets changes.
> 
> 	* gdb.texinfo (General Query Packets): Document qOffsets changes.

I have committed an updated version of this, below.  The only change
is that it no longer breaks the build on non-ELF targets.  Since the
BFD developers did not want to unconditionally build bfd/elf.lo, I
conditionally disabled gdb/elfread.o depending on whether BFD has ELF
support.

-- 
Daniel Jacobowitz
CodeSourcery

2007-06-18  Daniel Jacobowitz  <dan@codesourcery.com>

	* coffread.c (coff_sym_fns): Add default_symfile_segments.
	* dbxread.c (start_psymtab): Check HAVE_ELF.
	(aout_sym_fns): Likewise.
	* elfread.c (elf_symfile_segments): New.
	(elf_sym_fns): Add elf_symfile_segments.
	* mipsread.c (ecoff_sym_fns): Add default_symfile_segments.
	* remote.c (get_offsets): Use symfile_map_offsets_to_segments.
	Skip if there is no symfile_objfile.  Handle TextSeg and DataSeg.
	* somread.c (som_sym_fns): Use default_symfile_segments.
	* symfile.c (find_sym_fns): Take a BFD and return the sym_fns.
	(init_objfile_sect_indices): Call symfile_find_segment_sections.
	(default_symfile_segments): New function.
	(syms_from_objfile): Update call to find_sym_fns.
	(symfile_get_segment_data, free_symfile_segment_data): New.
	(symfile_map_offsets_to_segments): New.
	(symfile_find_segment_sections): New.
	* symfile.h (struct symfile_segment_data): New.
	(struct sym_fns): Add sym_segments.
	(default_symfile_segments, symfile_get_segment_data)
	(free_symfile_segment_data): New prototypes.
	(symfile_map_offsets_to_segments): Likewise.
	* xcoffread.c (xcoff_sym_fns): Add default_symfile_segments.
	* Makefile.in (COMMON_OBS): Remove elfread.o.
	(elf_internal_h): New.
	(elfread.o): Update.
	* configure.ac: Add elfread.o to COMMON_OBS if bfd/elf.o was
	compiled.
	* config.in, configure: Regenerated.
	* NEWS: Mention qOffsets changes.

	* gdb.texinfo (General Query Packets): Document qOffsets changes.

	* Makefile.def: Add dependency from configure-gdb to all-bfd.
	* Makefile.in: Regenerated.

---
 Makefile.def        |    2 
 Makefile.in         |    2 
 gdb/Makefile.in     |    6 -
 gdb/NEWS            |    4 
 gdb/coffread.c      |    2 
 gdb/config.in       |    3 
 gdb/configure       |   76 ++++++++++++++++++
 gdb/configure.ac    |   24 +++++
 gdb/dbxread.c       |    4 
 gdb/doc/gdb.texinfo |   27 +++++-
 gdb/elfread.c       |   74 +++++++++++++++++
 gdb/mipsread.c      |    2 
 gdb/remote.c        |  116 ++++++++++++++++++++++------
 gdb/somread.c       |    2 
 gdb/symfile.c       |  214 ++++++++++++++++++++++++++++++++++++++++++++++------
 gdb/symfile.h       |   39 +++++++++
 gdb/xcoffread.c     |    2 
 17 files changed, 544 insertions(+), 55 deletions(-)

Index: gdb/coffread.c
===================================================================
--- gdb/coffread.c.orig	2007-06-12 14:15:25.000000000 -0400
+++ gdb/coffread.c	2007-06-12 14:28:14.000000000 -0400
@@ -2139,6 +2139,8 @@ static struct sym_fns coff_sym_fns =
   coff_symfile_read,		/* sym_read: read a symbol file into symtab */
   coff_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets:  xlate external to internal form */
+  default_symfile_segments,	/* sym_segments: Get segment information from
+				   a file.  */
   NULL				/* next: pointer to next struct sym_fns */
 };
 
Index: gdb/dbxread.c
===================================================================
--- gdb/dbxread.c.orig	2007-06-12 14:15:28.000000000 -0400
+++ gdb/dbxread.c	2007-06-12 15:05:24.000000000 -0400
@@ -2148,11 +2148,13 @@ start_psymtab (struct objfile *objfile, 
   STRING_OFFSET (result) = string_table_offset;
   FILE_STRING_OFFSET (result) = file_string_table_offset;
 
+#ifdef HAVE_ELF
   /* If we're handling an ELF file, drag some section-relocation info
      for this source file out of the ELF symbol table, to compensate for
      Sun brain death.  This replaces the section_offsets in this psymtab,
      if successful.  */
   elfstab_offset_sections (objfile, result);
+#endif
 
   /* Deduce the source language from the filename for this psymtab. */
   psymtab_language = deduce_language_from_filename (filename);
@@ -3505,6 +3507,8 @@ static struct sym_fns aout_sym_fns =
   dbx_symfile_read,		/* sym_read: read a symbol file into symtab */
   dbx_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets: parse user's offsets to internal form */
+  default_symfile_segments,	/* sym_segments: Get segment information from
+				   a file.  */
   NULL				/* next: pointer to next struct sym_fns */
 };
 
Index: gdb/elfread.c
===================================================================
--- gdb/elfread.c.orig	2007-06-12 14:15:29.000000000 -0400
+++ gdb/elfread.c	2007-06-12 14:28:14.000000000 -0400
@@ -26,6 +26,8 @@
 #include "bfd.h"
 #include "gdb_string.h"
 #include "elf-bfd.h"
+#include "elf/common.h"
+#include "elf/internal.h"
 #include "elf/mips.h"
 #include "symtab.h"
 #include "symfile.h"
@@ -51,6 +53,76 @@ struct elfinfo
 
 static void free_elfinfo (void *);
 
+/* Locate the segments in ABFD.  */
+
+static struct symfile_segment_data *
+elf_symfile_segments (bfd *abfd)
+{
+  Elf_Internal_Phdr *phdrs, **segments;
+  long phdrs_size;
+  int num_phdrs, num_segments, num_sections, i;
+  asection *sect;
+  struct symfile_segment_data *data;
+
+  phdrs_size = bfd_get_elf_phdr_upper_bound (abfd);
+  if (phdrs_size == -1)
+    return NULL;
+
+  phdrs = alloca (phdrs_size);
+  num_phdrs = bfd_get_elf_phdrs (abfd, phdrs);
+  if (num_phdrs == -1)
+    return NULL;
+
+  num_segments = 0;
+  segments = alloca (sizeof (Elf_Internal_Phdr *) * num_phdrs);
+  for (i = 0; i < num_phdrs; i++)
+    if (phdrs[i].p_type == PT_LOAD)
+      segments[num_segments++] = &phdrs[i];
+
+  if (num_segments == 0)
+    return NULL;
+
+  data = XZALLOC (struct symfile_segment_data);
+  data->num_segments = num_segments;
+  data->segment_bases = XCALLOC (num_segments, CORE_ADDR);
+  data->segment_sizes = XCALLOC (num_segments, CORE_ADDR);
+
+  for (i = 0; i < num_segments; i++)
+    {
+      data->segment_bases[i] = segments[i]->p_vaddr;
+      data->segment_sizes[i] = segments[i]->p_memsz;
+    }
+
+  num_sections = bfd_count_sections (abfd);
+  data->segment_info = XCALLOC (num_sections, int);
+
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      int j;
+      CORE_ADDR vma;
+
+      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+	continue;
+
+      vma = bfd_get_section_vma (abfd, sect);
+
+      for (j = 0; j < num_segments; j++)
+	if (segments[j]->p_memsz > 0
+	    && vma >= segments[j]->p_vaddr
+	    && vma < segments[j]->p_vaddr + segments[j]->p_memsz)
+	  {
+	    data->segment_info[i] = j + 1;
+	    break;
+	  }
+
+      if (bfd_get_section_size (sect) > 0 && j == num_segments)
+	warning (_("Loadable segment \"%s\" outside of ELF segments"),
+		 bfd_section_name (abfd, sect));
+    }
+
+  return data;
+}
+
 /* We are called once per section from elf_symfile_read.  We
    need to examine each section we are passed, check to see
    if it is something we are interested in processing, and
@@ -741,6 +813,8 @@ static struct sym_fns elf_sym_fns =
   elf_symfile_read,		/* sym_read: read a symbol file into symtab */
   elf_symfile_finish,		/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets:  Translate ext. to int. relocation */
+  elf_symfile_segments,		/* sym_segments: Get segment information from
+				   a file.  */
   NULL				/* next: pointer to next struct sym_fns */
 };
 
Index: gdb/mipsread.c
===================================================================
--- gdb/mipsread.c.orig	2007-06-12 14:08:52.000000000 -0400
+++ gdb/mipsread.c	2007-06-12 14:28:14.000000000 -0400
@@ -394,6 +394,8 @@ static struct sym_fns ecoff_sym_fns =
   mipscoff_symfile_read,	/* sym_read: read a symbol file into symtab */
   mipscoff_symfile_finish,	/* sym_finish: finished with file, cleanup */
   default_symfile_offsets,	/* sym_offsets: dummy FIXME til implem sym reloc */
+  default_symfile_segments,	/* sym_segments: Get segment information from
+				   a file.  */
   NULL				/* next: pointer to next struct sym_fns */
 };
 
Index: gdb/remote.c
===================================================================
--- gdb/remote.c.orig	2007-06-12 14:15:39.000000000 -0400
+++ gdb/remote.c	2007-06-12 14:28:14.000000000 -0400
@@ -2016,9 +2016,13 @@ get_offsets (void)
   struct remote_state *rs = get_remote_state ();
   char *buf;
   char *ptr;
-  int lose;
-  CORE_ADDR text_addr, data_addr, bss_addr;
+  int lose, num_segments = 0, do_sections, do_segments;
+  CORE_ADDR text_addr, data_addr, bss_addr, segments[2];
   struct section_offsets *offs;
+  struct symfile_segment_data *data;
+
+  if (symfile_objfile == NULL)
+    return;
 
   putpkt ("qOffsets");
   getpkt (&rs->buf, &rs->buf_size, 0);
@@ -2047,47 +2051,109 @@ get_offsets (void)
       /* Don't use strtol, could lose on big values.  */
       while (*ptr && *ptr != ';')
 	text_addr = (text_addr << 4) + fromhex (*ptr++);
-    }
-  else
-    lose = 1;
 
-  if (!lose && strncmp (ptr, ";Data=", 6) == 0)
-    {
-      ptr += 6;
-      while (*ptr && *ptr != ';')
-	data_addr = (data_addr << 4) + fromhex (*ptr++);
-    }
-  else
-    lose = 1;
+      if (strncmp (ptr, ";Data=", 6) == 0)
+	{
+	  ptr += 6;
+	  while (*ptr && *ptr != ';')
+	    data_addr = (data_addr << 4) + fromhex (*ptr++);
+	}
+      else
+	lose = 1;
 
-  if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+      if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+	{
+	  ptr += 5;
+	  while (*ptr && *ptr != ';')
+	    bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+
+	  if (bss_addr != data_addr)
+	    warning (_("Target reported unsupported offsets: %s"), buf);
+	}
+      else
+	lose = 1;
+    }
+  else if (strncmp (ptr, "TextSeg=", 8) == 0)
     {
-      ptr += 5;
+      ptr += 8;
+      /* Don't use strtol, could lose on big values.  */
       while (*ptr && *ptr != ';')
-	bss_addr = (bss_addr << 4) + fromhex (*ptr++);
+	text_addr = (text_addr << 4) + fromhex (*ptr++);
+      num_segments = 1;
+
+      if (strncmp (ptr, ";DataSeg=", 9) == 0)
+	{
+	  ptr += 9;
+	  while (*ptr && *ptr != ';')
+	    data_addr = (data_addr << 4) + fromhex (*ptr++);
+	  num_segments++;
+	}
     }
   else
     lose = 1;
 
   if (lose)
     error (_("Malformed response to offset query, %s"), buf);
-
-  if (symfile_objfile == NULL)
-    return;
+  else if (*ptr != '\0')
+    warning (_("Target reported unsupported offsets: %s"), buf);
 
   offs = ((struct section_offsets *)
 	  alloca (SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections)));
   memcpy (offs, symfile_objfile->section_offsets,
 	  SIZEOF_N_SECTION_OFFSETS (symfile_objfile->num_sections));
 
-  offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
+  data = get_symfile_segment_data (symfile_objfile->obfd);
+  do_segments = (data != NULL);
+  do_sections = num_segments == 0;
+
+  /* Text= and Data= specify offsets for the text and data sections,
+     but symfile_map_offsets_to_segments expects base addresses
+     instead of offsets.  If we have two segments, we can still
+     try to relocate the whole segments instead of just ".text"
+     and ".data".  */
+  if (num_segments == 0)
+    {
+      do_sections = 1;
+      if (data == NULL || data->num_segments != 2)
+	do_segments = 0;
+      else
+	{
+	  segments[0] = data->segment_bases[0] + text_addr;
+	  segments[1] = data->segment_bases[1] + data_addr;
+	}
+    }
+  else
+    {
+      do_sections = 0;
+      segments[0] = text_addr;
+      segments[1] = data_addr;
+    }
+
+  if (do_segments)
+    {
+      int ret = symfile_map_offsets_to_segments (symfile_objfile->obfd, data,
+						 offs, num_segments, segments);
+
+      if (ret == 0 && !do_sections)
+	error (_("Can not handle qOffsets TextSeg response with this symbol file"));
 
-  /* This is a temporary kludge to force data and bss to use the same offsets
-     because that's what nlmconv does now.  The real solution requires changes
-     to the stub and remote.c that I don't have time to do right now.  */
+      if (ret > 0)
+	do_sections = 0;
+    }
 
-  offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
-  offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+  free_symfile_segment_data (data);
+
+  if (do_sections)
+    {
+      offs->offsets[SECT_OFF_TEXT (symfile_objfile)] = text_addr;
+
+      /* This is a temporary kludge to force data and bss to use the same offsets
+	 because that's what nlmconv does now.  The real solution requires changes
+	 to the stub and remote.c that I don't have time to do right now.  */
+
+      offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
+      offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
+    }
 
   objfile_relocate (symfile_objfile, offs);
 }
Index: gdb/somread.c
===================================================================
--- gdb/somread.c.orig	2007-06-12 14:15:41.000000000 -0400
+++ gdb/somread.c	2007-06-12 14:28:14.000000000 -0400
@@ -438,6 +438,8 @@ static struct sym_fns som_sym_fns =
   som_symfile_read,		/* sym_read: read a symbol file into symtab */
   som_symfile_finish,		/* sym_finish: finished with file, cleanup */
   som_symfile_offsets,		/* sym_offsets:  Translate ext. to int. relocation */
+  default_symfile_segments,	/* sym_segments: Get segment information from
+				   a file.  */
   NULL				/* next: pointer to next struct sym_fns */
 };
 
Index: gdb/symfile.c
===================================================================
--- gdb/symfile.c.orig	2007-06-12 14:15:42.000000000 -0400
+++ gdb/symfile.c	2007-06-12 14:28:14.000000000 -0400
@@ -106,7 +106,7 @@ bfd *symfile_bfd_open (char *);
 
 int get_section_index (struct objfile *, char *);
 
-static void find_sym_fns (struct objfile *);
+static struct sym_fns *find_sym_fns (bfd *);
 
 static void decrement_reading_symtab (void *);
 
@@ -146,6 +146,8 @@ static char *find_separate_debug_file (s
 
 static void init_filename_language_table (void);
 
+static void symfile_find_segment_sections (struct objfile *objfile);
+
 void _initialize_symfile (void);
 
 /* List of all available sym_fns.  On gdb startup, each object file reader
@@ -430,12 +432,19 @@ init_objfile_sect_indices (struct objfil
   /* This is where things get really weird...  We MUST have valid
      indices for the various sect_index_* members or gdb will abort.
      So if for example, there is no ".text" section, we have to
-     accomodate that.  Except when explicitly adding symbol files at
-     some address, section_offsets contains nothing but zeros, so it
-     doesn't matter which slot in section_offsets the individual
-     sect_index_* members index into.  So if they are all zero, it is
-     safe to just point all the currently uninitialized indices to the
-     first slot. */
+     accomodate that.  First, check for a file with the standard
+     one or two segments.  */
+
+  symfile_find_segment_sections (objfile);
+
+  /* Except when explicitly adding symbol files at some address,
+     section_offsets contains nothing but zeros, so it doesn't matter
+     which slot in section_offsets the individual sect_index_* members
+     index into.  So if they are all zero, it is safe to just point
+     all the currently uninitialized indices to the first slot.  But
+     beware: if this is the main executable, it may be relocated
+     later, e.g. by the remote qOffsets packet, and then this will
+     be wrong!  That's why we try segments first.  */
 
   for (i = 0; i < objfile->num_sections; i++)
     {
@@ -639,6 +648,70 @@ default_symfile_offsets (struct objfile 
 }
 
 
+/* Divide the file into segments, which are individual relocatable units.
+   This is the default version of the sym_fns.sym_segments function for
+   symbol readers that do not have an explicit representation of segments.
+   It assumes that object files do not have segments, and fully linked
+   files have a single segment.  */
+
+struct symfile_segment_data *
+default_symfile_segments (bfd *abfd)
+{
+  int num_sections, i;
+  asection *sect;
+  struct symfile_segment_data *data;
+  CORE_ADDR low, high;
+
+  /* Relocatable files contain enough information to position each
+     loadable section independently; they should not be relocated
+     in segments.  */
+  if ((bfd_get_file_flags (abfd) & (EXEC_P | DYNAMIC)) == 0)
+    return NULL;
+
+  /* Make sure there is at least one loadable section in the file.  */
+  for (sect = abfd->sections; sect != NULL; sect = sect->next)
+    {
+      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+	continue;
+
+      break;
+    }
+  if (sect == NULL)
+    return NULL;
+
+  low = bfd_get_section_vma (abfd, sect);
+  high = low + bfd_get_section_size (sect);
+
+  data = XZALLOC (struct symfile_segment_data);
+  data->num_segments = 1;
+  data->segment_bases = XCALLOC (1, CORE_ADDR);
+  data->segment_sizes = XCALLOC (1, CORE_ADDR);
+
+  num_sections = bfd_count_sections (abfd);
+  data->segment_info = XCALLOC (num_sections, int);
+
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      CORE_ADDR vma;
+
+      if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0)
+	continue;
+
+      vma = bfd_get_section_vma (abfd, sect);
+      if (vma < low)
+	low = vma;
+      if (vma + bfd_get_section_size (sect) > high)
+	high = vma + bfd_get_section_size (sect);
+
+      data->segment_info[i] = 1;
+    }
+
+  data->segment_bases[0] = low;
+  data->segment_sizes[0] = high - low;
+
+  return data;
+}
+
 /* Process a symbol file, as either the main file or as a dynamically
    loaded file.
 
@@ -685,7 +758,7 @@ syms_from_objfile (struct objfile *objfi
   gdb_assert (! (addrs && offsets));
 
   init_entry_point_info (objfile);
-  find_sym_fns (objfile);
+  objfile->sf = find_sym_fns (objfile->obfd);
 
   if (objfile->sf == NULL)
     return;	/* No symbols. */
@@ -1505,29 +1578,23 @@ add_symtab_fns (struct sym_fns *sf)
    struct sym_fns in the objfile structure, that contains cached
    information about the symbol file.  */
 
-static void
-find_sym_fns (struct objfile *objfile)
+static struct sym_fns *
+find_sym_fns (bfd *abfd)
 {
   struct sym_fns *sf;
-  enum bfd_flavour our_flavour = bfd_get_flavour (objfile->obfd);
-  char *our_target = bfd_get_target (objfile->obfd);
+  enum bfd_flavour our_flavour = bfd_get_flavour (abfd);
 
   if (our_flavour == bfd_target_srec_flavour
       || our_flavour == bfd_target_ihex_flavour
       || our_flavour == bfd_target_tekhex_flavour)
-    return;	/* No symbols.  */
+    return NULL;	/* No symbols.  */
 
   for (sf = symtab_fns; sf != NULL; sf = sf->next)
-    {
-      if (our_flavour == sf->sym_flavour)
-	{
-	  objfile->sf = sf;
-	  return;
-	}
-    }
+    if (our_flavour == sf->sym_flavour)
+      return sf;
 
   error (_("I'm sorry, Dave, I can't do that.  Symbol format `%s' unknown."),
-	 bfd_get_target (objfile->obfd));
+	 bfd_get_target (abfd));
 }
 
 
@@ -3771,6 +3838,111 @@ symfile_relocate_debug_section (bfd *abf
   return bfd_simple_get_relocated_section_contents (abfd, sectp, buf, NULL);
 }
 
+struct symfile_segment_data *
+get_symfile_segment_data (bfd *abfd)
+{
+  struct sym_fns *sf = find_sym_fns (abfd);
+
+  if (sf == NULL)
+    return NULL;
+
+  return sf->sym_segments (abfd);
+}
+
+void
+free_symfile_segment_data (struct symfile_segment_data *data)
+{
+  xfree (data->segment_bases);
+  xfree (data->segment_sizes);
+  xfree (data->segment_info);
+  xfree (data);
+}
+
+int
+symfile_map_offsets_to_segments (bfd *abfd, struct symfile_segment_data *data,
+				 struct section_offsets *offsets,
+				 int num_segment_bases,
+				 const CORE_ADDR *segment_bases)
+{
+  int i;
+  asection *sect;
+
+  /* If we do not have segment mappings for the object file, we
+     can not relocate it by segments.  */
+  gdb_assert (data != NULL);
+  gdb_assert (data->num_segments > 0);
+
+  /* If more offsets are provided than we have segments, make sure the
+     excess offsets are all the same as the last segment's offset.
+     This allows "Text=X;Data=X" for files which have only a single
+     segment.  */
+  if (num_segment_bases > data->num_segments)
+    for (i = data->num_segments; i < num_segment_bases; i++)
+      if (segment_bases[i] != segment_bases[data->num_segments - 1])
+	return 0;
+
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      CORE_ADDR vma;
+      int which = data->segment_info[i];
+
+      if (which > num_segment_bases)
+	offsets->offsets[i] = segment_bases[num_segment_bases - 1];
+      else if (which > 0)
+	offsets->offsets[i] = segment_bases[which - 1];
+      else
+	continue;
+
+      offsets->offsets[i] -= data->segment_bases[which - 1];
+    }
+
+  return 1;
+}
+
+static void
+symfile_find_segment_sections (struct objfile *objfile)
+{
+  bfd *abfd = objfile->obfd;
+  int i;
+  asection *sect;
+  struct symfile_segment_data *data;
+
+  data = get_symfile_segment_data (objfile->obfd);
+  if (data == NULL)
+    return;
+
+  if (data->num_segments != 1 && data->num_segments != 2)
+    {
+      free_symfile_segment_data (data);
+      return;
+    }
+
+  for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next)
+    {
+      CORE_ADDR vma;
+      int which = data->segment_info[i];
+
+      if (which == 1)
+	{
+	  if (objfile->sect_index_text == -1)
+	    objfile->sect_index_text = sect->index;
+
+	  if (objfile->sect_index_rodata == -1)
+	    objfile->sect_index_rodata = sect->index;
+	}
+      else if (which == 2)
+	{
+	  if (objfile->sect_index_data == -1)
+	    objfile->sect_index_data = sect->index;
+
+	  if (objfile->sect_index_bss == -1)
+	    objfile->sect_index_bss = sect->index;
+	}
+    }
+
+  free_symfile_segment_data (data);
+}
+
 void
 _initialize_symfile (void)
 {
Index: gdb/symfile.h
===================================================================
--- gdb/symfile.h.orig	2007-06-12 14:15:43.000000000 -0400
+++ gdb/symfile.h	2007-06-12 14:28:14.000000000 -0400
@@ -85,6 +85,28 @@ struct section_addr_info
   } other[1];
 };
 
+struct symfile_segment_data
+{
+  /* How many segments are present in this file.  If there are
+     two, the text segment is the first one and the data segment
+     is the second one.  */
+  int num_segments;
+
+  /* If NUM_SEGMENTS is greater than zero, the original base address
+     of each segment.  */
+  CORE_ADDR *segment_bases;
+
+  /* If NUM_SEGMENTS is greater than zero, the memory size of each
+     segment.  */
+  CORE_ADDR *segment_sizes;
+
+  /* If NUM_SEGMENTS is greater than zero, this is an array of entries
+     recording which segment contains each BFD section.  It is
+     ordered by section index.  A zero means that the section is not
+     in any segment.  */
+  int *segment_info;
+};
+
 /* Structure to keep track of symbol reading functions for various
    object file types.  */
 
@@ -131,6 +153,12 @@ struct sym_fns
 
   void (*sym_offsets) (struct objfile *, struct section_addr_info *);
 
+  /* This function produces a format-independent description of
+     the segments of ABFD.  Each segment is a unit of the file
+     which may be relocated independently.  */
+
+  struct symfile_segment_data *(*sym_segments) (bfd *abfd);
+
   /* Finds the next struct sym_fns.  They are allocated and
      initialized in whatever module implements the functions pointed
      to; an initializer calls add_symtab_fns to add them to the global
@@ -146,6 +174,10 @@ struct sym_fns
 extern void default_symfile_offsets (struct objfile *objfile,
 				     struct section_addr_info *);
 
+/* The default version of sym_fns.sym_segments for readers that don't
+   do anything special.  */
+
+extern struct symfile_segment_data *default_symfile_segments (bfd *abfd);
 
 extern void extend_psymbol_list (struct psymbol_allocation_list *,
 				 struct objfile *);
@@ -313,6 +345,13 @@ extern void simple_overlay_update (struc
 extern bfd_byte *symfile_relocate_debug_section (bfd *abfd, asection *sectp,
 						 bfd_byte * buf);
 
+extern int symfile_map_offsets_to_segments (bfd *,
+					    struct symfile_segment_data *,
+					    struct section_offsets *,
+					    int, const CORE_ADDR *);
+struct symfile_segment_data *get_symfile_segment_data (bfd *abfd);
+void free_symfile_segment_data (struct symfile_segment_data *data);
+
 /* From dwarf2read.c */
 
 extern int dwarf2_has_info (struct objfile *);
Index: gdb/xcoffread.c
===================================================================
--- gdb/xcoffread.c.orig	2007-06-12 14:15:45.000000000 -0400
+++ gdb/xcoffread.c	2007-06-12 14:28:14.000000000 -0400
@@ -3015,6 +3015,8 @@ static struct sym_fns xcoff_sym_fns =
   xcoff_initial_scan,		/* sym_read: read a symbol file into symtab */
   xcoff_symfile_finish,		/* sym_finish: finished with file, cleanup */
   xcoff_symfile_offsets,	/* sym_offsets: xlate offsets ext->int form */
+  default_symfile_segments,	/* sym_segments: Get segment information from
+				   a file.  */
   NULL				/* next: pointer to next struct sym_fns */
 };
 
Index: gdb/Makefile.in
===================================================================
--- gdb/Makefile.in.orig	2007-06-12 14:15:22.000000000 -0400
+++ gdb/Makefile.in	2007-06-12 14:51:21.000000000 -0400
@@ -586,6 +586,7 @@ coff_ecoff_h =	$(INCLUDE_DIR)/coff/ecoff
 coff_internal_h =	$(INCLUDE_DIR)/coff/internal.h
 dis_asm_h =	$(INCLUDE_DIR)/dis-asm.h $(bfd_h)
 elf_common_h =	$(INCLUDE_DIR)/elf/common.h
+elf_internal_h =	$(INCLUDE_DIR)/elf/internal.h
 elf_reloc_macros_h =	$(INCLUDE_DIR)/elf/reloc-macros.h
 elf_sh_h =	$(INCLUDE_DIR)/elf/sh.h
 elf_arm_h =	$(INCLUDE_DIR)/elf/arm.h $(elf_reloc_macros_h)
@@ -946,7 +947,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $
 	signals.o \
 	gdb-events.o \
 	exec.o bcache.o objfiles.o observer.o minsyms.o maint.o demangle.o \
-	dbxread.o coffread.o coff-pe-read.o elfread.o \
+	dbxread.o coffread.o coff-pe-read.o \
 	dwarf2read.o mipsread.o stabsread.o corefile.o \
 	dwarf2expr.o dwarf2loc.o dwarf2-frame.o \
 	ada-lang.o c-lang.o f-lang.o objc-lang.o \
@@ -1958,7 +1959,8 @@ dwarf2read.o: dwarf2read.c $(defs_h) $(b
 	$(gdb_string_h) $(gdb_assert_h)
 elfread.o: elfread.c $(defs_h) $(bfd_h) $(gdb_string_h) $(elf_bfd_h) \
 	$(elf_mips_h) $(symtab_h) $(symfile_h) $(objfiles_h) $(buildsym_h) \
-	$(stabsread_h) $(gdb_stabs_h) $(complaints_h) $(demangle_h)
+	$(stabsread_h) $(gdb_stabs_h) $(complaints_h) $(demangle_h) \
+	$(elf_common_h) $(elf_internal_h)
 environ.o: environ.c $(defs_h) $(environ_h) $(gdb_string_h)
 eval.o: eval.c $(defs_h) $(gdb_string_h) $(symtab_h) $(gdbtypes_h) \
 	$(value_h) $(expression_h) $(target_h) $(frame_h) $(language_h) \
Index: gdb/NEWS
===================================================================
--- gdb/NEWS.orig	2007-06-12 14:15:22.000000000 -0400
+++ gdb/NEWS	2007-06-12 14:28:14.000000000 -0400
@@ -37,6 +37,10 @@ has been rewritten to use the standard G
 
 * GDB for the Cell/B.E. SPU now supports overlay debugging.
 
+* The GDB remote protocol "qOffsets" packet can now honor ELF segment
+layout.  It also supports a TextSeg= and DataSeg= response when only
+segment base addresses (rather than offsets) are available.
+
 * New commands
 
 set remoteflow
Index: gdb/doc/gdb.texinfo
===================================================================
--- gdb/doc/gdb.texinfo.orig	2007-06-12 14:15:51.000000000 -0400
+++ gdb/doc/gdb.texinfo	2007-06-12 14:28:14.000000000 -0400
@@ -23433,14 +23433,31 @@ digits).  See @code{remote.c:parse_threa
 @item qOffsets
 @cindex section offsets, remote request
 @cindex @samp{qOffsets} packet
-Get section offsets that the target used when re-locating the downloaded
-image.  @emph{Note: while a @code{Bss} offset is included in the
-response, @value{GDBN} ignores this and instead applies the @code{Data}
-offset to the @code{Bss} section.}
+Get section offsets that the target used when relocating the downloaded
+image.
 
 Reply:
 @table @samp
-@item Text=@var{xxx};Data=@var{yyy};Bss=@var{zzz}
+@item Text=@var{xxx};Data=@var{yyy}@r{[};Bss=@var{zzz}@r{]}
+Relocate the @code{Text} section by @var{xxx} from its original address.
+Relocate the @code{Data} section by @var{yyy} from its original address.
+If the object file format provides segment information (e.g.@: @sc{elf}
+@samp{PT_LOAD} program headers), @value{GDBN} will relocate entire
+segments by the supplied offsets.
+
+@emph{Note: while a @code{Bss} offset may be included in the response,
+@value{GDBN} ignores this and instead applies the @code{Data} offset
+to the @code{Bss} section.}
+
+@item TextSeg=@var{xxx}@r{[};DataSeg=@var{yyy}@r{]}
+Relocate the first segment of the object file, which conventionally
+contains program code, to a starting address of @var{xxx}.  If
+@samp{DataSeg} is specified, relocate the second segment, which
+conventionally contains modifiable data, to a starting address of
+@var{yyy}.  @value{GDBN} will report an error if the object file
+does not contain segment information, or does not contain at least
+as many segments as mentioned in the reply.  Extra segments are
+kept at fixed offsets relative to the last relocated segment.
 @end table
 
 @item qP @var{mode} @var{threadid}
Index: Makefile.def
===================================================================
--- Makefile.def.orig	2007-06-12 14:49:04.000000000 -0400
+++ Makefile.def	2007-06-12 14:49:47.000000000 -0400
@@ -314,10 +314,10 @@ dependencies = { module=configure-mpfr; 
 // Host modules specific to gdb.
 dependencies = { module=configure-gdb; on=configure-intl; };
 dependencies = { module=configure-gdb; on=configure-sim; };
+dependencies = { module=configure-gdb; on=all-bfd; };
 dependencies = { module=all-gdb; on=all-intl; };
 dependencies = { module=all-gdb; on=all-libiberty; };
 dependencies = { module=all-gdb; on=all-opcodes; };
-dependencies = { module=all-gdb; on=all-bfd; };
 dependencies = { module=all-gdb; on=all-readline; };
 dependencies = { module=all-gdb; on=all-build-bison; };
 dependencies = { module=all-gdb; on=all-build-byacc; };
Index: Makefile.in
===================================================================
--- Makefile.in.orig	2007-06-12 14:49:53.000000000 -0400
+++ Makefile.in	2007-06-12 14:49:55.000000000 -0400
@@ -49016,10 +49016,10 @@ configure-stageprofile-mpfr: maybe-all-s
 configure-stagefeedback-mpfr: maybe-all-stagefeedback-gmp
 configure-gdb: maybe-configure-intl
 configure-gdb: maybe-configure-sim
+configure-gdb: maybe-all-bfd
 all-gdb: maybe-all-intl
 all-gdb: maybe-all-libiberty
 all-gdb: maybe-all-opcodes
-all-gdb: maybe-all-bfd
 all-gdb: maybe-all-readline
 all-gdb: maybe-all-build-bison
 all-gdb: maybe-all-build-byacc
Index: gdb/config.in
===================================================================
--- gdb/config.in.orig	2007-06-12 15:03:24.000000000 -0400
+++ gdb/config.in	2007-06-12 15:03:32.000000000 -0400
@@ -110,6 +110,9 @@
    */
 #undef HAVE_DIRENT_H
 
+/* Define if ELF support should be included. */
+#undef HAVE_ELF
+
 /* Define to 1 if you have the `fork' function. */
 #undef HAVE_FORK
 
Index: gdb/configure
===================================================================
--- gdb/configure.orig	2007-06-12 14:50:51.000000000 -0400
+++ gdb/configure	2007-06-12 15:30:33.000000000 -0400
@@ -21797,6 +21797,82 @@ _ACEOF
 esac
 
 
+# Add ELF support to GDB, but only if BFD includes ELF support.
+OLD_CFLAGS=$CFLAGS
+OLD_LDFLAGS=$LDFLAGS
+OLD_LIBS=$LIBS
+CFLAGS="$CFLAGS -I${srcdir}/../include -I${objdir}/../bfd -I${srcdir}/../bfd"
+LDFLAGS="$LDFLAGS -L../bfd -L../libiberty"
+LIBS="$LIBS -lbfd -liberty"
+echo "$as_me:$LINENO: checking for ELF support in BFD" >&5
+echo $ECHO_N "checking for ELF support in BFD... $ECHO_C" >&6
+if test "${gdb_cv_var_elf+set}" = set; then
+  echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+  cat >conftest.$ac_ext <<_ACEOF
+/* confdefs.h.  */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h.  */
+#include <stdlib.h>
+#include "bfd.h"
+#include "elf-bfd.h"
+
+int
+main ()
+{
+bfd *abfd = NULL; bfd_get_elf_phdr_upper_bound (abfd);
+  ;
+  return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext conftest$ac_exeext
+if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5
+  (eval $ac_link) 2>conftest.er1
+  ac_status=$?
+  grep -v '^ *+' conftest.er1 >conftest.err
+  rm -f conftest.er1
+  cat conftest.err >&5
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); } &&
+	 { ac_try='test -z "$ac_c_werror_flag"
+			 || test ! -s conftest.err'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; } &&
+	 { ac_try='test -s conftest$ac_exeext'
+  { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  echo "$as_me:$LINENO: \$? = $ac_status" >&5
+  (exit $ac_status); }; }; then
+  gdb_cv_var_elf=yes
+else
+  echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+gdb_cv_var_elf=no
+fi
+rm -f conftest.err conftest.$ac_objext \
+      conftest$ac_exeext conftest.$ac_ext
+fi
+echo "$as_me:$LINENO: result: $gdb_cv_var_elf" >&5
+echo "${ECHO_T}$gdb_cv_var_elf" >&6
+if test $gdb_cv_var_elf = yes; then
+  CONFIG_OBS="$CONFIG_OBS elfread.o"
+
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_ELF 1
+_ACEOF
+
+fi
+CFLAGS=$OLD_CFLAGS
+LDFLAGS=$OLD_LDFLAGS
+LIBS=$OLD_LIBS
+
 # Add any host-specific objects to GDB.
 CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}"
 
Index: gdb/configure.ac
===================================================================
--- gdb/configure.ac.orig	2007-06-12 14:42:00.000000000 -0400
+++ gdb/configure.ac	2007-06-12 15:30:25.000000000 -0400
@@ -1255,6 +1255,30 @@ case ${host} in
 esac	    
 AC_SUBST(WIN32LIBS)
 
+# Add ELF support to GDB, but only if BFD includes ELF support.
+OLD_CFLAGS=$CFLAGS
+OLD_LDFLAGS=$LDFLAGS
+OLD_LIBS=$LIBS
+CFLAGS="$CFLAGS -I${srcdir}/../include -I${objdir}/../bfd -I${srcdir}/../bfd"
+LDFLAGS="$LDFLAGS -L../bfd -L../libiberty"
+LIBS="$LIBS -lbfd -liberty"
+AC_CACHE_CHECK([for ELF support in BFD], gdb_cv_var_elf,
+[AC_TRY_LINK(
+[#include <stdlib.h>
+#include "bfd.h"
+#include "elf-bfd.h"
+],
+[bfd *abfd = NULL; bfd_get_elf_phdr_upper_bound (abfd); ],
+gdb_cv_var_elf=yes, gdb_cv_var_elf=no)])
+if test $gdb_cv_var_elf = yes; then
+  CONFIG_OBS="$CONFIG_OBS elfread.o"
+  AC_DEFINE(HAVE_ELF, 1,
+	    [Define if ELF support should be included.])
+fi
+CFLAGS=$OLD_CFLAGS
+LDFLAGS=$OLD_LDFLAGS
+LIBS=$OLD_LIBS
+
 # Add any host-specific objects to GDB.
 CONFIG_OBS="${CONFIG_OBS} ${gdb_host_obs}"
 


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