* 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.
This commit is contained in:
Alan Modra 2012-08-09 06:25:53 +00:00
parent 2588feef11
commit eeb1f9aea6
5 changed files with 95 additions and 35 deletions

View file

@ -1,3 +1,19 @@
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.
2012-08-07 Tom Tromey <tromey@redhat.com> 2012-08-07 Tom Tromey <tromey@redhat.com>
* archive.c (_bfd_delete_archive_data): New function. * archive.c (_bfd_delete_archive_data): New function.

View file

@ -42,11 +42,17 @@ DESCRIPTION
have to read the entire archive if you don't want have to read the entire archive if you don't want
to! Read it until you find what you 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 Archive contents of output BFDs are chained through the
<<next>> pointer in a BFD. The first one is findable through <<archive_next>> pointer in a BFD. The first one is findable
the <<archive_head>> slot of the archive. Set it with 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 <<bfd_set_archive_head>> (q.v.). A given BFD may be in only
open output archive at a time. one open output archive at a time.
As expected, the BFD archive code is more general than the As expected, the BFD archive code is more general than the
archive code of any given environment. BFD archives may 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; 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 *
_bfd_look_for_bfd_in_cache (bfd *arch_bfd, file_ptr filepos) _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; cache->arbfd = new_elt;
*htab_find_slot (hash_table, (const void *) cache, INSERT) = cache; *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; return TRUE;
} }
@ -2695,3 +2692,58 @@ coff_write_armap (bfd *arch,
return TRUE; 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;
}

View file

@ -96,6 +96,8 @@ struct areltdata
bfd_size_type extra_size; /* BSD4.4: extra bytes after the header. */ bfd_size_type extra_size; /* BSD4.4: extra bytes after the header. */
char *filename; /* Null-terminated. */ char *filename; /* Null-terminated. */
file_ptr origin; /* For element of a thin archive. */ 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) #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 * _bfd_create_empty_archive_element_shell
(bfd *obfd); (bfd *obfd);
void _bfd_delete_archive_data
(bfd *abfd);
bfd * _bfd_look_for_bfd_in_cache bfd * _bfd_look_for_bfd_in_cache
(bfd *, file_ptr); (bfd *, file_ptr);
bfd_boolean _bfd_add_bfd_to_archive_cache 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 /* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use
BFD_JUMP_TABLE_GENERIC (_bfd_generic). */ 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 #define _bfd_generic_bfd_free_cached_info bfd_true
extern bfd_boolean _bfd_generic_new_section_hook extern bfd_boolean _bfd_generic_new_section_hook
(bfd *, asection *); (bfd *, asection *);

View file

@ -101,6 +101,8 @@ struct areltdata
bfd_size_type extra_size; /* BSD4.4: extra bytes after the header. */ bfd_size_type extra_size; /* BSD4.4: extra bytes after the header. */
char *filename; /* Null-terminated. */ char *filename; /* Null-terminated. */
file_ptr origin; /* For element of a thin archive. */ 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) #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 * _bfd_create_empty_archive_element_shell
(bfd *obfd); (bfd *obfd);
void _bfd_delete_archive_data
(bfd *abfd);
bfd * _bfd_look_for_bfd_in_cache bfd * _bfd_look_for_bfd_in_cache
(bfd *, file_ptr); (bfd *, file_ptr);
bfd_boolean _bfd_add_bfd_to_archive_cache 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 /* Generic routines to use for BFD_JUMP_TABLE_GENERIC. Use
BFD_JUMP_TABLE_GENERIC (_bfd_generic). */ 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 #define _bfd_generic_bfd_free_cached_info bfd_true
extern bfd_boolean _bfd_generic_new_section_hook extern bfd_boolean _bfd_generic_new_section_hook
(bfd *, asection *); (bfd *, asection *);

View file

@ -130,9 +130,6 @@ _bfd_new_bfd_contained_in (bfd *obfd)
static void static void
_bfd_delete_bfd (bfd *abfd) _bfd_delete_bfd (bfd *abfd)
{ {
if (abfd->format == bfd_archive)
_bfd_delete_archive_data (abfd);
if (abfd->memory) if (abfd->memory)
{ {
bfd_hash_table_free (&abfd->section_htab); bfd_hash_table_free (&abfd->section_htab);
@ -711,8 +708,6 @@ bfd_boolean
bfd_close (bfd *abfd) bfd_close (bfd *abfd)
{ {
bfd_boolean ret; bfd_boolean ret;
bfd *nbfd;
bfd *next;
if (bfd_write_p (abfd)) if (bfd_write_p (abfd))
{ {
@ -720,13 +715,6 @@ bfd_close (bfd *abfd)
return FALSE; 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))) if (! BFD_SEND (abfd, _close_and_cleanup, (abfd)))
return FALSE; return FALSE;