Bug 135 - bfd crashes when processing nested archives.
Summary: bfd crashes when processing nested archives.
Status: RESOLVED FIXED
Alias: None
Product: binutils
Classification: Unclassified
Component: binutils (show other bugs)
Version: 2.14
: P2 normal
Target Milestone: ---
Assignee: unassigned
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2004-04-27 13:41 UTC by Mikulas Patocka
Modified: 2004-05-19 21:52 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mikulas Patocka 2004-04-27 13:41:48 UTC
BFD 2.14 crashes when program is opening and operating on archives containing
other archives (with bfd_openr_next_archived_file).

The problems arise usually when there are too many open files and open file
caching takes effect.

At many places in code, there are constructs like
if (bfd->my_archive) offset += bfd->origin;
and similar.

The problem with these is that if bfd->my_archive is contained in some archive
too, you add only offset of inner archive, not offset of outer
archive. Similarly, in bfd_cache_lookup_worker you do
if (abfd->my_archive) abfd = abfd->my_archive; --- now if archives are nested,
you need to get to the topmost archive.

The crash becomes because of this and other bug --- bfd cache doesn't check if
files was reopened succesfully --- see my next bug report.

The attached patch fixes the problems with nested archives --- it modifies
archive creating so that bfd->my_archive always points to the topmost
archive, not to the immediate descendant. With the patch, i can link large
programs with nested archives flawlessly.

--- bfd/archive.c_      Wed Apr 21 19:28:07 2004
+++ bfd/archive.c       Wed Apr 21 20:54:25 2004
@@ -498,6 +498,11 @@
   struct areltdata *new_areldata;
   bfd *n_nfd;

+  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;
@@ -593,6 +598,7 @@
         BSD-4.4-style element with a long odd size.  */
       filestart = last_file->origin + size;
       filestart += filestart % 2;
+      if (archive->my_archive) filestart -= archive->origin;
     }

   return _bfd_get_elt_at_filepos (archive, filestart);
Comment 1 Ben Elliston 2004-05-03 06:28:03 UTC
Can you supply a simple test case (in the dejagnu harness) to demonstrate that
this patch works?  Thanks,

Ben
Comment 2 Mikulas Patocka 2004-05-04 16:37:38 UTC
Probably not --- it was triggered with custom linker using bfd (not gnu-ld ...
gnu ld walks all archives only once, so maybe this bug is not triggerable with
it at all) and several megabyte application. It can't be triggered with simple
nested archives, because bfd caching doesn't take effect.

Or do you want that big application and linker?
Comment 3 Ben Elliston 2004-05-06 01:25:06 UTC
Adding here for the audit trail:

From: Nick Clifton <nickc@redhat.com>
Subject: Re: crashes with nested archives
Cc: bug-binutils@gnu.org
Date: Wed, 05 May 2004 15:59:12 +0100

Hi Mikulas,

>Binutils-2.14 have serious problems when processing archives containing
> other archives.

Thanks for bringing this to our attention.  I hope that you do not
mind, but there are a couple of problems with your proposed patch:

  * It is not clear to me how nested archives can be successfully
used.  I tried a simplest test like this:

    gcc hello-world.c -c -o file1.o
    cp file1.o file2.o
    cp file1.o file3.o
    cp file1.o file4.o
    ar cr lib1.a file1.o file2.o
    ar cr lib2.a file3.o file4.o
    ar cr lib3.a  lib1.a lib2.s
   objdump -p lib3.a
   In archive lib3.a:
     objdump: lib1.a: File format not recognized
     objdump: lib2.a: File format not recognized

  So in order to proceed with fixing this bug we definitely need a
test case that can reproduce the problem.

  * The patch assumes that there will only be one level of nested
archives.  Instead it should recurse until there are no more nested
archive levels to process.

  * The patch to bfd_generic_openr_next_archived_file() puts the new
code *after* filestart has been aligned to an even byte boundary.  It
ought to be *before* the alignment.

   * It would be helpful if you could include a ChangeLog entry for
the patch as well.

I hope that you will consider resubmitting your patch with these
points addressed.

Cheers
  Nick
Comment 4 Ben Elliston 2004-05-14 06:23:19 UTC
The PR is not host or target specific. 
 
Comment 5 Ben Elliston 2004-05-19 21:52:18 UTC
Nick committed the patch.