This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch 06/15] PIE: Fix displacement of separate debug info files
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 9 Nov 2009 21:58:55 +0100
- Subject: [patch 06/15] PIE: Fix displacement of separate debug info files
Hi,
separate debug info files currently in some special cases were not properly
relocated.
There are three different addresses to track:
* in-memory VMA
* on-disk BFD VMA in the main binary file (possibly prelinked)
* on-disk BFD VMA in the debug info file (usually not but possibly prelinked)
objfile_relocate() by this patch relocates both the objfile and its separate
debug info file.
Its caller spu_relocate_main_executable() now does not have to do it itself.
symbol_file_add_with_addrs_or_offsets() has been fixed in the case of calling
it with addrs == NULL as in such case in-memory VMAs may not be 0-based.
In fact this probably happens only for PIEs as shared libraries have their
address specified during their load.
One needs to be careful which addresses are absolute, which are displacements
against BFD file and of the two BFDs we are dealing with.
Thanks,
Jan
Fix displacement of separate debug info files.
* objfiles.c (objfile_relocate): Rename to ...
(objfile_relocate1): ... here and make it static. Extend the comment.
(objfile_relocate): New function.
* solib-spu.c (spu_relocate_main_executable): Explicitly check if
SYMFILE_OBJFILE is NULL. Remove variables objfile and old_chain.
Remove following of SEPARATE_DEBUG_OBJFILE. new_offsets is now
allocated using alloca.
* symfile.c (build_section_addr_info_from_objfile): New function.
(symbol_file_add_with_addrs_or_offsets): Remove variable orig_addrs and
its initialization.
(symbol_file_add_with_addrs_or_offsets <debugfile>): Call
build_section_addr_info_from_objfile instead.
* symfile.h (build_section_addr_info_from_objfile): New prototype.
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -600,9 +600,10 @@ free_all_objfiles (void)
}
/* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS
- entries in new_offsets. */
-void
-objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
+ entries in new_offsets. SEPARATE_DEBUG_OBJFILE is not touched here. */
+
+static void
+objfile_relocate1 (struct objfile *objfile, struct section_offsets *new_offsets)
{
struct obj_section *s;
struct section_offsets *delta =
@@ -752,6 +753,49 @@ objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
exec_set_section_address (bfd_get_filename (objfile->obfd), idx,
obj_section_addr (s));
}
+}
+
+/* Relocate OBJFILE to NEW_OFFSETS. There should be OBJFILE->NUM_SECTIONS
+ entries in new_offsets. Process also OBJFILE's SEPARATE_DEBUG_OBJFILE.
+
+ The number and ordering of sections does differ between the two objfiles.
+ Only their names match. Also the file offsets will differ (objfile being
+ possibly prelinked but separate_debug_objfile is probably not prelinked) but
+ the in-memory absolute address as specified by NEW_OFFSETS must match both
+ files. */
+
+void
+objfile_relocate (struct objfile *objfile, struct section_offsets *new_offsets)
+{
+ objfile_relocate1 (objfile, new_offsets);
+
+ if (objfile->separate_debug_objfile != NULL)
+ {
+ struct objfile *debug_objfile = objfile->separate_debug_objfile;
+ struct section_addr_info *objfile_addrs;
+ struct section_offsets *new_debug_offsets;
+ int new_debug_num_sections;
+ struct cleanup *my_cleanups;
+
+ objfile_addrs = build_section_addr_info_from_objfile (objfile);
+ my_cleanups = make_cleanup (xfree, objfile_addrs);
+
+ /* Here OBJFILE_ADDRS contain the correct absolute addresses, the
+ relative ones must be already created according to debug_objfile. */
+
+ addr_info_make_relative (objfile_addrs, debug_objfile->obfd);
+
+ gdb_assert (debug_objfile->num_sections
+ == bfd_count_sections (debug_objfile->obfd));
+ new_debug_offsets = alloca (SIZEOF_N_SECTION_OFFSETS
+ (debug_objfile->num_sections));
+ relative_addr_info_to_section_offsets (new_debug_offsets,
+ debug_objfile->num_sections,
+ objfile_addrs);
+ do_cleanups (my_cleanups);
+
+ objfile_relocate1 (debug_objfile, new_debug_offsets);
+ }
/* Relocate breakpoints as necessary, after things are relocated. */
breakpoint_re_set ();
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -52,25 +52,19 @@
static void
spu_relocate_main_executable (int spufs_fd)
{
- struct objfile *objfile;
- struct cleanup *old_chain;
struct section_offsets *new_offsets;
int i;
- for (objfile = symfile_objfile;
- objfile;
- objfile = objfile->separate_debug_objfile)
- {
- new_offsets = xcalloc (objfile->num_sections,
- sizeof (struct section_offsets));
- old_chain = make_cleanup (xfree, new_offsets);
+ if (symfile_objfile == NULL)
+ return;
- for (i = 0; i < objfile->num_sections; i++)
- new_offsets->offsets[i] = SPUADDR (spufs_fd, 0);
+ new_offsets = alloca (symfile_objfile->num_sections
+ * sizeof (struct section_offsets));
- objfile_relocate (objfile, new_offsets);
- do_cleanups (old_chain);
- }
+ for (i = 0; i < symfile_objfile->num_sections; i++)
+ new_offsets->offsets[i] = SPUADDR (spufs_fd, 0);
+
+ objfile_relocate (symfile_objfile, new_offsets);
}
/* When running a stand-alone SPE executable, we may need to skip one more
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -536,6 +536,46 @@ place_section (bfd *abfd, asection *sect, void *obj)
arg->lowest = start_addr + bfd_get_section_size (sect);
}
+/* Build (allocate and populate) struct section_addr_info with absolute
+ addresses from OBJFILE->OBFD and OBJFILE->SECTION_OFFSETS. */
+
+struct section_addr_info *
+build_section_addr_info_from_objfile (struct objfile *objfile)
+{
+ struct target_section *sections = NULL, *sections_end;
+ struct target_section *p;
+ int addr_bit = gdbarch_addr_bit (objfile->gdbarch);
+ CORE_ADDR mask = CORE_ADDR_MAX;
+ struct section_addr_info *retval;
+ struct cleanup *my_cleanups;
+
+ if (build_section_table (objfile->obfd, §ions, §ions_end))
+ error (_("Can't find the file sections in `%s': %s"),
+ bfd_get_filename (objfile->obfd), bfd_errmsg (bfd_get_error ()));
+ my_cleanups = make_cleanup (xfree, sections);
+
+ if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
+ mask = ((CORE_ADDR) 1 << addr_bit) - 1;
+
+ for (p = sections; p < sections_end; p++)
+ {
+ CORE_ADDR baseaddr;
+
+ gdb_assert (p->the_bfd_section->index < objfile->num_sections);
+ baseaddr = ANOFFSET (objfile->section_offsets,
+ p->the_bfd_section->index);
+
+ p->addr = (p->addr + baseaddr) & mask;
+ p->endaddr = (p->endaddr + baseaddr) & mask;
+ }
+
+ retval = build_section_addr_info_from_section_table (sections, sections_end);
+
+ do_cleanups (my_cleanups);
+
+ return retval;
+}
+
/* Store struct section_addr_info as prepared (made relative and with SECTINDEX
filled-in) by addr_info_make_relative into SECTION_OFFSETS of NUM_SECTIONS
entries. */
@@ -962,7 +1002,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
struct objfile *objfile;
struct partial_symtab *psymtab;
char *debugfile = NULL;
- struct section_addr_info *orig_addrs = NULL;
struct cleanup *my_cleanups;
const char *name = bfd_get_filename (abfd);
const int from_tty = add_flags & SYMFILE_VERBOSE;
@@ -981,12 +1020,6 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
objfile = allocate_objfile (abfd, flags);
discard_cleanups (my_cleanups);
- if (addrs)
- {
- orig_addrs = copy_section_addr_info (addrs);
- make_cleanup_free_section_addr_info (orig_addrs);
- }
-
/* We either created a new mapped symbol table, mapped an existing
symbol table file which has not had initial symbol reading
performed, or need to read an unmapped symbol table. */
@@ -1031,18 +1064,17 @@ symbol_file_add_with_addrs_or_offsets (bfd *abfd,
`.gnu_debuglink' may no longer be present with `.note.gnu.build-id'. */
if (objfile->psymtabs == NULL)
debugfile = find_separate_debug_file (objfile);
+
if (debugfile)
{
- if (addrs != NULL)
- {
- objfile->separate_debug_objfile
- = symbol_file_add (debugfile, add_flags, orig_addrs, flags);
- }
- else
- {
- objfile->separate_debug_objfile
- = symbol_file_add (debugfile, add_flags, NULL, flags);
- }
+ struct section_addr_info *objfile_addrs;
+
+ objfile_addrs = build_section_addr_info_from_objfile (objfile);
+ make_cleanup (xfree, objfile_addrs);
+
+ objfile->separate_debug_objfile = symbol_file_add (debugfile, add_flags,
+ objfile_addrs, flags);
+
objfile->separate_debug_objfile->separate_debug_objfile_backlink
= objfile;
--- a/gdb/symfile.h
+++ b/gdb/symfile.h
@@ -175,6 +175,9 @@ struct sym_fns
};
+extern struct section_addr_info *
+ build_section_addr_info_from_objfile (struct objfile *objfile);
+
extern void relative_addr_info_to_section_offsets
(struct section_offsets *section_offsets, int num_sections,
struct section_addr_info *addrs);