Add support to skip import libraries for performance reasons and instead

use the direct auto-import of dll's
This commit is contained in:
Nick Clifton 2002-12-16 18:02:16 +00:00
parent 273f84299e
commit 939ba9d0fc
9 changed files with 207 additions and 71 deletions

View File

@ -1,3 +1,33 @@
2002-12-13 Ralf Habacker <Ralf.Habacker@freenet.de>
Charles Wilson <cwilson@ece.gatech.edu>
* configure.in: Add check for realpath function.
* configure: Regenerate.
* config.in: Regenerate.
* aclocal.m4: Regenerate.
* deffile.h: Add .data field to def_file_import
structure.
* pe-dll.c (pe_proces_import_defs): Use .data field of
def_file_import structure to initialize flag_data field of
def_file_export structure.
(pe_implied_import_dll): New variables exp_funcbase and
[data|bss]_[start|end]. Use DLL's internal name to set dll_name,
not filename (which may be a symlink). Scan the sections and
initialize [data|bss]_[start|end]. When scanning the export
table, skip _nm_ symbols, and mark any symbols whose rva indicates
that it is in the .bss or .data sections as data.
* sysdep.h: Include limits.h and sys/param.h, and define
LD_PATHMAX as appropriate. Also define REALPATH as realpath if it
exists, NULL otherwise.
* emultempl/pe.em (gld_${EMULATION_NAME}_after_open): Call
pe_process_import_defs before pe_find_data_imports, so that
auto-import will check the virtual implib as well as "real"
implibs.
(gld_${EMULATION_NAME}_recognized_file): Use REALPATH to follow
symlinks to their target; check that the target's extension is
.dll before calling pe_implied_import_dll(), not the filename
itself (which may be a symlink).
2002-12-10 Alan Modra <amodra@bigpond.net.au>
* emultempl/elf32.em (struct orphan_save): Add os_tail field.

View File

@ -538,7 +538,7 @@ deffilep.c ldgram.c ldlex.c
DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST)
TAR = tar
TAR = gtar
GZIP_ENV = --best
SOURCES = $(ld_new_SOURCES) $(EXTRA_ld_new_SOURCES)
OBJECTS = $(ld_new_OBJECTS)

18
ld/aclocal.m4 vendored
View File

@ -27,6 +27,24 @@ AC_DEFUN([CY_WITH_NLS],)
AC_SUBST(INTLLIBS)
])
#serial 1
# This test replaces the one in autoconf.
# Currently this macro should have the same name as the autoconf macro
# because gettext's gettext.m4 (distributed in the automake package)
# still uses it. Otherwise, the use in gettext.m4 makes autoheader
# give these diagnostics:
# configure.in:556: AC_TRY_COMPILE was called before AC_ISC_POSIX
# configure.in:556: AC_TRY_RUN was called before AC_ISC_POSIX
undefine([AC_ISC_POSIX])
AC_DEFUN([AC_ISC_POSIX],
[
dnl This test replaces the obsolescent AC_ISC_POSIX kludge.
AC_CHECK_LIB(cposix, strerror, [LIBS="$LIBS -lcposix"])
]
)
# Do all the work for Automake. This macro actually does too much --
# some checks are only needed if your package does certain things.
# But this isn't really a big deal.

2
ld/configure vendored
View File

@ -4551,7 +4551,7 @@ else
fi
done
for ac_func in sbrk
for ac_func in sbrk realpath
do
echo $ac_n "checking for $ac_func""... $ac_c" 1>&6
echo "configure:4558: checking for $ac_func" >&5

View File

@ -83,7 +83,7 @@ AC_SUBST(HOSTING_LIBS)
AC_SUBST(NATIVE_LIB_DIRS)
AC_CHECK_HEADERS(string.h strings.h stdlib.h unistd.h)
AC_CHECK_FUNCS(sbrk)
AC_CHECK_FUNCS(sbrk realpath)
AC_HEADER_DIRENT
BFD_BINARY_FOPEN

