aboutsummaryrefslogtreecommitdiff
path: root/ld/pe-dll.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/pe-dll.c')
-rw-r--r--ld/pe-dll.c101
1 files changed, 64 insertions, 37 deletions
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");
+ }
}