From 54727719911a60fc42f9fe74a4762c00add6cb75 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Fri, 19 Jan 2007 15:40:55 +0000 Subject: * pe-dll.c: (make_one) Conditionally include jump stubs. * emultempl/pe.em (gld_${EMULATION_NAME}_after_open): Identify redundant jump stubs from import libraries and exclude them from link. --- ld/emultempl/pe.em | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) (limited to 'ld/emultempl/pe.em') diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 1396e98..ae4356f 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -11,7 +11,7 @@ rm -f e${EMULATION_NAME}.c cat >>e${EMULATION_NAME}.c <, there + is a object file in the import library with a .text section + and several .idata$* sections. The .text section contains the + symbol definition for which is a jump stub of the form + jmp *__imp_. The .idata$5 contains the symbol definition + for __imp_ which is the address of the slot for in + the import address table. When a symbol is imported explicitly + using __declspec(dllimport) declaration, the compiler generates + a reference to __imp_ which directly resolves to the + symbol in .idata$5, in which case the jump stub code is not + needed. The following code tries to identify jump stub sections + in import libraries which are not referred to by anyone and + marks them for exclusion from the final link. */ + LANG_FOR_EACH_INPUT_STATEMENT (is) + { + if (is->the_bfd->my_archive) + { + int is_imp = 0; + asection *sec, *stub_sec = NULL; + + /* See if this is an import library thunk. */ + for (sec = is->the_bfd->sections; sec; sec = sec->next) + { + if (strncmp (sec->name, ".idata\$", 7) == 0) + is_imp = 1; + /* The section containing the jmp stub has code + and has a reloc. */ + if ((sec->flags & SEC_CODE) && sec->reloc_count) + stub_sec = sec; + } + + if (is_imp && stub_sec) + { + long symsize; + asymbol **symbols; + long src_count; + struct bfd_link_hash_entry * blhe; + + symsize = bfd_get_symtab_upper_bound (is->the_bfd); + symbols = xmalloc (symsize); + symsize = bfd_canonicalize_symtab (is->the_bfd, symbols); + + for (src_count = 0; src_count < symsize; src_count++) + { + if (symbols[src_count]->section->id == stub_sec->id) + { + /* This symbol belongs to the section containing + the stub. */ + blhe = bfd_link_hash_lookup (link_info.hash, + symbols[src_count]->name, + FALSE, FALSE, TRUE); + /* If the symbol in the stub section has no other + undefined references, exclude the stub section + from the final link. */ + if (blhe && (blhe->type == bfd_link_hash_defined) + && (blhe->u.undef.next == NULL)) + stub_sec->flags |= SEC_EXCLUDE; + } + } + free (symbols); + } + } + } + } } static void -- cgit v1.1