From 0d888aac30824dd7fc2481efefd0a0f4808812e8 Mon Sep 17 00:00:00 2001 From: Charles Wilson Date: Wed, 12 Sep 2001 15:58:10 +0000 Subject: [PATCH] 2001-09-12 Paul Sokolovsky * 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 * ld.texinfo: add verbose documentation for auto-import direct-addressing workaround, to compliment the terse error message. --- ld/ChangeLog | 19 +++++++++ ld/emultempl/pe.em | 28 ++++++++++--- ld/ld.texinfo | 98 +++++++++++++++++++++++++++++++++++++++++++++- ld/pe-dll.c | 10 ++--- ld/pe-dll.h | 2 +- 5 files changed, 143 insertions(+), 14 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index 2abef7e7688..466aa0ba24a 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,22 @@ +2001-09-12 Paul Sokolovsky + + * 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 + + * ld.texinfo: add verbose documentation for auto-import + direct-addressing workaround, to compliment the terse + error message. + 2001-09-12 Andrew MacLeod * scripttempl/v850.sc: Add gcc_except_table sections. diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index baca171f1bc..093c0815439 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -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; } diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 69bc3a789c5..209875c7b0e 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -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 '' 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 diff --git a/ld/pe-dll.c b/ld/pe-dll.c index e47a17fd3be..9914eac8395 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -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; diff --git a/ld/pe-dll.h b/ld/pe-dll.h index b1c5c75f874..f5e9324882b 100644 --- a/ld/pe-dll.h +++ b/ld/pe-dll.h @@ -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 */ -- 2.30.2