* emultempl/pe.em (gld_*_after_open): detect case where there two
authorDJ Delorie <dj@redhat.com>
Mon, 2 Oct 2000 14:39:46 +0000 (14:39 +0000)
committerDJ Delorie <dj@redhat.com>
Mon, 2 Oct 2000 14:39:46 +0000 (14:39 +0000)
import libraries for same dll; rename one to ensure proper link
order.

* pe-dll.c (process_def_file): compare ordinals to -1, not 0; fix
typo
(generate_edata): fix typo

ld/ChangeLog
ld/emultempl/pe.em
ld/pe-dll.c

index 8a14306..5695170 100644 (file)
@@ -1,3 +1,13 @@
+2000-10-02  DJ Delorie  <dj@redhat.com>
+
+       * emultempl/pe.em (gld_*_after_open): detect case where there two
+       import libraries for same dll; rename one to ensure proper link
+       order.
+
+       * pe-dll.c (process_def_file): compare ordinals to -1, not 0; fix
+       typo
+       (generate_edata): fix typo
+
 2000-09-29  Hans-Peter Nilsson  <hp@axis.com>
 
        * scripttempl/crisaout.sc (ENTRY): Now __start.
index 0ffeffc..78a72d7 100644 (file)
@@ -814,6 +814,82 @@ gld_${EMULATION_NAME}_after_open ()
 #endif
 
   {
+    lang_input_statement_type *is2;
+
+    /* This next chunk of code tries to detect the case where you have
+       two import libraries for the same DLL (specifically,
+       symbolically linking libm.a and libc.a in cygwin to
+       libcygwin.a).  In those cases, it's possible for function
+       thunks from the second implib to be used but without the
+       head/tail objects, causing an improper import table.  We detect
+       those cases and rename the "other" import libraries to match
+       the one the head/tail come from, so that the linker will sort
+       things nicely and produce a valid import table. */
+
+    LANG_FOR_EACH_INPUT_STATEMENT (is)
+      {
+       if (is->the_bfd->my_archive)
+         {
+           int idata2 = 0, reloc_count=0, is_imp = 0;
+           asection *sec;
+           /* See if this is an import library thunk */
+           for (sec = is->the_bfd->sections; sec; sec = sec->next)
+             {
+               if (strcmp (sec->name, ".idata\$2") == 0)
+                 idata2 = 1;
+               if (strncmp (sec->name, ".idata\$", 7) == 0)
+                 is_imp = 1;
+               reloc_count += sec->reloc_count;
+             }
+           if (is_imp && !idata2 && reloc_count)
+             {
+               /* it is, look for the reference to head and see if it's
+                  from our own library */
+               for (sec = is->the_bfd->sections; sec; sec = sec->next)
+                 {
+                   int i;
+                   int symsize = bfd_get_symtab_upper_bound (is->the_bfd);
+                   asymbol **symbols = (asymbol **) xmalloc (symsize);
+                   int nsyms = bfd_canonicalize_symtab (is->the_bfd, symbols);
+
+                   int relsize = bfd_get_reloc_upper_bound (is->the_bfd, sec);
+                   arelent **relocs = (arelent **) xmalloc ((size_t) relsize);
+                   int nrelocs = bfd_canonicalize_reloc (is->the_bfd, sec,
+                                                         relocs, symbols);
+                   for (i=0; i<nrelocs; i++)
+                     {
+                       struct symbol_cache_entry *s;
+                       s = (relocs[i]->sym_ptr_ptr)[0];
+                       if (!s->flags & BSF_LOCAL)
+                         {
+                           /* thunk section with reloc to another bfd... */
+                           struct bfd_link_hash_entry *blhe;
+                           blhe = bfd_link_hash_lookup (link_info.hash,
+                                                        s->name,
+                                                        false, false, true);
+                           if (blhe && blhe->type == bfd_link_hash_defined)
+                             {
+                               bfd *other_bfd = blhe->u.def.section->owner;
+                               if (strcmp (is->the_bfd->my_archive->filename,
+                                           other_bfd->my_archive->filename))
+                                 {
+                                   /* Rename this implib to match the other */
+                                   char *n = (char *) xmalloc (strlen (other_bfd->my_archive->filename) + 1);
+                                   strcpy (n, other_bfd->my_archive->filename);
+                                   is->the_bfd->my_archive->filename = n;
+                                 }
+                             }
+                         }
+                     }
+
+                   free (relocs);
+                 }
+             }
+         }
+      }
+  }
+
+  {
     int is_ms_arch = 0;
     bfd *cur_arch = 0;
     lang_input_statement_type *is2;
index 456f7b8..a4be5f0 100644 (file)
@@ -378,7 +378,7 @@ process_def_file (abfd, info)
            {
              if (pe_dll_warn_dup_exports)
                /* xgettext:c-format */
-               einfo (_("%XError, duplicate EXPORT with oridinals: %s (%d vs %d)\n"),
+               einfo (_("%XError, duplicate EXPORT with ordinals: %s (%d vs %d)\n"),
                       e[j - 1].name, e[j - 1].ordinal, e[i].ordinal);
            }
          else
@@ -388,7 +388,7 @@ process_def_file (abfd, info)
                einfo (_("Warning, duplicate EXPORT: %s\n"),
                       e[j - 1].name);
            }
-         if (e[i].ordinal)
+         if (e[i].ordinal != -1)
            e[j - 1].ordinal = e[i].ordinal;
          e[j - 1].flag_private |= e[i].flag_private;
          e[j - 1].flag_constant |= e[i].flag_constant;
@@ -585,7 +585,7 @@ generate_edata (abfd, info)
              if (pi != -1)
                {
                  /* xgettext:c-format */
-                 einfo (_("%XError, oridinal used twice: %d (%s vs %s)\n"),
+                 einfo (_("%XError, ordinal used twice: %d (%s vs %s)\n"),
                         pe_def_file->exports[i].ordinal,
                         pe_def_file->exports[i].name,
                         pe_def_file->exports[pi].name);