Add support to skip import libraries for performance reasons and instead
authorNick Clifton <nickc@redhat.com>
Mon, 16 Dec 2002 18:02:16 +0000 (18:02 +0000)
committerNick Clifton <nickc@redhat.com>
Mon, 16 Dec 2002 18:02:16 +0000 (18:02 +0000)
use the direct auto-import of dll's

ld/ChangeLog
ld/Makefile.in
ld/aclocal.m4
ld/configure
ld/configure.in
ld/deffile.h
ld/emultempl/pe.em
ld/pe-dll.c
ld/sysdep.h

index 74c92009e76100af7d0e9e60ecde0561c5bf99ca..75d04d928617d8216c5233e9f10885866540c7f7 100644 (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.
index 84b36724c51bb6b69dff09b47ad3f0174616580f..8defa7e75cea637ef63e31594b1e5a65449e6045 100644 (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)
index 6111817b29be5dce268febb0c297bafb75b17bd9..7b50bb9050f18ccc5397a6bfef58885e67683a62 100644 (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.
index 2b3f531903957878bb8403b7dd8ab77279810c93..baeaf28a13a152029311079ca5d9929cf487a200 100755 (executable)
@@ -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
index b067e960c8e773d1a027f21df42b9ba95acd0006..12efcccd7212f64dbf5d6e2a3d09b6fe49ac2e32 100644 (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
index efd7834887201eb81791be8615101c69804f5d87..09f84071e1d9a94795953f1a2990fa6a1a4aa9ca 100644 (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 */
index ca970238ce2c2223d791ef19140f401e3488ca4c..d350ee8bfcb2a9f271853487c26e3febf5bf11fb 100644 (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 ()
 }
 \f
 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)
 }
 \f
 static char *
-gld_${EMULATION_NAME}_get_script(isfile)
+gld_${EMULATION_NAME}_get_script (isfile)
      int *isfile;
 EOF
 # Scripts compiled in.
index 1c870e29953dc56a7057e596452b6956769b5550..45f54e4df010bb18eb76ca1e7390c6c6eee871a5 100644 (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;
-
-      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;
index 24688a6b66848cb6334e34c3425d86b4e1ea9e26..7151f14adfa1886c6561e9b472c668e0dd15a1a4 100644 (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