static bfd_boolean
elf_i386_mkobject (bfd *abfd)
{
- bfd_size_type amt = sizeof (struct elf_i386_obj_tdata);
- abfd->tdata.any = bfd_zalloc (abfd, amt);
if (abfd->tdata.any == NULL)
- return FALSE;
- return TRUE;
+ {
+ bfd_size_type amt = sizeof (struct elf_i386_obj_tdata);
+ abfd->tdata.any = bfd_zalloc (abfd, amt);
+ if (abfd->tdata.any == NULL)
+ return FALSE;
+ }
+ return bfd_elf_mkobject (abfd);
}
/* i386 ELF linker hash table. */
/* The (unloaded but important) .rel.plt.unloaded section on VxWorks. */
asection *srelplt2;
- /* Short-cuts to frequently used symbols for VxWorks targets. */
- struct elf_link_hash_entry *hgot, *hplt;
-
/* True if the target system is VxWorks. */
int is_vxworks;
/* Value used to fill the last word of the first plt entry. */
bfd_byte plt0_pad_byte;
+ /* The index of the next unused R_386_TLS_DESC slot in .rel.plt. */
+ bfd_vma next_tls_desc_index;
+
union {
bfd_signed_vma refcount;
bfd_vma offset;
((struct elf_i386_link_hash_table *) ((p)->hash))
#define elf_i386_compute_jump_table_size(htab) \
- ((htab)->srelplt->reloc_count * 4)
+ ((htab)->next_tls_desc_index * 4)
/* Create an entry in an i386 ELF linker hash table. */
if (ret == NULL)
return NULL;
- if (! _bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc))
+ if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd, link_hash_newfunc,
+ sizeof (struct elf_i386_link_hash_entry)))
{
free (ret);
return NULL;
ret->sdynbss = NULL;
ret->srelbss = NULL;
ret->tls_ldm_got.refcount = 0;
+ ret->next_tls_desc_index = 0;
ret->sgotplt_jump_table_size = 0;
ret->sym_sec.abfd = NULL;
ret->is_vxworks = 0;
ret->srelplt2 = NULL;
- ret->hgot = NULL;
- ret->hplt = NULL;
ret->plt0_pad_byte = 0;
return &ret->elf.root;
elf_i386_create_dynamic_sections (bfd *dynobj, struct bfd_link_info *info)
{
struct elf_i386_link_hash_table *htab;
- asection * s;
- int flags;
- const struct elf_backend_data *bed = get_elf_backend_data (dynobj);
htab = elf_i386_hash_table (info);
if (!htab->sgot && !create_got_section (dynobj, info))
|| (!info->shared && !htab->srelbss))
abort ();
- if (htab->is_vxworks && !info->shared)
- {
- s = bfd_make_section (dynobj, ".rel.plt.unloaded");
- flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_READONLY
- | SEC_LINKER_CREATED);
- if (s == NULL
- || ! bfd_set_section_flags (dynobj, s, flags)
- || ! bfd_set_section_alignment (dynobj, s, bed->s->log_file_align))
- return FALSE;
- htab->srelplt2 = s;
- }
+ if (htab->is_vxworks
+ && !elf_vxworks_create_dynamic_sections (dynobj, info, &htab->srelplt2))
+ return FALSE;
return TRUE;
}
&& (sec->flags & SEC_ALLOC) != 0
&& (r_type != R_386_PC32
|| (h != NULL
- && (! info->symbolic
+ && (! SYMBOLIC_BIND (info, h)
|| h->root.type == bfd_link_hash_defweak
|| !h->def_regular))))
|| (ELIMINATE_COPY_RELOCS
if (name == NULL)
return FALSE;
- if (strncmp (name, ".rel", 4) != 0
+ if (! CONST_STRNEQ (name, ".rel")
|| strcmp (bfd_get_section_name (abfd, sec),
name + 4) != 0)
{
/* We also need to make an entry in the .rel.plt section. */
htab->srelplt->size += sizeof (Elf32_External_Rel);
- htab->srelplt->reloc_count++;
+ htab->next_tls_desc_index++;
if (htab->is_vxworks && !info->shared)
{
/* Also discard relocs on undefined weak syms with non-default
visibility. */
- if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
+ if (eh->dyn_relocs != NULL
&& h->root.type == bfd_link_hash_undefweak)
- eh->dyn_relocs = NULL;
+ {
+ if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
+ eh->dyn_relocs = NULL;
+
+ /* Make sure undefined weak symbols are output as a dynamic
+ symbol in PIEs. */
+ else if (h->dynindx == -1
+ && !h->forced_local)
+ {
+ if (! bfd_elf_link_record_dynamic_symbol (info, h))
+ return FALSE;
+ }
+ }
}
else if (ELIMINATE_COPY_RELOCS)
{
else
htab->tls_ldm_got.offset = -1;
- if (htab->is_vxworks)
- {
- /* Save the GOT and PLT symbols in the hash table for easy access.
- Mark them as having relocations; they might not, but we won't
- know for sure until we build the GOT in finish_dynamic_symbol. */
-
- htab->hgot = elf_link_hash_lookup (elf_hash_table (info),
- "_GLOBAL_OFFSET_TABLE_",
- FALSE, FALSE, FALSE);
- if (htab->hgot)
- htab->hgot->indx = -2;
- htab->hplt = elf_link_hash_lookup (elf_hash_table (info),
- "_PROCEDURE_LINKAGE_TABLE_",
- FALSE, FALSE, FALSE);
- if (htab->hplt)
- htab->hplt->indx = -2;
-
- if (htab->is_vxworks && htab->hplt && htab->splt->flags & SEC_CODE)
- htab->hplt->type = STT_FUNC;
- }
-
/* Allocate global sym .plt and .got entries, and space for global
sym dynamic relocs. */
elf_link_hash_traverse (&htab->elf, allocate_dynrelocs, (PTR) info);
for them, it suffices to multiply the reloc count by the jump
slot size. */
if (htab->srelplt)
- htab->sgotplt_jump_table_size = htab->srelplt->reloc_count * 4;
+ htab->sgotplt_jump_table_size = htab->next_tls_desc_index * 4;
/* We now have determined the sizes of the various dynamic sections.
Allocate memory for them. */
we've exported dynamic symbols from them we must leave them.
It's too late to tell BFD to get rid of the symbols. */
- if (htab->hplt != NULL)
+ if (htab->elf.hplt != NULL)
strip_section = FALSE;
}
- else if (strncmp (bfd_get_section_name (dynobj, s), ".rel", 4) == 0)
+ else if (CONST_STRNEQ (bfd_get_section_name (dynobj, s), ".rel"))
{
if (s->size != 0 && s != htab->srelplt && s != htab->srelplt2)
relocs = TRUE;
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
- if (s != htab->srelplt)
- s->reloc_count = 0;
+ s->reloc_count = 0;
}
else
{
&& h->dynindx != -1
&& (r_type == R_386_PC32
|| !info->shared
- || !info->symbolic
+ || !SYMBOLIC_BIND (info, h)
|| !h->def_regular))
outrel.r_info = ELF32_R_INFO (h->dynindx, r_type);
else
val = bfd_get_8 (input_bfd, contents + roff + 1);
BFD_ASSERT (val == 0x10);
- /* Now modify the instruction as appropriate. */
- bfd_put_8 (output_bfd, 0x90, contents + roff);
+ /* Now modify the instruction as appropriate. Use
+ xchg %ax,%ax instead of 2 nops. */
+ bfd_put_8 (output_bfd, 0x66, contents + roff);
bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
continue;
}
+ htab->sgotplt_jump_table_size);
sreloc = htab->srelplt;
loc = sreloc->contents;
- loc += sreloc->reloc_count++
- * sizeof (Elf32_External_Rel);
+ loc += (htab->next_tls_desc_index++
+ * sizeof (Elf32_External_Rel));
BFD_ASSERT (loc + sizeof (Elf32_External_Rel)
<= sreloc->contents + sreloc->size);
bfd_elf32_swap_reloc_out (output_bfd, &outrel, loc);
subl $foo@gottpoff(%reg), %eax
into:
addl $foo@gotntpoff(%reg), %eax. */
- if (r_type == R_386_TLS_GOTIE)
- {
- contents[roff + 6] = 0x03;
- if (tls_type == GOT_TLS_IE_BOTH)
- off += 4;
- }
+ if (tls_type == GOT_TLS_IE_POS)
+ contents[roff + 6] = 0x03;
bfd_put_32 (output_bfd,
htab->sgot->output_section->vma
+ htab->sgot->output_offset + off
/* Now modify the instruction as appropriate. */
if (tls_type != GOT_TLS_IE_NEG)
{
- /* nop; nop */
- bfd_put_8 (output_bfd, 0x90, contents + roff);
+ /* xchg %ax,%ax */
+ bfd_put_8 (output_bfd, 0x66, contents + roff);
bfd_put_8 (output_bfd, 0x90, contents + roff + 1);
}
else
rel.r_offset = (htab->splt->output_section->vma
+ htab->splt->output_offset
+ h->plt.offset + 2),
- rel.r_info = ELF32_R_INFO (htab->hgot->indx, R_386_32);
+ rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
bfd_elf32_swap_reloc_out (output_bfd, &rel, loc);
/* Create the R_386_32 relocation referencing the beginning of
rel.r_offset = (htab->sgotplt->output_section->vma
+ htab->sgotplt->output_offset
+ got_offset);
- rel.r_info = ELF32_R_INFO (htab->hplt->indx, R_386_32);
+ rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32);
bfd_elf32_swap_reloc_out (output_bfd, &rel,
loc + sizeof (Elf32_External_Rel));
}
On VxWorks, the _GLOBAL_OFFSET_TABLE_ symbol is not absolute: it
is relative to the ".got" section. */
if (strcmp (h->root.root.string, "_DYNAMIC") == 0
- || (strcmp (h->root.root.string, "_GLOBAL_OFFSET_TABLE_") == 0
- && !htab->is_vxworks))
+ || (!htab->is_vxworks && h == htab->elf.hgot))
sym->st_shndx = SHN_ABS;
return TRUE;
if (htab->is_vxworks)
{
Elf_Internal_Rela rel;
- struct elf_link_hash_entry *hgot;
-
- /* The VxWorks GOT is relocated by the dynamic linker.
- Therefore, we must emit relocations rather than
- simply computing the values now. */
- hgot = elf_link_hash_lookup (elf_hash_table (info),
- "_GLOBAL_OFFSET_TABLE_",
- FALSE, FALSE, FALSE);
+
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 4.
On IA32 we use REL relocations so the addend goes in
the PLT directly. */
rel.r_offset = (htab->splt->output_section->vma
+ htab->splt->output_offset
+ 2);
- rel.r_info = ELF32_R_INFO (hgot->indx, R_386_32);
+ rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
bfd_elf32_swap_reloc_out (output_bfd, &rel,
htab->srelplt2->contents);
/* Generate a relocation for _GLOBAL_OFFSET_TABLE_ + 8. */
rel.r_offset = (htab->splt->output_section->vma
+ htab->splt->output_offset
+ 8);
- rel.r_info = ELF32_R_INFO (hgot->indx, R_386_32);
+ rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
bfd_elf32_swap_reloc_out (output_bfd, &rel,
htab->srelplt2->contents +
sizeof (Elf32_External_Rel));
{
Elf_Internal_Rela rel;
bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
- rel.r_info = ELF32_R_INFO (htab->hgot->indx, R_386_32);
+ rel.r_info = ELF32_R_INFO (htab->elf.hgot->indx, R_386_32);
bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
p += sizeof (Elf32_External_Rel);
bfd_elf32_swap_reloc_in (output_bfd, p, &rel);
- rel.r_info = ELF32_R_INFO (htab->hplt->indx, R_386_32);
+ rel.r_info = ELF32_R_INFO (htab->elf.hplt->indx, R_386_32);
bfd_elf32_swap_reloc_out (output_bfd, &rel, p);
p += sizeof (Elf32_External_Rel);
}
return plt->vma + (i + 1) * PLT_ENTRY_SIZE;
}
+/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
+
+static bfd_boolean
+elf_i386_hash_symbol (struct elf_link_hash_entry *h)
+{
+ if (h->plt.offset != (bfd_vma) -1
+ && !h->def_regular
+ && !h->pointer_equality_needed)
+ return FALSE;
+
+ return _bfd_elf_hash_symbol (h);
+}
#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
#define TARGET_LITTLE_NAME "elf32-i386"
#define elf_backend_size_dynamic_sections elf_i386_size_dynamic_sections
#define elf_backend_always_size_sections elf_i386_always_size_sections
#define elf_backend_plt_sym_val elf_i386_plt_sym_val
+#define elf_backend_hash_symbol elf_i386_hash_symbol
#include "elf32-target.h"
}
-/* Tweak magic VxWorks symbols as they are written to the output file. */
-static bfd_boolean
-elf_i386_vxworks_link_output_symbol_hook (struct bfd_link_info *info
- ATTRIBUTE_UNUSED,
- const char *name,
- Elf_Internal_Sym *sym,
- asection *input_sec ATTRIBUTE_UNUSED,
- struct elf_link_hash_entry *h
- ATTRIBUTE_UNUSED)
-{
- /* Ignore the first dummy symbol. */
- if (!name)
- return TRUE;
-
- return elf_vxworks_link_output_symbol_hook (name, sym);
-}
-
#undef elf_backend_post_process_headers
#undef bfd_elf32_bfd_link_hash_table_create
#define bfd_elf32_bfd_link_hash_table_create \
elf_vxworks_add_symbol_hook
#undef elf_backend_link_output_symbol_hook
#define elf_backend_link_output_symbol_hook \
- elf_i386_vxworks_link_output_symbol_hook
+ elf_vxworks_link_output_symbol_hook
#undef elf_backend_emit_relocs
#define elf_backend_emit_relocs elf_vxworks_emit_relocs
#undef elf_backend_final_write_processing