View File

@ -1,5 +1,5 @@
/* deffile.h - header for .DEF file parser
Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
Copyright 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
Written by DJ Delorie dj@cygnus.com
This file is part of GLD, the Gnu Linker.
@ -52,65 +52,57 @@ typedef struct def_file_import {
def_file_module *module; /* always set */
char *name; /* may be NULL; either this or ordinal will be set */
int ordinal; /* may be -1 */
int data; /* = 1 if data */
} def_file_import;
typedef struct def_file {
/* from the NAME or LIBRARY command */
/* From the NAME or LIBRARY command. */
char *name;
int is_dll; /* -1 if NAME/LIBRARY not given */
bfd_vma base_address; /* (bfd_vma)(-1) if unspecified */
/* from the DESCRIPTION command */
/* From the DESCRIPTION command. */
char *description;
/* from the STACK/HEAP command, -1 if unspecified */
/* From the STACK/HEAP command, -1 if unspecified. */
int stack_reserve, stack_commit;
int heap_reserve, heap_commit;
/* from the SECTION/SEGMENT commands */
/* From the SECTION/SEGMENT commands. */
int num_section_defs;
def_file_section *section_defs;
/* from the EXPORTS commands */
/* From the EXPORTS commands. */
int num_exports;
def_file_export *exports;
/* used by imports for module names */
/* Used by imports for module names. */
def_file_module *modules;
/* from the IMPORTS commands */
/* From the IMPORTS commands. */
int num_imports;
def_file_import *imports;
/* from the VERSION command, -1 if not specified */
/* From the VERSION command, -1 if not specified. */
int version_major, version_minor;
} def_file;
extern def_file *def_file_empty PARAMS ((void));
/* add_to may be NULL. If not, this .def is appended to it */
extern def_file *def_file_parse PARAMS ((const char *_filename,
def_file * _add_to));
extern void def_file_free PARAMS ((def_file * _def));
extern def_file_export *def_file_add_export PARAMS ((def_file * _def,
const char *_name,
const char *_internal_name,
int _ordinal));
extern def_file_import *def_file_add_import PARAMS ((def_file * _def,
const char *_name,
const char *_from,
int _ordinal,
const char *_imported_name));
extern void def_file_add_directive PARAMS ((def_file * _def,
const char *param,
int len));
/* The second arg may be NULL. If not, this .def is appended to it. */
extern def_file * def_file_parse
PARAMS ((const char *, def_file *));
extern void def_file_free
PARAMS ((def_file *));
extern def_file_export * def_file_add_export
PARAMS ((def_file *, const char *, const char *, int));
extern def_file_import * def_file_add_import
PARAMS ((def_file *, const char *, const char *, int, const char *));
extern void def_file_add_directive
PARAMS ((def_file *, const char *, int));
#ifdef DEF_FILE_PRINT
extern void def_file_print PARAMS ((FILE * _file, def_file * _def));
extern void def_file_print
PARAMS ((FILE *, def_file *));
#endif
#endif /* DEFFILE_H */

View File

