Mirror of the gdb mailing list
 help / color / mirror / Atom feed
* Solibs and objfile BFD ownership
@ 2009-07-28 15:40 Daniel Jacobowitz
  2009-07-29 23:56 ` Paul Pluzhnikov
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2009-07-28 15:40 UTC (permalink / raw)
  To: Paul Pluzhnikov, gdb

I'm seeing ARM test failures caused by this patch:

2009-03-05  Paul Pluzhnikov  <ppluzhnikov@google.com>

        * printcmd.c (do_one_display): Reparse exp_string.
        (display_uses_solib_p): New function.
        (clear_dangling_display_expressions): New function.
        (_initialize_printcmd): Add observer.
        * solib.c (no_shared_libraries): Swap order of calls to
        clear_solib and objfile_purge_solibs.

Specifically this bit:

  /* The order of the two routines below is important: clear_solib notifies
     the solib_unloaded observers, and some of these observers might need
     access to their associated objfiles.  Therefore, we can not purge the
     solibs' objfiles before clear_solib has been called.  */

  clear_solib ();
  objfile_purge_solibs ();

The problem with doing things in this order is that both the solib and
the objfile have a reference to the same BFD.  The solib is
responsible for releasing it (OBJF_KEEPBFD).  arm_objfile_data_cleanup
accesses objfile->obfd during free_objfile, to find the number
of sections; at that point it's already been free'd.

Any thoughts?  I could change the ARM code to work around this, but
that means banning access to objfile->obfd during a not well specified
range of functions.  Handing off the ownership of the BFD seems like
it would be messy.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-07-28 15:40 Solibs and objfile BFD ownership Daniel Jacobowitz
@ 2009-07-29 23:56 ` Paul Pluzhnikov
  2009-07-30 16:16   ` Tom Tromey
  0 siblings, 1 reply; 13+ messages in thread
From: Paul Pluzhnikov @ 2009-07-29 23:56 UTC (permalink / raw)
  To: Paul Pluzhnikov, gdb

[-- Attachment #1: Type: text/plain, Size: 974 bytes --]

On Tue, Jul 28, 2009 at 8:40 AM, Daniel Jacobowitz<drow@false.org> wrote:

>  clear_solib ();
>  objfile_purge_solibs ();
>
> The problem with doing things in this order is that both the solib and
> the objfile have a reference to the same BFD.  The solib is
> responsible for releasing it (OBJF_KEEPBFD).  arm_objfile_data_cleanup
> accesses objfile->obfd during free_objfile, to find the number
> of sections; at that point it's already been free'd.

That is a problem.

> Any thoughts?

There doesn't appear to be a correct order of destruction :-(

Attached patch restores the original order, while still keeping
solib_unloaded observers from accessing danglig objfiles.

I do not know if there is a better way to fix this.

Tested on Linux/x86_64 with no new regressions.

Thanks,
-- 
Paul Pluzhnikov

2009-07-29  Paul Pluzhnikov  <ppluzhnikov@google.com>

	* solib.c (clear_solib): Rename to clear_solib_1
	(clear_solib): New function.
	(no_shared_libraries): Adjust.

[-- Attachment #2: gdb-clear-solib-20090729.txt --]
[-- Type: text/plain, Size: 2102 bytes --]

Index: solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.122
diff -u -p -u -r1.122 solib.c
--- solib.c	17 Jul 2009 17:08:23 -0000	1.122
+++ solib.c	29 Jul 2009 23:39:11 -0000
@@ -893,10 +893,8 @@ solib_name_from_address (CORE_ADDR addre
   return (0);
 }
 
-/* Called by free_all_symtabs */
-
-void
-clear_solib (void)
+static void
+clear_solib_1 (int notify_observers)
 {
   struct target_so_ops *ops = solib_ops (target_gdbarch);
 
@@ -928,7 +926,8 @@ clear_solib (void)
     {
       struct so_list *so = so_list_head;
       so_list_head = so->next;
-      observer_notify_solib_unloaded (so);
+      if (notify_observers)
+        observer_notify_solib_unloaded (so);
       if (so->abfd)
 	remove_target_sections (so->abfd);
       free_so (so);
@@ -937,6 +936,15 @@ clear_solib (void)
   ops->clear_solib ();
 }
 
+/* Called by free_all_symtabs */
+
+void
+clear_solib (void)
+{
+  clear_solib_1 (1);
+}
+
+
 /* GLOBAL FUNCTION
 
    solib_create_inferior_hook -- shared library startup support
@@ -1018,13 +1026,20 @@ sharedlibrary_command (char *args, int f
 void
 no_shared_libraries (char *ignored, int from_tty)
 {
-  /* The order of the two routines below is important: clear_solib notifies
-     the solib_unloaded observers, and some of these observers might need
-     access to their associated objfiles.  Therefore, we can not purge the
-     solibs' objfiles before clear_solib has been called.  */
+  struct so_list *so = so_list_head;
+
+  /* We notify all solib_unloaded observers before destroying any objfiles,
+     because some observers need access to their associated objfiles.  */
+
+  for (so = so_list_head; so; so = so->next)
+    observer_notify_solib_unloaded (so);
+
+  /* The order of the two routines below is important: clear_solib_1
+     will free/close objfile->obfd (solib owns it), but objfile_purge_solibs
+     needs access to it (at least on ARM, see arm_objfile_data_cleanup).  */
 
-  clear_solib ();
   objfile_purge_solibs ();
+  clear_solib_1 (0);
 }
 
 static void

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-07-29 23:56 ` Paul Pluzhnikov
@ 2009-07-30 16:16   ` Tom Tromey
  2009-08-04  0:50     ` Paul Pluzhnikov
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2009-07-30 16:16 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb

