From: Alan Modra Date: Thu, 9 Aug 2012 06:25:53 +0000 (+0000) Subject: * archive.c (SECTION Archives): Update documentation. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=eeb1f9aea6773f39b281b43600d38ec0aa3fed6d;p=binutils-gdb.git * 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 ): 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. --- diff --git a/bfd/ChangeLog b/bfd/ChangeLog index da2a229eadc..3f40b9e7768 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,19 @@ +2012-08-09 Alan Modra + Tom Tromey + + * 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 ): 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. + 2012-08-07 Tom Tromey * archive.c (_bfd_delete_archive_data): New function. diff --git a/bfd/archive.c b/bfd/archive.c index 1148c115fd5..dc67da79e0c 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 <> can be + closed manually with <>. 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 - <> pointer in a BFD. The first one is findable through - the <> slot of the archive. Set it with - <> (q.v.). A given BFD may be in only one - open output archive at a time. + <> pointer in a BFD. The first one is findable + through the <> slot of the archive. Set it with + <> (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; +} diff --git a/bfd/libbfd-in.h b/bfd/libbfd-in.h index 8cdb1c65c36..80cb05104e0 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. */ + 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 *); diff --git a/bfd/libbfd.h b/bfd/libbfd.h index a1e544f75fe..03b065fd956 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. */ + void *parent_cache; /* Where and how to find this member. */ + file_ptr key; }; #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 e538981f6d8..b2ed9beb901 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;