#define GOT_TLS_IE_NEG 6
#define GOT_TLS_IE_BOTH 7
#define GOT_TLS_GDESC 8
+#define GOT_TLS_MASK 0x0f
+#define GOT_TLS_IE_IE 0x10
+#define GOT_TLS_IE_GD 0x20
+#define GOT_TLS_IE_MASK 0x30
#define GOT_TLS_GD_BOTH_P(type) \
((type) == (GOT_TLS_GD | GOT_TLS_GDESC))
#define GOT_TLS_GD_P(type) \
/* 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;
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;
}
case R_386_TLS_IE_32:
if (ELF32_R_TYPE (rel->r_info) == r_type)
tls_type = GOT_TLS_IE_NEG;
+ else if (h
+ && ELF32_R_TYPE (rel->r_info) == R_386_TLS_GD)
+ /* If this is a GD->IE transition, we may use either
+ of R_386_TLS_TPOFF and R_386_TLS_TPOFF32. But if
+ we may have both R_386_TLS_IE and R_386_TLS_GD,
+ we can't share the same R_386_TLS_TPOFF since
+ they require different offsets. So we remember
+ it comes from R_386_TLS_GD. */
+ tls_type = GOT_TLS_IE | GOT_TLS_IE_GD;
else
- /* If this is a GD->IE transition, we may use either of
- R_386_TLS_TPOFF and R_386_TLS_TPOFF32. */
tls_type = GOT_TLS_IE;
break;
case R_386_TLS_IE:
+ if (h)
+ {
+ /* We remember it comes from R_386_TLS_IE. */
+ tls_type = GOT_TLS_IE_POS | GOT_TLS_IE_IE;
+ break;
+ }
case R_386_TLS_GOTIE:
tls_type = GOT_TLS_IE_POS; break;
}
tls_type |= old_tls_type;
/* If a TLS symbol is accessed using IE at least once,
there is no point to use dynamic model for it. */
- else if (old_tls_type != tls_type && old_tls_type != GOT_UNKNOWN
+ else if (old_tls_type != tls_type
+ && old_tls_type != GOT_UNKNOWN
&& (! GOT_TLS_GD_ANY_P (old_tls_type)
|| (tls_type & GOT_TLS_IE) == 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)
{
asection *s;
bfd_boolean dyn;
int tls_type = elf_i386_hash_entry(h)->tls_type;
+
+ /* If we have both R_386_TLS_IE and R_386_TLS_GD, GOT_TLS_IE_BOTH
+ should be used. */
+ if ((tls_type & GOT_TLS_IE_MASK)
+ == (GOT_TLS_IE_IE | GOT_TLS_IE_GD))
+ tls_type = GOT_TLS_IE_BOTH;
+ else
+ tls_type &= GOT_TLS_MASK;
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
else
htab->tls_ldm_got.offset = -1;
- if (htab->is_vxworks)
- {
- /* Mark the GOT and PLT symbols as having relocations; they might
- not, but we won't know for sure until we build the GOT in
- finish_dynamic_symbol. */
- if (htab->elf.hgot)
- htab->elf.hgot->indx = -2;
- if (htab->elf.hplt)
- {
- htab->elf.hplt->indx = -2;
- if (htab->splt->flags & SEC_CODE)
- htab->elf.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 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
{
else if (h != NULL)
{
tls_type = elf_i386_hash_entry(h)->tls_type;
+ /* If we have both R_386_TLS_IE and R_386_TLS_GD,
+ GOT_TLS_IE_BOTH should be used. */
+ if ((tls_type & GOT_TLS_IE_MASK)
+ == (GOT_TLS_IE_IE | GOT_TLS_IE_GD))
+ tls_type = GOT_TLS_IE_BOTH;
+ else
+ tls_type &= GOT_TLS_MASK;
if (!info->shared && h->dynindx == -1 && (tls_type & GOT_TLS_IE))
r_type = R_386_TLS_LE_32;
}
+ 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);
}
-/* 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