>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:

Paul> There doesn't appear to be a correct order of destruction :-(
[...]
Paul> I do not know if there is a better way to fix this.

It seems to me that there are not many choices.  Either we must pick a
single owner, pick an order, implement something like reference counting
for BFDs, or have a separate function to clean up the BFDs.

Tom


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-07-30 16:16   ` Tom Tromey
@ 2009-08-04  0:50     ` Paul Pluzhnikov
  2009-08-04 14:53       ` Daniel Jacobowitz
  0 siblings, 1 reply; 13+ messages in thread
From: Paul Pluzhnikov @ 2009-08-04  0:50 UTC (permalink / raw)
  To: tromey; +Cc: gdb

[-- Attachment #1: Type: text/plain, Size: 730 bytes --]

On Thu, Jul 30, 2009 at 9:15 AM, Tom Tromey<tromey@redhat.com> wrote:

> It seems to me that there are not many choices.  Either we must pick a
> single owner, pick an order, implement something like reference counting
> for BFDs, or have a separate function to clean up the BFDs.

Right.

Conveniently, 'struct bfd' has usrdata, which is unused in GDB.
Here is a stab at reference-counted sharing of BFDs between solib and
objfile.

-- 
Paul Pluzhnikov


2009-08-03  Paul Pluzhnikov  <ppluzhnikov@google.com>

	* objfiles.h (OBJF_KEEPBFD): Delete.
	(gdb_bfd_unref): New prototype.
	* objfiles.c (gdb_bfd_unref): New function.
	(free_objfile): Call gdb_bfd_unref.
	* solib.c (free_so): Likewise.
	(symbol_add_stub): Set refcount.

[-- Attachment #2: gdb-bfd-ownership-20090803.txt --]
[-- Type: text/plain, Size: 4166 bytes --]

Index: objfiles.h
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.h,v
retrieving revision 1.60
diff -u -p -u -r1.60 objfiles.h
--- objfiles.h	22 Jul 2009 19:21:31 -0000	1.60
+++ objfiles.h	4 Aug 2009 00:40:55 -0000
@@ -414,12 +414,6 @@ struct objfile
 
 #define OBJF_USERLOADED	(1 << 3)	/* User loaded */
 
-/* The bfd of this objfile is used outside of the objfile (e.g. by solib).
-   Do not try to free it.  */
-
-#define OBJF_KEEPBFD	(1 << 4)	/* Do not delete bfd */
-
-
 /* The object file that the main symbol table was loaded from (e.g. the
    argument to the "symbol-file" or "file" command).  */
 
@@ -510,6 +504,8 @@ extern void set_objfile_data (struct obj
 			      const struct objfile_data *data, void *value);
 extern void *objfile_data (struct objfile *objfile,
 			   const struct objfile_data *data);
+
+extern void gdb_bfd_unref (struct bfd *abfd);
 \f
 
 /* Traverse all object files.  ALL_OBJFILES_SAFE works even if you delete
Index: objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.88
diff -u -p -u -r1.88 objfiles.c
--- objfiles.c	28 Jul 2009 16:39:06 -0000	1.88
+++ objfiles.c	4 Aug 2009 00:40:55 -0000
@@ -452,16 +452,7 @@ free_objfile (struct objfile *objfile)
   /* Discard any data modules have associated with the objfile.  */
   objfile_free_data (objfile);
 
-  /* We always close the bfd, unless the OBJF_KEEPBFD flag is set.  */
-
-  if (objfile->obfd != NULL && !(objfile->flags & OBJF_KEEPBFD))
-    {
-      char *name = bfd_get_filename (objfile->obfd);
-      if (!bfd_close (objfile->obfd))
-	warning (_("cannot close \"%s\": %s"),
-		 name, bfd_errmsg (bfd_get_error ()));
-      xfree (name);
-    }
+  gdb_bfd_unref (objfile->obfd);
 
   /* Remove it from the chain of all objfiles. */
 
@@ -1020,3 +1011,31 @@ objfiles_changed (void)
 {
   objfiles_changed_p = 1;  /* Rebuild section map next time we need it.  */
 }
+
+/* Unreference and possibly close abfd.  */
+void
+gdb_bfd_unref (struct bfd *abfd)
+{
+  int *p_refcount;
+  char *name;
+
+  if (abfd == NULL)
+    return;
+
+  p_refcount = abfd->usrdata;
+  if (p_refcount != NULL)
+    {
+      gdb_assert (*p_refcount > 0);
+      *p_refcount -= 1;
+      if (*p_refcount > 0)
+	return;
+    }
+  xfree (p_refcount);
+  abfd->usrdata = NULL;  /* Paranoia.  */
+
+  name = bfd_get_filename (abfd);
+  if (!bfd_close (abfd))
+    warning (_("cannot close \"%s\": %s"),
+	     name, bfd_errmsg (bfd_get_error ()));
+  xfree (name);
+}
Index: solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.122
diff -u -p -u -r1.122 solib.c
--- solib.c	17 Jul 2009 17:08:23 -0000	1.122
+++ solib.c	4 Aug 2009 00:40:55 -0000
@@ -421,21 +421,11 @@ void
 free_so (struct so_list *so)
 {
   struct target_so_ops *ops = solib_ops (target_gdbarch);
-  char *bfd_filename = 0;
 
   if (so->sections)
     xfree (so->sections);
-      
-  if (so->abfd)
-    {
-      bfd_filename = bfd_get_filename (so->abfd);
-      if (! bfd_close (so->abfd))
-	warning (_("cannot close \"%s\": %s"),
-		 bfd_filename, bfd_errmsg (bfd_get_error ()));
-    }
 
-  if (bfd_filename)
-    xfree (bfd_filename);
+  gdb_bfd_unref (so->abfd);
 
   ops->free_so (so);
 
@@ -454,6 +444,7 @@ static void
 symbol_add_stub (struct so_list *so, int flags)
 {
   struct section_addr_info *sap;
+  int *p_refcount;
 
   /* Have we already loaded this shared object?  */
   ALL_OBJFILES (so->objfile)
@@ -465,8 +456,11 @@ symbol_add_stub (struct so_list *so, int
   sap = build_section_addr_info_from_section_table (so->sections,
                                                     so->sections_end);
 
-  so->objfile = symbol_file_add_from_bfd (so->abfd, flags,
-					  sap, OBJF_SHARED | OBJF_KEEPBFD);
+  so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED);
+  p_refcount = malloc (sizeof (*p_refcount));
+  *p_refcount = 2;  /* Both solib and objfile refer to this abfd.  */
+  so->abfd->usrdata = p_refcount;
+
   free_section_addr_info (sap);
 
   return;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-04  0:50     ` Paul Pluzhnikov
