* coffread.c (coff_sym_fns): Add default_symfile_segments.
authorDaniel Jacobowitz <drow@false.org>
Mon, 18 Jun 2007 15:46:38 +0000 (15:46 +0000)
committerDaniel Jacobowitz <drow@false.org>
Mon, 18 Jun 2007 15:46:38 +0000 (15:46 +0000)
* 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.

20 files changed:
ChangeLog
Makefile.def
Makefile.in
gdb/ChangeLog
gdb/Makefile.in
gdb/NEWS
gdb/coffread.c
gdb/config.in
gdb/configure
gdb/configure.ac
gdb/dbxread.c
gdb/doc/ChangeLog
gdb/doc/gdb.texinfo
gdb/elfread.c
gdb/mipsread.c
gdb/remote.c
gdb/somread.c
gdb/symfile.c
gdb/symfile.h
gdb/xcoffread.c

index 4fc9fc74c9c5ebbed2e39f3ef393040b470c8ffc..f5cd00cee27f718671c21a117eff6c199a9979ae 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2007-06-18  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * Makefile.def: Add dependency from configure-gdb to all-bfd.
+       * Makefile.in: Regenerated.
+
 2007-06-14  Paolo Bonzini  <bonzini@gnu.org>
 
         * Makefile.tpl (cleanstrap): Don't delete the toplevel Makefile.
index 6436272ae9c0c439ea5bf15012c852b140529710..3d2c6eeeb44b3e6444959a00c1330088fcd47fde 100644 (file)
@@ -314,10 +314,10 @@ dependencies = { module=configure-mpfr; on=all-gmp; };
 // 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 785f53ba45a813a9b072f55e3e618415d995215c..e34410cf18bcacb759a5a257ead6507368770322 100644 (file)
@@ -49030,10 +49030,10 @@ configure-stageprofile-mpfr: maybe-all-stageprofile-gmp
 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 00c31410064a76f14d3f2deaa9fa106ba306364e..0ed2af062ca8c38a1f6c8eef254913b2a5d8fc28 100644 (file)
@@ -1,3 +1,35 @@
+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.
+
 2007-06-16  Ulrich Weigand  <uweigand@de.ibm.com>
 
        * gdbtypes.h (builtin_type_m2_char, builtin_type_m2_int,
index 13570eba4ce6c3ddc0b73a7fb70583e0b558792d..3d0fa409a307f6ea9ebe07394773c98306edcc8a 100644 (file)
@@ -586,6 +586,7 @@ coff_ecoff_h =      $(INCLUDE_DIR)/coff/ecoff.h
 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) $(YYOBJ) \
        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) $(bfd_h) $(symtab_h) $(gdbtypes_h) \
        $(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 596456daee0e4abbb45547b295e621d27f0252a2..59c241a7c113673d5b8e73274acf97b787aea1f3 100644 (file)
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -37,6 +37,10 @@ has been rewritten to use the standard GDB remote protocol.
 
 * 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 7ff53b7134bbe3c18ef2550bf987c4e3ed28e96a..dcd17d35faa069f805840a86b61acf60f702cf9c 100644 (file)
@@ -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 1ca8e46f99b17260a9ff0ee51350a103fdcea71d..1534afe82754fa9e8b018ef3c88f4fec7286fea4 100644 (file)
    */
 #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 9d9309ea161f83a4012c47e17a5cd595c2f7598f..788351176a8a2d8ad26b33be1f150d897d49cbab 100755 (executable)
@@ -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 ea160990662bffe199fddeb1c71d3990a5b0858c..680a43e2a73b32add58be908bf5d1dc07941f68d 100644 (file)
@@ -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 702e315fd7c2dd53fca4416cabd218c1dd29fb35..bba9995a5e281843b46b9f5986f5197a532e6595 100644 (file)
@@ -2148,11 +2148,13 @@ start_psymtab (struct objfile *objfile, char *filename, CORE_ADDR textlow,
   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 8f7e7325d15025e753936b3ef408c485abd25277..a3192a3d00ac8418a5995b35ff6add510d2a971a 100644 (file)
@@ -1,3 +1,7 @@
+2007-06-18  Daniel Jacobowitz  <dan@codesourcery.com>
+
+       * gdb.texinfo (General Query Packets): Document qOffsets changes.
+
 2007-06-13  Daniel Jacobowitz  <dan@codesourcery.com>
 
        * gdb.texinfo (Target Description Format): Add version attribute
index 230a6cad85ede1c1b0c9ab6db06d35a216df7b99..377278611c5c22710fe8190b4677becd21712710 100644 (file)
@@ -23433,14 +23433,31 @@ digits).  See @code{remote.c:parse_threadlist_response()}.
 @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 ea28d7c258a9d171fd35898a6bbc6446347edab2..7b84ede6c7165f329f12667307e587b4c3a2f8e1 100644 (file)
@@ -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 eb06f30a9dc474d69effc69591a4bdaf38aa46b6..daa4ba72a432743113304a1d8455dba398cfa99f 100644 (file)
@@ -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 f4f267b420d0be43f5e3fe0de8b97dd16e9baa46..3990a34285ac0cd32a04652b3de2166f9f32905a 100644 (file)
@@ -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)
+       {
+         ptr += 5;
+         while (*ptr && *ptr != ';')
+           bss_addr = (bss_addr << 4) + fromhex (*ptr++);
 
-  if (!lose && strncmp (ptr, ";Bss=", 5) == 0)
+         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;
 
-  /* 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.  */
+  /* 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"));
+
+      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 c4f0744716f246c2530f5022974604b6b5f9dab5..199825c911e91f534bd1e1d6b84cef5d208b4a53 100644 (file)
@@ -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 fac4c87ea0669940a3cc6288ef60834113645294..f513dfa6f1b52208de59cffe024a63c80d2ef0f1 100644 (file)
@@ -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 (struct objfile *objfile);
 
 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 objfile *objfile)
   /* 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 *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 *objfile,
   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));
 }
 \f
 
@@ -3771,6 +3838,111 @@ symfile_relocate_debug_section (bfd *abfd, asection *sectp, bfd_byte *buf)
   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 b24acc1c931574fce208ff084960b18f56d5e561..4d08c71ecc741e6bb2729de77c07caa256bd782e 100644 (file)
@@ -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 (struct obj_section *);
 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 8c8208ef51be3ab049c3fa176a5a78ab63f927ea..e5c2e08bbdf518452cecc675e7832a3131491e74 100644 (file)
@@ -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 */
 };