| Index: bfd/archive.c
|
| diff --git a/bfd/archive.c b/bfd/archive.c
|
| index fe57755770bbbfc43be705fb5c437dd8619dff7d..32b07a718a2b9825c41885572dbd544d6803c16f 100644
|
| --- a/bfd/archive.c
|
| +++ b/bfd/archive.c
|
| @@ -1,7 +1,5 @@
|
| /* BFD back-end for archive files (libraries).
|
| - Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
|
| - 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011,
|
| - 2012 Free Software Foundation, Inc.
|
| + Copyright 1990-2013 Free Software Foundation, Inc.
|
| Written by Cygnus Support. Mostly Gumby Henkel-Wallace's fault.
|
|
|
| This file is part of BFD, the Binary File Descriptor library.
|
| @@ -42,11 +40,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
|
| @@ -362,6 +366,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;
|
| }
|
|
|
| @@ -371,6 +379,13 @@ _bfd_find_nested_archive (bfd *arch_bfd, const char *filename)
|
| bfd *abfd;
|
| const char *target;
|
|
|
| + /* PR 15140: Don't allow a nested archive pointing to itself. */
|
| + if (filename_cmp (filename, arch_bfd->filename) == 0)
|
| + {
|
| + bfd_set_error (bfd_error_malformed_archive);
|
| + return NULL;
|
| + }
|
| +
|
| for (abfd = arch_bfd->nested_archives;
|
| abfd != NULL;
|
| abfd = abfd->archive_next)
|
| @@ -507,7 +522,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
|
| parsed_size -= namelen;
|
| extra_size = namelen;
|
|
|
| - allocptr = (char *) bfd_zalloc (abfd, allocsize);
|
| + allocptr = (char *) bfd_zmalloc (allocsize);
|
| if (allocptr == NULL)
|
| return NULL;
|
| filename = (allocptr
|
| @@ -515,6 +530,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
|
| + sizeof (struct ar_hdr));
|
| if (bfd_bread (filename, namelen, abfd) != namelen)
|
| {
|
| + free (allocptr);
|
| if (bfd_get_error () != bfd_error_system_call)
|
| bfd_set_error (bfd_error_no_more_archived_files);
|
| return NULL;
|
| @@ -550,7 +566,7 @@ _bfd_generic_read_ar_hdr_mag (bfd *abfd, const char *mag)
|
|
|
| if (!allocptr)
|
| {
|
| - allocptr = (char *) bfd_zalloc (abfd, allocsize);
|
| + allocptr = (char *) bfd_zmalloc (allocsize);
|
| if (allocptr == NULL)
|
| return NULL;
|
| }
|
| @@ -633,7 +649,10 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
| {
|
| filename = _bfd_append_relative_path (archive, filename);
|
| if (filename == NULL)
|
| - return NULL;
|
| + {
|
| + free (new_areldata);
|
| + return NULL;
|
| + }
|
| }
|
|
|
| if (new_areldata->origin > 0)
|
| @@ -645,13 +664,13 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
| if (ext_arch == NULL
|
| || ! bfd_check_format (ext_arch, bfd_archive))
|
| {
|
| - bfd_release (archive, new_areldata);
|
| + free (new_areldata);
|
| return NULL;
|
| }
|
| n_nfd = _bfd_get_elt_at_filepos (ext_arch, new_areldata->origin);
|
| if (n_nfd == NULL)
|
| {
|
| - bfd_release (archive, new_areldata);
|
| + free (new_areldata);
|
| return NULL;
|
| }
|
| n_nfd->proxy_origin = bfd_tell (archive);
|
| @@ -673,7 +692,7 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
|
|
| if (n_nfd == NULL)
|
| {
|
| - bfd_release (archive, new_areldata);
|
| + free (new_areldata);
|
| return NULL;
|
| }
|
|
|
| @@ -697,7 +716,8 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
|
| if (_bfd_add_bfd_to_archive_cache (archive, filepos, n_nfd))
|
| return n_nfd;
|
|
|
| - bfd_release (archive, new_areldata);
|
| + free (new_areldata);
|
| + n_nfd->arelt_data = NULL;
|
| return NULL;
|
| }
|
|
|
| @@ -837,11 +857,7 @@ bfd_generic_archive_p (bfd *abfd)
|
| first->target_defaulted = FALSE;
|
| if (bfd_check_format (first, bfd_object)
|
| && first->xvec != abfd->xvec)
|
| - {
|
| - bfd_set_error (bfd_error_wrong_object_format);
|
| - bfd_ardata (abfd) = tdata_hold;
|
| - return NULL;
|
| - }
|
| + bfd_set_error (bfd_error_wrong_object_format);
|
| /* And we ought to close `first' here too. */
|
| }
|
| }
|
| @@ -884,7 +900,7 @@ do_slurp_bsd_armap (bfd *abfd)
|
| if (mapdata == NULL)
|
| return FALSE;
|
| parsed_size = mapdata->parsed_size;
|
| - bfd_release (abfd, mapdata); /* Don't need it any more. */
|
| + free (mapdata);
|
|
|
| raw_armap = (bfd_byte *) bfd_zalloc (abfd, parsed_size);
|
| if (raw_armap == NULL)
|
| @@ -960,7 +976,7 @@ do_slurp_coff_armap (bfd *abfd)
|
| if (mapdata == NULL)
|
| return FALSE;
|
| parsed_size = mapdata->parsed_size;
|
| - bfd_release (abfd, mapdata); /* Don't need it any more. */
|
| + free (mapdata);
|
|
|
| if (bfd_bread (int_buf, 4, abfd) != 4)
|
| {
|
| @@ -1053,7 +1069,7 @@ do_slurp_coff_armap (bfd *abfd)
|
| ardata->first_file_filepos +=
|
| (tmp->parsed_size + sizeof (struct ar_hdr) + 1) & ~(unsigned) 1;
|
| }
|
| - bfd_release (abfd, tmp);
|
| + free (tmp);
|
| }
|
| }
|
|
|
| @@ -1170,15 +1186,17 @@ bfd_slurp_bsd_armap_f2 (bfd *abfd)
|
|
|
| if (mapdata->parsed_size < HPUX_SYMDEF_COUNT_SIZE + BSD_STRING_COUNT_SIZE)
|
| {
|
| + free (mapdata);
|
| wrong_format:
|
| bfd_set_error (bfd_error_wrong_format);
|
| byebye:
|
| - bfd_release (abfd, mapdata);
|
| return FALSE;
|
| }
|
| left = mapdata->parsed_size - HPUX_SYMDEF_COUNT_SIZE - BSD_STRING_COUNT_SIZE;
|
|
|
| amt = mapdata->parsed_size;
|
| + free (mapdata);
|
| +
|
| raw_armap = (bfd_byte *) bfd_zalloc (abfd, amt);
|
| if (raw_armap == NULL)
|
| goto byebye;
|
| @@ -1280,7 +1298,7 @@ _bfd_slurp_extended_name_table (bfd *abfd)
|
| if (bfd_ardata (abfd)->extended_names == NULL)
|
| {
|
| byebye:
|
| - bfd_release (abfd, namedata);
|
| + free (namedata);
|
| return FALSE;
|
| }
|
|
|
| @@ -1317,8 +1335,7 @@ _bfd_slurp_extended_name_table (bfd *abfd)
|
| bfd_ardata (abfd)->first_file_filepos +=
|
| (bfd_ardata (abfd)->first_file_filepos) % 2;
|
|
|
| - /* FIXME, we can't release namedata here because it was allocated
|
| - below extended_names on the objalloc... */
|
| + free (namedata);
|
| }
|
| return TRUE;
|
| }
|
| @@ -1886,7 +1903,7 @@ bfd_ar_hdr_from_filesystem (bfd *abfd, const char *filename, bfd *member)
|
| }
|
|
|
| amt = sizeof (struct ar_hdr) + sizeof (struct areltdata);
|
| - ared = (struct areltdata *) bfd_zalloc (abfd, amt);
|
| + ared = (struct areltdata *) bfd_zmalloc (amt);
|
| if (ared == NULL)
|
| return NULL;
|
| hdr = (struct ar_hdr *) (((char *) ared) + sizeof (struct areltdata));
|
| @@ -2408,9 +2425,6 @@ bsd_write_armap (bfd *arch,
|
| unsigned int count;
|
| struct ar_hdr hdr;
|
| long uid, gid;
|
| - file_ptr max_first_real = 1;
|
| -
|
| - max_first_real <<= 31;
|
|
|
| firstreal = mapsize + elength + sizeof (struct ar_hdr) + SARMAG;
|
|
|
| @@ -2453,6 +2467,7 @@ bsd_write_armap (bfd *arch,
|
|
|
| for (count = 0; count < orl_count; count++)
|
| {
|
| + unsigned int offset;
|
| bfd_byte buf[BSD_SYMDEF_SIZE];
|
|
|
| if (map[count].u.abfd != last_elt)
|
| @@ -2472,12 +2487,13 @@ bsd_write_armap (bfd *arch,
|
| /* The archive file format only has 4 bytes to store the offset
|
| of the member. Check to make sure that firstreal has not grown
|
| too big. */
|
| - if (firstreal >= max_first_real)
|
| + offset = (unsigned int) firstreal;
|
| + if (firstreal != (file_ptr) offset)
|
| {
|
| bfd_set_error (bfd_error_file_truncated);
|
| return FALSE;
|
| }
|
| -
|
| +
|
| last_elt = current;
|
| H_PUT_32 (arch, map[count].namidx, buf);
|
| H_PUT_32 (arch, firstreal, buf + BSD_SYMDEF_OFFSET_SIZE);
|
| @@ -2682,3 +2698,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;
|
| + }
|
| + }
|
| + 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;
|
| +}
|
|
|