@ 2009-08-04 14:53       ` Daniel Jacobowitz
  2009-08-04 17:37         ` Paul Pluzhnikov
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2009-08-04 14:53 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: tromey, gdb

On Mon, Aug 03, 2009 at 05:49:54PM -0700, Paul Pluzhnikov wrote:
> Conveniently, 'struct bfd' has usrdata, which is unused in GDB.
> Here is a stab at reference-counted sharing of BFDs between solib and
> objfile.

I can't see a better solution, so let's use this.

A comment somewhere about the usage of the usrdata field would be
nice.  I gather that NULL and 1 behave the same?

> +  p_refcount = malloc (sizeof (*p_refcount));

xmalloc

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-04 14:53       ` Daniel Jacobowitz
@ 2009-08-04 17:37         ` Paul Pluzhnikov
  2009-08-04 18:40           ` Daniel Jacobowitz
  0 siblings, 1 reply; 13+ messages in thread
From: Paul Pluzhnikov @ 2009-08-04 17:37 UTC (permalink / raw)
  To: Paul Pluzhnikov, tromey, gdb

[-- Attachment #1: Type: text/plain, Size: 725 bytes --]

On Tue, Aug 4, 2009 at 7:53 AM, Daniel Jacobowitz<drow@false.org> wrote:

> A comment somewhere about the usage of the usrdata field would be
> nice.  I gather that NULL and 1 behave the same?

Yes. I added comment to gdb_bfd_unref.
Updated patch attached. Tested on Linux/x86_64 with no new failures.

Daniel, could you confirm that this fixes the ARM failures?

Thanks,
-- 
Paul Pluzhnikov

2009-08-04  Paul Pluzhnikov  <ppluzhnikov@google.com>

       * objfiles.h (OBJF_KEEPBFD): Delete.
       (gdb_bfd_unref): New prototype.
       * objfiles.c (gdb_bfd_unref): New function.
       (free_objfile): Call gdb_bfd_unref.
       * solib.c (free_so): Likewise.
       (symbol_add_stub): Set refcount.

[-- Attachment #2: gdb-bfd-ownership-20090804.txt --]
[-- Type: text/plain, Size: 4357 bytes --]

Index: objfiles.h
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.h,v
retrieving revision 1.60
diff -u -p -u -r1.60 objfiles.h
--- objfiles.h	22 Jul 2009 19:21:31 -0000	1.60
+++ objfiles.h	4 Aug 2009 17:22:33 -0000
@@ -414,12 +414,6 @@ struct objfile
 
 #define OBJF_USERLOADED	(1 << 3)	/* User loaded */
 
-/* The bfd of this objfile is used outside of the objfile (e.g. by solib).
-   Do not try to free it.  */
-
-#define OBJF_KEEPBFD	(1 << 4)	/* Do not delete bfd */
-
-
 /* The object file that the main symbol table was loaded from (e.g. the
    argument to the "symbol-file" or "file" command).  */
 
@@ -510,6 +504,8 @@ extern void set_objfile_data (struct obj
 			      const struct objfile_data *data, void *value);
 extern void *objfile_data (struct objfile *objfile,
 			   const struct objfile_data *data);
+
+extern void gdb_bfd_unref (struct bfd *abfd);
 \f
 
 /* Traverse all object files.  ALL_OBJFILES_SAFE works even if you delete
Index: objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.88
diff -u -p -u -r1.88 objfiles.c
--- objfiles.c	28 Jul 2009 16:39:06 -0000	1.88
+++ objfiles.c	4 Aug 2009 17:22:33 -0000
@@ -452,16 +452,7 @@ free_objfile (struct objfile *objfile)
   /* Discard any data modules have associated with the objfile.  */
   objfile_free_data (objfile);
 
-  /* We always close the bfd, unless the OBJF_KEEPBFD flag is set.  */
-
-  if (objfile->obfd != NULL && !(objfile->flags & OBJF_KEEPBFD))
-    {
-      char *name = bfd_get_filename (objfile->obfd);
-      if (!bfd_close (objfile->obfd))
-	warning (_("cannot close \"%s\": %s"),
-		 name, bfd_errmsg (bfd_get_error ()));
-      xfree (name);
-    }
+  gdb_bfd_unref (objfile->obfd);
 
   /* Remove it from the chain of all objfiles. */
 
@@ -1020,3 +1011,35 @@ objfiles_changed (void)
 {
   objfiles_changed_p = 1;  /* Rebuild section map next time we need it.  */
 }
+
+/* Unreference and possibly close abfd.  */
+void
+gdb_bfd_unref (struct bfd *abfd)
+{
+  int *p_refcount;
+  char *name;
+
+  if (abfd == NULL)
+    return;
+
+  p_refcount = abfd->usrdata;
+
+  /* Valid range for p_refcount: NULL (single owner), or a pointer
+     to int counter, which has a value of 1 (single owner) or 2 (shared).  */
+  gdb_assert (p_refcount == NULL || *p_refcount == 1 || *p_refcount == 2);
+
+  if (p_refcount != NULL)
+    {
+      *p_refcount -= 1;
+      if (*p_refcount > 0)
+	return;
+    }
+  xfree (p_refcount);
+  abfd->usrdata = NULL;  /* Paranoia.  */
+
+  name = bfd_get_filename (abfd);
+  if (!bfd_close (abfd))
+    warning (_("cannot close \"%s\": %s"),
+	     name, bfd_errmsg (bfd_get_error ()));
+  xfree (name);
+}
Index: solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.122
diff -u -p -u -r1.122 solib.c
--- solib.c	17 Jul 2009 17:08:23 -0000	1.122
+++ solib.c	4 Aug 2009 17:22:33 -0000
@@ -421,21 +421,11 @@ void
 free_so (struct so_list *so)
 {
   struct target_so_ops *ops = solib_ops (target_gdbarch);
-  char *bfd_filename = 0;
 
   if (so->sections)
     xfree (so->sections);
-      
-  if (so->abfd)
-    {
-      bfd_filename = bfd_get_filename (so->abfd);
-      if (! bfd_close (so->abfd))
-	warning (_("cannot close \"%s\": %s"),
-		 bfd_filename, bfd_errmsg (bfd_get_error ()));
-    }
 
-  if (bfd_filename)
-    xfree (bfd_filename);
+  gdb_bfd_unref (so->abfd);
 
   ops->free_so (so);
 
@@ -454,6 +444,7 @@ static void
 symbol_add_stub (struct so_list *so, int flags)
 {
   struct section_addr_info *sap;
+  int *p_refcount;
 
   /* Have we already loaded this shared object?  */
   ALL_OBJFILES (so->objfile)
@@ -465,8 +456,11 @@ symbol_add_stub (struct so_list *so, int
   sap = build_section_addr_info_from_section_table (so->sections,
                                                     so->sections_end);
 
-  so->objfile = symbol_file_add_from_bfd (so->abfd, flags,
-					  sap, OBJF_SHARED | OBJF_KEEPBFD);
+  so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED);
+  p_refcount = xmalloc (sizeof (*p_refcount));
+  *p_refcount = 2;  /* Both solib and objfile refer to this abfd.  */
+  so->abfd->usrdata = p_refcount;
+
   free_section_addr_info (sap);
 
   return;

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-04 17:37         ` Paul Pluzhnikov
@ 2009-08-04 18:40           ` Daniel Jacobowitz
  2009-08-04 18:47             ` Paul Pluzhnikov
  0 siblings, 1 reply; 13+ messages in thread
