* 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.
This commit is contained in:
parent
d856f2ddfa
commit
31d99776c7
20 changed files with 585 additions and 55 deletions
|
@ -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.
|
||||
|
|
|
@ -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; };
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) \
|
||||
|
|
4
gdb/NEWS
4
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
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
76
gdb/configure
vendored
76
gdb/configure
vendored
|
@ -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}"
|
||||
|
||||
|
|
|
@ -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}"
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
84
gdb/remote.c
84
gdb/remote.c
|
@ -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,11 +2051,8 @@ 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)
|
||||
if (strncmp (ptr, ";Data=", 6) == 0)
|
||||
{
|
||||
ptr += 6;
|
||||
while (*ptr && *ptr != ';')
|
||||
|
@ -2065,21 +2066,85 @@ get_offsets (void)
|
|||
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 += 8;
|
||||
/* Don't use strtol, could lose on big values. */
|
||||
while (*ptr && *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));
|
||||
|
||||
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"));
|
||||
|
||||
if (ret > 0)
|
||||
do_sections = 0;
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -2088,6 +2153,7 @@ get_offsets (void)
|
|||
|
||||
offs->offsets[SECT_OFF_DATA (symfile_objfile)] = data_addr;
|
||||
offs->offsets[SECT_OFF_BSS (symfile_objfile)] = data_addr;
|
||||
}
|
||||
|
||||
objfile_relocate (symfile_objfile, offs);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
212
gdb/symfile.c
212
gdb/symfile.c
|
@ -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;
|
||||
}
|
||||
}
|
||||
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 *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)
|
||||
{
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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 */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue