2001-09-12 Paul Sokolovsky <Paul.Sokolovsky@technologist.com>
authorCharles Wilson <cygwin@cwilson.fastmail.fm>
Wed, 12 Sep 2001 15:58:10 +0000 (15:58 +0000)
committerCharles Wilson <cygwin@cwilson.fastmail.fm>
Wed, 12 Sep 2001 15:58:10 +0000 (15:58 +0000)
        * emultempl/pe.em(make_import_fixup): change signature to
        take asection as well as arelec; we need this for proper
        error reporting.  Only call pe_create_import_fixup() if
        there is no attempt to add a constant addend to the reloc;
        otherwise, report error condition.
        * pe-dll.c(pe_walk_relocs_of_symbol): change signature,
        since final argument is a pointer to make_import_fixup().
        Change call to cb() to match make_import_fixup() signature.
        (make_import_fixup_mark): make buffer_len unsigned.
        * pe-dll.h: change signature of pe_walk_relocs_of_symbol.
2001-09-12  Charles Wilson  <cwilson@ece.gatech.edu>
        * ld.texinfo: add verbose documentation for auto-import
        direct-addressing workaround, to compliment the terse
        error message.

ld/ChangeLog
ld/emultempl/pe.em
ld/ld.texinfo
ld/pe-dll.c
ld/pe-dll.h

index 2abef7e..466aa0b 100644 (file)
@@ -1,3 +1,22 @@
+2001-09-12  Paul Sokolovsky  <Paul.Sokolovsky@technologist.com>
+
+       * emultempl/pe.em(make_import_fixup): change signature to
+       take asection as well as arelec; we need this for proper
+       error reporting.  Only call pe_create_import_fixup() if 
+       there is no attempt to add a constant addend to the reloc;
+       otherwise, report error condition.
+       * pe-dll.c(pe_walk_relocs_of_symbol): change signature,
+       since final argument is a pointer to make_import_fixup().
+       Change call to cb() to match make_import_fixup() signature.
+       (make_import_fixup_mark): make buffer_len unsigned.
+       * pe-dll.h: change signature of pe_walk_relocs_of_symbol.
+
+2001-09-12  Charles Wilson  <cwilson@ece.gatech.edu>
+
+       * ld.texinfo: add verbose documentation for auto-import
+       direct-addressing workaround, to compliment the terse 
+       error message.
+
 2001-09-12  Andrew MacLeod  <amacleod@redhat.com>
 
      * scripttempl/v850.sc: Add gcc_except_table sections.
index baca171..093c081 100644 (file)
@@ -127,7 +127,7 @@ static void set_pe_stack_heap PARAMS ((char *, char *));
 static boolean pe_undef_cdecl_match
   PARAMS ((struct bfd_link_hash_entry *, PTR));
 static void pe_fixup_stdcalls PARAMS ((void));
-static int make_import_fixup PARAMS ((arelent *));
+static int make_import_fixup PARAMS ((arelent *, asection *));
 static void pe_find_data_imports PARAMS ((void));
 #endif
 
@@ -845,20 +845,36 @@ pe_fixup_stdcalls ()
 }
 
 static int
-make_import_fixup (rel)
+make_import_fixup (rel, s)
   arelent *rel;
+  asection *s;
 {
   struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
-/*
-  bfd *b;
-*/
 
   if (pe_dll_extra_pe_debug)
     {
       printf ("arelent: %s@%#x: add=%li\n", sym->name,
               (int) rel->address, rel->addend);
     }
-  pe_create_import_fixup (rel);
+
+  {
+    int addend = 0;
+    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);
+      }
+
+    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");
+      }
+  }
+
   return 1;
 }
 
index 69bc3a7..209875c 100644 (file)
@@ -1726,9 +1726,103 @@ uwin, pw, etc.  For instance, cygwin DLLs typically use
 
 @kindex --enable-auto-import
 @item --enable-auto-import
-Do sophisticalted linking of @code{_symbol} to @code{__imp__symbol} for 
+Do sophisticated linking of @code{_symbol} to @code{__imp__symbol} for 
 DATA imports from DLLs, and create the necessary thunking symbols when 
