aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2002-12-16 18:02:16 +0000
committerNick Clifton <nickc@redhat.com>2002-12-16 18:02:16 +0000
commit939ba9d0fcf7265d9c8920f8dcfda5263268b034 (patch)
tree7305249914abdc6c46661ea7c9b6733ee813220e /ld
parent273f84299e5c9d87fae959920f2f3b728d553e75 (diff)
downloadfsf-binutils-gdb-939ba9d0fcf7265d9c8920f8dcfda5263268b034.zip
fsf-binutils-gdb-939ba9d0fcf7265d9c8920f8dcfda5263268b034.tar.gz
fsf-binutils-gdb-939ba9d0fcf7265d9c8920f8dcfda5263268b034.tar.bz2
Add support to skip import libraries for performance reasons and instead
use the direct auto-import of dll's
Diffstat (limited to 'ld')
-rw-r--r--ld/ChangeLog30
-rw-r--r--ld/Makefile.in2
-rw-r--r--ld/aclocal.m418
-rwxr-xr-xld/configure2
-rw-r--r--ld/configure.in2
-rw-r--r--ld/deffile.h54
-rw-r--r--ld/emultempl/pe.em63
-rw-r--r--ld/pe-dll.c83
-rw-r--r--ld/sysdep.h26
9 files changed, 208 insertions, 72 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index 74c9200..75d04d9 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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.
diff --git a/ld/Makefile.in b/ld/Makefile.in
index 84b3672..8defa7e 100644
--- a/ld/Makefile.in
+++ b/ld/Makefile.in
@@ -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)
diff --git a/ld/aclocal.m4 b/ld/aclocal.m4
index 6111817..7b50bb9 100644
--- a/ld/aclocal.m4
+++ b/ld/aclocal.m4
@@ -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.
diff --git a/ld/configure b/ld/configure
index 2b3f531..baeaf28 100755
--- a/ld/configure
+++ b/ld/configure
@@ -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
diff --git a/ld/configure.in b/ld/configure.in
index b067e96..12efccc 100644
--- a/ld/configure.in
+++ b/ld/configure.in
@@ -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
diff --git a/ld/deffile.h b/ld/deffile.h
index efd7834..09f8407 100644
--- a/ld/deffile.h
+++ b/ld/deffile.h
@@ -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 */
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index ca97023..d350ee8 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -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.
diff --git a/ld/pe-dll.c b/ld/pe-dll.c
index 1c870e2..45f54e4 100644
--- a/ld/pe-dll.c
+++ b/ld/pe-dll.c
@@ -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;
-
- imp = def_file_add_import (pe_def_file, erva + name_rva, dll_name,
- i, 0);
+ /* Pointer to the function address vector. */
+ unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);
+ int is_data = 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;
diff --git a/ld/sysdep.h b/ld/sysdep.h
index 24688a6..7151f14 100644
--- a/ld/sysdep.h
+++ b/ld/sysdep.h
@@ -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