From 2fa9fc65a53ee02ca5dd15d12ebb903a22207051 Mon Sep 17 00:00:00 2001 From: Nick Clifton Date: Thu, 14 Nov 2002 18:03:17 +0000 Subject: [PATCH] Add --enable-auto-import extension. --- include/ChangeLog | 5 ++ include/bfdlink.h | 5 ++ ld/ChangeLog | 16 +++++ ld/emultempl/pe.em | 48 +++++++++------ ld/ld.texinfo | 22 ++++++- ld/ldmain.c | 28 ++++----- ld/pe-dll.c | 143 ++++++++++++++++++++++++++++++++++++++++++--- ld/pe-dll.h | 2 +- 8 files changed, 224 insertions(+), 45 deletions(-) diff --git a/include/ChangeLog b/include/ChangeLog index 425f3db54cd..2dfed5ae4ce 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2002-11-14 Egor Duda + + * bfdlink.h (struct bfd_link_info): Add new boolean + field pei386_runtime_pseudo_reloc. + 2002-11-11 Svein E. Seldal * opcode/tic4x.h: Added new opcodes and corrected some bugs. Add diff --git a/include/bfdlink.h b/include/bfdlink.h index 4998fe3dbf7..9263bcc126d 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -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; diff --git a/ld/ChangeLog b/ld/ChangeLog index 0e37adbe823..3e98cde6e09 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,19 @@ +2002-11-14 Egor Duda + + * 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 * ldlang.c (lang_add_section): Discard debugging sections that have diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 0eb3eeda57c..e2342d4325f 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -12,19 +12,19 @@ cat >>e${EMULATION_NAME}.c <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; } diff --git a/ld/ld.texinfo b/ld/ld.texinfo index edf628d36d0..03702dc6c7b 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -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. diff --git a/ld/ldmain.c b/ld/ldmain.c index 6e9909f44d1..ef7b4428648 100644 --- a/ld/ldmain.c +++ b/ld/ldmain.c @@ -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; diff --git a/ld/pe-dll.c b/ld/pe-dll.c index af0cd51a8b9..d9e40783e35 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -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"); + } + } } diff --git a/ld/pe-dll.h b/ld/pe-dll.h index b8fcdb93431..6273e3bccc2 100644 --- a/ld/pe-dll.h +++ b/ld/pe-dll.h @@ -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 */ -- 2.30.2