@ -384,7 +384,7 @@ set_pe_name (name, val)
return;
}
}
abort();
abort ();
}
@ -507,7 +507,7 @@ set_pe_stack_heap (resname, comname)
static int
gld_${EMULATION_NAME}_parse_args(argc, argv)
gld_${EMULATION_NAME}_parse_args (argc, argv)
int argc;
char **argv;
{
@ -633,7 +633,7 @@ gld_${EMULATION_NAME}_parse_args(argc, argv)
pe_enable_auto_image_base = 0;
break;
case OPTION_DLL_SEARCH_PREFIX:
pe_dll_search_prefix = xstrdup( optarg );
pe_dll_search_prefix = xstrdup (optarg);
break;
case OPTION_NO_DEFAULT_EXCLUDES:
pe_dll_do_default_excludes = 0;
@ -733,16 +733,16 @@ gld_${EMULATION_NAME}_set_symbols ()
lang_assignment_statement_type *rv;
rv = lang_add_assignment (exp_assop ('=', init[j].symbol,
exp_intop (val)));
if (init[j].size == sizeof(short))
*(short *)init[j].ptr = val;
else if (init[j].size == sizeof(int))
*(int *)init[j].ptr = val;
else if (init[j].size == sizeof(long))
*(long *)init[j].ptr = val;
if (init[j].size == sizeof (short))
*(short *) init[j].ptr = val;
else if (init[j].size == sizeof (int))
*(int *) init[j].ptr = val;
else if (init[j].size == sizeof (long))
*(long *) init[j].ptr = val;
/* This might be a long long or other special type. */
else if (init[j].size == sizeof(bfd_vma))
*(bfd_vma *)init[j].ptr = val;
else abort();
else if (init[j].size == sizeof (bfd_vma))
*(bfd_vma *) init[j].ptr = val;
else abort ();
if (j == IMAGEBASEOFF)
image_base_statement = rv;
}
@ -843,8 +843,8 @@ pe_fixup_stdcalls ()
if (! gave_warning_message)
{
gave_warning_message = 1;
einfo(_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo(_("Use --disable-stdcall-fixup to disable these fixups\n"));
einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
}
}
}
@ -869,8 +869,8 @@ pe_fixup_stdcalls ()
if (! gave_warning_message)
{
gave_warning_message = 1;
einfo(_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo(_("Use --disable-stdcall-fixup to disable these fixups\n"));
einfo (_("Use --enable-stdcall-fixup to disable these warnings\n"));
einfo (_("Use --disable-stdcall-fixup to disable these fixups\n"));
}
}
}
@ -890,7 +890,7 @@ make_import_fixup (rel, s)
printf ("arelent: %s@%#lx: add=%li\n", sym->name,
(long) rel->address, (long) rel->addend);
if (!bfd_get_section_contents(s->owner, s, &addend, rel->address, sizeof(addend)))
if (! bfd_get_section_contents (s->owner, s, &addend, rel->address, sizeof (addend)))
einfo (_("%C: Cannot get section contents - auto-import exception\n"),
s->owner, s, rel->address);
@ -935,8 +935,8 @@ pe_find_data_imports ()
for (i = 0; i < nsyms; i++)
{
if (memcmp(symbols[i]->name, "__head_",
sizeof ("__head_") - 1))
if (memcmp (symbols[i]->name, "__head_",
sizeof ("__head_") - 1))
continue;
if (pe_dll_extra_pe_debug)
@ -1009,9 +1009,10 @@ gld_${EMULATION_NAME}_after_open ()
if (pe_enable_stdcall_fixup) /* -1=warn or 1=disable */
pe_fixup_stdcalls ();
pe_process_import_defs (output_bfd, & link_info);
pe_find_data_imports ();
pe_process_import_defs(output_bfd, &link_info);
if (link_info.shared)
pe_dll_build_sections (output_bfd, &link_info);
@ -1219,7 +1220,7 @@ gld_${EMULATION_NAME}_after_open ()
}
static void
gld_${EMULATION_NAME}_before_allocation()
gld_${EMULATION_NAME}_before_allocation ()
{
#ifdef TARGET_IS_ppcpe
/* Here we rummage through the found bfds to collect toc information. */
@ -1280,7 +1281,7 @@ saw_option (char * option)
#endif /* DLL_SUPPORT */
static bfd_boolean
gld_${EMULATION_NAME}_unrecognized_file(entry)
gld_${EMULATION_NAME}_unrecognized_file (entry)
lang_input_statement_type *entry ATTRIBUTE_UNUSED;
{
#ifdef DLL_SUPPORT
@ -1300,7 +1301,7 @@ gld_${EMULATION_NAME}_unrecognized_file(entry)
for (i = 0; i < pe_def_file->num_exports; i++)
{
len = strlen(pe_def_file->exports[i].internal_name);
len = strlen (pe_def_file->exports[i].internal_name);
if (buflen < len + 2)
buflen = len + 2;
}
@ -1311,7 +1312,7 @@ gld_${EMULATION_NAME}_unrecognized_file(entry)
{
struct bfd_link_hash_entry *h;
sprintf(buf, "_%s", pe_def_file->exports[i].internal_name);
sprintf (buf, "_%s", pe_def_file->exports[i].internal_name);
h = bfd_link_hash_lookup (link_info.hash, buf, TRUE, TRUE, TRUE);
if (h == (struct bfd_link_hash_entry *) NULL)
@ -1370,7 +1371,7 @@ gld_${EMULATION_NAME}_unrecognized_file(entry)
}
static bfd_boolean
gld_${EMULATION_NAME}_recognized_file(entry)
gld_${EMULATION_NAME}_recognized_file (entry)
lang_input_statement_type *entry ATTRIBUTE_UNUSED;
{
#ifdef DLL_SUPPORT
@ -1388,10 +1389,16 @@ gld_${EMULATION_NAME}_recognized_file(entry)
#endif
if (bfd_get_format (entry->the_bfd) == bfd_object)
{
const char *ext = entry->filename + strlen (entry->filename) - 4;
char fbuf[LD_PATHMAX];
const char *ext;
if (REALPATH (entry->filename, fbuf) == NULL)
strncpy (fbuf, entry->filename, LD_PATHMAX);
ext = fbuf + strlen (fbuf) - 4;
if (strcmp (ext, ".dll") == 0 || strcmp (ext, ".DLL") == 0)
return pe_implied_import_dll (entry->filename);
return pe_implied_import_dll (fbuf);
}
#endif
return FALSE;
@ -1903,7 +1910,7 @@ gld_${EMULATION_NAME}_find_potential_libraries (name, entry)
}
static char *
gld_${EMULATION_NAME}_get_script(isfile)
gld_${EMULATION_NAME}_get_script (isfile)
int *isfile;
EOF
# Scripts compiled in.

View File

@ -2418,7 +2418,7 @@ pe_process_import_defs (output_bfd, link_info)
exp.hint = exp.ordinal >= 0 ? exp.ordinal : 0;
exp.flag_private = 0;
exp.flag_constant = 0;
exp.flag_data = 0;
exp.flag_data = pe_def_file->imports[i].data;
exp.flag_noname = exp.name ? 0 : 1;
one = make_one (&exp, output_bfd);
add_bfd_to_link (one, one->filename, link_info);
@ -2491,9 +2491,16 @@ pe_implied_import_dll (filename)
bfd *dll;
unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
unsigned long export_rva, export_size, nsections, secptr, expptr;
unsigned long exp_funcbase;
unsigned char *expdata, *erva;
unsigned long name_rvas, ordinals, nexp, ordbase;
const char *dll_name;
/* Initialization with start > end guarantees that is_data
will not be set by mistake, and avoids compiler warning. */
unsigned long data_start = 1;
unsigned long data_end = 0;
unsigned long bss_start = 1;
unsigned long bss_end = 0;
/* No, I can't use bfd here. kernel32.dll puts its export table in
the middle of the .rdata section. */
@ -2511,11 +2518,7 @@ pe_implied_import_dll (filename)
return FALSE;
}
dll_name = filename;
for (i = 0; filename[i]; i++)
if (filename[i] == '/' || filename[i] == '\\' || filename[i] == ':')
dll_name = filename + i + 1;
/* Get pe_header, optional header and numbers of export entries. */
pe_header_offset = pe_get32 (dll, 0x3c);
opthdr_ofs = pe_header_offset + 4 + 20;
num_entries = pe_get32 (dll, opthdr_ofs + 92);
@ -2530,6 +2533,7 @@ pe_implied_import_dll (filename)
pe_get16 (dll, pe_header_offset + 4 + 16));
expptr = 0;
/* Get the rva and size of the export section. */
for (i = 0; i < nsections; i++)
{
char sname[8];
@ -2550,6 +2554,40 @@ pe_implied_import_dll (filename)
}
}
/* Scan sections and store the base and size of the
data and bss segments in data/base_start/end. */
for (i = 0; i < nsections; i++)
{
unsigned long secptr1 = secptr + 40 * i;
unsigned long vsize = pe_get32 (dll, secptr1 + 8);
unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
unsigned long flags = pe_get32 (dll, secptr1 + 36);
char sec_name[9];
sec_name[8] = '\0';
bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
bfd_bread (sec_name, (bfd_size_type) 8, dll);
if (strcmp(sec_name,".data") == 0)
{
data_start = vaddr;
data_end = vaddr + vsize;
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
__FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
}
else if (strcmp (sec_name,".bss") == 0)
{
bss_start = vaddr;
bss_end = vaddr + vsize;
if (pe_dll_extra_pe_debug)
printf ("%s %s: 0x%08lx-0x%08lx (0x%08lx)\n",
__FUNCTION__, sec_name, vaddr, vaddr + vsize, flags);
}
}
expdata = (unsigned char *) xmalloc (export_size);
bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
bfd_bread (expdata, (bfd_size_type) export_size, dll);
@ -2562,14 +2600,41 @@ pe_implied_import_dll (filename)
name_rvas = pe_as32 (expdata + 32);
ordinals = pe_as32 (expdata + 36);
ordbase = pe_as32 (expdata + 16);
exp_funcbase = pe_as32 (expdata + 28);
/* Use internal dll name instead of filename
to enable symbolic dll linking. */
dll_name = pe_as32 (expdata + 12) + erva;
/* Iterate through the list of symbols. */
for (i = 0; i < nexp; i++)
{
/* Pointer to the names vector. */
unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
def_file_import *imp;
/* Pointer to the function address vector. */
unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);
int is_data = 0;
imp = def_file_add_import (pe_def_file, erva + name_rva, dll_name,
i, 0);
/* Skip unwanted symbols, which are
exported in buggy auto-import releases. */
if (strncmp (erva + name_rva, "_nm_", 4) != 0)
{
/* is_data is true if the address is in the data or bss segment. */
is_data =
(func_rva >= data_start && func_rva < data_end)
|| (func_rva >= bss_start && func_rva < bss_end);
imp = def_file_add_import (pe_def_file, erva + name_rva,
dll_name, i, 0);
/* Mark symbole type. */
imp->data = is_data;
if (pe_dll_extra_pe_debug)
printf ("%s dll-name: %s sym: %s addr: 0x%lx %s\n",
__FUNCTION__, dll_name, erva + name_rva,
func_rva, is_data ? "(data)" : "");
}
}
return TRUE;

View File

@ -1,5 +1,5 @@
/* sysdep.h -- handle host dependencies for the GNU linker
Copyright 1995, 1996, 1997, 1999 Free Software Foundation, Inc.
Copyright 1995, 1996, 1997, 1999, 2002 Free Software Foundation, Inc.
This file is part of GLD, the Gnu Linker.
@ -48,6 +48,30 @@ extern char *strrchr ();
#include <unistd.h>
#endif
/* for PATH_MAX */
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
/* for MAXPATHLEN */
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif
#ifdef PATH_MAX
# define LD_PATHMAX PATH_MAX
#else
# ifdef MAXPATHLEN
# define LD_PATHMAX MAXPATHLEN
# else
# define LD_PATHMAX 1024
# endif
#endif
#ifdef HAVE_REALPATH
# define REALPATH(a,b) realpath (a, b)
#else
# define REALPATH(a,b) NULL
#endif
#ifdef USE_BINARY_FOPEN
#include "fopen-bin.h"
#else