Add --enable-auto-import extension.
authorNick Clifton <nickc@redhat.com>
Thu, 14 Nov 2002 18:03:17 +0000 (18:03 +0000)
committerNick Clifton <nickc@redhat.com>
Thu, 14 Nov 2002 18:03:17 +0000 (18:03 +0000)
include/ChangeLog
include/bfdlink.h
ld/ChangeLog
ld/emultempl/pe.em
ld/ld.texinfo
ld/ldmain.c
ld/pe-dll.c
ld/pe-dll.h

index 425f3db54cdeb5fec12019714cc39285a9d30ba6..2dfed5ae4ce125f2a8a40eef832718ee11689060 100644 (file)
@@ -1,3 +1,8 @@
+2002-11-14  Egor Duda  <deo@logos-m.ru>
+
+       * bfdlink.h (struct bfd_link_info): Add new boolean
+       field pei386_runtime_pseudo_reloc.
+
 2002-11-11  Svein E. Seldal  <Svein.Seldal@solidas.com>
 
        * opcode/tic4x.h: Added new opcodes and corrected some bugs.  Add
index 4998fe3dbf7d0dcc835fb6d633a73bef1b7bcc78..9263bcc126d6ebc48f3b71a4483dae78f0148189 100644 (file)
@@ -340,6 +340,11 @@ struct bfd_link_info
      is explicitly requested by the user, -1 if enabled by default.  */
   int pei386_auto_import;
 
+  /* Non-zero if runtime relocs for DATA items with non-zero addends
+     in pei386 DLLs should be generated.  Set to 1 if this feature
+     is explicitly requested by the user, -1 if enabled by default.  */
+  int pei386_runtime_pseudo_reloc;
+
   /* True if non-PLT relocs should be merged into one reloc section
      and sorted so that relocs against the same symbol come together.  */
   boolean combreloc;
index 0e37adbe823b8c5a98a57d82216f326e88ecb95b..3e98cde6e09d0a8bf07a3804009cdfd957d9018a 100644 (file)
@@ -1,3 +1,19 @@
+2002-11-14  Egor Duda  <deo@logos-m.ru>
+
+       * ldmain.c (main): Make runtime relocs disabled by default. Remove
+       assignment which has no effect.
+       * pe-dll.h (pe_create_import_fixup): Change prototype.
+       * pe-dll.c (make_runtime_pseudo_reloc): New function.
+       (pe_create_runtime_relocator_reference): Ditto.
+       (pe_create_import_fixup): Handle relocations with non-zero addends.
+       * emultempl/pe.em: Add options --enable-runtime-pseudo-reloc and
+       --disable-runtime-pseudo-reloc.
+       (make_import_fixup): Handle relocations with non-zero addends. Create
+       an external reference to _pei386_runtime_relocator symbol if at least
+       one pseudo reloc was created.
+       * ld.texinfo: Document --enable-runtime-pseudo-reloc and
+       --disable-runtime-pseudo-reloc options.
+
 2002-11-12  Earl Chew <earl_chew@agilent.com>
 
        * ldlang.c (lang_add_section): Discard debugging sections that have
index 0eb3eeda57c71f05104dd8589196d68634799c67..e2342d4325faedcfe5b260af34fb8314c22c9d0c 100644 (file)
@@ -12,19 +12,19 @@ cat >>e${EMULATION_NAME}.c <<EOF
    Copyright 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    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
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   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
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 /* For WINDOWS_NT */
 /* The original file generated returned different default scripts depending
@@ -174,6 +174,7 @@ gld_${EMULATION_NAME}_before_parse()
   config.dynamic_link = true;
   config.has_shared = 1;
   link_info.pei386_auto_import = -1;
+  link_info.pei386_runtime_pseudo_reloc = false;
 
 #if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2)
 #if defined TARGET_IS_mipspe || defined TARGET_IS_armpe
@@ -222,6 +223,10 @@ gld_${EMULATION_NAME}_before_parse()
 #define OPTION_DLL_DISABLE_AUTO_IMPORT (OPTION_DLL_ENABLE_AUTO_IMPORT + 1)
 #define OPTION_ENABLE_EXTRA_PE_DEBUG   (OPTION_DLL_DISABLE_AUTO_IMPORT + 1)
 #define OPTION_EXCLUDE_LIBS            (OPTION_ENABLE_EXTRA_PE_DEBUG + 1)
+#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC \
+                                       (OPTION_EXCLUDE_LIBS + 1)
+#define OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC        \
+                                       (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1)
 
 static struct option longopts[] = {
   /* PE options */
