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]

[PATCH] Fix for pr 16426


Hi.

This patch fixes pr 16426.

https://sourceware.org/bugzilla/show_bug.cgi?id=16426

The problem is described pretty well in the pr I think,
but to summarize, demanged_names_hash (which lives in the objfile's bfd's
space) has pointers to data that can be freed when the objfile is freed.

This fixes things by recording fission dwo/dwp files as being "included"
by the objfile's bfd, preserving them for the lifetime of the objfile's bfd.

Regression tested on amd64-linux,
and run with valgrind using the repro in the pr
to verify no errors reported there as well.

Tom, I *think* this fixes dwz files as well, but it could use more eyes
(not just for the dwz part).

2014-01-10  Doug Evans  <dje@google.com>

	PR symtab/16426
	* dwarf2read.c (dwarf2_get_dwz_file): Call gdb_bfd_record_inclusion.
	(try_open_dwop_file): Ditto.
	* gdb_bfd.c: #include "vec.h".
	(bfdp): New typedef.
	(struct gdb_bfd_data): New member included_bfds.
	(gdb_bfd_unref): Unref all included bfds.
	(gdb_bfd_record_inclusion): New function.
	* gdb_bfd.h (gdb_bfd_record_inclusion): Declare.

diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 23bcfe0..bcd93e7 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -2432,6 +2432,7 @@ dwarf2_get_dwz_file (void)
 
   do_cleanups (cleanup);
 
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, dwz_bfd);
   dwarf2_per_objfile->dwz_file = result;
   return result;
 }
@@ -10122,6 +10123,8 @@ lookup_dwo_unit_in_dwp (struct dwp_file *dwp_file, const char *comp_dir,
    If IS_DWP is TRUE, we're opening a DWP file, otherwise a DWO file.
    SEARCH_CWD is true if the current directory is to be searched.
    It will be searched before debug-file-directory.
+   If successful, the file is added to the bfd include table of the
+   objfile's bfd (see gdb_bfd_record_inclusion).
    If unable to find/open the file, return NULL.
    NOTE: This function is derived from symfile_bfd_open.  */
 
@@ -10169,6 +10172,12 @@ try_open_dwop_file (const char *file_name, int is_dwp, int search_cwd)
       return NULL;
     }
 
+  /* Success.  Record the bfd as having been included by the objfile's bfd.
+     This is important because things like demangled_names_hash lives in the
+     objfile's per_bfd space and may have references to things like symbol
+     names that live in the DWO/DWP file's per_bfd space.  PR 16426.  */
+  gdb_bfd_record_inclusion (dwarf2_per_objfile->objfile->obfd, sym_bfd);
+
   return sym_bfd;
 }
 
diff --git a/gdb/gdb_bfd.c b/gdb/gdb_bfd.c
index 5230d21..4d4b0a5 100644
--- a/gdb/gdb_bfd.c
+++ b/gdb/gdb_bfd.c
@@ -25,6 +25,7 @@
 #include "gdbcmd.h"
 #include "hashtab.h"
 #include "filestuff.h"
+#include "vec.h"
 #ifdef HAVE_ZLIB_H
 #include <zlib.h>
 #endif
@@ -35,6 +36,9 @@
 #endif
 #endif
 
+typedef bfd *bfdp;
+DEF_VEC_P (bfdp);
+
 /* An object of this type is stored in the section's user data when
    mapping a section.  */
 
@@ -84,6 +88,9 @@ struct gdb_bfd_data
      BFD.  Otherwise, this is NULL.  */
   bfd *archive_bfd;
 
+  /* Table of all the bfds this bfd has included.  */
+  VEC (bfdp) *included_bfds;
+
   /* The registry.  */
   REGISTRY_FIELDS;
 };
@@ -277,9 +284,10 @@ gdb_bfd_ref (struct bfd *abfd)
 void
 gdb_bfd_unref (struct bfd *abfd)
 {
+  int ix;
   struct gdb_bfd_data *gdata;
   struct gdb_bfd_cache_search search;
-  bfd *archive_bfd;
+  bfd *archive_bfd, *included_bfd;
 
   if (abfd == NULL)
     return;
@@ -307,6 +315,12 @@ gdb_bfd_unref (struct bfd *abfd)
 	htab_clear_slot (gdb_bfd_cache, slot);
     }
 
+  for (ix = 0;
+       VEC_iterate (bfdp, gdata->included_bfds, ix, included_bfd);
+       ++ix)
+    gdb_bfd_unref (included_bfd);
+  VEC_free (bfdp, gdata->included_bfds);
+
   bfd_free_data (abfd);
   bfd_usrdata (abfd) = NULL;  /* Paranoia.  */
 
@@ -569,6 +583,18 @@ gdb_bfd_openr_next_archived_file (bfd *archive, bfd *previous)
 
 /* See gdb_bfd.h.  */
 
+void
+gdb_bfd_record_inclusion (bfd *includer, bfd *includee)
+{
+  struct gdb_bfd_data *gdata;
+
+  gdb_bfd_ref (includee);
+  gdata = bfd_usrdata (includer);
+  VEC_safe_push (bfdp, gdata->included_bfds, includee);
+}
+
+/* See gdb_bfd.h.  */
+
 bfd *
 gdb_bfd_fdopenr (const char *filename, const char *target, int fd)
 {
diff --git a/gdb/gdb_bfd.h b/gdb/gdb_bfd.h
index d415005..61ad348 100644
--- a/gdb/gdb_bfd.h
+++ b/gdb/gdb_bfd.h
@@ -52,6 +52,20 @@ void gdb_bfd_unref (struct bfd *abfd);
 
 void gdb_bfd_mark_parent (bfd *child, bfd *parent);
 
+/* Mark INCLUDEE as being included by INCLUDER.
+   This is used to associate the life time of INCLUDEE with INCLUDER.
+   For example, with Fission, one file can refer to debug info in another
+   file, and internal tables we build for the main file (INCLUDER) may refer
+   to data contained in INCLUDEE.  Therefore we want to keep INCLUDEE around
+   at least as long as INCLUDER exists.
+
+   Note that this is different than gdb_bfd_mark_parent because in our case
+   lifetime tracking is based on the "parent" whereas in gdb_bfd_mark_parent
+   lifetime tracking is based on the "child".  Plus in our case INCLUDEE could
+   have multiple different "parents".  */
+
+void gdb_bfd_record_inclusion (bfd *includer, bfd *includee);
+
 /* Try to read or map the contents of the section SECT.  If
    successful, the section data is returned and *SIZE is set to the
    size of the section data; this may not be the same as the size



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