bug-binutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Bug in linker for Win32.


From: Eric Youngdale
Subject: Bug in linker for Win32.
Date: Fri, 12 Dec 2003 17:58:21 -0500


    I have run across a bug in GNU ld for Win32 (I am using the mingw32
version).  The bug is exposed when you link against a Microsoft
linker-generated .lib file that has both import and static members -
typically one would create this by first creating the import library and
then manually adding some static .obj files to the thing with ar or the
Microsoft librarian.  Microsoft's linker doesn't have a problem with this
arrangement.

    The problem in the executable can be traced to a messed up .idata$2
section in the generated executable.  Typically this has section-relative
pointers to the import address table, the name of the dll, and the import
name table.  The contents of the two tables (import address and import name)
appear to be correct - the only fault appears to be that two of the pointers
in the IMAGE_IMPORT_DESCRIPTOR are wrong - in other words, the pointer to
the import name table and import address table are incorrect - the result of
all of this is that if you dump the imports for the executable, only a
subset of the full list of imports is displayed.

    If I split the library into static and dynamic bits, then life is good.
The .idata section is then correct.

    I have been poking at the ld/bfd sources to try and figure out what the
fault is, and have traced it to the function gld_i386pe_after_open(), in
ei386pe.c (which is a generated source file).  Essentially there is extra
magic that takes place for Microsoft import libraries to make sure that the
.idata$[2,3,4] sections are properly sorted, and the presence of the .obj
files causes this section of code to decide that the library isn't a
Microsoft import library, and hence the hack isn't required.

    For my testcase, the enclosed patch does work, but I haven't tested much
beyond this however.  The patch is a bit on the ugly side - it is on the
conservative side I suppose in that I am not sure what harm there would be
in mistakenly concluding that we have a Microsoft import library. 

        In fact, there is a harmless nit whereby the object files that are
included appear as foo.obj.b in the linker map.  Doesn't hurt anything, but
I suppose I ought to fix it before any patch is official.

-Eric

*** ld/emultempl/pe.em.~1~ Sun Dec  7 11:23:31 2003
--- ld/emultempl/pe.em Sun Dec  7 16:10:49 2003
***************
*** 1113,1118 ****
--- 1113,1119 ----
      int is_ms_arch = 0;
      bfd *cur_arch = 0;
      lang_input_statement_type *is2;
+     lang_input_statement_type *is3;

      /* Careful - this is a shell script.  Watch those dollar signs! */
      /* Microsoft import libraries have every member named the same,
***************
*** 1130,1143 ****
       bfd *arch = is->the_bfd->my_archive;
       if (cur_arch != arch)
         {
    cur_arch = arch;
    is_ms_arch = 1;
!   for (is2 = is;
!        is2 && is2->the_bfd->my_archive == arch;
!        is2 = (lang_input_statement_type *)is2->next)
      {
!       if (strcmp (is->the_bfd->filename, is2->the_bfd->filename))
!         is_ms_arch = 0;
      }
         }

--- 1131,1182 ----
       bfd *arch = is->the_bfd->my_archive;
       if (cur_arch != arch)
         {
+   char * pnt;
    cur_arch = arch;
    is_ms_arch = 1;
!   for (is3 = is;
!        is3 && is3->the_bfd->my_archive == arch;
!        is3 = (lang_input_statement_type *)is3->next)
      {
!    pnt = strrchr(is3->the_bfd->filename, '.');
!    /*
!     * A MS dynamic import library can also contain static members,
!     * so look for the first element with a .dll extension, and use
!     * that for the remainder of the comparisons.
!     */
!    if( pnt != NULL && strcmp(pnt, ".dll") != 0 )
!      {
!        continue;
!      }
!    /*
!     * OK, found one.  Now make sure the remainder are consistent.
!     */
!    for (is2 = is;
!         is2 && is2->the_bfd->my_archive == arch;
!         is2 = (lang_input_statement_type *)is2->next)
!      {
!        /*
!         * A MS dynamic import library can also contain static members,
!         * so looking for archive members that have names other than the
!         * one we are processing is bound to fail.  As a heuristic
!         * to help with this, we ignore elements with a .obj extension.
!         */
!        pnt = strrchr(is2->the_bfd->filename, '.');
!        if( pnt != NULL && strcmp(pnt, ".obj") == 0 )
!          {
!     continue;
!          }
!
!        if (strcmp (is3->the_bfd->filename, is2->the_bfd->filename))
!          {
!     is_ms_arch = 0;
!          }
!      }
!    break;
!     }
!   if( is3 == NULL )
!     {
!       is_ms_arch = 0;
      }
         }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]