From: Daniel Jacobowitz @ 2009-08-04 18:40 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: tromey, gdb

On Tue, Aug 04, 2009 at 10:37:24AM -0700, Paul Pluzhnikov wrote:
> On Tue, Aug 4, 2009 at 7:53 AM, Daniel Jacobowitz<drow@false.org> wrote:
> 
> > A comment somewhere about the usage of the usrdata field would be
> > nice.  I gather that NULL and 1 behave the same?
> 
> Yes. I added comment to gdb_bfd_unref.
> Updated patch attached. Tested on Linux/x86_64 with no new failures.
> 
> Daniel, could you confirm that this fixes the ARM failures?

Yes - looks much better with this patch!

> 2009-08-04  Paul Pluzhnikov  <ppluzhnikov@google.com>
> 
>        * objfiles.h (OBJF_KEEPBFD): Delete.
>        (gdb_bfd_unref): New prototype.
>        * objfiles.c (gdb_bfd_unref): New function.
>        (free_objfile): Call gdb_bfd_unref.
>        * solib.c (free_so): Likewise.
>        (symbol_add_stub): Set refcount.

OK.

-- 
Daniel Jacobowitz
CodeSourcery


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-04 18:40           ` Daniel Jacobowitz
@ 2009-08-04 18:47             ` Paul Pluzhnikov
  2009-08-18  5:56               ` Paul Pluzhnikov
  0 siblings, 1 reply; 13+ messages in thread
From: Paul Pluzhnikov @ 2009-08-04 18:47 UTC (permalink / raw)
  To: Paul Pluzhnikov, tromey, gdb

On Tue, Aug 4, 2009 at 11:40 AM, Daniel Jacobowitz<drow@false.org> wrote:

>> Daniel, could you confirm that this fixes the ARM failures?
> Yes - looks much better with this patch!

So committed. Thanks,
-- 
Paul Pluzhnikov


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-04 18:47             ` Paul Pluzhnikov
@ 2009-08-18  5:56               ` Paul Pluzhnikov
  2009-08-19 22:29                 ` Tom Tromey
  0 siblings, 1 reply; 13+ messages in thread
