/* Intel 80386/80486-specific support for 32-bit ELF
Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
case BFD_RELOC_386_IRELATIVE:
TRACE ("BFD_RELOC_386_IRELATIVE");
- return &elf_howto_table[R_386_IRELATIVE];
+ return &elf_howto_table[R_386_IRELATIVE - R_386_tls_offset];
case BFD_RELOC_VTABLE_INHERIT:
TRACE ("BFD_RELOC_VTABLE_INHERIT");
r_symndx = ELF32_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
- struct elf_i386_link_hash_entry *eh;
- struct elf_dyn_relocs **pp;
- struct elf_dyn_relocs *p;
-
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
while (h->root.type == bfd_link_hash_indirect
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- eh = (struct elf_i386_link_hash_entry *) h;
-
- for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
- if (p->sec == sec)
- {
- /* Everything must go for SEC. */
- *pp = p->next;
- break;
- }
}
else
{
}
}
+ if (h)
+ {
+ struct elf_i386_link_hash_entry *eh;
+ struct elf_dyn_relocs **pp;
+ struct elf_dyn_relocs *p;
+
+ eh = (struct elf_i386_link_hash_entry *) h;
+ for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
+ if (p->sec == sec)
+ {
+ /* Everything must go for SEC. */
+ *pp = p->next;
+ break;
+ }
+ }
+
r_type = ELF32_R_TYPE (rel->r_info);
if (! elf_i386_tls_transition (info, abfd, sec, NULL,
symtab_hdr, sym_hashes,
case R_386_32:
case R_386_PC32:
- if (info->shared)
+ if (info->shared
+ && (h == NULL || h->type != STT_GNU_IFUNC))
break;
/* Fall through */
if (h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
+ /* Skip local IFUNC symbols. */
+ if (h->forced_local && h->type == STT_GNU_IFUNC)
+ return TRUE;
+
eh = (struct elf_i386_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
info->flags |= DF_TEXTREL;
+ if (info->warn_shared_textrel && info->shared)
+ info->callbacks->einfo (_("%P: %B: warning: relocation against `%s' in readonly section `%A'.\n"),
+ p->sec->owner, h->root.root.string,
+ p->sec);
+
/* Not an error, just cut short the traversal. */
return FALSE;
}
srel = elf_section_data (p->sec)->sreloc;
srel->size += p->count * sizeof (Elf32_External_Rel);
if ((p->sec->output_section->flags & SEC_READONLY) != 0)
- info->flags |= DF_TEXTREL;
+ {
+ info->flags |= DF_TEXTREL;
+ if (info->warn_shared_textrel && info->shared)
+ info->callbacks->einfo (_("%P: %B: warning: relocation in readonly section `%A'.\n"),
+ p->sec->owner, p->sec);
+ break;
+ }
}
}
}
if (htab->elf.sgotplt)
{
+ struct elf_link_hash_entry *got;
+ got = elf_link_hash_lookup (elf_hash_table (info),
+ "_GLOBAL_OFFSET_TABLE_",
+ FALSE, FALSE, FALSE);
+
/* Don't allocate .got.plt section if there are no GOT nor PLT
- entries. */
- if ((htab->elf.sgotplt->size
- == get_elf_backend_data (output_bfd)->got_header_size)
+ entries and there is no refeence to _GLOBAL_OFFSET_TABLE_. */
+ if ((got == NULL
+ || !got->ref_regular_nonweak)
+ && (htab->elf.sgotplt->size
+ == get_elf_backend_data (output_bfd)->got_header_size)
&& (htab->elf.splt == NULL
|| htab->elf.splt->size == 0)
&& (htab->elf.sgot == NULL
elf_i386_tpoff (struct bfd_link_info *info, bfd_vma address)
{
struct elf_link_hash_table *htab = elf_hash_table (info);
+ const struct elf_backend_data *bed = get_elf_backend_data (info->output_bfd);
+ bfd_vma static_tls_size;
/* If tls_sec is NULL, we should have signalled an error already. */
if (htab->tls_sec == NULL)
return 0;
- return htab->tls_size + htab->tls_sec->vma - address;
+
+ /* Consider special static TLS alignment requirements. */
+ static_tls_size = BFD_ALIGN (htab->tls_size, bed->static_tls_alignment);
+ return static_tls_size + htab->tls_sec->vma - address;
}
/* Relocate an i386 ELF section. */
internal symbol, we have updated addend. */
continue;
}
-
+ /* FALLTHROUGH */
case R_386_PC32:
case R_386_PLT32:
goto do_relocation;
sreloc = elf_section_data (input_section)->sreloc;
- BFD_ASSERT (sreloc != NULL && sreloc->contents != NULL);
+ if (sreloc == NULL || sreloc->contents == NULL)
+ {
+ r = bfd_reloc_notsupported;
+ goto check_relocation_error;
+ }
loc = sreloc->contents;
loc += sreloc->reloc_count++ * sizeof (Elf32_External_Rel);
break;
case R_386_TLS_LDO_32:
- if (info->shared || (input_section->flags & SEC_CODE) == 0)
+ if (!info->executable || (input_section->flags & SEC_CODE) == 0)
relocation -= elf_i386_dtpoff_base (info);
else
/* When converting LDO to LE, we must negate. */
contents, rel->r_offset,
relocation, 0);
+check_relocation_error:
if (r != bfd_reloc_ok)
{
const char *name;
|| plt == NULL
|| gotplt == NULL
|| relplt == NULL)
- abort ();
+ return FALSE;
/* Get the index in the procedure linkage table which
corresponds to this symbol. This is the index of this symbol
bfd_vma * valp ATTRIBUTE_UNUSED)
{
if ((abfd->flags & DYNAMIC) == 0
- && ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
- elf_tdata (info->output_bfd)->has_ifunc_symbols = TRUE;
+ && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+ elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}
#undef elf32_bed
#define elf32_bed elf32_i386_sol2_bed
+/* The 32-bit static TLS arena size is rounded to the nearest 8-byte
+ boundary. */
+#undef elf_backend_static_tls_alignment
+#define elf_backend_static_tls_alignment 8
+
/* The Solaris 2 ABI requires a plt symbol on all platforms.
Cf. Linker and Libraries Guide, Ch. 2, Link-Editor, Generating the Output
#undef elf_backend_final_write_processing
#define elf_backend_final_write_processing \
elf_vxworks_final_write_processing
+#undef elf_backend_static_tls_alignment
/* On VxWorks, we emit relocations against _PROCEDURE_LINKAGE_TABLE_, so
define it. */