@@ -263,6 +268,8 @@ static struct option longopts[] = {
   {"enable-auto-import", no_argument, NULL, OPTION_DLL_ENABLE_AUTO_IMPORT},
   {"disable-auto-import", no_argument, NULL, OPTION_DLL_DISABLE_AUTO_IMPORT},
   {"enable-extra-pe-debug", no_argument, NULL, OPTION_ENABLE_EXTRA_PE_DEBUG},
+  {"enable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC},
+  {"disable-runtime-pseudo-reloc", no_argument, NULL, OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC},
 #endif
   {NULL, no_argument, NULL, 0}
 };
@@ -352,6 +359,10 @@ gld_${EMULATION_NAME}_list_options (file)
   fprintf (file, _("  --enable-auto-import               Do sophistcated linking of _sym to \n\
                                        __imp_sym for DATA references\n"));
   fprintf (file, _("  --disable-auto-import              Do not auto-import DATA items from DLLs\n"));
+  fprintf (file, _("  --enable-runtime-pseudo-reloc      Work around auto-import limitations by\n\
+                                       adding pseudo-relocations resolved at runtime.\n"));
+  fprintf (file, _("  --disable-runtime-pseudo-reloc     Do not add runtime pseudo-relocations for\n\
+                                       auto-imported DATA.\n"));
   fprintf (file, _("  --enable-extra-pe-debug            Enable verbose debug output when building\n\
                                        or linking to DLLs (esp. auto-import)\n"));
 #endif
@@ -633,6 +644,12 @@ gld_${EMULATION_NAME}_parse_args(argc, argv)
     case OPTION_DLL_DISABLE_AUTO_IMPORT:
       link_info.pei386_auto_import = 0;
       break;
+    case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 1;
+      break;
+    case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC:
+      link_info.pei386_runtime_pseudo_reloc = 0;
+      break;
     case OPTION_ENABLE_EXTRA_PE_DEBUG:
       pe_dll_extra_pe_debug = 1;
       break;
@@ -877,14 +894,7 @@ make_import_fixup (rel, s)
     einfo (_("%C: Cannot get section contents - auto-import exception\n"),
           s->owner, s, rel->address);
 
-  if (addend == 0)
-    pe_create_import_fixup (rel);
-  else
-    {
-      einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
-            s->owner, s, rel->address, sym->name);
-      einfo ("%X");
-    }
+  pe_create_import_fixup (rel, s, addend);
 
   return 1;
 }
index edf628d36d0358ed278341c8863c4d287a91dfd7..03702dc6c7b9346b6788f8ca90ea73900d63bdaa 100644 (file)
@@ -1808,7 +1808,11 @@ the warning, and exit.
 There are several ways to address this difficulty, regardless of the
 data type of the exported variable:
 
-One solution is to force one of the 'constants' to be a variable -- 
+One way is to use --enable-runtime-pseudo-reloc switch. This leaves the task
+of adjusting references in your client code for runtime environment, so
+this method works only when runtime environtment supports this feature.
+
+A second solution is to force one of the 'constants' to be a variable -- 
 that is, unknown and un-optimizable at compile time.  For arrays, 
 there are two possibilities: a) make the indexee (the array's address) 
 a variable, or b) make the 'constant' index a variable.  Thus:
@@ -1844,7 +1848,7 @@ extern_ll -->
   @{ volatile long long * local_ll=&extern_ll; *local_ll @}
 @end example
 
-A second method of dealing with this difficulty is to abandon
+A third method of dealing with this difficulty is to abandon
 'auto-import' for the offending symbol and mark it with 
 @code{__declspec(dllimport)}.  However, in practice that
 requires using compile-time #defines to indicate whether you are
@@ -1895,7 +1899,7 @@ void main(int argc, char **argv)@{
 @}
 @end example
 
-A third way to avoid this problem is to re-code your 
+A fourth way to avoid this problem is to re-code your 
 library to use a functional interface rather than a data interface
 for the offending variables (e.g. set_foo() and get_foo() accessor
 functions).
@@ -1905,6 +1909,18 @@ functions).
 Do not attempt to do sophisticalted linking of @code{_symbol} to 
 @code{__imp__symbol} for DATA imports from DLLs.
 
