This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]