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]

[RFA] crash while re-reading symbols from objfile on ppc-aix.


Hello,

This patch aims at fixing the following problem, where the user:

  . debugs its program
  . makes a modification and rebuilds it *without exiting the debugger*
  . returns to its debugging session and restarts the inferior

(this is mostly what reread.exp verifies)

In that situation, the debugger notices that the underlying executable
has changed and that re-reading its symbols is needed. Shortly after
displaying a message informing the user of the situation, GDB crashes:

   (gdb) run
   [...]
   `/[...]/dest' has changed; re-reading symbols.
   zsh: 13434922 segmentation fault (core dumped)

The crash occurs while trying to allocate some memory on the bfd_bfd
obstack.  But, at some point in time, the whole obstack data gets
corrupted, nullified. So the memory allocation fails with a SIGILL
trying to call a function at a NULL address.

The corruption occurred because the region where the per_bfd data
got free'ed nearly after it got allocated! This is what happens,
in chronological order (see reread_symbols):

  1. GDB notices that the executable has changed, decides to
     re-read its symbols.

  2. Opens a new bfd, unrefs the old one

  3. Calls set_objfile_per_bfd (objfile);

  4. Re-initializes the objfile's obstack:
     obstack_init (&objfile->objfile_obstack);

I think that the normal behavior for set_objfile_per_bfd would
be to search for already-allocated shared per_bfd data, and
allocate new one if not found.  The critical difference between
a platform such as x86_64-linuxe where it works, and ppc-aix,
where it doesn't lies in the fact that bfd-data sharing is not
activated on ppc-aix, and as a result, the per-bfd data gets
allocated on the objfile's obstack instead of in the bfd objalloc:

      /* If the object requires gdb to do relocations, we simply fall
         back to not sharing data across users.  These cases are rare
         enough that this seems reasonable.  */
      if (abfd != NULL && !gdb_bfd_requires_relocations (abfd))
        {
          storage = bfd_zalloc (abfd, sizeof (struct objfile_per_bfd_storage));
          set_bfd_data (abfd, objfiles_bfd_data, storage);
        }
      else
        storage = OBSTACK_ZALLOC (&objfile->objfile_obstack,
                                  struct objfile_per_bfd_storage);

Allocating that per_bfd storage is of course nearly useless since
we end up free-ing right after in step (4) above. Eventually,
the memory region ends up being re-used, hence the corruption
leading to the crash.

This fix was simply to move the call to set_objfile_per_bfd after
the objfile's obstack re-initialization.

gdb/ChangeLog:

        * symfile.c (reread_symbols): Move call to set_objfile_per_bfd
        after re-initialization of OBJFILE's obstack.

Tested on x86_64-linux, no regression. Also tested on ppc-aix using
AdaCore's testsuite (expect hangs at the end of the test, on ppc-aix,
so I can't collect any result).

Ok to commit?

Thanks,
-- 
Joel

---
 gdb/symfile.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/gdb/symfile.c b/gdb/symfile.c
index 1307189..61e3e44 100644
--- a/gdb/symfile.c
+++ b/gdb/symfile.c
@@ -2591,13 +2591,17 @@ reread_symbols (void)
 	  memset (&objfile->msymbol_demangled_hash, 0,
 		  sizeof (objfile->msymbol_demangled_hash));
 
-	  set_objfile_per_bfd (objfile);
-
 	  /* obstack_init also initializes the obstack so it is
 	     empty.  We could use obstack_specify_allocation but
 	     gdb_obstack.h specifies the alloc/dealloc functions.  */
 	  obstack_init (&objfile->objfile_obstack);
 
+	  /* set_objfile_per_bfd potentially allocates the per-bfd
+	     data on the objfile's obstack (if sharing data across
+	     multiple users is not possible), so it's important to
+	     do it *after* the obstack has been initialized.  */
+	  set_objfile_per_bfd (objfile);
+
 	  objfile->original_name = obstack_copy0 (&objfile->objfile_obstack,
 						  original_name,
 						  strlen (original_name));
-- 
1.8.1.2


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