aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog10
-rw-r--r--ld/emultempl/pe.em76
-rw-r--r--ld/pe-dll.c6
3 files changed, 89 insertions, 3 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 8a14306..5695170 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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.
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 0ffeffc..78a72d7 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -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;
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index 456f7b8..a4be5f0 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -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);