* 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.
This commit is contained in:
parent
d8cf8b5133
commit
5472771991
3 changed files with 124 additions and 30 deletions
|
@ -1,3 +1,10 @@
|
|||
2007-01-19 Murali Vemulapati <murali.vemulapati@gmail.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2007-01-19 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
* ld.h (args_type): Add new symbolic and dynamic_list fields.
|
||||
|
|
|
@ -11,7 +11,7 @@ rm -f e${EMULATION_NAME}.c
|
|||
cat >>e${EMULATION_NAME}.c <<EOF
|
||||
/* This file is part of GLD, the Gnu Linker.
|
||||
Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
|
||||
2005, 2006 Free Software Foundation, Inc.
|
||||
2005, 2006, 2007 Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
|
@ -1250,6 +1250,74 @@ gld_${EMULATION_NAME}_after_open (void)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
/* The following chunk of code tries to identify jump stubs in
|
||||
import libraries which are dead code and eliminates them
|
||||
from the final link. For each exported symbol <sym>, 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 <sym> which is a jump stub of the form
|
||||
jmp *__imp_<sym>. The .idata$5 contains the symbol definition
|
||||
for __imp_<sym> which is the address of the slot for <sym> in
|
||||
the import address table. When a symbol is imported explicitly
|
||||
using __declspec(dllimport) declaration, the compiler generates
|
||||
a reference to __imp_<sym> 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
|
||||
|
|
77
ld/pe-dll.c
77
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 <dj@cygnus.com>
|
||||
|
||||
|
@ -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 <sym> is a function
|
||||
symbol and there is at least one undefined reference to that
|
||||
symbol. In other words, if all the import references to <sym> 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);
|
||||
|
@ -1986,6 +1995,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 +2061,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,7 +2410,8 @@ 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 = make_one (def->exports + i, outarch,
|
||||
! (def->exports + i)->flag_data);
|
||||
n->next = head;
|
||||
head = n;
|
||||
def->exports[i].internal_name = internal;
|
||||
|
@ -2474,6 +2487,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 +2499,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 <sym> only if the <sym>
|
||||
is undefined. */
|
||||
if (!blhe || (blhe && blhe->type != bfd_link_hash_undefined))
|
||||
{
|
||||
if (lead_at)
|
||||
|
@ -2497,6 +2513,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 +2536,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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue