From 6cb442d374a04461bbdd63ef85ce370c51a06e4f Mon Sep 17 00:00:00 2001 From: Kai Tietz Date: Fri, 14 Nov 2008 15:13:05 +0000 Subject: [PATCH] 2008-11-14 Kai Tietz * emultempl/pep.em (..._before_parse): initialize pei386_runtime_pseudo_reloc by version 2. (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1): New option. (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2): New option. (make_import_fixup): Use relocation size to read addend. * emultempl/pe.em (..._before_parse): initialize pei386_runtime_pseudo_reloc by version 1. (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1): New option. (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2): New option. * pe-dll.c (pe-dll.h): Remove useless include. (make_runtime_pseudo_reloc): Change addend to use bfd_vma. Handle the two variants of pseudo-relocation. (pe_create_import_fixup): Change addend to type bfd_vma. Modify for the two pseudo_relocation variants. (runtime_pseudp_reloc_v2_init): New static variable. * pe-dll.h (pe_create_import_fixup): Change addend argument type to bfd_vma. * pep-dll.h (pep_create_import_fixup): Likewise. * NEWS: Add comment. --- ld/ChangeLog | 22 ++++++++++ ld/NEWS | 6 +++ ld/emultempl/pe.em | 14 +++++- ld/emultempl/pep.em | 60 +++++++++++++++++++++++--- ld/pe-dll.c | 101 ++++++++++++++++++++++++++++---------------- ld/pe-dll.h | 2 +- ld/pep-dll.h | 2 +- 7 files changed, 161 insertions(+), 46 deletions(-) diff --git a/ld/ChangeLog b/ld/ChangeLog index e26ee7e6178..44160c9f2ad 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,25 @@ +2008-11-14 Kai Tietz + + * emultempl/pep.em (..._before_parse): initialize + pei386_runtime_pseudo_reloc by version 2. + (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1): New option. + (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2): New option. + (make_import_fixup): Use relocation size to read addend. + * emultempl/pe.em (..._before_parse): initialize + pei386_runtime_pseudo_reloc by version 1. + (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1): New option. + (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2): New option. + * pe-dll.c (pe-dll.h): Remove useless include. + (make_runtime_pseudo_reloc): Change addend to use bfd_vma. + Handle the two variants of pseudo-relocation. + (pe_create_import_fixup): Change addend to type bfd_vma. + Modify for the two pseudo_relocation variants. + (runtime_pseudp_reloc_v2_init): New static variable. + * pe-dll.h (pe_create_import_fixup): Change addend argument type + to bfd_vma. + * pep-dll.h (pep_create_import_fixup): Likewise. + * NEWS: Add comment. + 2008-11-14 Alan Modra * Makefile.am (spu_ovl.o_c): Add missing line continuations. diff --git a/ld/NEWS b/ld/NEWS index e28e3d84016..962c2dba36c 100644 --- a/ld/NEWS +++ b/ld/NEWS @@ -1,5 +1,11 @@ -*- text -*- +* Add to the PE/PE+ targets the support of two different kinds of + pseudo-relocations. They can be selected by the switches + --enable-runtime-pseudo-reloc-v1 and --enable-runtime-pseudo-reloc-v2. + For the switch --enable-runtime-pseudo-reloc it uses for 32-bit + runtime pseudo relocation version one, for 64-bit the version two. + Changes in 2.19: * Linker scripts support a new INSERT command that makes it easier to diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index b963d030918..43c0be348f3 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -146,7 +146,7 @@ gld_${EMULATION_NAME}_before_parse (void) config.dynamic_link = TRUE; config.has_shared = 1; link_info.pei386_auto_import = -1; - link_info.pei386_runtime_pseudo_reloc = -1; + link_info.pei386_runtime_pseudo_reloc = 1; /* Use by default version 1. */ #if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2) #if defined TARGET_IS_mipspe || defined TARGET_IS_armpe || defined TARGET_IS_arm_wince_pe @@ -203,6 +203,10 @@ gld_${EMULATION_NAME}_before_parse (void) (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC + 1) #define OPTION_LARGE_ADDRESS_AWARE \ (OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + 1) +#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 \ + (OPTION_LARGE_ADDRESS_AWARE + 1) +#define OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 \ + (OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1 + 1) static void gld${EMULATION_NAME}_add_options @@ -255,6 +259,8 @@ gld${EMULATION_NAME}_add_options {"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}, + {"enable-runtime-pseudo-reloc-v1", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1}, + {"enable-runtime-pseudo-reloc-v2", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2}, #endif {"large-address-aware", no_argument, NULL, OPTION_LARGE_ADDRESS_AWARE}, {NULL, no_argument, NULL, 0} @@ -639,6 +645,12 @@ gld${EMULATION_NAME}_handle_option (int optc) case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC: link_info.pei386_runtime_pseudo_reloc = 1; break; + case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1: + link_info.pei386_runtime_pseudo_reloc = 1; + break; + case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2: + link_info.pei386_runtime_pseudo_reloc = 2; + break; case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC: link_info.pei386_runtime_pseudo_reloc = 0; break; diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index d70f635f6ec..35fd6e0924f 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -124,7 +124,7 @@ gld_${EMULATION_NAME}_before_parse (void) config.dynamic_link = TRUE; config.has_shared = 1; link_info.pei386_auto_import = -1; - link_info.pei386_runtime_pseudo_reloc = -1; + link_info.pei386_runtime_pseudo_reloc = 2; /* Use by default version 2. */ #if (PE_DEF_SUBSYSTEM == 9) || (PE_DEF_SUBSYSTEM == 2) lang_default_entry ("_WinMainCRTStartup"); @@ -173,7 +173,9 @@ enum options OPTION_ENABLE_EXTRA_PE_DEBUG, OPTION_EXCLUDE_LIBS, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC, - OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC + OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC, + OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1, + OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2 }; static void @@ -230,6 +232,8 @@ gld${EMULATION_NAME}_add_options {"enable-extra-pep-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}, + {"enable-runtime-pseudo-reloc-v1", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1}, + {"enable-runtime-pseudo-reloc-v2", no_argument, NULL, OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2}, #endif {NULL, no_argument, NULL, 0} }; @@ -600,11 +604,17 @@ gld${EMULATION_NAME}_handle_option (int optc) link_info.pei386_auto_import = 0; break; case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC: - link_info.pei386_runtime_pseudo_reloc = 1; + link_info.pei386_runtime_pseudo_reloc = 2; break; case OPTION_DLL_DISABLE_RUNTIME_PSEUDO_RELOC: link_info.pei386_runtime_pseudo_reloc = 0; break; + case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V1: + link_info.pei386_runtime_pseudo_reloc = 1; + break; + case OPTION_DLL_ENABLE_RUNTIME_PSEUDO_RELOC_V2: + link_info.pei386_runtime_pseudo_reloc = 2; + break; case OPTION_ENABLE_EXTRA_PE_DEBUG: pep_dll_extra_pe_debug = 1; break; @@ -840,17 +850,55 @@ static int make_import_fixup (arelent *rel, asection *s) { struct bfd_symbol *sym = *rel->sym_ptr_ptr; - char addend[4]; + char addend[8]; + bfd_vma _addend = 0; + int suc = 0; if (pep_dll_extra_pe_debug) printf ("arelent: %s@%#lx: add=%li\n", sym->name, (unsigned long) rel->address, (long) rel->addend); - if (! bfd_get_section_contents (s->owner, s, addend, rel->address, sizeof (addend))) + memset (addend, 0, sizeof (addend)); + switch ((rel->howto->bitsize)) + { + case 8: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 1); + if (suc && rel->howto->pc_relative) + _addend = (bfd_vma) ((bfd_signed_vma) ((char) bfd_get_8 (s->owner, addend))); + else if (suc) + _addend = ((bfd_vma) bfd_get_8 (s->owner, addend)) & 0xff; + break; + case 16: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 2); + if (suc && rel->howto->pc_relative) + _addend = (bfd_vma) ((bfd_signed_vma) ((short) bfd_get_16 (s->owner, addend))); + else if (suc) + _addend = ((bfd_vma) bfd_get_16 (s->owner, addend)) & 0xffff; + break; + case 32: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 4); + if (suc && rel->howto->pc_relative) + _addend = (bfd_vma) ((bfd_signed_vma) ((int) bfd_get_32 (s->owner, addend))); + else if (suc) + _addend = ((bfd_vma) bfd_get_32 (s->owner, addend)) & 0xffffffff; + break; + case 64: + suc = bfd_get_section_contents (s->owner, s, addend, rel->address, 8); + if (suc) + _addend = ((bfd_vma) bfd_get_64 (s->owner, addend)); + break; + } + if (! suc) einfo (_("%C: Cannot get section contents - auto-import exception\n"), s->owner, s, rel->address); - pep_create_import_fixup (rel, s, bfd_get_32 (s->owner, addend)); + if (pep_dll_extra_pe_debug) + { + printf ("import of 0x%lx(0x%lx) sec_addr=0x%lx", (long) _addend, (long) rel->addend, (long) rel->address); + if (rel->howto->pc_relative) printf (" pcrel"); + printf (" %d bit rel.\n",(int) rel->howto->bitsize); + } + pep_create_import_fixup (rel, s, _addend); return 1; } diff --git a/ld/pe-dll.c b/ld/pe-dll.c index bf4b5093336..35836a7566f 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -40,7 +40,6 @@ #include "coff/internal.h" #include "../bfd/libcoff.h" #include "deffile.h" -#include "pe-dll.h" #ifdef pe_use_x86_64 @@ -165,6 +164,7 @@ static struct bfd_section *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; +static int runtime_pseudp_reloc_v2_init = 0; typedef struct { @@ -2264,14 +2264,14 @@ make_import_fixup_entry (const char *name, static bfd * make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED, const char *fixup_name, - int addend, + bfd_vma addend ATTRIBUTE_UNUSED, + bfd_vma bitsize, bfd *parent) { asection *rt_rel; unsigned char *rt_rel_d; char *oname; bfd *abfd; - oname = xmalloc (20); sprintf (oname, "rtr%06d.o", tmp_seq); tmp_seq++; @@ -2290,19 +2290,47 @@ make_runtime_pseudo_reloc (const char *name ATTRIBUTE_UNUSED, quick_symbol (abfd, "", fixup_name, "", UNDSEC, BSF_GLOBAL, 0); - bfd_set_section_size (abfd, rt_rel, 8); - rt_rel_d = xmalloc (8); - rt_rel->contents = rt_rel_d; - memset (rt_rel_d, 0, 8); - bfd_put_32 (abfd, addend, rt_rel_d); + if (link_info.pei386_runtime_pseudo_reloc == 2) + { + size_t size = 12; + if (! runtime_pseudp_reloc_v2_init) + { + size += 12; + runtime_pseudp_reloc_v2_init = 1; + } + quick_symbol (abfd, U ("_imp_"), name, "", UNDSEC, BSF_GLOBAL, 0); + + bfd_set_section_size (abfd, rt_rel, size); + rt_rel_d = xmalloc (size); + rt_rel->contents = rt_rel_d; + memset (rt_rel_d, 0, size); + quick_reloc (abfd, size - 8, BFD_RELOC_RVA, 1); + quick_reloc (abfd, size - 12, BFD_RELOC_RVA, 2); + bfd_put_32 (abfd, bitsize, rt_rel_d + (size - 4)); + if (size != 12) + bfd_put_32 (abfd, 1, rt_rel_d + 8); + save_relocs (rt_rel); + + bfd_set_symtab (abfd, symtab, symptr); + + bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, size); + } + else + { + bfd_set_section_size (abfd, rt_rel, 8); + rt_rel_d = xmalloc (8); + rt_rel->contents = rt_rel_d; + memset (rt_rel_d, 0, 8); - quick_reloc (abfd, 4, BFD_RELOC_RVA, 1); - save_relocs (rt_rel); + bfd_put_32 (abfd, addend, rt_rel_d); + quick_reloc (abfd, 4, BFD_RELOC_RVA, 1); - bfd_set_symtab (abfd, symtab, symptr); + save_relocs (rt_rel); - bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8); + bfd_set_symtab (abfd, symtab, symptr); + bfd_set_section_contents (abfd, rt_rel, rt_rel_d, 0, 8); + } bfd_make_readable (abfd); return abfd; } @@ -2352,7 +2380,7 @@ pe_create_runtime_relocator_reference (bfd *parent) } void -pe_create_import_fixup (arelent *rel, asection *s, int addend) +pe_create_import_fixup (arelent *rel, asection *s, bfd_vma addend) { char buf[300]; struct bfd_symbol *sym = *rel->sym_ptr_ptr; @@ -2385,31 +2413,30 @@ pe_create_import_fixup (arelent *rel, asection *s, int addend) 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, - link_info.output_bfd); - add_bfd_to_link (b, b->filename, &link_info); + if ((link_info.pei386_runtime_pseudo_reloc != 0 && addend != 0) + || link_info.pei386_runtime_pseudo_reloc == 2) + { + if (pe_dll_extra_pe_debug) + printf ("creating runtime pseudo-reloc entry for %s (addend=%d)\n", + fixup_name, (int) addend); - if (runtime_pseudo_relocs_created == 0) - { - b = pe_create_runtime_relocator_reference (link_info.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"); - } - } + b = make_runtime_pseudo_reloc (name, fixup_name, addend, rel->howto->bitsize, + link_info.output_bfd); + add_bfd_to_link (b, b->filename, &link_info); + + if (runtime_pseudo_relocs_created == 0) + { + b = pe_create_runtime_relocator_reference (link_info.output_bfd); + add_bfd_to_link (b, b->filename, &link_info); + } + runtime_pseudo_relocs_created++; + } + else if (addend != 0) + { + 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 ce4a2e6d11b..6645c4c83b8 100644 --- a/ld/pe-dll.h +++ b/ld/pe-dll.h @@ -59,7 +59,7 @@ extern void pe_exe_fill_sections extern void pe_walk_relocs_of_symbol (struct bfd_link_info *, const char *, int (*) (arelent *, asection *)); extern void pe_create_import_fixup - (arelent * rel, asection *, int); + (arelent * rel, asection *, bfd_vma); extern bfd_boolean pe_bfd_is_dll (bfd *); diff --git a/ld/pep-dll.h b/ld/pep-dll.h index dba76bed1f0..ae0dcbe9d83 100644 --- a/ld/pep-dll.h +++ b/ld/pep-dll.h @@ -48,7 +48,7 @@ extern void pep_dll_fill_sections (bfd *, struct bfd_link_info *); extern void pep_exe_fill_sections (bfd *, struct bfd_link_info *); extern void pep_walk_relocs_of_symbol (struct bfd_link_info *, const char *, int (*) (arelent *, asection *)); -extern void pep_create_import_fixup (arelent * rel, asection *, int); +extern void pep_create_import_fixup (arelent * rel, asection *, bfd_vma); extern bfd_boolean pep_bfd_is_dll (bfd *); #endif /* PEP_DLL_H */ -- 2.30.2