+@kindex --enable-runtime-pseudo-reloc
+@item --enable-runtime-pseudo-reloc
+If your code contains expressions described in --enable-auto-import section,
+that is, DATA imports from DLL with non-zero offset, this switch will create
+a vector of 'runtime pseudo relocations' which can be used by runtime
+environment to adjust references to such data in your client code. 
+
+@kindex --disable-runtime-pseudo-reloc
+@item --disable-runtime-pseudo-reloc
+Do not create pseudo relocations for non-zero offset DATA imports from
+DLLs.  This is the default.
+
 @kindex --enable-extra-pe-debug
 @item --enable-extra-pe-debug
 Show additional debug info related to auto-import symbol thunking.
index 6e9909f44d12dee88fa57390d7161ada6b9b92fa..ef7b4428648db1a7001c0c8fbbc42fdd93641b9c 100644 (file)
@@ -4,22 +4,22 @@
    Free Software Foundation, Inc.
    Written by Steve Chamberlain steve@cygnus.com
 
-This file is part of GLD, the Gnu Linker.
+   This file is part of GLD, the Gnu Linker.
 
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+   GLD is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
 
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   GLD is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with GLD; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 #include "bfd.h"
 #include "sysdep.h"
@@ -261,8 +261,8 @@ main (argc, argv)
   link_info.eh_frame_hdr = false;
   link_info.flags = (bfd_vma) 0;
   link_info.flags_1 = (bfd_vma) 0;
-  link_info.pei386_auto_import = false;
   link_info.pei386_auto_import = -1;
+  link_info.pei386_runtime_pseudo_reloc = false;
   link_info.combreloc = true;
   link_info.spare_dynamic_tags = 5;
   link_info.common_skip_ar_aymbols = bfd_link_common_skip_none;
index af0cd51a8b9cb9ae9eb3abb5afe8746fbb23dbaf..d9e40783e35588dfdf8ac9ad27746d4a3e98e113 100644 (file)
@@ -141,6 +141,7 @@ static bfd *filler_bfd;
 static struct sec *edata_s, *reloc_s;
 static unsigned char *edata_d, *reloc_d;
 static size_t edata_sz, reloc_sz;
+static int runtime_pseudo_relocs_created = 0;
 
 typedef struct
   {
@@ -305,6 +306,10 @@ static bfd *make_singleton_name_thunk PARAMS ((const char *, bfd *));
 static char *make_import_fixup_mark PARAMS ((arelent *));
 static bfd *make_import_fixup_entry
   PARAMS ((const char *, const char *, const char *, bfd *));
+static bfd *make_runtime_pseudo_reloc
+  PARAMS ((const char *, const char *, int, bfd *));
+static bfd *pe_create_runtime_relocator_reference
+  PARAMS ((bfd *));
 static unsigned int pe_get16 PARAMS ((bfd *, int));
 static unsigned int pe_get32 PARAMS ((bfd *, int));
 static unsigned int pe_as32 PARAMS ((void *));
@@ -2094,15 +2099,112 @@ make_import_fixup_entry (name, fixup_name, dll_symname, parent)
   return abfd;
 }
 