-building the DLLs with those DATA exports.
+building the DLLs with those DATA exports.  This generally will 'just 
+work' -- but sometimes you may see this message:
+
+"variable '<var>' can't be auto-imported. Please read the 
+documentation for ld's @code{--enable-auto-import} for details."
+
+This message occurs when some (sub)expression accesses an address 
+ultimately given by the sum of two constants (Win32 import tables only 
+allow one).  Instances where this may occur include accesses to member 
+fields of struct variables imported from a DLL, as well as using a 
+constant index into an array variable imported from a DLL.  There are
+several ways to address this difficulty.
+
+One 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:
+
+@example
+extern type extern_array[];
+extern_array[1] --> 
+   @{ volatile type *t=extern_array; t[1] @}
+@end example
+
+or
+
+@example
+extern type extern_array[];
+extern_array[1] --> 
+   @{ volatile int t=1; extern_array[t] @}
+@end example
+
+For structs, the only option is to make the struct itself variable:
+
+@example
+extern struct s extern_struct;
+extern_struct.field --> 
+   @{ volatile struct s *t=&extern_struct; t->field @}
+@end example
+
+A second 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
+building a DLL, building client code that will link to the DLL, or 
+merely building/linking to a static library.   In making the choice 
+between the various methods of resolving the 'direct address with 
+constant offset' problem, you should consider typical real-world usage:
+
+Original:
+@example
+--foo.h
+extern int arr[];
+--foo.c
+#include "foo.h"
+void main(int argc, char **argv)@{
+  printf("%d\n",arr[1]);
+@}
+@end example
+
+Solution 1:
+@example
+--foo.h
+extern int arr[];
+--foo.c
+#include "foo.h"
+void main(int argc, char **argv)@{
+  /* This workaround is for win32 and cygwin; do not "optimize" */
+  volatile int *parr = arr;
+  printf("%d\n",parr[1]);
+@}
+@end example
+
+Solution 2:
+@example
+--foo.h
+/* Note: auto-export is assumed (no __declspec(dllexport)) */
+#if (defined(_WIN32) || defined(__CYGWIN__)) && \
+  !(defined(FOO_BUILD_DLL) || defined(FOO_STATIC))
+#define FOO_IMPORT __declspec(dllimport)
+#else
+#define FOO_IMPORT
+#endif
+extern FOO_IMPORT int arr[];
+--foo.c
+#include "foo.h"
+void main(int argc, char **argv)@{
+  printf("%d\n",arr[1]);
+@}
+@end example
+
+A third 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).
 
 @kindex --disable-auto-import
 @item --disable-auto-import
index e47a17f..9914eac 100644 (file)
@@ -982,10 +982,10 @@ void
 pe_walk_relocs_of_symbol (info, name, cb)
      struct bfd_link_info *info;
      CONST char *name;
-     int (*cb) (arelent *);
+     int (*cb) (arelent *, asection *);
 {
   bfd *b;
-  struct sec *s;
+  asection *s;
 
   for (b = info->input_bfds; b; b = b->link_next)
     {
@@ -1003,7 +1003,7 @@ pe_walk_relocs_of_symbol (info, name, cb)
              && s->output_section == bfd_abs_section_ptr)
            continue;
 
-         current_sec=s;
+         current_sec = s;
 
          symsize = bfd_get_symtab_upper_bound (b);
          symbols = (asymbol **) xmalloc (symsize);
@@ -1016,7 +1016,7 @@ pe_walk_relocs_of_symbol (info, name, cb)
          for (i = 0; i < nrelocs; i++)
            {
              struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
-             if (!strcmp(name,sym->name)) cb(relocs[i]);
+             if (!strcmp(name,sym->name)) cb(relocs[i], s);
            }
          free (relocs);
          /* Warning: the allocated symbols are remembered in BFD and reused
@@ -1908,7 +1908,7 @@ make_import_fixup_mark (rel)
   /* we convert reloc to symbol, for later reference */
   static int counter;
   static char *fixup_name = NULL;
-  static int buffer_len = 0;
+  static unsigned int buffer_len = 0;
   
   struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
   
index b1c5c75..f5e9324 100644 (file)
@@ -48,7 +48,7 @@ extern void pe_exe_fill_sections PARAMS ((bfd *, struct bfd_link_info *));
 
 extern void pe_walk_relocs_of_symbol PARAMS ((struct bfd_link_info * info,
                                             CONST char *name,
-                                            int (*cb) (arelent *)));
+                                            int (*cb) (arelent *, asection *)));
 
 extern void pe_create_import_fixup PARAMS ((arelent * rel));
 #endif /* PE_DLL_H */