diff options
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 10 | ||||
-rw-r--r-- | ld/emultempl/pe.em | 76 | ||||
-rw-r--r-- | ld/pe-dll.c | 6 |
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); |