X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=ld%2Fpe-dll.c;h=ab743eed7c915478681ba23203f59394894f067d;hb=cc481421d02b8d2b7881bdf12e469e23aa9021e7;hp=335bc05c4ca8ae313c07051714e44962d9c8b400;hpb=799133e8cd4a2a85e40b64ceaadc571c432e7771;p=deliverable%2Fbinutils-gdb.git diff --git a/ld/pe-dll.c b/ld/pe-dll.c index 335bc05c4c..ab743eed7c 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -1,5 +1,5 @@ /* Routines to help build PEI-format DLLs (Win32 etc) - Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 + Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. Written by DJ Delorie @@ -20,8 +20,8 @@ Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "bfd.h" #include "sysdep.h" +#include "bfd.h" #include "bfdlink.h" #include "libiberty.h" #include "safe-ctype.h" @@ -1873,7 +1873,7 @@ static const unsigned char jmp_arm_bytes[] = static bfd * -make_one (def_file_export *exp, bfd *parent) +make_one (def_file_export *exp, bfd *parent, bfd_boolean include_jmp_stub) { asection *tx, *id7, *id5, *id4, *id6; unsigned char *td = NULL, *d7, *d5, *d4, *d6 = NULL; @@ -1883,28 +1883,37 @@ make_one (def_file_export *exp, bfd *parent) const unsigned char *jmp_bytes = NULL; int jmp_byte_count = 0; - switch (pe_details->pe_arch) + /* Include the jump stub section only if it is needed. A jump + stub is needed if the symbol being imported is a function + symbol and there is at least one undefined reference to that + symbol. In other words, if all the import references to are + explicitly through _declspec(dllimport) then the jump stub is not + needed. */ + if (include_jmp_stub) { - case PE_ARCH_i386: - jmp_bytes = jmp_ix86_bytes; - jmp_byte_count = sizeof (jmp_ix86_bytes); - break; - case PE_ARCH_sh: - jmp_bytes = jmp_sh_bytes; - jmp_byte_count = sizeof (jmp_sh_bytes); - break; - case PE_ARCH_mips: - jmp_bytes = jmp_mips_bytes; - jmp_byte_count = sizeof (jmp_mips_bytes); - break; - case PE_ARCH_arm: - case PE_ARCH_arm_epoc: - case PE_ARCH_arm_wince: - jmp_bytes = jmp_arm_bytes; - jmp_byte_count = sizeof (jmp_arm_bytes); - break; - default: - abort (); + switch (pe_details->pe_arch) + { + case PE_ARCH_i386: + jmp_bytes = jmp_ix86_bytes; + jmp_byte_count = sizeof (jmp_ix86_bytes); + break; + case PE_ARCH_sh: + jmp_bytes = jmp_sh_bytes; + jmp_byte_count = sizeof (jmp_sh_bytes); + break; + case PE_ARCH_mips: + jmp_bytes = jmp_mips_bytes; + jmp_byte_count = sizeof (jmp_mips_bytes); + break; + case PE_ARCH_arm: + case PE_ARCH_arm_epoc: + case PE_ARCH_arm_wince: + jmp_bytes = jmp_arm_bytes; + jmp_byte_count = sizeof (jmp_arm_bytes); + break; + default: + abort (); + } } oname = xmalloc (20); @@ -1930,7 +1939,7 @@ make_one (def_file_export *exp, bfd *parent) { quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0); - if (! exp->flag_data) + if (include_jmp_stub) quick_symbol (abfd, "", exp->internal_name, "", tx, BSF_GLOBAL, 0); quick_symbol (abfd, "__imp_", exp->internal_name, "", id5, BSF_GLOBAL, 0); @@ -1941,7 +1950,7 @@ make_one (def_file_export *exp, bfd *parent) { quick_symbol (abfd, U ("_head_"), dll_symname, "", UNDSEC, BSF_GLOBAL, 0); - if (! exp->flag_data) + if (include_jmp_stub) quick_symbol (abfd, U (""), exp->internal_name, "", tx, BSF_GLOBAL, 0); quick_symbol (abfd, "__imp_", U (""), exp->internal_name, id5, @@ -1956,7 +1965,7 @@ make_one (def_file_export *exp, bfd *parent) quick_symbol (abfd, U ("__imp_"), exp->internal_name, "", id5, BSF_GLOBAL, 0); - if (! exp->flag_data) + if (include_jmp_stub) { bfd_set_section_size (abfd, tx, jmp_byte_count); td = xmalloc (jmp_byte_count); @@ -1966,7 +1975,11 @@ make_one (def_file_export *exp, bfd *parent) switch (pe_details->pe_arch) { case PE_ARCH_i386: - quick_reloc (abfd, 2, BFD_RELOC_32, 2); +#ifdef pe_use_x86_64 + quick_reloc (abfd, 2, BFD_RELOC_32_PCREL, 2); +#else + quick_reloc (abfd, 2, BFD_RELOC_32, 2); +#endif break; case PE_ARCH_sh: quick_reloc (abfd, 8, BFD_RELOC_32, 2); @@ -1986,6 +1999,8 @@ make_one (def_file_export *exp, bfd *parent) } save_relocs (tx); } + else + bfd_set_section_size (abfd, tx, 0); bfd_set_section_size (abfd, id7, 4); d7 = xmalloc (4); @@ -2050,7 +2065,8 @@ make_one (def_file_export *exp, bfd *parent) bfd_set_symtab (abfd, symtab, symptr); - bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count); + if (include_jmp_stub) + bfd_set_section_contents (abfd, tx, td, 0, jmp_byte_count); bfd_set_section_contents (abfd, id7, d7, 0, 4); bfd_set_section_contents (abfd, id5, d5, 0, PE_IDATA5_SIZE); bfd_set_section_contents (abfd, id4, d4, 0, PE_IDATA4_SIZE); @@ -2398,8 +2414,9 @@ pe_dll_generate_implib (def_file *def, const char *impfilename) if (pe_def_file->exports[i].flag_private) continue; def->exports[i].internal_name = def->exports[i].name; - n = make_one (def->exports + i, outarch); - n->next = head; + n = make_one (def->exports + i, outarch, + ! (def->exports + i)->flag_data); + n->archive_next = head; head = n; def->exports[i].internal_name = internal; } @@ -2410,8 +2427,8 @@ pe_dll_generate_implib (def_file *def, const char *impfilename) return; /* Now stick them all into the archive. */ - ar_head->next = head; - ar_tail->next = ar_head; + ar_head->archive_next = head; + ar_tail->archive_next = ar_head; head = ar_tail; if (! bfd_set_archive_head (outarch, head)) @@ -2422,7 +2439,7 @@ pe_dll_generate_implib (def_file *def, const char *impfilename) while (head != NULL) { - bfd *n = head->next; + bfd *n = head->archive_next; bfd_close (head); head = n; } @@ -2474,6 +2491,7 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info) /* See if we need this import. */ size_t len = strlen (pe_def_file->imports[i].internal_name); char *name = xmalloc (len + 2 + 6); + bfd_boolean include_jmp_stub = FALSE; if (lead_at) sprintf (name, "%s", @@ -2485,6 +2503,8 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info) blhe = bfd_link_hash_lookup (link_info->hash, name, FALSE, FALSE, FALSE); + /* Include the jump stub for only if the + is undefined. */ if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined)) { if (lead_at) @@ -2497,6 +2517,9 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info) blhe = bfd_link_hash_lookup (link_info->hash, name, FALSE, FALSE, FALSE); } + else + include_jmp_stub = TRUE; + free (name); if (blhe && blhe->type == bfd_link_hash_undefined) @@ -2517,7 +2540,7 @@ pe_process_import_defs (bfd *output_bfd, struct bfd_link_info *link_info) exp.flag_constant = 0; exp.flag_data = pe_def_file->imports[i].data; exp.flag_noname = exp.name ? 0 : 1; - one = make_one (&exp, output_bfd); + one = make_one (&exp, output_bfd, (! exp.flag_data) && include_jmp_stub); add_bfd_to_link (one, one->filename, link_info); } }