diff options
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; +} |