This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[Patch]: Handle nested archives (in bfd)
- From: Tristan Gingold <gingold at adacore dot com>
- To: binutils Development <binutils at sourceware dot org>
- Date: Wed, 4 Jan 2012 15:23:56 +0100
- Subject: [Patch]: Handle nested archives (in bfd)
Hi,
with Mach-O, nested archives become a reality:
it is possible (and this is used by Apple) to have a fat binary composed of libraries.
As we represent fat binary as an archive, this become nested archives in BFD.
But this doesn't work as is now.
First there are some obvious changes for bfd_tell/bfd_seek and in cache.c to handle several levels.
Second, there were some code in archive.c that deal with nested archive, but assume that archives were of the same kind. Was not true in my case and resulted in a crash. I remove this code, and as a result homogenous nested archives won't share the cache of the greatest parent. I suppose nobody will notice the difference in memory usage given that bfd_seek/tell issue make me think nested archives weren't used.
No regression for x86_64 gnu/linux.
Ok for trunk ?
Tristan.
bfd/
2012-01-04 Tristan Gingold <gingold@adacore.com>
* bfdio.c (bfd_tell): Handle nested archives.
(bfd_seek): Ditto.
* cache.c (bfd_cache_lookup_worker): Ditto.
* archive.c (_bfd_get_elt_at_filepos): Remove code dealing with
nested archives.
(bfd_generic_openr_next_archived_file): Likewise.
diff --git a/bfd/archive.c b/bfd/archive.c
index 3e333c7..ac2be3e 100644
--- a/bfd/archive.c
+++ b/bfd/archive.c
@@ -581,12 +581,6 @@ _bfd_get_elt_at_filepos (bfd *archive, file_ptr filepos)
bfd *n_nfd;
char *filename;
- if (archive->my_archive)
- {
- filepos += archive->origin;
- archive = archive->my_archive;
- }
-
n_nfd = _bfd_look_for_bfd_in_cache (archive, filepos);
if (n_nfd)
return n_nfd;
@@ -732,8 +726,6 @@ bfd_generic_openr_next_archived_file (bfd *archive, bfd *last_file)
filestart = last_file->proxy_origin;
if (! bfd_is_thin_archive (archive))
filestart += size;
- if (archive->my_archive)
- filestart -= archive->origin;
/* Pad to an even boundary...
Note that last_file->origin can be odd in the case of
BSD-4.4-style element with a long odd size. */
diff --git a/bfd/bfdio.c b/bfd/bfdio.c
index f8c9f3e..c142c17 100644
--- a/bfd/bfdio.c
+++ b/bfd/bfdio.c
@@ -233,10 +233,14 @@ bfd_tell (bfd *abfd)
if (abfd->iovec)
{
+ bfd *parent_bfd = abfd;
ptr = abfd->iovec->btell (abfd);
- if (abfd->my_archive)
- ptr -= abfd->origin;
+ while (parent_bfd->my_archive != NULL)
+ {
+ ptr -= parent_bfd->origin;
+ parent_bfd = parent_bfd->my_archive;
+ }
}
else
ptr = 0;
@@ -308,8 +312,16 @@ bfd_seek (bfd *abfd, file_ptr position, int direction)
}
file_position = position;
- if (direction == SEEK_SET && abfd->my_archive != NULL)
- file_position += abfd->origin;
+ if (direction == SEEK_SET)
+ {
+ bfd *parent_bfd = abfd;
+
+ while (parent_bfd->my_archive != NULL)
+ {
+ file_position += parent_bfd->origin;
+ parent_bfd = parent_bfd->my_archive;
+ }
+ }
if (abfd->iovec)
result = abfd->iovec->bseek (abfd, file_position, direction);
diff --git a/bfd/cache.c b/bfd/cache.c
index 5ddbbe4..3842f51 100644
--- a/bfd/cache.c
+++ b/bfd/cache.c
@@ -198,7 +198,7 @@ bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag)
if ((abfd->flags & BFD_IN_MEMORY) != 0)
abort ();
- if (abfd->my_archive)
+ while (abfd->my_archive)
abfd = abfd->my_archive;
if (abfd->iostream != NULL)