+/*     .section        .rdata_runtime_pseudo_reloc
+       .long           addend
+       .rva            __fuNN_SYM (pointer to reference (address) in text)  */
+
+static bfd *
+make_runtime_pseudo_reloc (name, fixup_name, addend, parent)
+     const char *name ATTRIBUTE_UNUSED;
+     const char *fixup_name;
+     int addend;
+     bfd *parent;
+{
+  asection *rt_rel;
+  unsigned char *rt_rel_d;
+  char *oname;
+  bfd *abfd;
+
+  oname = (char *) xmalloc (20);
+  sprintf (oname, "rtr%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pe_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = (asymbol **) xmalloc (2 * sizeof (asymbol *));
+  rt_rel = quick_section (abfd, ".rdata_runtime_pseudo_reloc", SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0);
+
+  bfd_set_section_size (abfd, rt_rel, 8);
+  rt_rel_d = (unsigned char *) xmalloc (8);
+  rt_rel->contents = rt_rel_d;
+  memset (rt_rel_d, 0, 8);
+  bfd_put_32 (abfd, addend, rt_rel_d);
+
+  quick_reloc (abfd, 4, BFD_RELOC_RVA, 1);
+  save_relocs (rt_rel);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
+/*     .section        .rdata
+       .rva            __pei386_runtime_relocator */
+
+static bfd *
+pe_create_runtime_relocator_reference (parent)
+     bfd *parent;
+{
+  asection *extern_rt_rel;
+  unsigned char *extern_rt_rel_d;
+  char *oname;
+  bfd *abfd;
+
+  oname = (char *) xmalloc (20);
+  sprintf (oname, "ertr%06d.o", tmp_seq);
+  tmp_seq++;
+
+  abfd = bfd_create (oname, parent);
+  bfd_find_target (pe_details->object_target, abfd);
+  bfd_make_writable (abfd);
+
+  bfd_set_format (abfd, bfd_object);
+  bfd_set_arch_mach (abfd, pe_details->bfd_arch, 0);
+
+  symptr = 0;
+  symtab = (asymbol **) xmalloc (2 * sizeof (asymbol *));
+  extern_rt_rel = quick_section (abfd, ".rdata", SEC_HAS_CONTENTS, 2);
+
+  quick_symbol (abfd, "", "__pei386_runtime_relocator", "", UNDSEC, BSF_NO_FLAGS, 0);
+
+  bfd_set_section_size (abfd, extern_rt_rel, 4);
+  extern_rt_rel_d = (unsigned char *) xmalloc (4);
+  extern_rt_rel->contents = extern_rt_rel_d;
+
+  quick_reloc (abfd, 0, BFD_RELOC_RVA, 1);
+  save_relocs (extern_rt_rel);
+
+  bfd_set_symtab (abfd, symtab, symptr);
+
+  bfd_set_section_contents (abfd, extern_rt_rel, extern_rt_rel_d, 0, 4);
+
+  bfd_make_readable (abfd);
+  return abfd;
+}
+
 void
-pe_create_import_fixup (rel)
+pe_create_import_fixup (rel, s, addend)
      arelent *rel;
+     asection *s;
+     int addend;
 {
   char buf[300];
   struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
   struct bfd_link_hash_entry *name_thunk_sym;
   const char *name = sym->name;
   char *fixup_name = make_import_fixup_mark (rel);
+  bfd *b;
 
   sprintf (buf, U ("_nm_thnk_%s"), name);
 
@@ -2117,14 +2219,39 @@ pe_create_import_fixup (rel)
       config.text_read_only = false;
     }
 
-  {
-    extern char * pe_data_import_dll;
-    char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
+  if (addend == 0 || link_info.pei386_runtime_pseudo_reloc)
+    {
+      extern char * pe_data_import_dll;
+      char * dll_symname = pe_data_import_dll ? pe_data_import_dll : "unknown";
 
-    bfd *b = make_import_fixup_entry (name, fixup_name, dll_symname,
-                                     output_bfd);
-    add_bfd_to_link (b, b->filename, &link_info);
-  }
+      b = make_import_fixup_entry (name, fixup_name, dll_symname, output_bfd);
+      add_bfd_to_link (b, b->filename, &link_info);
+    }
+
+  if (addend != 0)
+    {
+      if (link_info.pei386_runtime_pseudo_reloc)
+       {
+         if (pe_dll_extra_pe_debug)
+           printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n",
+                  fixup_name, addend);
+         b = make_runtime_pseudo_reloc (name, fixup_name, addend, output_bfd);
+         add_bfd_to_link (b, b->filename, &link_info);
+
+         if (runtime_pseudo_relocs_created == 0)
+           {
+             b = pe_create_runtime_relocator_reference (output_bfd);
+             add_bfd_to_link (b, b->filename, &link_info);
+           }
+         runtime_pseudo_relocs_created++;
+       } 
+      else
+       {
+         einfo (_("%C: variable '%T' can't be auto-imported. Please read the documentation for ld's --enable-auto-import for details.\n"),
+                s->owner, s, rel->address, sym->name);
+         einfo ("%X");
+       }
+    }
 }
 
 
index b8fcdb93431a4d0e0c846e95d52e2180f4a9c93e..6273e3bccc2f7f5935cee199f92573dea6be555e 100644 (file)
@@ -50,5 +50,5 @@ extern void pe_walk_relocs_of_symbol PARAMS ((struct bfd_link_info * info,
                                              const char *name,
                                              int (*cb) (arelent *, asection *)));
 
-extern void pe_create_import_fixup PARAMS ((arelent * rel));
+extern void pe_create_import_fixup PARAMS ((arelent * rel, asection *, int));
 #endif /* PE_DLL_H */