aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ld/ChangeLog22
-rw-r--r--ld/NEWS6
-rw-r--r--ld/emultempl/pe.em14
-rw-r--r--ld/emultempl/pep.em60
-rw-r--r--ld/pe-dll.c101
-rw-r--r--ld/pe-dll.h2
-rw-r--r--ld/pep-dll.h2
7 files changed, 161 insertions, 46 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog
index e26ee7e..44160c9 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -1,3 +1,25 @@
+2008-11-14 Kai Tietz <kai.tietz@onevision.com>
+
+ * 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 <amodra@bigpond.net.au>
* Makefile.am (spu_ovl.o_c): Add missing line continuations.
diff --git a/ld/NEWS b/ld/NEWS
index e28e3d8..962c2db 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 b963d03..43c0be3 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 d70f635..35fd6e0 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 bf4b509..35836a7 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 ce4a2e6..6645c4c 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 dba76be..ae0dcbe 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 */