* 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>
* 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
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;
}

View file

@ -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 *);

View file

@ -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 *);

View file

@ -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;