From: Paul Pluzhnikov @ 2009-08-18  5:56 UTC (permalink / raw)
  To: Paul Pluzhnikov, tromey, gdb

[-- Attachment #1: Type: text/plain, Size: 1445 bytes --]

On Tue, Aug 4, 2009 at 11:47 AM, Paul Pluzhnikov<ppluzhnikov@google.com> wrote:

> So committed. Thanks,

I seem to have hit a rough patch with my patches :-(

The BFD refcounting patch from 2009-08-04 causes GDB to crash when I attach
to a process with many solibs, then (while GDB is reading solib symbols)
change my mind about attaching and hit Control-C, then 'run'.

This is happening because in symbol_add_stub refcount may not be set:

   so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED);

---> QUIT could be executed deep inside symbol_file_add_from_bfd, and
---> bfd_userdata below is never set.

   p_refcount = xmalloc (sizeof (*p_refcount));
   *p_refcount = 2;  /* Both solib and objfile refer to this abfd.  */
   bfd_usrdata (so->abfd) = p_refcount;

Later, we re-enter symbol_add_stub, and this:

   ALL_OBJFILES (so->objfile)
     {
       if (strcmp (so->objfile->name, so->so_name) == 0)
         return;

re-connects the so with the objfile, but never sets the bfd_usrdata.

Later still (during execution of 'run'), we go through clear_solib and
objfile_purge_solibs, and the latter crashes trying to bfd_close the abfd
which has already been bfd_close()d by the former.

Here is a proposed patch. Tested on Linux/x86_64 with no new failures.

Thanks,
-- 
Paul Pluzhnikov

2009-08-17  Paul Pluzhnikov  <ppluzhnikov@google.com>

	* solib.c (set_ref_count): New function.
	(symbol_add_stub): Call it.

[-- Attachment #2: gdb-bfd-ownership-20090817.txt --]
[-- Type: text/plain, Size: 1914 bytes --]

Index: solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.124
diff -u -p -u -r1.124 solib.c
--- solib.c	10 Aug 2009 22:09:22 -0000	1.124
+++ solib.c	17 Aug 2009 22:27:07 -0000
@@ -440,26 +440,53 @@ master_so_list (void)
   return so_list_head;
 }
 
+/* Set reference count on ABFD to COUNT.  */
+
+static void
+set_ref_count (struct bfd *abfd, int count)
+{
+  int *p_refcount = (int *) xmalloc (sizeof (*p_refcount));
+  *p_refcount = count;
+
+  gdb_assert (bfd_usrdata (abfd) == NULL);
+  bfd_usrdata (abfd) = p_refcount;
+}
+
 static void
 symbol_add_stub (struct so_list *so, int flags)
 {
   struct section_addr_info *sap;
-  int *p_refcount;
+  struct objfile *objfile;
 
   /* Have we already loaded this shared object?  */
-  ALL_OBJFILES (so->objfile)
+  ALL_OBJFILES (objfile)
     {
-      if (strcmp (so->objfile->name, so->so_name) == 0)
-	return;
+      if (strcmp (objfile->name, so->so_name) == 0)
+	{
+	  if (objfile != so->objfile)
+	    {
+	      /* This could happen when symbol_file_add_from_bfd
+		 below is interrupted.  */
+
+	      gdb_assert (so->objfile == NULL);
+	      gdb_assert (bfd_usrdata (so->abfd) == NULL);
+
+	      so->objfile = objfile;  /* Reconnect.  */
+
+	      /* Both solib and objfile refer to this abfd.  */
+	      set_ref_count (so->abfd, 2);
+	    }
+	  return;
+	}
     }
 
   sap = build_section_addr_info_from_section_table (so->sections,
                                                     so->sections_end);
 
   so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED);
-  p_refcount = xmalloc (sizeof (*p_refcount));
-  *p_refcount = 2;  /* Both solib and objfile refer to this abfd.  */
-  bfd_usrdata (so->abfd) = p_refcount;
+
+  /* Both solib and objfile refer to this abfd.  */
+  set_ref_count (so->abfd, 2);
 
   free_section_addr_info (sap);
 

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-18  5:56               ` Paul Pluzhnikov
@ 2009-08-19 22:29                 ` Tom Tromey
  2009-08-20  1:50                   ` Paul Pluzhnikov
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2009-08-19 22:29 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb

>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:

Paul> I seem to have hit a rough patch with my patches :-(

Yeah, that happens to me too.

Paul> This is happening because in symbol_add_stub refcount may not be set:
so-> objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED);
---> QUIT could be executed deep inside symbol_file_add_from_bfd, and
---> bfd_userdata below is never set.

Paul>    p_refcount = xmalloc (sizeof (*p_refcount));
Paul>    *p_refcount = 2;  /* Both solib and objfile refer to this abfd.  */
Paul>    bfd_usrdata (so->abfd) = p_refcount;

I haven't had time to read this patch fully and try to understand it.

It just struck me from a first reading that it would be simpler, and
more conventional, to have a "gdb_bfd_ref" function, to go along with
gdb_bfd_unref, which we call whenever we assign a 'bfd*' to a field
somewhere.

What do you think?

Tom


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-19 22:29                 ` Tom Tromey
@ 2009-08-20  1:50                   ` Paul Pluzhnikov
  2009-08-21 17:32                     ` Tom Tromey
  0 siblings, 1 reply; 13+ messages in thread
From: Paul Pluzhnikov @ 2009-08-20  1:50 UTC (permalink / raw)
  To: Tom Tromey; +Cc: gdb

[-- Attachment #1: Type: text/plain, Size: 1196 bytes --]

On Wed, Aug 19, 2009 at 3:11 PM, Tom Tromey<tromey@redhat.com> wrote:

> Paul>      *p_refcount = 2;  /* Both solib and objfile refer to this abfd.  */
> Paul>      bfd_usrdata (so->abfd) = p_refcount;
>
> I haven't had time to read this patch fully and try to understand it.
>
> It just struck me from a first reading that it would be simpler, and
> more conventional, to have a "gdb_bfd_ref" function, to go along with
> gdb_bfd_unref, which we call whenever we assign a 'bfd*' to a field
> somewhere.

It would be slightly wasteful to set refcount to 1 everywhere, since solib
is the only place where sharing could (currently) occur.

But maybe it *is* a good idea anyway. Here is a proposed fix.
Tested on Linux/x86_64 with no new failures. Also tested to fix the crash
I observed.

Thanks,
-- 
Paul Pluzhnikov

2009-08-19  Paul Pluzhnikov  <ppluzhnikov@google.com>

	* objfiles.h (gdb_bfd_ref): New prototype.
	* objfiles.c (gdb_bfd_ref): New function.
	(allocate_objfile): Call it.
	(gdb_bfd_unref): Adjust assertion.
	* solib.c (solib_map_sections): Add reference.
	(symbol_add_stub): Don't add reference here.
	* symfile.c (reread_symbols): Add reference.

[-- Attachment #2: gdb-bfd-ownership-20090819.txt --]
[-- Type: text/plain, Size: 4362 bytes --]

Index: objfiles.h
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.h,v
retrieving revision 1.61
diff -u -p -u -r1.61 objfiles.h
--- objfiles.h	4 Aug 2009 18:46:05 -0000	1.61
+++ objfiles.h	19 Aug 2009 23:30:43 -0000
@@ -505,6 +505,7 @@ extern void set_objfile_data (struct obj
 extern void *objfile_data (struct objfile *objfile,
 			   const struct objfile_data *data);
 
+extern struct bfd *gdb_bfd_ref (struct bfd *abfd);
 extern void gdb_bfd_unref (struct bfd *abfd);
 \f
 
Index: objfiles.c
===================================================================
RCS file: /cvs/src/src/gdb/objfiles.c,v
retrieving revision 1.92
diff -u -p -u -r1.92 objfiles.c
--- objfiles.c	17 Aug 2009 11:16:13 -0000	1.92
+++ objfiles.c	19 Aug 2009 23:30:43 -0000
@@ -181,7 +181,7 @@ allocate_objfile (bfd *abfd, int flags)
      that any data that is reference is saved in the per-objfile data
      region. */
 
-  objfile->obfd = abfd;
+  objfile->obfd = gdb_bfd_ref (abfd);
   if (objfile->name != NULL)
     {
       xfree (objfile->name);
@@ -1062,7 +1062,26 @@ objfiles_changed (void)
   objfiles_changed_p = 1;  /* Rebuild section map next time we need it.  */
 }
 
-/* Unreference and possibly close abfd.  */
+/* Add reference to ABFD.  Returns ABFD.  */
+struct bfd *
+gdb_bfd_ref (struct bfd *abfd)
+{
+  int *p_refcount = bfd_usrdata (abfd);
+
+  if (p_refcount != NULL)
+    {
+      *p_refcount += 1;
+      return abfd;
+    }
+
+  p_refcount = xmalloc (sizeof (*p_refcount));
+  *p_refcount = 1;
+  bfd_usrdata (abfd) = p_refcount;
+
+  return abfd;
+}
+
+/* Unreference and possibly close ABFD.  */
 void
 gdb_bfd_unref (struct bfd *abfd)
 {
@@ -1074,16 +1093,14 @@ gdb_bfd_unref (struct bfd *abfd)
 
   p_refcount = bfd_usrdata (abfd);
 
-  /* Valid range for p_refcount: NULL (single owner), or a pointer
-     to int counter, which has a value of 1 (single owner) or 2 (shared).  */
-  gdb_assert (p_refcount == NULL || *p_refcount == 1 || *p_refcount == 2);
+  /* Valid range for p_refcount: a pointer to int counter, which has a
+     value of 1 (single owner) or 2 (shared).  */
+  gdb_assert (*p_refcount == 1 || *p_refcount == 2);
+
+  *p_refcount -= 1;
+  if (*p_refcount > 0)
+    return;
 
-  if (p_refcount != NULL)
-    {
-      *p_refcount -= 1;
-      if (*p_refcount > 0)
-	return;
-    }
   xfree (p_refcount);
   bfd_usrdata (abfd) = NULL;  /* Paranoia.  */
 
Index: solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.124
diff -u -p -u -r1.124 solib.c
--- solib.c	10 Aug 2009 22:09:22 -0000	1.124
+++ solib.c	19 Aug 2009 23:30:44 -0000
@@ -361,7 +361,7 @@ solib_map_sections (void *arg)
   do_cleanups (old_chain);
 
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
-  so->abfd = abfd;
+  so->abfd = gdb_bfd_ref (abfd);
 
   /* copy full path name into so_name, so that later symbol_file_add
      can find it */
@@ -444,7 +444,6 @@ static void
 symbol_add_stub (struct so_list *so, int flags)
 {
   struct section_addr_info *sap;
-  int *p_refcount;
 
   /* Have we already loaded this shared object?  */
   ALL_OBJFILES (so->objfile)
@@ -457,10 +456,6 @@ symbol_add_stub (struct so_list *so, int
                                                     so->sections_end);
 
   so->objfile = symbol_file_add_from_bfd (so->abfd, flags, sap, OBJF_SHARED);
-  p_refcount = xmalloc (sizeof (*p_refcount));
-  *p_refcount = 2;  /* Both solib and objfile refer to this abfd.  */
-  bfd_usrdata (so->abfd) = p_refcount;
-
   free_section_addr_info (sap);
 
   return;
Index: symfile.c
===================================================================
RCS file: /cvs/src/src/gdb/symfile.c,v
retrieving revision 1.243
diff -u -p -u -r1.243 symfile.c
--- symfile.c	17 Aug 2009 20:09:38 -0000	1.243
+++ symfile.c	19 Aug 2009 23:30:45 -0000
@@ -2333,6 +2333,8 @@ reread_symbols (void)
 		objfile->obfd = bfd_openr (obfd_filename, gnutarget);
 	      if (objfile->obfd == NULL)
 		error (_("Can't open %s to read symbols."), objfile->name);
+	      else
+		objfile->obfd = gdb_bfd_ref (objfile->obfd);
 	      /* bfd_openr sets cacheable to true, which is what we want.  */
 	      if (!bfd_check_format (objfile->obfd, bfd_object))
 		error (_("Can't read symbols from %s: %s."), objfile->name,

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-20  1:50                   ` Paul Pluzhnikov
@ 2009-08-21 17:32                     ` Tom Tromey
  2009-08-21 18:04                       ` Paul Pluzhnikov
  0 siblings, 1 reply; 13+ messages in thread
From: Tom Tromey @ 2009-08-21 17:32 UTC (permalink / raw)
  To: Paul Pluzhnikov; +Cc: gdb

>>>>> "Paul" == Paul Pluzhnikov <ppluzhnikov@google.com> writes:

Paul> It would be slightly wasteful to set refcount to 1 everywhere,
Paul> since solib is the only place where sharing could (currently)
Paul> occur.

Yeah, I suppose.  But it seems clearer and more future-proof to me.

Paul> 2009-08-19  Paul Pluzhnikov  <ppluzhnikov@google.com>
Paul> 	* objfiles.h (gdb_bfd_ref): New prototype.
Paul> 	* objfiles.c (gdb_bfd_ref): New function.
Paul> 	(allocate_objfile): Call it.
Paul> 	(gdb_bfd_unref): Adjust assertion.
Paul> 	* solib.c (solib_map_sections): Add reference.
Paul> 	(symbol_add_stub): Don't add reference here.
Paul> 	* symfile.c (reread_symbols): Add reference.

This is ok.  Thanks.

Paul> +  gdb_assert (*p_refcount == 1 || *p_refcount == 2);

This assertion is a bit strange, but I suppose it is harmless.  If we
ever want more sharing, we can always just remove it.  In the meantime I
suppose it is checking that we don't over-share somehow.

Tom


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: Solibs and objfile BFD ownership
  2009-08-21 17:32                     ` Tom Tromey
@ 2009-08-21 18:04                       ` Paul Pluzhnikov
  0 siblings, 0 replies; 13+ messages in thread
From: Paul Pluzhnikov @ 2009-08-21 18:04 UTC (permalink / raw)
  To: tromey; +Cc: gdb

On Fri, Aug 21, 2009 at 10:29 AM, Tom Tromey<tromey@redhat.com> wrote:

> This is ok.   Thanks.

So committed.

> Paul> +   gdb_assert (*p_refcount == 1 || *p_refcount == 2);
>
> This assertion is a bit strange, but I suppose it is harmless.   If we
> ever want more sharing, we can always just remove it.   In the meantime I
> suppose it is checking that we don't over-share somehow.

The assertion was intended to catch somebody else in GDB using bfd_usrdata
for some other purpose (in a way I didn't find).

I think it's safe to leave it in for now.

Thanks,
-- 
Paul Pluzhnikov


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2009-08-21 17:57 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-07-28 15:40 Solibs and objfile BFD ownership Daniel Jacobowitz
2009-07-29 23:56 ` Paul Pluzhnikov
2009-07-30 16:16   ` Tom Tromey
2009-08-04  0:50     ` Paul Pluzhnikov
2009-08-04 14:53       ` Daniel Jacobowitz
2009-08-04 17:37         ` Paul Pluzhnikov
2009-08-04 18:40           ` Daniel Jacobowitz
2009-08-04 18:47             ` Paul Pluzhnikov
2009-08-18  5:56               ` Paul Pluzhnikov
2009-08-19 22:29                 ` Tom Tromey
2009-08-20  1:50                   ` Paul Pluzhnikov
2009-08-21 17:32                     ` Tom Tromey
2009-08-21 18:04                       ` Paul Pluzhnikov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox