/* 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, 2011, 2012, 2013
- Free Software Foundation, Inc.
+ Copyright (C) 1993-2014 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
== I386_ELF_DATA ? ((struct elf_i386_link_hash_table *) ((p)->hash)) : NULL)
#define elf_i386_compute_jump_table_size(htab) \
- ((htab)->next_tls_desc_index * 4)
+ ((htab)->elf.srelplt->reloc_count * 4)
/* Create an entry in an i386 ELF linker hash table. */
return &ret->elf;
}
+/* Destroy an i386 ELF linker hash table. */
+
+static void
+elf_i386_link_hash_table_free (bfd *obfd)
+{
+ struct elf_i386_link_hash_table *htab
+ = (struct elf_i386_link_hash_table *) obfd->link.hash;
+
+ if (htab->loc_hash_table)
+ htab_delete (htab->loc_hash_table);
+ if (htab->loc_hash_memory)
+ objalloc_free ((struct objalloc *) htab->loc_hash_memory);
+ _bfd_elf_link_hash_table_free (obfd);
+}
+
/* Create an i386 ELF linker hash table. */
static struct bfd_link_hash_table *
ret->loc_hash_memory = objalloc_create ();
if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
- free (ret);
+ elf_i386_link_hash_table_free (abfd);
return NULL;
}
+ ret->elf.root.hash_table_free = elf_i386_link_hash_table_free;
return &ret->elf.root;
}
-/* Destroy an i386 ELF linker hash table. */
-
-static void
-elf_i386_link_hash_table_free (struct bfd_link_hash_table *hash)
-{
- struct elf_i386_link_hash_table *htab
- = (struct elf_i386_link_hash_table *) hash;
-
- if (htab->loc_hash_table)
- htab_delete (htab->loc_hash_table);
- if (htab->loc_hash_memory)
- objalloc_free ((struct objalloc *) htab->loc_hash_memory);
- _bfd_elf_link_hash_table_free (hash);
-}
-
/* Create .plt, .rel.plt, .got, .got.plt, .rel.got, .dynbss, and
.rel.bss sections in DYNOBJ, and set up shortcuts to them in our
hash table. */
/* If this is the first .plt entry, make room for the special
first entry. */
if (s->size == 0)
- s->size += plt_entry_size;
+ s->size = plt_entry_size;
h->plt.offset = s->size;
/* Nothing to do if there are no codes, no relocations or no output. */
if ((sec->flags & (SEC_CODE | SEC_RELOC)) != (SEC_CODE | SEC_RELOC)
|| sec->reloc_count == 0
- || discarded_section (sec))
+ || bfd_is_abs_section (sec->output_section))
return TRUE;
symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
/* STT_GNU_IFUNC must keep R_386_GOT32 relocation. */
if (ELF_ST_TYPE (isym->st_info) != STT_GNU_IFUNC
+ && irel->r_offset >= 2
&& bfd_get_8 (input_bfd,
contents + irel->r_offset - 2) == 0x8b)
{
&& h->type != STT_GNU_IFUNC
&& h != htab->elf.hdynamic
&& SYMBOL_REFERENCES_LOCAL (link_info, h)
+ && irel->r_offset >= 2
&& bfd_get_8 (input_bfd,
contents + irel->r_offset - 2) == 0x8b)
{
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
- for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link_next)
+ for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
{
bfd_signed_vma *local_got;
bfd_signed_vma *end_local_got;
else
{
bfd_boolean warned ATTRIBUTE_UNUSED;
+ bfd_boolean ignored ATTRIBUTE_UNUSED;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
st_size = h->size;
}
return TRUE;
}
-/* Return address for Ith PLT stub in section PLT, for relocation REL
- or (bfd_vma) -1 if it should not be included. */
+/* Return address in section PLT for the Ith GOTPLT relocation, for
+ relocation REL or (bfd_vma) -1 if it should not be included. */
static bfd_vma
-elf_i386_plt_sym_val (bfd_vma i, const asection *plt,
- const arelent *rel ATTRIBUTE_UNUSED)
+elf_i386_plt_sym_val (bfd_vma i, const asection *plt, const arelent *rel)
{
- return plt->vma + (i + 1) * GET_PLT_ENTRY_SIZE (plt->owner);
+ bfd *abfd;
+ const struct elf_i386_backend_data *bed;
+ bfd_vma plt_offset;
+
+ /* Only match R_386_JUMP_SLOT and R_386_IRELATIVE. */
+ if (rel->howto->type != R_386_JUMP_SLOT
+ && rel->howto->type != R_386_IRELATIVE)
+ return (bfd_vma) -1;
+
+ abfd = plt->owner;
+ bed = get_elf_i386_backend_data (abfd);
+ plt_offset = bed->plt->plt_entry_size;
+
+ if (elf_elfheader (abfd)->e_ident[EI_OSABI] != ELFOSABI_GNU)
+ return plt->vma + (i + 1) * plt_offset;
+
+ while (plt_offset < plt->size)
+ {
+ bfd_vma reloc_offset;
+ bfd_byte reloc_offset_raw[4];
+
+ if (!bfd_get_section_contents (abfd, (asection *) plt,
+ reloc_offset_raw,
+ plt_offset + bed->plt->plt_reloc_offset,
+ sizeof (reloc_offset_raw)))
+ return (bfd_vma) -1;
+
+ reloc_offset = H_GET_32 (abfd, reloc_offset_raw);
+ if (reloc_offset == i * sizeof (Elf32_External_Rel))
+ return plt->vma + plt_offset;
+ plt_offset += bed->plt->plt_entry_size;
+ }
+
+ abort ();
}
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
static bfd_boolean
elf_i386_add_symbol_hook (bfd * abfd,
- struct bfd_link_info * info ATTRIBUTE_UNUSED,
+ struct bfd_link_info * info,
Elf_Internal_Sym * sym,
const char ** namep ATTRIBUTE_UNUSED,
flagword * flagsp ATTRIBUTE_UNUSED,
asection ** secp ATTRIBUTE_UNUSED,
bfd_vma * valp ATTRIBUTE_UNUSED)
{
- if ((abfd->flags & DYNAMIC) == 0
- && (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
- || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
+ if ((ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+ || ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
+ && (abfd->flags & DYNAMIC) == 0
+ && bfd_get_flavour (info->output_bfd) == bfd_target_elf_flavour)
elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}
-#define TARGET_LITTLE_SYM bfd_elf32_i386_vec
+#define TARGET_LITTLE_SYM i386_elf32_vec
#define TARGET_LITTLE_NAME "elf32-i386"
#define ELF_ARCH bfd_arch_i386
#define ELF_TARGET_ID I386_ELF_DATA
#define bfd_elf32_bfd_is_local_label_name elf_i386_is_local_label_name
#define bfd_elf32_bfd_link_hash_table_create elf_i386_link_hash_table_create
-#define bfd_elf32_bfd_link_hash_table_free elf_i386_link_hash_table_free
#define bfd_elf32_bfd_reloc_type_lookup elf_i386_reloc_type_lookup
#define bfd_elf32_bfd_reloc_name_lookup elf_i386_reloc_name_lookup
#define elf_backend_plt_sym_val elf_i386_plt_sym_val
#define elf_backend_hash_symbol elf_i386_hash_symbol
#define elf_backend_add_symbol_hook elf_i386_add_symbol_hook
-#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers _bfd_elf_set_osabi
#include "elf32-target.h"
/* FreeBSD support. */
#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM bfd_elf32_i386_freebsd_vec
+#define TARGET_LITTLE_SYM i386_elf32_fbsd_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-freebsd"
#undef ELF_OSABI
static void
elf_i386_fbsd_post_process_headers (bfd *abfd, struct bfd_link_info *info)
{
- _bfd_elf_set_osabi (abfd, info);
+ _bfd_elf_post_process_headers (abfd, info);
#ifdef OLD_FREEBSD_ABI_LABEL
- /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
- memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
+ {
+ /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
+ Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+ memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
+ }
#endif
}
/* Solaris 2. */
#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM bfd_elf32_i386_sol2_vec
+#define TARGET_LITTLE_SYM i386_elf32_sol2_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-sol2"
/* Native Client support. */
#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM bfd_elf32_i386_nacl_vec
+#define TARGET_LITTLE_SYM i386_elf32_nacl_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-nacl"
#undef elf32_bed
#undef elf_backend_want_plt_sym
#define elf_backend_want_plt_sym 0
#undef elf_backend_post_process_headers
-#define elf_backend_post_process_headers _bfd_elf_set_osabi
#undef elf_backend_static_tls_alignment
/* NaCl uses substantially different PLT entries for the same effects. */
0, /* is_vxworks */
};
+static bfd_boolean
+elf32_i386_nacl_elf_object_p (bfd *abfd)
+{
+ /* Set the right machine number for a NaCl i386 ELF32 file. */
+ bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386_nacl);
+ return TRUE;
+}
+
#undef elf_backend_arch_data
#define elf_backend_arch_data &elf_i386_nacl_arch_bed
+#undef elf_backend_object_p
+#define elf_backend_object_p elf32_i386_nacl_elf_object_p
#undef elf_backend_modify_segment_map
#define elf_backend_modify_segment_map nacl_modify_segment_map
#undef elf_backend_modify_program_headers
#include "elf32-target.h"
/* Restore defaults. */
+#undef elf_backend_object_p
#undef elf_backend_modify_segment_map
#undef elf_backend_modify_program_headers
#undef elf_backend_final_write_processing
/* VxWorks support. */
#undef TARGET_LITTLE_SYM
-#define TARGET_LITTLE_SYM bfd_elf32_i386_vxworks_vec
+#define TARGET_LITTLE_SYM i386_elf32_vxworks_vec
#undef TARGET_LITTLE_NAME
#define TARGET_LITTLE_NAME "elf32-i386-vxworks"
#undef ELF_OSABI
#define elf_backend_arch_data &elf_i386_vxworks_arch_bed
#undef elf_backend_relocs_compatible
-#undef elf_backend_post_process_headers
#undef elf_backend_add_symbol_hook
#define elf_backend_add_symbol_hook \
elf_vxworks_add_symbol_hook