From: Tom Tromey <tromey@redhat.com>
To: Binutils Development <binutils@sourceware.org>
Subject: Re: [PATCH 3/5] remove deleted BFDs from the archive cache
Date: Wed, 08 Aug 2012 22:47:00 -0000 [thread overview]
Message-ID: <87hasdgv0h.fsf@fleche.redhat.com> (raw)
In-Reply-To: <20120803160934.GE4430@bubble.grove.modra.org> (Alan Modra's message of "Sat, 4 Aug 2012 01:39:34 +0930")
>>>>> "Alan" == Alan Modra <amodra@gmail.com> writes:
Alan> Here's something I hacked together to go a little further than your
Alan> patch and actually close archive member bfds when the archive is
Alan> closed. You'll see I solved the problem of looking up the member BFD
Alan> by saving the filepos in arelt_data. What I haven't done is make this
Alan> all work with thin archives, but that shouldn't be too hard.
Alan> Just a matter of adding a field to struct areltdata instead of
Alan> reusing "origin", and solving the fact that my_archive isn't set for
Alan> thin archives, I think. Care to run with this?
Here's a revised patch.
This patch rolls my various remaining patches into one. I think it
remains pretty clear now.
It adds a couple of new fields to areltdata -- the origin for the
purposes of the cache, and the containing thin archive. I looked a
little at reusing my_archive for thin archives, but this seemed complex.
I tested this under valgrind using a little program that opens an
archive and iterates over the contents, closing each member in turn.
Before the patch, I could provoke either memory leaks or crashes; but
now it is all clean. I ran the test program on itself (to test the
non-archive case), an ordinary archive, a thin archive, and a thin
archive containing a nested archive. I can send the test program if you
want.
Alan, in a private note you mentioned using bfd_read_p in the check in
_bfd_archive_close_and_cleanup. I didn't understand this, so I left it out;
but I can certainly add it if you think it necessary.
Ok?
Tom
2012-08-08 Alan Modra <amodra@gmail.com>
Tom Tromey <tromey@redhat.com>
* archive.c (SECTION Archives): Update documentation.
(_bfd_delete_archive_data): Remove.
(_bfd_get_elt_at_filepos): Set 'thin_archive' and
'cache_origin' fields on new_areldata.
(archive_close_worker, _bfd_archive_close_and_cleanup): New
functions.
* libbfd-in.h (struct areltdata) <cache_origin, thin_archive>:
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.
diff --git a/bfd/archive.c b/bfd/archive.c
index 1148c11..1b19f00 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -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_archive, bfd *new_head)
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)
{
@@ -678,6 +671,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
n_nfd = bfd_openr (filename, target);
if (n_nfd == NULL)
bfd_set_error (bfd_error_malformed_archive);
+ new_areldata->thin_archive = archive;
}
else
{
@@ -702,6 +696,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
n_nfd->filename = filename;
}
+ new_areldata->cache_origin = filepos;
n_nfd->arelt_data = new_areldata;
/* Copy BFD_COMPRESS and BFD_DECOMPRESS flags. */
@@ -2695,3 +2690,68 @@ 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)
+{
+ bfd *archive;
+
+ if (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;
+ }
+ }
+
+ if (abfd->my_archive != NULL)
+ archive = abfd->my_archive;
+ else if (arch_eltdata (abfd) != NULL
+ && arch_eltdata (abfd)->thin_archive != NULL)
+ archive = arch_eltdata (abfd)->thin_archive;
+ else
+ archive = NULL;
+ if (archive != NULL)
+ {
+ htab_t htab = bfd_ardata (archive)->cache;
+
+ if (htab)
+ {
+ struct ar_cache ent;
+ void **slot;
+ struct areltdata *ared = arch_eltdata (abfd);
+
+ ent.ptr = ared->cache_origin;
+ 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;
+}
diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h
index 8cdb1c6..a557e36 100644
--- a/bfd/libbfd-in.h
+++ b/bfd/libbfd-in.h
@@ -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. */
+ file_ptr cache_origin; /* Origin as recorded in the archive cache. */
+ struct bfd *thin_archive; /* The containing thin archive. */
};
#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 *);
diff --git a/bfd/libbfd.h b/bfd/libbfd.h
index a1e544f..6b7055a 100644
--- a/bfd/libbfd.h
+++ b/bfd/libbfd.h
@@ -101,6 +101,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. */
+ file_ptr cache_origin; /* Origin as recorded in the archive cache. */
+ struct bfd *thin_archive; /* The containing thin archive. */
};
#define arelt_size(bfd) (((struct areltdata *)((bfd)->arelt_data))->parsed_size)
@@ -135,8 +137,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
@@ -237,7 +237,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 *);
diff --git a/bfd/opncls.c b/bfd/opncls.c
index e538981..b2ed9be 100644
--- a/bfd/opncls.c
+++ b/bfd/opncls.c
@@ -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;
next prev parent reply other threads:[~2012-08-08 17:21 UTC|newest]
Thread overview: 48+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-08-03 14:55 Tom Tromey
2012-08-03 16:12 ` Alan Modra
2012-08-03 20:56 ` Tom Tromey
2012-08-08 22:47 ` Tom Tromey [this message]
2012-08-09 10:35 ` Alan Modra
2012-08-15 20:14 ` H.J. Lu
2012-08-15 21:30 ` Tom Tromey
2012-08-16 14:47 ` Alan Modra
2012-08-16 16:31 ` H.J. Lu
2012-08-16 18:14 ` Tom Tromey
2012-08-16 18:33 ` H.J. Lu
2012-08-16 18:45 ` Tom Tromey
2012-08-16 18:49 ` H.J. Lu
2012-08-16 18:55 ` Tom Tromey
2012-08-16 20:33 ` Tom Tromey
2012-08-16 20:38 ` H.J. Lu
2012-08-16 21:11 ` H.J. Lu
2012-08-16 21:35 ` H.J. Lu
2012-08-17 1:01 ` Alan Modra
2012-08-17 1:06 ` H.J. Lu
2012-08-17 2:44 ` Alan Modra
2012-08-17 4:56 ` Hans-Peter Nilsson
2012-08-17 5:04 ` Alan Modra
2012-08-17 5:08 ` H.J. Lu
2012-08-17 5:30 ` H.J. Lu
2012-08-17 5:42 ` H.J. Lu
2012-08-17 5:45 ` H.J. Lu
2012-08-17 6:01 ` H.J. Lu
2012-08-17 13:10 ` H.J. Lu
2012-08-17 16:50 ` Hans-Peter Nilsson
2012-08-17 16:01 ` Hans-Peter Nilsson
2012-08-17 16:10 ` H.J. Lu
2012-08-17 16:14 ` Hans-Peter Nilsson
2012-08-17 16:13 ` Tom Tromey
2012-08-17 16:26 ` H.J. Lu
2012-08-17 16:51 ` Tom Tromey
2012-08-17 17:11 ` H.J. Lu
2012-08-17 17:22 ` Tom Tromey
2012-08-17 17:22 ` H.J. Lu
2012-08-17 19:03 ` Tom Tromey
2012-08-17 19:13 ` H.J. Lu
2012-08-18 4:37 ` Alan Modra
2012-08-21 9:55 ` Tom Tromey
2012-08-17 1:17 ` Alan Modra
2012-08-17 15:36 ` Tom Tromey
2012-08-17 15:38 ` H.J. Lu
2012-08-17 15:43 ` Tom Tromey
2012-08-17 0:48 ` H.J. Lu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87hasdgv0h.fsf@fleche.redhat.com \
--to=tromey@redhat.com \
--cc=binutils@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).