This is the mail archive of the binutils@sourceware.org mailing list for the binutils 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]

Re: [PATCH 3/5] remove deleted BFDs from the archive cache


On Wed, Aug 08, 2012 at 11:21:02AM -0600, Tom Tromey wrote:
> Alan, in a private note you mentioned using bfd_read_p in the check in
> _bfd_archive_close_and_cleanup.

I'm reasonably sure that the code as it was doesn't mess with archive
bfds opened for writing, but wanted to make it obvious.  I've also
moved the code setting new areltdata fields (and renamed them) to
_bfd_add_bfd_to_archive_cache to make the code a bit tidier.
Committed.

2012-08-09  Alan Modra  <amodra@gmail.com>
	    Tom Tromey  <tromey@redhat.com>

	* archive.c (SECTION Archives): Update documentation.
	(_bfd_delete_archive_data): Remove.
	(_bfd_add_bfd_to_archive_cache): Set 'parent_cache' and 'key'.
	(archive_close_worker, _bfd_archive_close_and_cleanup): New
	functions.
	* libbfd-in.h (struct areltdata <parent_cache, key>): New fields.
	(_bfd_delete_archive_data): Don't declare.
	(_bfd_archive_close_and_cleanup): Declare.
	(_bfd_generic_close_and_cleanup): Redefine.
	* libbfd.h: Rebuild.
	* opncls.c (_bfd_delete_bfd): Don't call _bfd_delete_archive_data.
	(bfd_close): Don't close nested thin archives here.

Index: bfd/archive.c
===================================================================
RCS file: /cvs/src/src/bfd/archive.c,v
retrieving revision 1.88
diff -u -p -r1.88 archive.c
--- bfd/archive.c	7 Aug 2012 13:47:14 -0000	1.88
+++ bfd/archive.c	9 Aug 2012 04:51:31 -0000
@@ -42,11 +42,17 @@ DESCRIPTION
 	have to read the entire archive if you don't want
 	to!  Read it until you find what you want.
 
+	A BFD returned by <<bfd_openr_next_archived_file>> can be
+	closed manually with <<bfd_close>>.  If you do not close it,
+	then a second iteration through the members of an archive may
+	return the same BFD.  If you close the archive BFD, then all
+	the member BFDs will automatically be closed as well.
+
 	Archive contents of output BFDs are chained through the
-	<<next>> pointer in a BFD.  The first one is findable through
-	the <<archive_head>> slot of the archive.  Set it with
-	<<bfd_set_archive_head>> (q.v.).  A given BFD may be in only one
-	open output archive at a time.
+	<<archive_next>> pointer in a BFD.  The first one is findable
+	through the <<archive_head>> slot of the archive.  Set it with
+	<<bfd_set_archive_head>> (q.v.).  A given BFD may be in only
+	one open output archive at a time.
 
 	As expected, the BFD archive code is more general than the
 	archive code of any given environment.  BFD archives may
@@ -293,19 +299,6 @@ bfd_set_archive_head (bfd *output_archiv
   return TRUE;
 }
 
