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.
This commit is contained in:
parent
cedacdc05a
commit
0d888aac30
5 changed files with 143 additions and 14 deletions
19
ld/ChangeLog
19
ld/ChangeLog
|
@ -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>
|
2001-09-12 Andrew MacLeod <amacleod@redhat.com>
|
||||||
|
|
||||||
* scripttempl/v850.sc: Add gcc_except_table sections.
|
* scripttempl/v850.sc: Add gcc_except_table sections.
|
||||||
|
|
|
@ -127,7 +127,7 @@ static void set_pe_stack_heap PARAMS ((char *, char *));
|
||||||
static boolean pe_undef_cdecl_match
|
static boolean pe_undef_cdecl_match
|
||||||
PARAMS ((struct bfd_link_hash_entry *, PTR));
|
PARAMS ((struct bfd_link_hash_entry *, PTR));
|
||||||
static void pe_fixup_stdcalls PARAMS ((void));
|
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));
|
static void pe_find_data_imports PARAMS ((void));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -845,20 +845,36 @@ pe_fixup_stdcalls ()
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
make_import_fixup (rel)
|
make_import_fixup (rel, s)
|
||||||
arelent *rel;
|
arelent *rel;
|
||||||
|
asection *s;
|
||||||
{
|
{
|
||||||
struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
|
struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
|
||||||
/*
|
|
||||||
bfd *b;
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (pe_dll_extra_pe_debug)
|
if (pe_dll_extra_pe_debug)
|
||||||
{
|
{
|
||||||
printf ("arelent: %s@%#x: add=%li\n", sym->name,
|
printf ("arelent: %s@%#x: add=%li\n", sym->name,
|
||||||
(int) rel->address, rel->addend);
|
(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;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1726,9 +1726,103 @@ uwin, pw, etc. For instance, cygwin DLLs typically use
|
||||||
|
|
||||||
@kindex --enable-auto-import
|
@kindex --enable-auto-import
|
||||||
@item --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
|
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
|
@kindex --disable-auto-import
|
||||||
@item --disable-auto-import
|
@item --disable-auto-import
|
||||||
|
|
10
ld/pe-dll.c
10
ld/pe-dll.c
|
@ -982,10 +982,10 @@ void
|
||||||
pe_walk_relocs_of_symbol (info, name, cb)
|
pe_walk_relocs_of_symbol (info, name, cb)
|
||||||
struct bfd_link_info *info;
|
struct bfd_link_info *info;
|
||||||
CONST char *name;
|
CONST char *name;
|
||||||
int (*cb) (arelent *);
|
int (*cb) (arelent *, asection *);
|
||||||
{
|
{
|
||||||
bfd *b;
|
bfd *b;
|
||||||
struct sec *s;
|
asection *s;
|
||||||
|
|
||||||
for (b = info->input_bfds; b; b = b->link_next)
|
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)
|
&& s->output_section == bfd_abs_section_ptr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
current_sec=s;
|
current_sec = s;
|
||||||
|
|
||||||
symsize = bfd_get_symtab_upper_bound (b);
|
symsize = bfd_get_symtab_upper_bound (b);
|
||||||
symbols = (asymbol **) xmalloc (symsize);
|
symbols = (asymbol **) xmalloc (symsize);
|
||||||
|
@ -1016,7 +1016,7 @@ pe_walk_relocs_of_symbol (info, name, cb)
|
||||||
for (i = 0; i < nrelocs; i++)
|
for (i = 0; i < nrelocs; i++)
|
||||||
{
|
{
|
||||||
struct symbol_cache_entry *sym = *relocs[i]->sym_ptr_ptr;
|
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);
|
free (relocs);
|
||||||
/* Warning: the allocated symbols are remembered in BFD and reused
|
/* 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 */
|
/* we convert reloc to symbol, for later reference */
|
||||||
static int counter;
|
static int counter;
|
||||||
static char *fixup_name = NULL;
|
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;
|
struct symbol_cache_entry *sym = *rel->sym_ptr_ptr;
|
||||||
|
|
||||||
|
|
|
@ -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,
|
extern void pe_walk_relocs_of_symbol PARAMS ((struct bfd_link_info * info,
|
||||||
CONST char *name,
|
CONST char *name,
|
||||||
int (*cb) (arelent *)));
|
int (*cb) (arelent *, asection *)));
|
||||||
|
|
||||||
extern void pe_create_import_fixup PARAMS ((arelent * rel));
|
extern void pe_create_import_fixup PARAMS ((arelent * rel));
|
||||||
#endif /* PE_DLL_H */
|
#endif /* PE_DLL_H */
|
||||||
|
|
Loading…
Reference in a new issue