diff options
author | Alan Modra <amodra@gmail.com> | 2012-08-09 06:25:53 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2012-08-09 06:25:53 +0000 |
commit | eeb1f9aea6773f39b281b43600d38ec0aa3fed6d (patch) | |
tree | d361dc01b6b1cfa93f129aab36f4c8a75d5a58bd /bfd/archive.c | |
parent | 2588feef114cd2dc404453c36827e32b40ccc143 (diff) | |
download | gdb-eeb1f9aea6773f39b281b43600d38ec0aa3fed6d.zip gdb-eeb1f9aea6773f39b281b43600d38ec0aa3fed6d.tar.gz gdb-eeb1f9aea6773f39b281b43600d38ec0aa3fed6d.tar.bz2 |
* 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.
Diffstat (limited to 'bfd/archive.c')
-rw-r--r-- | bfd/archive.c | 86 |
1 files changed, 69 insertions, 17 deletions
diff --git a/bfd/archive.c b/bfd/archive.c index 1148c11..dc67da7 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) { @@ -375,6 +368,10 @@ _bfd_add_bfd_to_archive_cache (bfd *arch_bfd, file_ptr filepos, bfd *new_elt) 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; +} |