-/* Free the archive hash table, if it exists.  */
-
-void
-_bfd_delete_archive_data (bfd *abfd)
-{
-  struct artdata *ardata = bfd_ardata (abfd);
-
-  BFD_ASSERT (abfd->format == bfd_archive);
-
-  if (ardata && ardata->cache)
-    htab_delete (ardata->cache);
-}
-
 bfd *
 _bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos)
 {
@@ -375,6 +368,10 @@ _bfd_add_bfd_to_archive_cache (bfd *arch
   cache->arbfd = new_elt;
   *htab_find_slot (hash_table, (const void *) cache, INSERT) = cache;
 
+  /* Provide a means of accessing this from child.  */
+  arch_eltdata (new_elt)->parent_cache = hash_table;
+  arch_eltdata (new_elt)->key = filepos;
+
   return TRUE;
 }
 
@@ -2695,3 +2692,58 @@ coff_write_armap (bfd *arch,
 
   return TRUE;
 }
+
+static int
+archive_close_worker (void **slot, void *inf ATTRIBUTE_UNUSED)
+{
+  struct ar_cache *ent = (struct ar_cache *) *slot;
+
+  bfd_close_all_done (ent->arbfd);
+  return 1;
+}
+
+bfd_boolean
+_bfd_archive_close_and_cleanup (bfd *abfd)
+{
+  if (bfd_read_p (abfd) && abfd->format == bfd_archive)
+    {
+      bfd *nbfd;
+      bfd *next;
+      htab_t htab;
+
+      /* Close nested archives (if this bfd is a thin archive).  */
+      for (nbfd = abfd->nested_archives; nbfd; nbfd = next)
+	{
+	  next = nbfd->archive_next;
+	  bfd_close (nbfd);
+	}
+
+      htab = bfd_ardata (abfd)->cache;
+      if (htab)
+	{
+	  htab_traverse_noresize (htab, archive_close_worker, NULL);
+	  htab_delete (htab);
+	  bfd_ardata (abfd)->cache = NULL;
+	}
+    }
+  else if (arch_eltdata (abfd) != NULL)
+    {
+      struct areltdata *ared = arch_eltdata (abfd);
+      htab_t htab = (htab_t) ared->parent_cache;
+
+      if (htab)
+	{
+	  struct ar_cache ent;
+	  void **slot;
+
+	  ent.ptr = ared->key;
+	  slot = htab_find_slot (htab, &ent, NO_INSERT);
+	  if (slot != NULL)
+	    {
+	      BFD_ASSERT (((struct ar_cache *) *slot)->arbfd == abfd);
+	      htab_clear_slot (htab, slot);
+	    }
+	}
+    }
+  return TRUE;
+}
Index: bfd/libbfd-in.h
===================================================================
RCS file: /cvs/src/src/bfd/libbfd-in.h,v
retrieving revision 1.101
diff -u -p -r1.101 libbfd-in.h
--- bfd/libbfd-in.h	7 Aug 2012 13:47:14 -0000	1.101
+++ bfd/libbfd-in.h	9 Aug 2012 04:51:31 -0000
@@ -96,6 +96,8 @@ struct areltdata
   bfd_size_type extra_size;	/* BSD4.4: extra bytes after the header.  */
   char *filename;		/* Null-terminated.  */
   file_ptr origin;		/* For element of a thin archive.  */
+  void *parent_cache;		/* Where and how to find this member.  */
+  file_ptr key;
 };
 
 #define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
@@ -130,8 +132,6 @@ extern void bfd_release
 
 bfd * _bfd_create_empty_archive_element_shell
   (bfd *obfd);
-void _bfd_delete_archive_data
-  (bfd *abfd);
 bfd * _bfd_look_for_bfd_in_cache
   (bfd *, file_ptr);
 bfd_boolean _bfd_add_bfd_to_archive_cache
@@ -232,7 +232,9 @@ int bfd_generic_stat_arch_elt
 /* Generic routines to use for BFD_JUMP_TABLE_GENERIC.  Use
    BFD_JUMP_TABLE_GENERIC (_bfd_generic).  */
 
-#define _bfd_generic_close_and_cleanup bfd_true
+#define _bfd_generic_close_and_cleanup _bfd_archive_close_and_cleanup
+extern bfd_boolean _bfd_archive_close_and_cleanup
+  (bfd *);
 #define _bfd_generic_bfd_free_cached_info bfd_true
 extern bfd_boolean _bfd_generic_new_section_hook
   (bfd *, asection *);
Index: bfd/opncls.c
===================================================================
RCS file: /cvs/src/src/bfd/opncls.c,v
retrieving revision 1.71
diff -u -p -r1.71 opncls.c
--- bfd/opncls.c	7 Aug 2012 13:47:15 -0000	1.71
+++ bfd/opncls.c	9 Aug 2012 04:51:31 -0000
@@ -130,9 +130,6 @@ _bfd_new_bfd_contained_in (bfd *obfd)
 static void
 _bfd_delete_bfd (bfd *abfd)
 {
-  if (abfd->format == bfd_archive)
-    _bfd_delete_archive_data (abfd);
-
   if (abfd->memory)
     {
       bfd_hash_table_free (&abfd->section_htab);
@@ -711,8 +708,6 @@ bfd_boolean
 bfd_close (bfd *abfd)
 {
   bfd_boolean ret;
-  bfd *nbfd;
-  bfd *next;
 
   if (bfd_write_p (abfd))
     {
@@ -720,13 +715,6 @@ bfd_close (bfd *abfd)
 	return FALSE;
     }
 
-  /* Close nested archives (if this bfd is a thin archive).  */
-  for (nbfd = abfd->nested_archives; nbfd; nbfd = next)
-    {
-      next = nbfd->archive_next;
-      bfd_close (nbfd);
-    }
-
   if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
     return FALSE;
 

-- 
Alan Modra
Australia Development Lab, IBM


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