#define PLTRESOLVE_RELOCS 2
#define PLT_NON_JUMP_SLOT_RELOCS 2
+/* Architecture-specific backend data for i386. */
+
+struct elf_i386_backend_data
+{
+ /* Value used to fill the unused bytes of the first PLT entry. */
+ bfd_byte plt0_pad_byte;
+
+ /* True if the target system is VxWorks. */
+ int is_vxworks;
+};
+
+#define get_elf_i386_backend_data(abfd) \
+ ((const struct elf_i386_backend_data *) \
+ get_elf_backend_data (abfd)->arch_data)
+
+/* These are the standard parameters. */
+static const struct elf_i386_backend_data elf_i386_arch_bed =
+ {
+ 0, /* plt0_pad_byte */
+ 0, /* is_vxworks */
+ };
+
+#define elf_backend_arch_data &elf_i386_arch_bed
+
/* i386 ELF linker hash entry. */
struct elf_i386_link_hash_entry
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
asection *srelplt2;
- /* True if the target system is VxWorks. */
- int is_vxworks;
-
/* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */
bfd_vma next_tls_desc_index;
-
- /* Value used to fill the last word of the first plt entry. */
- bfd_byte plt0_pad_byte;
};
/* Get the i386 ELF linker hash table from a link_info structure. */
ret->next_tls_desc_index = 0;
ret->sgotplt_jump_table_size = 0;
ret->sym_cache.abfd = NULL;
- ret->is_vxworks = 0;
ret->srelplt2 = NULL;
- ret->plt0_pad_byte = 0;
ret->tls_module_base = NULL;
ret->loc_hash_table = htab_try_create (1024,
|| (!info->shared && !htab->srelbss))
abort ();
- if (htab->is_vxworks
+ if (get_elf_i386_backend_data (dynobj)->is_vxworks
&& !elf_vxworks_create_dynamic_sections (dynobj, info,
&htab->srelplt2))
return FALSE;
_bfd_elf_link_hash_copy_indirect (info, dir, ind);
}
-typedef union
+typedef union
{
unsigned char c[2];
uint16_t i;
if (! elf_i386_tls_transition (info, abfd, sec, NULL,
symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN,
- rel, rel_end, h, r_symndx))
+ rel, rel_end, h, r_symndx))
return FALSE;
switch (r_type)
if (! elf_i386_tls_transition (info, abfd, sec, NULL,
symtab_hdr, sym_hashes,
&r_type, GOT_UNKNOWN,
- rel, relend, h, r_symndx))
+ rel, relend, h, r_symndx))
return FALSE;
switch (r_type)
we can keep the dynamic relocs and avoid the copy reloc. This
doesn't work on VxWorks, where we can not have dynamic relocations
(other than copy and jump slot relocations) in an executable. */
- if (ELIMINATE_COPY_RELOCS && !htab->is_vxworks)
+ if (ELIMINATE_COPY_RELOCS
+ && !get_elf_i386_backend_data (info->output_bfd)->is_vxworks)
{
struct elf_i386_link_hash_entry * eh;
struct elf_dyn_relocs *p;
htab->elf.srelplt->size += sizeof (Elf32_External_Rel);
htab->next_tls_desc_index++;
- if (htab->is_vxworks && !info->shared)
+ if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks
+ && !info->shared)
{
/* VxWorks has a second set of relocations for each PLT entry
in executables. They go in a separate relocation section,
}
}
- if (htab->is_vxworks)
+ if (get_elf_i386_backend_data (info->output_bfd)->is_vxworks)
{
struct elf_dyn_relocs **pp;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
/* Set the sizes of the dynamic sections. */
static bfd_boolean
-elf_i386_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info)
+elf_i386_size_dynamic_sections (bfd *output_bfd, struct bfd_link_info *info)
{
struct elf_i386_link_hash_table *htab;
bfd *dynobj;
linker script /DISCARD/, so we'll be discarding
the relocs too. */
}
- else if (htab->is_vxworks
+ else if (get_elf_i386_backend_data (output_bfd)->is_vxworks
&& strcmp (p->sec->output_section->name,
".tls_vars") == 0)
{
return FALSE;
}
}
- if (htab->is_vxworks
+ if (get_elf_i386_backend_data (output_bfd)->is_vxworks
&& !elf_vxworks_add_dynamic_entries (output_bfd, info))
return FALSE;
}
local_tlsdesc_gotents = elf_i386_local_tlsdesc_gotent (input_bfd);
/* We have to handle relocations in vxworks .tls_vars sections
specially, because the dynamic loader is 'weird'. */
- is_vxworks_tls = (htab->is_vxworks && info->shared
+ is_vxworks_tls = (get_elf_i386_backend_data (output_bfd)->is_vxworks
+ && info->shared
&& !strcmp (input_section->output_section->name,
".tls_vars"));
if (h == NULL)
abort ();
- /* Set STT_GNU_IFUNC symbol value. */
+ /* Set STT_GNU_IFUNC symbol value. */
h->root.u.def.value = sym->st_value;
h->root.u.def.section = sec;
}
/* This symbol is resolved locally. */
outrel.r_info = ELF32_R_INFO (0, R_386_IRELATIVE);
bfd_put_32 (output_bfd,
- (h->root.u.def.value
+ (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset),
contents + offset);
relocation - elf_i386_dtpoff_base (info),
htab->elf.sgot->contents + off);
else if (dr_type == R_386_TLS_TPOFF32 && indx == 0)
- bfd_put_32 (output_bfd,
+ bfd_put_32 (output_bfd,
elf_i386_dtpoff_base (info) - relocation,
htab->elf.sgot->contents + off);
else if (dr_type != R_386_TLS_DESC)
+ got_offset),
plt->contents + h->plt.offset + 2);
- if (htab->is_vxworks)
+ if (get_elf_i386_backend_data (output_bfd)->is_vxworks)
{
int s, k, reloc_index;
R_386_IRELATIVE instead of R_386_JUMP_SLOT. Store addend
in the .got.plt section. */
bfd_put_32 (output_bfd,
- (h->root.u.def.value
+ (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset),
gotplt->contents + got_offset);
is relative to the ".got" section. */
if (sym != NULL
&& (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || (!htab->is_vxworks && h == htab->elf.hgot)))
+ || (!get_elf_i386_backend_data (output_bfd)->is_vxworks
+ && h == htab->elf.hgot)))
sym->st_shndx = SHN_ABS;
return TRUE;
struct elf_link_hash_entry *h
= (struct elf_link_hash_entry *) *slot;
struct bfd_link_info *info
- = (struct bfd_link_info *) inf;
+ = (struct bfd_link_info *) inf;
return elf_i386_finish_dynamic_symbol (info->output_bfd, info,
h, NULL);
switch (dyn.d_tag)
{
default:
- if (htab->is_vxworks
+ if (get_elf_i386_backend_data (output_bfd)->is_vxworks
&& elf_vxworks_finish_dynamic_entry (output_bfd, &dyn))
break;
continue;
memcpy (htab->elf.splt->contents, elf_i386_pic_plt0_entry,
sizeof (elf_i386_pic_plt0_entry));
memset (htab->elf.splt->contents + sizeof (elf_i386_pic_plt0_entry),
- htab->plt0_pad_byte,
+ get_elf_i386_backend_data (output_bfd)->plt0_pad_byte,
PLT_ENTRY_SIZE - sizeof (elf_i386_pic_plt0_entry));
}
else
memcpy (htab->elf.splt->contents, elf_i386_plt0_entry,
sizeof(elf_i386_plt0_entry));
memset (htab->elf.splt->contents + sizeof (elf_i386_plt0_entry),
- htab->plt0_pad_byte,
+ get_elf_i386_backend_data (output_bfd)->plt0_pad_byte,
PLT_ENTRY_SIZE - sizeof (elf_i386_plt0_entry));
bfd_put_32 (output_bfd,
(htab->elf.sgotplt->output_section->vma
+ 8),
htab->elf.splt->contents + 8);
- if (htab->is_vxworks)
+ if (get_elf_i386_backend_data (output_bfd)->is_vxworks)
{
Elf_Internal_Rela rel;
->this_hdr.sh_entsize = 4;
/* Correct the .rel.plt.unloaded relocations. */
- if (htab->is_vxworks && !info->shared)
+ if (get_elf_i386_backend_data (output_bfd)->is_vxworks
+ && !info->shared)
{
int num_plts = (htab->elf.splt->size / PLT_ENTRY_SIZE) - 1;
unsigned char *p;
#define TARGET_LITTLE_NAME "elf32-i386-vxworks"
#undef ELF_OSABI
-/* Like elf_i386_link_hash_table_create but with tweaks for VxWorks. */
-
-static struct bfd_link_hash_table *
-elf_i386_vxworks_link_hash_table_create (bfd *abfd)
-{
- struct bfd_link_hash_table *ret;
- struct elf_i386_link_hash_table *htab;
-
- ret = elf_i386_link_hash_table_create (abfd);
- if (ret)
- {
- htab = (struct elf_i386_link_hash_table *) ret;
- htab->is_vxworks = 1;
- htab->plt0_pad_byte = 0x90;
- }
-
- return ret;
-}
+static const struct elf_i386_backend_data elf_i386_vxworks_arch_bed =
+ {
+ 0x90, /* plt0_pad_byte */
+ 1, /* is_vxworks */
+ };
+#undef elf_backend_arch_data
+#define elf_backend_arch_data &elf_i386_vxworks_arch_bed
#undef elf_backend_relocs_compatible
#undef elf_backend_post_process_headers
-#undef bfd_elf32_bfd_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_create \
- elf_i386_vxworks_link_hash_table_create
#undef elf_backend_add_symbol_hook
#define elf_backend_add_symbol_hook \
elf_vxworks_add_symbol_hook