aboutsummaryrefslogtreecommitdiff
path: root/bfd/elf64-x86-64.c
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2017-08-28 06:23:25 -0700
committerH.J. Lu <hjl.tools@gmail.com>2017-08-29 12:58:51 -0700
commit0afcef5384c656b69706fed61d91f6d886c4c0f1 (patch)
tree5b28bd844807ef807fd4a179558c8beb0d1a62de /bfd/elf64-x86-64.c
parent823cb06774ad6a2aee0afcf6f011c3a134f25747 (diff)
downloadgdb-0afcef5384c656b69706fed61d91f6d886c4c0f1.zip
gdb-0afcef5384c656b69706fed61d91f6d886c4c0f1.tar.gz
gdb-0afcef5384c656b69706fed61d91f6d886c4c0f1.tar.bz2
Add elfxx-x86.h and elfxx-x86.c
Move common codes in elf32-i386.c and elf64-x86-64.c to elfxx-x86.c. * Makefile.am (BFD32_BACKENDS): Add elfxx-x86.lo. (BFD64_BACKENDS): Likewise. (BFD32_BACKENDS_CFILES): Add elfxx-x86.c. (BFD64_BACKENDS_CFILES): Likewise. * Makefile.in: Regenerated. * configure.ac (bfd_backends): Add elfxx-x86.lo together with elf32-i386.lo and elf64-x86-64.lo. * configure: Regenerated. * elf32-i386.c: Include "elfxx-x86.h" instead of "sysdep.h", "bfd.h", "bfdlink.h", "libbfd.h", "elf-bfd.h", "bfd_stdint.h", "objalloc.h" and "hashtab.h". (ELIMINATE_COPY_RELOCS): Removed. (UNDEFINED_WEAK_RESOLVED_TO_ZERO):Likewise. (SYMBOL_NO_COPYRELOC): Likewise. (elf_i386_link_hash_entry): Likewise. (GOT_UNKNOWN): Likewise. (GOT_NORMAL): Likewise. (GOT_TLS_GD): Likewise. (elf_i386_hash_entry): Likewise. (elf_i386_obj_tdata): Likewise. (elf_i386_tdata): Likewise. (elf_i386_local_got_tls_type): Likewise. (elf_i386_local_tlsdesc_gotent): Likewise. (elf_i386_hash_table): Likewise. (elf_i386_link_hash_newfunc): Likewise. (elf_i386_local_htab_hash): Likewise. (elf_i386_local_htab_eq): Likewise. (elf_i386_get_local_sym_hash): Likewise. (elf_i386_link_hash_table_free): Likewise. (elf_i386_copy_indirect_symbol): Likewise. (elf_i386_fixup_symbol): Likewise. (elf_i386_readonly_dynrelocs): Likewise. (elf_i386_always_size_sections): Likewise. (elf_i386_set_tls_module_base): Likewise. (elf_i386_dtpoff_base): Likewise. (compare_relocs): Likewise. (elf_i386_hash_symbol): Likewise. (elf_i386_parse_gnu_properties): Likewise. (elf_i386_merge_gnu_properties): Likewise. (elf_i386_link_check_relocs): Likewise. (elf_i386_merge_symbol_attribute): Likewise. (bfd_elf32_bfd_link_check_relocs): Likewise. (elf_backend_copy_indirect_symbol): Likewise. (elf_backend_always_size_sections): Likewise. (elf_backend_omit_section_dynsym): Likewise. (elf_backend_hash_symbol): Likewise. (elf_backend_fixup_symbol): Likewise. (elf_backend_parse_gnu_properties): Likewise. (elf_backend_merge_gnu_properties): Likewise. (elf_backend_merge_symbol_attribute): Likewise. (elf_i386_mkobject): Updated. (elf_i386_link_hash_table_create): Likewise. (elf_i386_check_tls_transition): Likewise. (elf_i386_tls_transition): Likewise. (elf_i386_convert_load_reloc): Likewise. (elf_i386_check_relocs): Likewise. (elf_i386_adjust_dynamic_symbol): Likewise. (elf_i386_allocate_dynrelocs): Likewise. (elf_i386_convert_load): Likewise. (elf_i386_size_dynamic_sections): Likewise. (elf_i386_relocate_section): Likewise. (elf_i386_finish_dynamic_symbol ): Likewise. (elf_i386_finish_dynamic_sections): Likewise. (elf_i386_output_arch_local_syms): Likewise. (elf_i386_get_synthetic_symtab): Likewise. (elf_i386_link_setup_gnu_properties): Likewise. (elf_i386_link_hash_table): Use elf_x86_link_hash_table, instead of elf_link_hash_table, as base. (elf_i386_next_tls_desc_index): New. (elf_i386_srelplt2): Likewise. (elf_i386_plt): Likewise. (elf_i386_lazy_plt): Likewise. (elf_i386_non_lazy_plt): Likewise. * elf32-x86-64.c: Include "elfxx-x86.h" instead of "sysdep.h", "bfd.h", "bfdlink.h", "libbfd.h", "elf-bfd.h", "bfd_stdint.h", "objalloc.h" and "hashtab.h". (ELIMINATE_COPY_RELOCS): Removed. (UNDEFINED_WEAK_RESOLVED_TO_ZERO):Likewise. (SYMBOL_NO_COPYRELOC): Likewise. (elf_x86_64_link_hash_entry): Likewise. (GOT_UNKNOWN): Likewise. (GOT_NORMAL): Likewise. (GOT_TLS_GD): Likewise. (elf_x86_64_hash_entry): Likewise. (elf_x86_64_obj_tdata): Likewise. (elf_x86_64_tdata): Likewise. (elf_x86_64_local_got_tls_type): Likewise. (elf_x86_64_local_tlsdesc_gotent): Likewise. (elf_x86_64_hash_table): Likewise. (elf_x86_64_link_hash_newfunc): Likewise. (elf_x86_64_local_htab_hash): Likewise. (elf_x86_64_local_htab_eq): Likewise. (elf_x86_64_get_local_sym_hash): Likewise. (elf_x86_64_link_hash_table_free): Likewise. (elf_x86_64_copy_indirect_symbol): Likewise. (elf_x86_64_fixup_symbol): Likewise. (elf_x86_64_readonly_dynrelocs): Likewise. (elf_x86_64_always_size_sections): Likewise. (elf_x86_64_set_tls_module_base): Likewise. (elf_x86_64_dtpoff_base): Likewise. (compare_relocs): Likewise. (elf_x86_64_merge_symbol_attribute): Likewise. (elf_x86_64_hash_symbol): Likewise. (elf_x86_64_parse_gnu_properties): Likewise. (elf_x86_64_merge_gnu_properties): Likewise. (elf_x86_64_link_check_relocs): Likewise. (elf_backend_copy_indirect_symbol): Likewise. (elf_backend_always_size_sections): Likewise. (bfd_elf64_bfd_link_check_relocs): Likewise. (elf_backend_merge_symbol_attribute): Likewise. (elf_backend_hash_symbol): Likewise. (elf_backend_omit_section_dynsym): Likewise. (elf_backend_fixup_symbol): Likewise. (elf_backend_parse_gnu_properties): Likewise. (elf_backend_merge_gnu_properties): Likewise. (bfd_elf32_bfd_link_check_relocs): Likewise. (elf_x86_64_mkobject): Updated. (elf_x86_64_link_hash_table_create): Likewise. (elf_x86_64_check_tls_transition): Likewise. (elf_x86_64_tls_transition): Likewise. (elf_x86_64_convert_load_reloc): Likewise. (elf_x86_64_check_relocs): Likewise. (elf_x86_64_adjust_dynamic_symbol): Likewise. (elf_x86_64_allocate_dynrelocs): Likewise. (elf_x86_64_convert_load): Likewise. (elf_x86_64_size_dynamic_sections): Likewise. (elf_x86_64_relocate_section): Likewise. (elf_x86_64_finish_dynamic_symbol ): Likewise. (elf_x86_64_finish_dynamic_sections): Likewise. (elf_x86_64_output_arch_local_syms): Likewise. (elf_x86_64_get_synthetic_symtab): Likewise. (elf_x86_64_link_setup_gnu_properties): Likewise. (elf_x86_64_link_hash_table): Use elf_x86_link_hash_table, instead of elf_link_hash_table, as base. (elf_x86_64_next_tls_desc_index): New. (elf_x86_64_srelplt2): Likewise. (elf_x86_64_plt): Likewise. (elf_x86_64_lazy_plt): Likewise. (elf_x86_64_non_lazy_plt): Likewise. * elfxx-x86.c: New file. * elfxx-x86.h: Likewise.
Diffstat (limited to 'bfd/elf64-x86-64.c')
-rw-r--r--bfd/elf64-x86-64.c1143
1 files changed, 240 insertions, 903 deletions
diff --git a/bfd/elf64-x86-64.c b/bfd/elf64-x86-64.c
index 847a182..442ee95 100644
--- a/bfd/elf64-x86-64.c
+++ b/bfd/elf64-x86-64.c
@@ -19,15 +19,8 @@
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#include "sysdep.h"
-#include "bfd.h"
-#include "bfdlink.h"
-#include "libbfd.h"
-#include "elf-bfd.h"
+#include "elfxx-x86.h"
#include "elf-nacl.h"
-#include "bfd_stdint.h"
-#include "objalloc.h"
-#include "hashtab.h"
#include "dwarf2.h"
#include "libiberty.h"
@@ -534,12 +527,6 @@ elf_x86_64_write_core_note (bfd *abfd, char *buf, int *bufsiz,
#define ELF64_DYNAMIC_INTERPRETER "/lib/ld64.so.1"
#define ELF32_DYNAMIC_INTERPRETER "/lib/ldx32.so.1"
-/* If ELIMINATE_COPY_RELOCS is non-zero, the linker will try to avoid
- copying dynamic variables from a shared lib into an app's dynbss
- section, and instead use a dynamic relocation to point into the
- shared lib. */
-#define ELIMINATE_COPY_RELOCS 1
-
/* The size in bytes of an entry in the global offset table. */
#define GOT_ENTRY_SIZE 8
@@ -1045,45 +1032,7 @@ static const struct elf_x86_64_backend_data elf_x86_64_arch_bed =
#define elf_backend_arch_data &elf_x86_64_arch_bed
-/* Is a undefined weak symbol which is resolved to 0. Reference to an
- undefined weak symbol is resolved to 0 when building executable if
- it isn't dynamic and
- 1. Has non-GOT/non-PLT relocations in text section. Or
- 2. Has no GOT/PLT relocation.
- Local undefined weak symbol is always resolved to 0.
- */
-#define UNDEFINED_WEAK_RESOLVED_TO_ZERO(INFO, GOT_RELOC, EH) \
- ((EH)->elf.root.type == bfd_link_hash_undefweak \
- && ((EH)->elf.forced_local \
- || (bfd_link_executable (INFO) \
- && (elf_x86_64_hash_table (INFO)->interp == NULL \
- || !(GOT_RELOC) \
- || (EH)->has_non_got_reloc \
- || !(INFO)->dynamic_undefined_weak))))
-
-/* Should copy relocation be generated for a symbol. Don't generate
- copy relocation against a protected symbol defined in a shared
- object with GNU_PROPERTY_NO_COPY_ON_PROTECTED. */
-#define SYMBOL_NO_COPYRELOC(INFO, EH) \
- ((EH)->def_protected \
- && ((EH)->elf.root.type == bfd_link_hash_defined \
- || (EH)->elf.root.type == bfd_link_hash_defweak) \
- && elf_has_no_copy_on_protected ((EH)->elf.root.u.def.section->owner) \
- && ((EH)->elf.root.u.def.section->owner->flags & DYNAMIC) != 0 \
- && ((EH)->elf.root.u.def.section->flags & SEC_CODE) == 0)
-
-/* x86-64 ELF linker hash entry. */
-
-struct elf_x86_64_link_hash_entry
-{
- struct elf_link_hash_entry elf;
-
- /* Track dynamic relocs copied for this symbol. */
- struct elf_dyn_relocs *dyn_relocs;
-
-#define GOT_UNKNOWN 0
-#define GOT_NORMAL 1
-#define GOT_TLS_GD 2
+/* Values in tls_type of x86 ELF linker hash entry. */
#define GOT_TLS_IE 3
#define GOT_TLS_GDESC 4
#define GOT_TLS_GD_BOTH_P(type) \
@@ -1094,68 +1043,6 @@ struct elf_x86_64_link_hash_entry
((type) == GOT_TLS_GDESC || GOT_TLS_GD_BOTH_P (type))
#define GOT_TLS_GD_ANY_P(type) \
(GOT_TLS_GD_P (type) || GOT_TLS_GDESC_P (type))
- unsigned char tls_type;
-
- /* TRUE if a weak symbol with a real definition needs a copy reloc.
- When there is a weak symbol with a real definition, the processor
- independent code will have arranged for us to see the real
- definition first. We need to copy the needs_copy bit from the
- real definition and check it when allowing copy reloc in PIE. */
- unsigned int needs_copy : 1;
-
- /* TRUE if symbol has GOT or PLT relocations. */
- unsigned int has_got_reloc : 1;
-
- /* TRUE if symbol has non-GOT/non-PLT relocations in text sections. */
- unsigned int has_non_got_reloc : 1;
-
- /* Don't call finish_dynamic_symbol on this symbol. */
- unsigned int no_finish_dynamic_symbol : 1;
-
- /* TRUE if symbol is __tls_get_addr. */
- unsigned int tls_get_addr : 1;
-
- /* TRUE if symbol is defined as a protected symbol. */
- unsigned int def_protected : 1;
-
- /* Reference count of C/C++ function pointer relocations in read-write
- section which can be resolved at run-time. */
- bfd_signed_vma func_pointer_refcount;
-
- /* Information about the GOT PLT entry. Filled when there are both
- GOT and PLT relocations against the same function. */
- union gotplt_union plt_got;
-
- /* Information about the second PLT entry. */
- union gotplt_union plt_second;
-
- /* Offset of the GOTPLT entry reserved for the TLS descriptor,
- starting at the end of the jump table. */
- bfd_vma tlsdesc_got;
-};
-
-#define elf_x86_64_hash_entry(ent) \
- ((struct elf_x86_64_link_hash_entry *)(ent))
-
-struct elf_x86_64_obj_tdata
-{
- struct elf_obj_tdata root;
-
- /* tls_type for each local got entry. */
- char *local_got_tls_type;
-
- /* GOTPLT entries for TLS descriptors. */
- bfd_vma *local_tlsdesc_gotent;
-};
-
-#define elf_x86_64_tdata(abfd) \
- ((struct elf_x86_64_obj_tdata *) (abfd)->tdata.any)
-
-#define elf_x86_64_local_got_tls_type(abfd) \
- (elf_x86_64_tdata (abfd)->local_got_tls_type)
-
-#define elf_x86_64_local_tlsdesc_gotent(abfd) \
- (elf_x86_64_tdata (abfd)->local_tlsdesc_gotent)
#define is_x86_64_elf(bfd) \
(bfd_get_flavour (bfd) == bfd_target_elf_flavour \
@@ -1165,7 +1052,7 @@ struct elf_x86_64_obj_tdata
static bfd_boolean
elf_x86_64_mkobject (bfd *abfd)
{
- return bfd_elf_allocate_object (abfd, sizeof (struct elf_x86_64_obj_tdata),
+ return bfd_elf_allocate_object (abfd, sizeof (struct elf_x86_obj_tdata),
X86_64_ELF_DATA);
}
@@ -1173,15 +1060,7 @@ elf_x86_64_mkobject (bfd *abfd)
struct elf_x86_64_link_hash_table
{
- struct elf_link_hash_table elf;
-
- /* Short-cuts to get to dynamic linker sections. */
- asection *interp;
- asection *plt_eh_frame;
- asection *plt_second;
- asection *plt_second_eh_frame;
- asection *plt_got;
- asection *plt_got_eh_frame;
+ struct elf_x86_link_hash_table x86;
/* Parameters describing PLT generation, lazy or non-lazy. */
struct elf_x86_64_plt_layout plt;
@@ -1191,201 +1070,41 @@ struct elf_x86_64_link_hash_table
/* Parameters describing non-lazy PLT generation. */
const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt;
-
- union
- {
- bfd_signed_vma refcount;
- bfd_vma offset;
- } tls_ld_got;
-
- /* The amount of space used by the jump slots in the GOT. */
- bfd_vma sgotplt_jump_table_size;
-
- /* Small local sym cache. */
- struct sym_cache sym_cache;
-
- bfd_vma (*r_info) (bfd_vma, bfd_vma);
- bfd_vma (*r_sym) (bfd_vma);
- unsigned int pointer_r_type;
- const char *dynamic_interpreter;
- int dynamic_interpreter_size;
-
- /* _TLS_MODULE_BASE_ symbol. */
- struct bfd_link_hash_entry *tls_module_base;
-
- /* Used by local STT_GNU_IFUNC symbols. */
- htab_t loc_hash_table;
- void * loc_hash_memory;
-
- /* The offset into splt of the PLT entry for the TLS descriptor
- resolver. Special values are 0, if not necessary (or not found
- to be necessary yet), and -1 if needed but not determined
- yet. */
- bfd_vma tlsdesc_plt;
- /* The offset into sgot of the GOT entry used by the PLT entry
- above. */
- bfd_vma tlsdesc_got;
-
- /* The index of the next R_X86_64_JUMP_SLOT entry in .rela.plt. */
- bfd_vma next_jump_slot_index;
- /* The index of the next R_X86_64_IRELATIVE entry in .rela.plt. */
- bfd_vma next_irelative_index;
-
- /* TRUE if there are dynamic relocs against IFUNC symbols that apply
- to read-only sections. */
- bfd_boolean readonly_dynrelocs_against_ifunc;
};
-/* Get the x86-64 ELF linker hash table from a link_info structure. */
-
-#define elf_x86_64_hash_table(p) \
- (elf_hash_table_id ((struct elf_link_hash_table *) ((p)->hash)) \
- == X86_64_ELF_DATA ? ((struct elf_x86_64_link_hash_table *) ((p)->hash)) : NULL)
-
-#define elf_x86_64_compute_jump_table_size(htab) \
- ((htab)->elf.srelplt->reloc_count * GOT_ENTRY_SIZE)
-
-/* Create an entry in an x86-64 ELF linker hash table. */
-
-static struct bfd_hash_entry *
-elf_x86_64_link_hash_newfunc (struct bfd_hash_entry *entry,
- struct bfd_hash_table *table,
- const char *string)
-{
- /* Allocate the structure if it has not already been allocated by a
- subclass. */
- if (entry == NULL)
- {
- entry = (struct bfd_hash_entry *)
- bfd_hash_allocate (table,
- sizeof (struct elf_x86_64_link_hash_entry));
- if (entry == NULL)
- return entry;
- }
+#define elf_x86_64_next_tls_desc_index(htab) \
+ ((struct elf_x86_64_link_hash_table *) (htab))->next_tls_desc_index
- /* Call the allocation method of the superclass. */
- entry = _bfd_elf_link_hash_newfunc (entry, table, string);
- if (entry != NULL)
- {
- struct elf_x86_64_link_hash_entry *eh;
+#define elf_x86_64_srelplt2(htab) \
+ ((struct elf_x86_64_link_hash_table *) (htab))->srelplt2
- eh = (struct elf_x86_64_link_hash_entry *) entry;
- eh->dyn_relocs = NULL;
- eh->tls_type = GOT_UNKNOWN;
- eh->needs_copy = 0;
- eh->has_got_reloc = 0;
- eh->has_non_got_reloc = 0;
- eh->no_finish_dynamic_symbol = 0;
- eh->tls_get_addr = 0;
- eh->def_protected = 0;
- eh->func_pointer_refcount = 0;
- eh->plt_second.offset = (bfd_vma) -1;
- eh->plt_got.offset = (bfd_vma) -1;
- eh->tlsdesc_got = (bfd_vma) -1;
- }
+#define elf_x86_64_plt(htab) \
+ ((struct elf_x86_64_link_hash_table *) (htab))->plt
- return entry;
-}
+#define elf_x86_64_lazy_plt(htab) \
+ ((struct elf_x86_64_link_hash_table *) (htab))->lazy_plt
-/* Compute a hash of a local hash entry. We use elf_link_hash_entry
- for local symbol so that we can handle local STT_GNU_IFUNC symbols
- as global symbol. We reuse indx and dynstr_index for local symbol
- hash since they aren't used by global symbols in this backend. */
-
-static hashval_t
-elf_x86_64_local_htab_hash (const void *ptr)
-{
- struct elf_link_hash_entry *h
- = (struct elf_link_hash_entry *) ptr;
- return ELF_LOCAL_SYMBOL_HASH (h->indx, h->dynstr_index);
-}
-
-/* Compare local hash entries. */
-
-static int
-elf_x86_64_local_htab_eq (const void *ptr1, const void *ptr2)
-{
- struct elf_link_hash_entry *h1
- = (struct elf_link_hash_entry *) ptr1;
- struct elf_link_hash_entry *h2
- = (struct elf_link_hash_entry *) ptr2;
+#define elf_x86_64_non_lazy_plt(htab) \
+ ((struct elf_x86_64_link_hash_table *) (htab))->non_lazy_plt
- return h1->indx == h2->indx && h1->dynstr_index == h2->dynstr_index;
-}
-
-/* Find and/or create a hash entry for local symbol. */
-
-static struct elf_link_hash_entry *
-elf_x86_64_get_local_sym_hash (struct elf_x86_64_link_hash_table *htab,
- bfd *abfd, const Elf_Internal_Rela *rel,
- bfd_boolean create)
-{
- struct elf_x86_64_link_hash_entry e, *ret;
- asection *sec = abfd->sections;
- hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id,
- htab->r_sym (rel->r_info));
- void **slot;
-
- e.elf.indx = sec->id;
- e.elf.dynstr_index = htab->r_sym (rel->r_info);
- slot = htab_find_slot_with_hash (htab->loc_hash_table, &e, h,
- create ? INSERT : NO_INSERT);
-
- if (!slot)
- return NULL;
-
- if (*slot)
- {
- ret = (struct elf_x86_64_link_hash_entry *) *slot;
- return &ret->elf;
- }
-
- ret = (struct elf_x86_64_link_hash_entry *)
- objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
- sizeof (struct elf_x86_64_link_hash_entry));
- if (ret)
- {
- memset (ret, 0, sizeof (*ret));
- ret->elf.indx = sec->id;
- ret->elf.dynstr_index = htab->r_sym (rel->r_info);
- ret->elf.dynindx = -1;
- ret->func_pointer_refcount = 0;
- ret->plt_got.offset = (bfd_vma) -1;
- *slot = ret;
- }
- return &ret->elf;
-}
-
-/* Destroy an X86-64 ELF linker hash table. */
-
-static void
-elf_x86_64_link_hash_table_free (bfd *obfd)
-{
- struct elf_x86_64_link_hash_table *htab
- = (struct elf_x86_64_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);
-}
+#define elf_x86_64_compute_jump_table_size(htab) \
+ ((htab)->elf.srelplt->reloc_count * GOT_ENTRY_SIZE)
/* Create an X86-64 ELF linker hash table. */
static struct bfd_link_hash_table *
elf_x86_64_link_hash_table_create (bfd *abfd)
{
- struct elf_x86_64_link_hash_table *ret;
+ struct elf_x86_link_hash_table *ret;
bfd_size_type amt = sizeof (struct elf_x86_64_link_hash_table);
- ret = (struct elf_x86_64_link_hash_table *) bfd_zmalloc (amt);
+ ret = (struct elf_x86_link_hash_table *) bfd_zmalloc (amt);
if (ret == NULL)
return NULL;
if (!_bfd_elf_link_hash_table_init (&ret->elf, abfd,
- elf_x86_64_link_hash_newfunc,
- sizeof (struct elf_x86_64_link_hash_entry),
+ _bfd_x86_elf_link_hash_newfunc,
+ sizeof (struct elf_x86_link_hash_entry),
X86_64_ELF_DATA))
{
free (ret);
@@ -1409,100 +1128,22 @@ elf_x86_64_link_hash_table_create (bfd *abfd)
ret->dynamic_interpreter_size = sizeof ELF32_DYNAMIC_INTERPRETER;
}
+ ret->tls_get_addr = "__tls_get_addr";
ret->loc_hash_table = htab_try_create (1024,
- elf_x86_64_local_htab_hash,
- elf_x86_64_local_htab_eq,
+ _bfd_x86_elf_local_htab_hash,
+ _bfd_x86_elf_local_htab_eq,
NULL);
ret->loc_hash_memory = objalloc_create ();
if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
- elf_x86_64_link_hash_table_free (abfd);
+ _bfd_x86_elf_link_hash_table_free (abfd);
return NULL;
}
- ret->elf.root.hash_table_free = elf_x86_64_link_hash_table_free;
+ ret->elf.root.hash_table_free = _bfd_x86_elf_link_hash_table_free;
return &ret->elf.root;
}
-/* Copy the extra info we tack onto an elf_link_hash_entry. */
-
-static void
-elf_x86_64_copy_indirect_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *dir,
- struct elf_link_hash_entry *ind)
-{
- struct elf_x86_64_link_hash_entry *edir, *eind;
-
- edir = (struct elf_x86_64_link_hash_entry *) dir;
- eind = (struct elf_x86_64_link_hash_entry *) ind;
-
- edir->has_got_reloc |= eind->has_got_reloc;
- edir->has_non_got_reloc |= eind->has_non_got_reloc;
-
- if (eind->dyn_relocs != NULL)
- {
- if (edir->dyn_relocs != NULL)
- {
- struct elf_dyn_relocs **pp;
- struct elf_dyn_relocs *p;
-
- /* Add reloc counts against the indirect sym to the direct sym
- list. Merge any entries against the same section. */
- for (pp = &eind->dyn_relocs; (p = *pp) != NULL; )
- {
- struct elf_dyn_relocs *q;
-
- for (q = edir->dyn_relocs; q != NULL; q = q->next)
- if (q->sec == p->sec)
- {
- q->pc_count += p->pc_count;
- q->count += p->count;
- *pp = p->next;
- break;
- }
- if (q == NULL)
- pp = &p->next;
- }
- *pp = edir->dyn_relocs;
- }
-
- edir->dyn_relocs = eind->dyn_relocs;
- eind->dyn_relocs = NULL;
- }
-
- if (ind->root.type == bfd_link_hash_indirect
- && dir->got.refcount <= 0)
- {
- edir->tls_type = eind->tls_type;
- eind->tls_type = GOT_UNKNOWN;
- }
-
- if (ELIMINATE_COPY_RELOCS
- && ind->root.type != bfd_link_hash_indirect
- && dir->dynamic_adjusted)
- {
- /* If called to transfer flags for a weakdef during processing
- of elf_adjust_dynamic_symbol, don't copy non_got_ref.
- We clear it ourselves for ELIMINATE_COPY_RELOCS. */
- if (dir->versioned != versioned_hidden)
- dir->ref_dynamic |= ind->ref_dynamic;
- dir->ref_regular |= ind->ref_regular;
- dir->ref_regular_nonweak |= ind->ref_regular_nonweak;
- dir->needs_plt |= ind->needs_plt;
- dir->pointer_equality_needed |= ind->pointer_equality_needed;
- }
- else
- {
- if (eind->func_pointer_refcount > 0)
- {
- edir->func_pointer_refcount += eind->func_pointer_refcount;
- eind->func_pointer_refcount = 0;
- }
-
- _bfd_elf_link_hash_copy_indirect (info, dir, ind);
- }
-}
-
static bfd_boolean
elf64_x86_64_elf_object_p (bfd *abfd)
{
@@ -1538,11 +1179,11 @@ elf_x86_64_check_tls_transition (bfd *abfd,
bfd_boolean largepic = FALSE;
struct elf_link_hash_entry *h;
bfd_vma offset;
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
bfd_byte *call;
bfd_boolean indirect_call;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
offset = rel->r_offset;
switch (r_type)
{
@@ -1682,7 +1323,7 @@ elf_x86_64_check_tls_transition (bfd *abfd,
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
if (h == NULL
- || !((struct elf_x86_64_link_hash_entry *) h)->tls_get_addr)
+ || !((struct elf_x86_link_hash_entry *) h)->tls_get_addr)
return FALSE;
else if (largepic)
return ELF32_R_TYPE (rel[1].r_info) == R_X86_64_PLTOFF64;
@@ -1861,9 +1502,9 @@ elf_x86_64_tls_transition (struct bfd_link_info *info, bfd *abfd,
name = h->root.root.string;
else
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
name = "*unknown*";
else
@@ -1923,7 +1564,7 @@ elf_x86_64_need_pic (struct bfd_link_info *info,
v = _("protected symbol ");
break;
default:
- if (((struct elf_x86_64_link_hash_entry *) h)->def_protected)
+ if (((struct elf_x86_link_hash_entry *) h)->def_protected)
v = _("protected symbol ");
else
v = _("symbol ");
@@ -1984,7 +1625,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
bfd_boolean *converted,
struct bfd_link_info *link_info)
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
bfd_boolean is_pic;
bfd_boolean require_reloc_pc32;
bfd_boolean relocx;
@@ -2007,7 +1648,7 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
if (raddend != -4)
return TRUE;
- htab = elf_x86_64_hash_table (link_info);
+ htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA);
is_pic = bfd_link_pic (link_info);
relocx = (r_type == R_X86_64_GOTPCRELX
@@ -2076,8 +1717,9 @@ elf_x86_64_convert_load_reloc (bfd *abfd, asection *sec,
R_X86_64_PC32. */
if ((relocx || opcode == 0x8b)
&& UNDEFINED_WEAK_RESOLVED_TO_ZERO (link_info,
+ X86_64_ELF_DATA,
TRUE,
- elf_x86_64_hash_entry (h)))
+ elf_x86_hash_entry (h)))
{
if (opcode == 0xff)
{
@@ -2251,8 +1893,8 @@ convert:
}
else
{
- struct elf_x86_64_link_hash_entry *eh
- = (struct elf_x86_64_link_hash_entry *) h;
+ struct elf_x86_link_hash_entry *eh
+ = (struct elf_x86_link_hash_entry *) h;
/* Convert to "nop call foo". ADDR_PREFIX_OPCODE
is a nop prefix. */
@@ -2386,7 +2028,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
asection *sec,
const Elf_Internal_Rela *relocs)
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
@@ -2408,7 +2050,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
BFD_ASSERT (is_x86_64_elf (abfd));
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
{
sec->check_relocs_failed = 1;
@@ -2435,7 +2077,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
unsigned int r_type;
unsigned int r_symndx;
struct elf_link_hash_entry *h;
- struct elf_x86_64_link_hash_entry *eh;
+ struct elf_x86_link_hash_entry *eh;
Elf_Internal_Sym *isym;
const char *name;
bfd_boolean size_reloc;
@@ -2462,8 +2104,8 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
/* Check relocation against local STT_GNU_IFUNC symbol. */
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
- h = elf_x86_64_get_local_sym_hash (htab, abfd, rel,
- TRUE);
+ h = _bfd_elf_x86_get_local_sym_hash (htab, abfd, rel,
+ TRUE);
if (h == NULL)
goto error_return;
@@ -2538,11 +2180,11 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
rel, rel_end, h, r_symndx, FALSE))
goto error_return;
- eh = (struct elf_x86_64_link_hash_entry *) h;
+ eh = (struct elf_x86_link_hash_entry *) h;
switch (r_type)
{
case R_X86_64_TLSLD:
- htab->tls_ld_got.refcount += 1;
+ htab->tls_ld_or_ldm_got.refcount += 1;
goto create_got;
case R_X86_64_TPOFF32:
@@ -2605,14 +2247,14 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
if (local_got_refcounts == NULL)
goto error_return;
elf_local_got_refcounts (abfd) = local_got_refcounts;
- elf_x86_64_local_tlsdesc_gotent (abfd)
+ elf_x86_local_tlsdesc_gotent (abfd)
= (bfd_vma *) (local_got_refcounts + symtab_hdr->sh_info);
- elf_x86_64_local_got_tls_type (abfd)
+ elf_x86_local_got_tls_type (abfd)
= (char *) (local_got_refcounts + 2 * symtab_hdr->sh_info);
}
local_got_refcounts[r_symndx] += 1;
old_tls_type
- = elf_x86_64_local_got_tls_type (abfd) [r_symndx];
+ = elf_x86_local_got_tls_type (abfd) [r_symndx];
}
/* If a TLS symbol is accessed using IE at least once,
@@ -2648,7 +2290,7 @@ elf_x86_64_check_relocs (bfd *abfd, struct bfd_link_info *info,
if (eh != NULL)
eh->tls_type = tls_type;
else
- elf_x86_64_local_got_tls_type (abfd) [r_symndx] = tls_type;
+ elf_x86_local_got_tls_type (abfd) [r_symndx] = tls_type;
}
}
/* Fall through */
@@ -2949,25 +2591,6 @@ elf_x86_64_gc_mark_hook (asection *sec,
return _bfd_elf_gc_mark_hook (sec, info, rel, h, sym);
}
-/* Remove undefined weak symbol from the dynamic symbol table if it
- is resolved to 0. */
-
-static bfd_boolean
-elf_x86_64_fixup_symbol (struct bfd_link_info *info,
- struct elf_link_hash_entry *h)
-{
- if (h->dynindx != -1
- && UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
- elf_x86_64_hash_entry (h)->has_got_reloc,
- elf_x86_64_hash_entry (h)))
- {
- h->dynindx = -1;
- _bfd_elf_strtab_delref (elf_hash_table (info)->dynstr,
- h->dynstr_index);
- }
- return TRUE;
-}
-
/* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to
@@ -2978,9 +2601,9 @@ static bfd_boolean
elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
struct elf_link_hash_entry *h)
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
asection *s, *srel;
- struct elf_x86_64_link_hash_entry *eh;
+ struct elf_x86_link_hash_entry *eh;
struct elf_dyn_relocs *p;
/* STT_GNU_IFUNC symbol must go through PLT. */
@@ -2994,7 +2617,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
bfd_size_type pc_count = 0, count = 0;
struct elf_dyn_relocs **pp;
- eh = (struct elf_x86_64_link_hash_entry *) h;
+ eh = (struct elf_x86_link_hash_entry *) h;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; )
{
pc_count += p->pc_count;
@@ -3061,7 +2684,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
the link may change h->type. So fix it now. */
h->plt.offset = (bfd_vma) -1;
- eh = (struct elf_x86_64_link_hash_entry *) h;
+ eh = (struct elf_x86_link_hash_entry *) h;
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
@@ -3106,7 +2729,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
if (ELIMINATE_COPY_RELOCS)
{
- eh = (struct elf_x86_64_link_hash_entry *) h;
+ eh = (struct elf_x86_link_hash_entry *) h;
for (p = eh->dyn_relocs; p != NULL; p = p->next)
{
s = p->sec->output_section;
@@ -3133,7 +2756,7 @@ elf_x86_64_adjust_dynamic_symbol (struct bfd_link_info *info,
both the dynamic object and the regular object will refer to the
same memory location for the variable. */
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return FALSE;
@@ -3168,26 +2791,32 @@ static bfd_boolean
elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
{
struct bfd_link_info *info;
- struct elf_x86_64_link_hash_table *htab;
- struct elf_x86_64_link_hash_entry *eh;
+ struct elf_x86_link_hash_table *htab;
+ struct elf_x86_link_hash_entry *eh;
struct elf_dyn_relocs *p;
const struct elf_backend_data *bed;
unsigned int plt_entry_size;
bfd_boolean resolved_to_zero;
+ const struct elf_x86_64_plt_layout *plt_layout;
+ const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
if (h->root.type == bfd_link_hash_indirect)
return TRUE;
- eh = (struct elf_x86_64_link_hash_entry *) h;
+ eh = (struct elf_x86_link_hash_entry *) h;
info = (struct bfd_link_info *) inf;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return FALSE;
bed = get_elf_backend_data (info->output_bfd);
- plt_entry_size = htab->plt.plt_entry_size;
+
+ plt_layout = &elf_x86_64_plt (htab);
+ non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
+ plt_entry_size = plt_layout->plt_entry_size;
resolved_to_zero = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
+ X86_64_ELF_DATA,
eh->has_got_reloc,
eh);
@@ -3223,7 +2852,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
&eh->dyn_relocs,
&htab->readonly_dynrelocs_against_ifunc,
plt_entry_size,
- (htab->plt.has_plt0
+ (plt_layout->has_plt0
* plt_entry_size),
GOT_ENTRY_SIZE, TRUE))
{
@@ -3234,7 +2863,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
eh->plt_second.offset = s->size;
/* Make room for this entry in the second PLT section. */
- s->size += htab->non_lazy_plt->plt_entry_size;
+ s->size += non_lazy_plt_layout->plt_entry_size;
}
return TRUE;
@@ -3276,7 +2905,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
first entry. The .plt section is used by prelink to undo
prelinking for dynamic relocations. */
if (s->size == 0)
- s->size = htab->plt.has_plt0 * plt_entry_size;
+ s->size = plt_layout->has_plt0 * plt_entry_size;
if (use_plt_got)
eh->plt_got.offset = got_s->size;
@@ -3321,12 +2950,12 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
/* Make room for this entry. */
if (use_plt_got)
- got_s->size += htab->non_lazy_plt->plt_entry_size;
+ got_s->size += non_lazy_plt_layout->plt_entry_size;
else
{
s->size += plt_entry_size;
if (second_s)
- second_s->size += htab->non_lazy_plt->plt_entry_size;
+ second_s->size += non_lazy_plt_layout->plt_entry_size;
/* We also need to make an entry in the .got.plt section,
which will be placed in the .got section by the linker
@@ -3365,7 +2994,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
if (h->got.refcount > 0
&& bfd_link_executable (info)
&& h->dynindx == -1
- && elf_x86_64_hash_entry (h)->tls_type == GOT_TLS_IE)
+ && elf_x86_hash_entry (h)->tls_type == GOT_TLS_IE)
{
h->got.offset = (bfd_vma) -1;
}
@@ -3373,7 +3002,7 @@ elf_x86_64_allocate_dynrelocs (struct elf_link_hash_entry *h, void * inf)
{
asection *s;
bfd_boolean dyn;
- int tls_type = elf_x86_64_hash_entry (h)->tls_type;
+ int tls_type = elf_x86_hash_entry (h)->tls_type;
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
@@ -3567,44 +3196,6 @@ elf_x86_64_allocate_local_dynrelocs (void **slot, void *inf)
return elf_x86_64_allocate_dynrelocs (h, inf);
}
-/* Find any dynamic relocs that apply to read-only sections. */
-
-static bfd_boolean
-elf_x86_64_readonly_dynrelocs (struct elf_link_hash_entry *h,
- void * inf)
-{
- struct elf_x86_64_link_hash_entry *eh;
- struct elf_dyn_relocs *p;
-
- /* Skip local IFUNC symbols. */
- if (h->forced_local && h->type == STT_GNU_IFUNC)
- return TRUE;
-
- eh = (struct elf_x86_64_link_hash_entry *) h;
- for (p = eh->dyn_relocs; p != NULL; p = p->next)
- {
- asection *s = p->sec->output_section;
-
- if (s != NULL && (s->flags & SEC_READONLY) != 0)
- {
- struct bfd_link_info *info = (struct bfd_link_info *) inf;
-
- info->flags |= DF_TEXTREL;
-
- if ((info->warn_shared_textrel && bfd_link_pic (info))
- || info->error_textrel)
- /* xgettext:c-format */
- 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;
- }
- }
- return TRUE;
-}
-
/* Convert load via the GOT slot to load immediate. */
static bfd_boolean
@@ -3615,7 +3206,7 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
Elf_Internal_Rela *internal_relocs;
Elf_Internal_Rela *irel, *irelend;
bfd_byte *contents;
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
bfd_boolean changed;
bfd_signed_vma *local_got_refcounts;
@@ -3639,7 +3230,7 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
return FALSE;
changed = FALSE;
- htab = elf_x86_64_hash_table (link_info);
+ htab = elf_x86_hash_table (link_info, X86_64_ELF_DATA);
local_got_refcounts = elf_local_got_refcounts (abfd);
/* Get the section contents. */
@@ -3666,9 +3257,9 @@ elf_x86_64_convert_load (bfd *abfd, asection *sec,
r_symndx = htab->r_sym (irel->r_info);
if (r_symndx < symtab_hdr->sh_info)
- h = elf_x86_64_get_local_sym_hash (htab, sec->owner,
- (const Elf_Internal_Rela *) irel,
- FALSE);
+ h = _bfd_elf_x86_get_local_sym_hash (htab, sec->owner,
+ (const Elf_Internal_Rela *) irel,
+ FALSE);
else
{
h = elf_sym_hashes (abfd)[r_symndx - symtab_hdr->sh_info];
@@ -3741,14 +3332,16 @@ static bfd_boolean
elf_x86_64_size_dynamic_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
bfd *dynobj;
asection *s;
bfd_boolean relocs;
bfd *ibfd;
const struct elf_backend_data *bed;
+ const struct elf_x86_64_plt_layout *plt_layout;
+ const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return FALSE;
bed = get_elf_backend_data (output_bfd);
@@ -3757,6 +3350,9 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
if (dynobj == NULL)
abort ();
+ plt_layout = &elf_x86_64_plt (htab);
+ non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
+
/* Set up .got offsets for local syms, and space for local dynamic
relocs. */
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
@@ -3817,8 +3413,8 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
symtab_hdr = &elf_symtab_hdr (ibfd);
locsymcount = symtab_hdr->sh_info;
end_local_got = local_got + locsymcount;
- local_tls_type = elf_x86_64_local_got_tls_type (ibfd);
- local_tlsdesc_gotent = elf_x86_64_local_tlsdesc_gotent (ibfd);
+ local_tls_type = elf_x86_local_got_tls_type (ibfd);
+ local_tlsdesc_gotent = elf_x86_local_tlsdesc_gotent (ibfd);
s = htab->elf.sgot;
srel = htab->elf.srelgot;
for (; local_got < end_local_got;
@@ -3862,16 +3458,16 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
}
}
- if (htab->tls_ld_got.refcount > 0)
+ if (htab->tls_ld_or_ldm_got.refcount > 0)
{
/* Allocate 2 got entries and 1 dynamic reloc for R_X86_64_TLSLD
relocs. */
- htab->tls_ld_got.offset = htab->elf.sgot->size;
+ htab->tls_ld_or_ldm_got.offset = htab->elf.sgot->size;
htab->elf.sgot->size += 2 * GOT_ENTRY_SIZE;
htab->elf.srelgot->size += bed->s->sizeof_rela;
}
else
- htab->tls_ld_got.offset = -1;
+ htab->tls_ld_or_ldm_got.offset = -1;
/* Allocate global sym .plt and .got entries, and space for global
sym dynamic relocs. */
@@ -3913,9 +3509,9 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
/* Reserve room for the initial entry.
FIXME: we could probably do away with it in this case. */
if (htab->elf.splt->size == 0)
- htab->elf.splt->size = htab->plt.plt_entry_size;
+ htab->elf.splt->size = plt_layout->plt_entry_size;
htab->tlsdesc_plt = htab->elf.splt->size;
- htab->elf.splt->size += htab->plt.plt_entry_size;
+ htab->elf.splt->size += plt_layout->plt_entry_size;
}
}
@@ -3944,14 +3540,14 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->elf.splt != NULL
&& htab->elf.splt->size != 0
&& !bfd_is_abs_section (htab->elf.splt->output_section))
- htab->plt_eh_frame->size = htab->plt.eh_frame_plt_size;
+ htab->plt_eh_frame->size = plt_layout->eh_frame_plt_size;
if (htab->plt_got_eh_frame != NULL
&& htab->plt_got != NULL
&& htab->plt_got->size != 0
&& !bfd_is_abs_section (htab->plt_got->output_section))
htab->plt_got_eh_frame->size
- = htab->non_lazy_plt->eh_frame_plt_size;
+ = non_lazy_plt_layout->eh_frame_plt_size;
/* Unwind info for the second PLT and .plt.got sections are
identical. */
@@ -3960,7 +3556,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_second->size != 0
&& !bfd_is_abs_section (htab->plt_second->output_section))
htab->plt_second_eh_frame->size
- = htab->non_lazy_plt->eh_frame_plt_size;
+ = non_lazy_plt_layout->eh_frame_plt_size;
}
/* We now have determined the sizes of the various dynamic sections.
@@ -4036,7 +3632,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_eh_frame->contents != NULL)
{
memcpy (htab->plt_eh_frame->contents,
- htab->plt.eh_frame_plt, htab->plt_eh_frame->size);
+ plt_layout->eh_frame_plt, htab->plt_eh_frame->size);
bfd_put_32 (dynobj, htab->elf.splt->size,
htab->plt_eh_frame->contents + PLT_FDE_LEN_OFFSET);
}
@@ -4045,7 +3641,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_got_eh_frame->contents != NULL)
{
memcpy (htab->plt_got_eh_frame->contents,
- htab->non_lazy_plt->eh_frame_plt,
+ non_lazy_plt_layout->eh_frame_plt,
htab->plt_got_eh_frame->size);
bfd_put_32 (dynobj, htab->plt_got->size,
(htab->plt_got_eh_frame->contents
@@ -4056,7 +3652,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
&& htab->plt_second_eh_frame->contents != NULL)
{
memcpy (htab->plt_second_eh_frame->contents,
- htab->non_lazy_plt->eh_frame_plt,
+ non_lazy_plt_layout->eh_frame_plt,
htab->plt_second_eh_frame->size);
bfd_put_32 (dynobj, htab->plt_second->size,
(htab->plt_second_eh_frame->contents
@@ -4111,7 +3707,7 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
then we need a DT_TEXTREL entry. */
if ((info->flags & DF_TEXTREL) == 0)
elf_link_hash_traverse (&htab->elf,
- elf_x86_64_readonly_dynrelocs,
+ _bfd_x86_elf_readonly_dynrelocs,
info);
if ((info->flags & DF_TEXTREL) != 0)
@@ -4134,88 +3730,6 @@ elf_x86_64_size_dynamic_sections (bfd *output_bfd,
return TRUE;
}
-static bfd_boolean
-elf_x86_64_always_size_sections (bfd *output_bfd,
- struct bfd_link_info *info)
-{
- asection *tls_sec = elf_hash_table (info)->tls_sec;
-
- if (tls_sec)
- {
- struct elf_link_hash_entry *tlsbase;
-
- tlsbase = elf_link_hash_lookup (elf_hash_table (info),
- "_TLS_MODULE_BASE_",
- FALSE, FALSE, FALSE);
-
- if (tlsbase && tlsbase->type == STT_TLS)
- {
- struct elf_x86_64_link_hash_table *htab;
- struct bfd_link_hash_entry *bh = NULL;
- const struct elf_backend_data *bed
- = get_elf_backend_data (output_bfd);
-
- htab = elf_x86_64_hash_table (info);
- if (htab == NULL)
- return FALSE;
-
- if (!(_bfd_generic_link_add_one_symbol
- (info, output_bfd, "_TLS_MODULE_BASE_", BSF_LOCAL,
- tls_sec, 0, NULL, FALSE,
- bed->collect, &bh)))
- return FALSE;
-
- htab->tls_module_base = bh;
-
- tlsbase = (struct elf_link_hash_entry *)bh;
- tlsbase->def_regular = 1;
- tlsbase->other = STV_HIDDEN;
- tlsbase->root.linker_def = 1;
- (*bed->elf_backend_hide_symbol) (info, tlsbase, TRUE);
- }
- }
-
- return TRUE;
-}
-
-/* _TLS_MODULE_BASE_ needs to be treated especially when linking
- executables. Rather than setting it to the beginning of the TLS
- section, we have to set it to the end. This function may be called
- multiple times, it is idempotent. */
-
-static void
-elf_x86_64_set_tls_module_base (struct bfd_link_info *info)
-{
- struct elf_x86_64_link_hash_table *htab;
- struct bfd_link_hash_entry *base;
-
- if (!bfd_link_executable (info))
- return;
-
- htab = elf_x86_64_hash_table (info);
- if (htab == NULL)
- return;
-
- base = htab->tls_module_base;
- if (base == NULL)
- return;
-
- base->u.def.value = htab->elf.tls_size;
-}
-
-/* Return the base VMA address which should be subtracted from real addresses
- when resolving @dtpoff relocation.
- This is PT_TLS segment p_vaddr. */
-
-static bfd_vma
-elf_x86_64_dtpoff_base (struct bfd_link_info *info)
-{
- /* If tls_sec is NULL, we should have signalled an error already. */
- if (elf_hash_table (info)->tls_sec == NULL)
- return 0;
- return elf_hash_table (info)->tls_sec->vma;
-}
-
/* Return the relocation value for @tpoff relocation
if STT_TLS virtual address is ADDRESS. */
@@ -4265,7 +3779,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
Elf_Internal_Sym *local_syms,
asection **local_sections)
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
bfd_vma *local_got_offsets;
@@ -4281,16 +3795,16 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (input_section->check_relocs_failed)
return FALSE;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return FALSE;
- plt_entry_size = htab->plt.plt_entry_size;
+ plt_entry_size = elf_x86_64_plt (htab).plt_entry_size;
symtab_hdr = &elf_symtab_hdr (input_bfd);
sym_hashes = elf_sym_hashes (input_bfd);
local_got_offsets = elf_local_got_offsets (input_bfd);
- local_tlsdesc_gotents = elf_x86_64_local_tlsdesc_gotent (input_bfd);
+ local_tlsdesc_gotents = elf_x86_local_tlsdesc_gotent (input_bfd);
- elf_x86_64_set_tls_module_base (info);
+ _bfd_x86_elf_set_tls_module_base (info);
rel = wrel = relocs;
relend = relocs + input_section->reloc_count;
@@ -4300,7 +3814,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
reloc_howto_type *howto;
unsigned long r_symndx;
struct elf_link_hash_entry *h;
- struct elf_x86_64_link_hash_entry *eh;
+ struct elf_x86_link_hash_entry *eh;
Elf_Internal_Sym *sym;
asection *sec;
bfd_vma off, offplt, plt_offset;
@@ -4349,8 +3863,8 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (!bfd_link_relocatable (info)
&& ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
{
- h = elf_x86_64_get_local_sym_hash (htab, input_bfd,
- rel, FALSE);
+ h = _bfd_elf_x86_get_local_sym_hash (htab, input_bfd,
+ rel, FALSE);
if (h == NULL)
abort ();
@@ -4414,7 +3928,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
}
}
- eh = (struct elf_x86_64_link_hash_entry *) h;
+ eh = (struct elf_x86_link_hash_entry *) h;
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
it here if it is defined in a non-shared object. */
@@ -4462,7 +3976,7 @@ elf_x86_64_relocate_section (bfd *output_bfd,
if (htab->elf.splt != NULL)
{
plt_index = (h->plt.offset / plt_entry_size
- - htab->plt.has_plt0);
+ - elf_x86_64_plt (htab).has_plt0);
off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = htab->elf.sgotplt;
}
@@ -4654,6 +4168,7 @@ do_ifunc_pointer:
resolved_to_zero = (eh != NULL
&& UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
+ X86_64_ELF_DATA,
eh->has_got_reloc,
eh));
@@ -4692,7 +4207,7 @@ do_ifunc_pointer:
finish_dynamic_symbol would use that as offset into
.got. */
bfd_vma plt_index = (h->plt.offset / plt_entry_size
- - htab->plt.has_plt0);
+ - elf_x86_64_plt (htab).has_plt0);
off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = htab->elf.sgotplt;
}
@@ -5193,9 +4708,9 @@ direct:
case R_X86_64_GOTTPOFF:
tls_type = GOT_UNKNOWN;
if (h == NULL && local_got_offsets)
- tls_type = elf_x86_64_local_got_tls_type (input_bfd) [r_symndx];
+ tls_type = elf_x86_local_got_tls_type (input_bfd) [r_symndx];
else if (h != NULL)
- tls_type = elf_x86_64_hash_entry (h)->tls_type;
+ tls_type = elf_x86_hash_entry (h)->tls_type;
if (! elf_x86_64_tls_transition (info, input_bfd,
input_section, contents,
@@ -5392,7 +4907,7 @@ direct:
if (h != NULL)
{
off = h->got.offset;
- offplt = elf_x86_64_hash_entry (h)->tlsdesc_got;
+ offplt = elf_x86_hash_entry (h)->tlsdesc_got;
}
else
{
@@ -5427,7 +4942,7 @@ direct:
+ htab->sgotplt_jump_table_size);
sreloc = htab->elf.srelplt;
if (indx == 0)
- outrel.r_addend = relocation - elf_x86_64_dtpoff_base (info);
+ outrel.r_addend = relocation - _bfd_x86_elf_dtpoff_base (info);
else
outrel.r_addend = 0;
elf_append_rela (output_bfd, sreloc, &outrel);
@@ -5449,7 +4964,7 @@ direct:
outrel.r_addend = 0;
if ((dr_type == R_X86_64_TPOFF64
|| dr_type == R_X86_64_TLSDESC) && indx == 0)
- outrel.r_addend = relocation - elf_x86_64_dtpoff_base (info);
+ outrel.r_addend = relocation - _bfd_x86_elf_dtpoff_base (info);
outrel.r_info = htab->r_info (indx, dr_type);
elf_append_rela (output_bfd, sreloc, &outrel);
@@ -5460,7 +4975,7 @@ direct:
{
BFD_ASSERT (! unresolved_reloc);
bfd_put_64 (output_bfd,
- relocation - elf_x86_64_dtpoff_base (info),
+ relocation - _bfd_x86_elf_dtpoff_base (info),
htab->elf.sgot->contents + off + GOT_ENTRY_SIZE);
}
else
@@ -5684,7 +5199,7 @@ direct:
if (htab->elf.sgot == NULL)
abort ();
- off = htab->tls_ld_got.offset;
+ off = htab->tls_ld_or_ldm_got.offset;
if (off & 1)
off &= ~1;
else
@@ -5705,7 +5220,7 @@ direct:
outrel.r_addend = 0;
elf_append_rela (output_bfd, htab->elf.srelgot,
&outrel);
- htab->tls_ld_got.offset |= 1;
+ htab->tls_ld_or_ldm_got.offset |= 1;
}
relocation = htab->elf.sgot->output_section->vma
+ htab->elf.sgot->output_offset + off;
@@ -5715,7 +5230,7 @@ direct:
case R_X86_64_DTPOFF32:
if (!bfd_link_executable (info)
|| (input_section->flags & SEC_CODE) == 0)
- relocation -= elf_x86_64_dtpoff_base (info);
+ relocation -= _bfd_x86_elf_dtpoff_base (info);
else
relocation = elf_x86_64_tpoff (info, relocation);
break;
@@ -5728,7 +5243,7 @@ direct:
case R_X86_64_DTPOFF64:
BFD_ASSERT ((input_section->flags & SEC_CODE) == 0);
- relocation -= elf_x86_64_dtpoff_base (info);
+ relocation -= _bfd_x86_elf_dtpoff_base (info);
break;
default:
@@ -5843,26 +5358,34 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
struct elf_link_hash_entry *h,
Elf_Internal_Sym *sym)
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
bfd_boolean use_plt_second;
- struct elf_x86_64_link_hash_entry *eh;
+ struct elf_x86_link_hash_entry *eh;
bfd_boolean local_undefweak;
+ const struct elf_x86_64_plt_layout *plt_layout;
+ const struct elf_x86_64_lazy_plt_layout *lazy_plt_layout;
+ const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return FALSE;
/* Use the second PLT section only if there is .plt section. */
use_plt_second = htab->elf.splt != NULL && htab->plt_second != NULL;
- eh = (struct elf_x86_64_link_hash_entry *) h;
+ eh = (struct elf_x86_link_hash_entry *) h;
if (eh->no_finish_dynamic_symbol)
abort ();
+ plt_layout = &elf_x86_64_plt (htab);
+ lazy_plt_layout = elf_x86_64_lazy_plt (htab);
+ non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
+
/* We keep PLT/GOT entries without dynamic PLT/GOT relocations for
resolved undefined weak symbols in executable so that their
references have value 0 at run-time. */
local_undefweak = UNDEFINED_WEAK_RESOLVED_TO_ZERO (info,
+ X86_64_ELF_DATA,
eh->has_got_reloc,
eh);
@@ -5916,24 +5439,24 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
if (plt == htab->elf.splt)
{
- got_offset = (h->plt.offset / htab->plt.plt_entry_size
- - htab->plt.has_plt0);
+ got_offset = (h->plt.offset / plt_layout->plt_entry_size
+ - plt_layout->has_plt0);
got_offset = (got_offset + 3) * GOT_ENTRY_SIZE;
}
else
{
- got_offset = h->plt.offset / htab->plt.plt_entry_size;
+ got_offset = h->plt.offset / plt_layout->plt_entry_size;
got_offset = got_offset * GOT_ENTRY_SIZE;
}
/* Fill in the entry in the procedure linkage table. */
- memcpy (plt->contents + h->plt.offset, htab->plt.plt_entry,
- htab->plt.plt_entry_size);
+ memcpy (plt->contents + h->plt.offset, plt_layout->plt_entry,
+ plt_layout->plt_entry_size);
if (use_plt_second)
{
memcpy (htab->plt_second->contents + eh->plt_second.offset,
- htab->non_lazy_plt->plt_entry,
- htab->non_lazy_plt->plt_entry_size);
+ non_lazy_plt_layout->plt_entry,
+ non_lazy_plt_layout->plt_entry_size);
resolved_plt = htab->plt_second;
plt_offset = eh->plt_second.offset;
@@ -5954,7 +5477,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
- resolved_plt->output_section->vma
- resolved_plt->output_offset
- plt_offset
- - htab->plt.plt_got_insn_size);
+ - plt_layout->plt_got_insn_size);
/* Check PC-relative offset overflow in PLT entry. */
if ((plt_got_pcrel_offset + 0x80000000) > 0xffffffff)
@@ -5964,7 +5487,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
bfd_put_32 (output_bfd, plt_got_pcrel_offset,
(resolved_plt->contents + plt_offset
- + htab->plt.plt_got_offset));
+ + plt_layout->plt_got_offset));
/* Fill in the entry in the global offset table, initially this
points to the second part of the PLT entry. Leave the entry
@@ -5972,11 +5495,11 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
against undefined weak symbol in PIE. */
if (!local_undefweak)
{
- if (htab->plt.has_plt0)
+ if (plt_layout->has_plt0)
bfd_put_64 (output_bfd, (plt->output_section->vma
+ plt->output_offset
+ h->plt.offset
- + htab->lazy_plt->plt_lazy_offset),
+ + lazy_plt_layout->plt_lazy_offset),
gotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
@@ -6011,15 +5534,15 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
/* Don't fill the second and third slots in PLT entry for
static executables nor without PLT0. */
- if (plt == htab->elf.splt && htab->plt.has_plt0)
+ if (plt == htab->elf.splt && plt_layout->has_plt0)
{
bfd_vma plt0_offset
- = h->plt.offset + htab->lazy_plt->plt_plt_insn_end;
+ = h->plt.offset + lazy_plt_layout->plt_plt_insn_end;
/* Put relocation index. */
bfd_put_32 (output_bfd, plt_index,
(plt->contents + h->plt.offset
- + htab->lazy_plt->plt_reloc_offset));
+ + lazy_plt_layout->plt_reloc_offset));
/* Put offset for jmp .PLT0 and check for overflow. We don't
check relocation index for overflow since branch displacement
@@ -6030,7 +5553,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
output_bfd, h->root.root.string);
bfd_put_32 (output_bfd, - plt0_offset,
(plt->contents + h->plt.offset
- + htab->lazy_plt->plt_plt_offset));
+ + lazy_plt_layout->plt_plt_offset));
}
bed = get_elf_backend_data (output_bfd);
@@ -6061,8 +5584,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
/* Fill in the entry in the GOT procedure linkage table. */
plt_offset = eh->plt_got.offset;
memcpy (plt->contents + plt_offset,
- htab->non_lazy_plt->plt_entry,
- htab->non_lazy_plt->plt_entry_size);
+ non_lazy_plt_layout->plt_entry,
+ non_lazy_plt_layout->plt_entry_size);
/* Put offset the PC-relative instruction referring to the GOT
entry, subtracting the size of that instruction. */
@@ -6072,7 +5595,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
- plt->output_section->vma
- plt->output_offset
- plt_offset
- - htab->non_lazy_plt->plt_got_insn_size);
+ - non_lazy_plt_layout->plt_got_insn_size);
/* Check PC-relative offset overflow in GOT PLT entry. */
got_after_plt = got->output_section->vma > plt->output_section->vma;
@@ -6084,7 +5607,7 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
bfd_put_32 (output_bfd, got_pcrel_offset,
(plt->contents + plt_offset
- + htab->non_lazy_plt->plt_got_offset));
+ + non_lazy_plt_layout->plt_got_offset));
}
if (!local_undefweak
@@ -6108,8 +5631,8 @@ elf_x86_64_finish_dynamic_symbol (bfd *output_bfd,
/* Don't generate dynamic GOT relocation against undefined weak
symbol in executable. */
if (h->got.offset != (bfd_vma) -1
- && ! GOT_TLS_GD_ANY_P (elf_x86_64_hash_entry (h)->tls_type)
- && elf_x86_64_hash_entry (h)->tls_type != GOT_TLS_IE
+ && ! GOT_TLS_GD_ANY_P (elf_x86_hash_entry (h)->tls_type)
+ && elf_x86_hash_entry (h)->tls_type != GOT_TLS_IE
&& !local_undefweak)
{
Elf_Internal_Rela rela;
@@ -6287,7 +5810,8 @@ elf_x86_64_reloc_type_class (const struct bfd_link_info *info,
{
bfd *abfd = info->output_bfd;
const struct elf_backend_data *bed = get_elf_backend_data (abfd);
- struct elf_x86_64_link_hash_table *htab = elf_x86_64_hash_table (info);
+ struct elf_x86_link_hash_table *htab
+ = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab->elf.dynsym != NULL
&& htab->elf.dynsym->contents != NULL)
@@ -6331,11 +5855,11 @@ static bfd_boolean
elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
struct bfd_link_info *info)
{
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
bfd *dynobj;
asection *sdyn;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return FALSE;
@@ -6347,6 +5871,9 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
bfd_byte *dyncon, *dynconend;
const struct elf_backend_data *bed;
bfd_size_type sizeof_dyn;
+ const struct elf_x86_64_plt_layout *plt_layout;
+ const struct elf_x86_64_lazy_plt_layout *lazy_plt_layout;
+ const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
if (sdyn == NULL || htab->elf.sgot == NULL)
abort ();
@@ -6397,18 +5924,22 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
(*bed->s->swap_dyn_out) (output_bfd, &dyn, dyncon);
}
+ plt_layout = &elf_x86_64_plt (htab);
+ lazy_plt_layout = elf_x86_64_lazy_plt (htab);
+ non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
+
if (htab->elf.splt && htab->elf.splt->size > 0)
{
elf_section_data (htab->elf.splt->output_section)
- ->this_hdr.sh_entsize = htab->plt.plt_entry_size;
+ ->this_hdr.sh_entsize = plt_layout->plt_entry_size;
- if (htab->plt.has_plt0)
+ if (plt_layout->has_plt0)
{
/* Fill in the special first entry in the procedure linkage
table. */
memcpy (htab->elf.splt->contents,
- htab->lazy_plt->plt0_entry,
- htab->lazy_plt->plt_entry_size);
+ lazy_plt_layout->plt0_entry,
+ lazy_plt_layout->plt_entry_size);
/* Add offset for pushq GOT+8(%rip), since the instruction
uses 6 bytes subtract this value. */
bfd_put_32 (output_bfd,
@@ -6419,7 +5950,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
- htab->elf.splt->output_offset
- 6),
(htab->elf.splt->contents
- + htab->lazy_plt->plt0_got1_offset));
+ + lazy_plt_layout->plt0_got1_offset));
/* Add offset for the PC-relative instruction accessing
GOT+16, subtracting the offset to the end of that
instruction. */
@@ -6429,9 +5960,9 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
+ 16
- htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset
- - htab->lazy_plt->plt0_got2_insn_end),
+ - lazy_plt_layout->plt0_got2_insn_end),
(htab->elf.splt->contents
- + htab->lazy_plt->plt0_got2_offset));
+ + lazy_plt_layout->plt0_got2_offset));
if (htab->tlsdesc_plt)
{
@@ -6439,8 +5970,8 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
htab->elf.sgot->contents + htab->tlsdesc_got);
memcpy (htab->elf.splt->contents + htab->tlsdesc_plt,
- htab->lazy_plt->plt0_entry,
- htab->lazy_plt->plt_entry_size);
+ lazy_plt_layout->plt0_entry,
+ lazy_plt_layout->plt_entry_size);
/* Add offset for pushq GOT+8(%rip), since the
instruction uses 6 bytes subtract this value. */
@@ -6454,7 +5985,7 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
- 6),
(htab->elf.splt->contents
+ htab->tlsdesc_plt
- + htab->lazy_plt->plt0_got1_offset));
+ + lazy_plt_layout->plt0_got1_offset));
/* Add offset for the PC-relative instruction accessing
GOT+TDG, where TDG stands for htab->tlsdesc_got,
subtracting the offset to the end of that
@@ -6466,22 +5997,22 @@ elf_x86_64_finish_dynamic_sections (bfd *output_bfd,
- htab->elf.splt->output_section->vma
- htab->elf.splt->output_offset
- htab->tlsdesc_plt
- - htab->lazy_plt->plt0_got2_insn_end),
+ - lazy_plt_layout->plt0_got2_insn_end),
(htab->elf.splt->contents
+ htab->tlsdesc_plt
- + htab->lazy_plt->plt0_got2_offset));
+ + lazy_plt_layout->plt0_got2_offset));
}
}
}
- }
- if (htab->plt_got != NULL && htab->plt_got->size > 0)
- elf_section_data (htab->plt_got->output_section)
- ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
+ if (htab->plt_got != NULL && htab->plt_got->size > 0)
+ elf_section_data (htab->plt_got->output_section)
+ ->this_hdr.sh_entsize = non_lazy_plt_layout->plt_entry_size;
- if (htab->plt_second != NULL && htab->plt_second->size > 0)
- elf_section_data (htab->plt_second->output_section)
- ->this_hdr.sh_entsize = htab->non_lazy_plt->plt_entry_size;
+ if (htab->plt_second != NULL && htab->plt_second->size > 0)
+ elf_section_data (htab->plt_second->output_section)
+ ->this_hdr.sh_entsize = non_lazy_plt_layout->plt_entry_size;
+ }
/* GOT is always created in setup_gnu_properties. But it may not be
needed. */
@@ -6623,7 +6154,8 @@ elf_x86_64_output_arch_local_syms
asection *,
struct elf_link_hash_entry *) ATTRIBUTE_UNUSED)
{
- struct elf_x86_64_link_hash_table *htab = elf_x86_64_hash_table (info);
+ struct elf_x86_link_hash_table *htab
+ = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return FALSE;
@@ -6635,22 +6167,6 @@ elf_x86_64_output_arch_local_syms
return TRUE;
}
-/* Sort relocs into address order. */
-
-static int
-compare_relocs (const void *ap, const void *bp)
-{
- const arelent *a = * (const arelent **) ap;
- const arelent *b = * (const arelent **) bp;
-
- if (a->address > b->address)
- return 1;
- else if (a->address < b->address)
- return -1;
- else
- return 0;
-}
-
enum elf_x86_64_plt_type
{
plt_non_lazy = 0,
@@ -6880,7 +6396,8 @@ elf_x86_64_get_synthetic_symtab (bfd *abfd,
dynsyms);
/* Sort the relocs by address. */
- qsort (dynrelbuf, dynrelcount, sizeof (arelent *), compare_relocs);
+ qsort (dynrelbuf, dynrelcount, sizeof (arelent *),
+ _bfd_x86_elf_compare_relocs);
size = count * sizeof (asymbol);
@@ -7170,21 +6687,6 @@ elf_x86_64_merge_symbol (struct elf_link_hash_entry *h,
return TRUE;
}
-static void
-elf_x86_64_merge_symbol_attribute (struct elf_link_hash_entry *h,
- const Elf_Internal_Sym *isym,
- bfd_boolean definition,
- bfd_boolean dynamic ATTRIBUTE_UNUSED)
-{
- if (definition)
- {
- struct elf_x86_64_link_hash_entry *eh
- = (struct elf_x86_64_link_hash_entry *) h;
- eh->def_protected = (ELF_ST_VISIBILITY (isym->st_other)
- == STV_PROTECTED);
- }
-}
-
static int
elf_x86_64_additional_program_headers (bfd *abfd,
struct bfd_link_info *info ATTRIBUTE_UNUSED)
@@ -7207,19 +6709,6 @@ elf_x86_64_additional_program_headers (bfd *abfd,
return count;
}
-/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
-
-static bfd_boolean
-elf_x86_64_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);
-}
-
/* Return TRUE iff relocations for INPUT are compatible with OUTPUT. */
static bfd_boolean
@@ -7231,136 +6720,6 @@ elf_x86_64_relocs_compatible (const bfd_target *input,
&& _bfd_elf_relocs_compatible (input, output));
}
-/* Parse x86-64 GNU properties. */
-
-static enum elf_property_kind
-elf_x86_64_parse_gnu_properties (bfd *abfd, unsigned int type,
- bfd_byte *ptr, unsigned int datasz)
-{
- elf_property *prop;
-
- switch (type)
- {
- case GNU_PROPERTY_X86_ISA_1_USED:
- case GNU_PROPERTY_X86_ISA_1_NEEDED:
- case GNU_PROPERTY_X86_FEATURE_1_AND:
- if (datasz != 4)
- {
- _bfd_error_handler
- ((type == GNU_PROPERTY_X86_ISA_1_USED
- ? _("error: %B: <corrupt x86 ISA used size: 0x%x>")
- : (type == GNU_PROPERTY_X86_ISA_1_NEEDED
- ? _("error: %B: <corrupt x86 ISA needed size: 0x%x>")
- : _("error: %B: <corrupt x86 feature size: 0x%x>"))),
- abfd, datasz);
- return property_corrupt;
- }
- prop = _bfd_elf_get_property (abfd, type, datasz);
- /* Combine properties of the same type. */
- prop->u.number |= bfd_h_get_32 (abfd, ptr);
- prop->pr_kind = property_number;
- break;
-
- default:
- return property_ignored;
- }
-
- return property_number;
-}
-
-/* Merge x86-64 GNU property BPROP with APROP. If APROP isn't NULL,
- return TRUE if APROP is updated. Otherwise, return TRUE if BPROP
- should be merged with ABFD. */
-
-static bfd_boolean
-elf_x86_64_merge_gnu_properties (struct bfd_link_info *info,
- bfd *abfd ATTRIBUTE_UNUSED,
- elf_property *aprop,
- elf_property *bprop)
-{
- unsigned int number, features;
- bfd_boolean updated = FALSE;
- unsigned int pr_type = aprop != NULL ? aprop->pr_type : bprop->pr_type;
-
- switch (pr_type)
- {
- case GNU_PROPERTY_X86_ISA_1_USED:
- case GNU_PROPERTY_X86_ISA_1_NEEDED:
- if (aprop != NULL && bprop != NULL)
- {
- number = aprop->u.number;
- aprop->u.number = number | bprop->u.number;
- updated = number != (unsigned int) aprop->u.number;
- }
- else
- {
- /* Return TRUE if APROP is NULL to indicate that BPROP should
- be added to ABFD. */
- updated = aprop == NULL;
- }
- break;
-
- case GNU_PROPERTY_X86_FEATURE_1_AND:
- /* Only one of APROP and BPROP can be NULL:
- 1. APROP & BPROP when both APROP and BPROP aren't NULL.
- 2. If APROP is NULL, remove x86 feature.
- 3. Otherwise, do nothing.
- */
- if (aprop != NULL && bprop != NULL)
- {
- features = 0;
- if (info->ibt)
- features = GNU_PROPERTY_X86_FEATURE_1_IBT;
- if (info->shstk)
- features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
- number = aprop->u.number;
- /* Add GNU_PROPERTY_X86_FEATURE_1_IBT and
- GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
- aprop->u.number = (number & bprop->u.number) | features;
- updated = number != (unsigned int) aprop->u.number;
- /* Remove the property if all feature bits are cleared. */
- if (aprop->u.number == 0)
- aprop->pr_kind = property_remove;
- }
- else
- {
- features = 0;
- if (info->ibt)
- features = GNU_PROPERTY_X86_FEATURE_1_IBT;
- if (info->shstk)
- features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
- if (features)
- {
- /* Add GNU_PROPERTY_X86_FEATURE_1_IBT and
- GNU_PROPERTY_X86_FEATURE_1_SHSTK. */
- if (aprop != NULL)
- {
- number = aprop->u.number;
- aprop->u.number = number | features;
- updated = number != (unsigned int) aprop->u.number;
- }
- else
- {
- bprop->u.number |= features;
- updated = TRUE;
- }
- }
- else if (aprop != NULL)
- {
- aprop->pr_kind = property_remove;
- updated = TRUE;
- }
- }
- break;
-
- default:
- /* Never should happen. */
- abort ();
- }
-
- return updated;
-}
-
/* Set up x86-64 GNU properties. Return the first relocatable ELF input
with GNU properties if found. Otherwise, return NULL. */
@@ -7373,10 +6732,13 @@ elf_x86_64_link_setup_gnu_properties (struct bfd_link_info *info)
bfd *dynobj;
bfd_boolean use_ibt_plt;
unsigned int plt_alignment, features;
- struct elf_x86_64_link_hash_table *htab;
+ struct elf_x86_link_hash_table *htab;
bfd *pbfd;
bfd *ebfd = NULL;
elf_property *prop;
+ struct elf_x86_64_plt_layout *plt_layout;
+ const struct elf_x86_64_lazy_plt_layout *lazy_plt_layout;
+ const struct elf_x86_64_non_lazy_plt_layout *non_lazy_plt_layout;
features = 0;
if (info->ibt)
@@ -7438,7 +6800,7 @@ error_alignment:
if (bfd_link_relocatable (info))
return pbfd;
- htab = elf_x86_64_hash_table (info);
+ htab = elf_x86_hash_table (info, X86_64_ELF_DATA);
if (htab == NULL)
return pbfd;
@@ -7493,10 +6855,12 @@ error_alignment:
}
}
+ plt_layout = &elf_x86_64_plt (htab);
+
/* Even when lazy binding is disabled by "-z now", the PLT0 entry may
still be used with LD_AUDIT or LD_PROFILE if PLT entry is used for
canonical function address. */
- htab->plt.has_plt0 = 1;
+ plt_layout->has_plt0 = 1;
if (get_elf_x86_64_backend_data (info->output_bfd)->os
== is_normal)
@@ -7505,70 +6869,77 @@ error_alignment:
{
if (ABI_64_P (dynobj))
{
- htab->lazy_plt = &elf_x86_64_lazy_ibt_plt;
- htab->non_lazy_plt = &elf_x86_64_non_lazy_ibt_plt;
+ elf_x86_64_lazy_plt (htab)
+ = &elf_x86_64_lazy_ibt_plt;
+ elf_x86_64_non_lazy_plt (htab)
+ = &elf_x86_64_non_lazy_ibt_plt;
}
else
{
- htab->lazy_plt = &elf_x32_lazy_ibt_plt;
- htab->non_lazy_plt = &elf_x32_non_lazy_ibt_plt;
+ elf_x86_64_lazy_plt (htab)
+ = &elf_x32_lazy_ibt_plt;
+ elf_x86_64_non_lazy_plt (htab)
+ = &elf_x32_non_lazy_ibt_plt;
}
}
else if (info->bndplt)
{
- htab->lazy_plt = &elf_x86_64_lazy_bnd_plt;
- htab->non_lazy_plt = &elf_x86_64_non_lazy_bnd_plt;
+ elf_x86_64_lazy_plt (htab) = &elf_x86_64_lazy_bnd_plt;
+ elf_x86_64_non_lazy_plt (htab) = &elf_x86_64_non_lazy_bnd_plt;
}
else
{
- htab->lazy_plt = &elf_x86_64_lazy_plt;
- htab->non_lazy_plt = &elf_x86_64_non_lazy_plt;
+ elf_x86_64_lazy_plt (htab) = &elf_x86_64_lazy_plt;
+ elf_x86_64_non_lazy_plt (htab) = &elf_x86_64_non_lazy_plt;
}
normal_target = TRUE;
}
else
{
- htab->lazy_plt = &elf_x86_64_nacl_plt;
- htab->non_lazy_plt = NULL;
+ elf_x86_64_lazy_plt (htab) = &elf_x86_64_nacl_plt;
+ elf_x86_64_non_lazy_plt (htab) = NULL;
normal_target = FALSE;
}
+ lazy_plt_layout = elf_x86_64_lazy_plt (htab);
+ non_lazy_plt_layout = elf_x86_64_non_lazy_plt (htab);
+
pltsec = htab->elf.splt;
/* If the non-lazy PLT is available, use it for all PLT entries if
there are no PLT0 or no .plt section. */
- if (htab->non_lazy_plt != NULL
- && (!htab->plt.has_plt0 || pltsec == NULL))
+ if (non_lazy_plt_layout != NULL
+ && (!plt_layout->has_plt0 || pltsec == NULL))
{
lazy_plt = FALSE;
- htab->plt.plt_entry
- = htab->non_lazy_plt->plt_entry;
- htab->plt.plt_entry_size
- = htab->non_lazy_plt->plt_entry_size;
- htab->plt.plt_got_offset
- = htab->non_lazy_plt->plt_got_offset;
- htab->plt.plt_got_insn_size
- = htab->non_lazy_plt->plt_got_insn_size;
- htab->plt.eh_frame_plt_size
- = htab->non_lazy_plt->eh_frame_plt_size;
- htab->plt.eh_frame_plt
- = htab->non_lazy_plt->eh_frame_plt;
+ plt_layout->plt_entry
+ = non_lazy_plt_layout->plt_entry;
+ plt_layout->plt_entry_size
+ = non_lazy_plt_layout->plt_entry_size;
+ plt_layout->plt_got_offset
+ = non_lazy_plt_layout->plt_got_offset;
+ plt_layout->plt_got_insn_size
+ = non_lazy_plt_layout->plt_got_insn_size;
+ plt_layout->eh_frame_plt_size
+ = non_lazy_plt_layout->eh_frame_plt_size;
+ plt_layout->eh_frame_plt
+ = non_lazy_plt_layout->eh_frame_plt;
}
else
{
lazy_plt = TRUE;
- htab->plt.plt_entry
- = htab->lazy_plt->plt_entry;
- htab->plt.plt_entry_size
- = htab->lazy_plt->plt_entry_size;
- htab->plt.plt_got_offset
- = htab->lazy_plt->plt_got_offset;
- htab->plt.plt_got_insn_size
- = htab->lazy_plt->plt_got_insn_size;
- htab->plt.eh_frame_plt_size
- = htab->lazy_plt->eh_frame_plt_size;
- htab->plt.eh_frame_plt
- = htab->lazy_plt->eh_frame_plt;
+ plt_layout->plt_entry
+ = lazy_plt_layout->plt_entry;
+ plt_layout->plt_entry_size
+ = lazy_plt_layout->plt_entry_size;
+ plt_layout->plt_got_offset
+ = lazy_plt_layout->plt_got_offset;
+ plt_layout->plt_got_insn_size
+ = lazy_plt_layout->plt_got_insn_size;
+ plt_layout->eh_frame_plt_size
+ = lazy_plt_layout->eh_frame_plt_size;
+ plt_layout->eh_frame_plt
+ = lazy_plt_layout->eh_frame_plt;
}
/* Return if there are no normal input files. */
@@ -7598,7 +6969,7 @@ error_alignment:
if (!_bfd_elf_create_ifunc_sections (dynobj, info))
info->callbacks->einfo (_("%F: failed to create ifunc sections\n"));
- plt_alignment = bfd_log2 (htab->plt.plt_entry_size);
+ plt_alignment = bfd_log2 (plt_layout->plt_entry_size);
if (pltsec != NULL)
{
@@ -7627,7 +6998,7 @@ error_alignment:
| SEC_LOAD
| SEC_READONLY);
unsigned int non_lazy_plt_alignment
- = bfd_log2 (htab->non_lazy_plt->plt_entry_size);
+ = bfd_log2 (non_lazy_plt_layout->plt_entry_size);
sec = pltsec;
if (!bfd_set_section_alignment (sec->owner, sec,
@@ -7749,23 +7120,6 @@ error_alignment:
return pbfd;
}
-static bfd_boolean
-elf_x86_64_link_check_relocs (bfd *abfd, struct bfd_link_info *info)
-{
- if (!bfd_link_relocatable (info))
- {
- /* Check for __tls_get_addr reference. */
- struct elf_link_hash_entry *h;
- h = elf_link_hash_lookup (elf_hash_table (info), "__tls_get_addr",
- FALSE, FALSE, FALSE);
- if (h != NULL)
- ((struct elf_x86_64_link_hash_entry *) h)->tls_get_addr = 1;
- }
-
- /* Invoke the regular ELF backend linker to do all the work. */
- return _bfd_elf_link_check_relocs (abfd, info);
-}
-
static const struct bfd_elf_special_section
elf_x86_64_special_sections[]=
{
@@ -7811,7 +7165,6 @@ elf_x86_64_special_sections[]=
#define elf_backend_adjust_dynamic_symbol elf_x86_64_adjust_dynamic_symbol
#define elf_backend_relocs_compatible elf_x86_64_relocs_compatible
#define elf_backend_check_relocs elf_x86_64_check_relocs
-#define elf_backend_copy_indirect_symbol elf_x86_64_copy_indirect_symbol
#define elf_backend_create_dynamic_sections _bfd_elf_create_dynamic_sections
#define elf_backend_finish_dynamic_sections elf_x86_64_finish_dynamic_sections
#define elf_backend_finish_dynamic_symbol elf_x86_64_finish_dynamic_symbol
@@ -7825,12 +7178,10 @@ elf_x86_64_special_sections[]=
#define elf_backend_reloc_type_class elf_x86_64_reloc_type_class
#define elf_backend_relocate_section elf_x86_64_relocate_section
#define elf_backend_size_dynamic_sections elf_x86_64_size_dynamic_sections
-#define elf_backend_always_size_sections elf_x86_64_always_size_sections
#define elf_backend_init_index_section _bfd_elf_init_1_index_section
#define elf_backend_object_p elf64_x86_64_elf_object_p
#define bfd_elf64_mkobject elf_x86_64_mkobject
#define bfd_elf64_get_synthetic_symtab elf_x86_64_get_synthetic_symtab
-#define bfd_elf64_bfd_link_check_relocs elf_x86_64_link_check_relocs
#define elf_backend_section_from_shdr \
elf_x86_64_section_from_shdr
@@ -7849,22 +7200,10 @@ elf_x86_64_special_sections[]=
elf_x86_64_common_definition
#define elf_backend_merge_symbol \
elf_x86_64_merge_symbol
-#define elf_backend_merge_symbol_attribute \
- elf_x86_64_merge_symbol_attribute
#define elf_backend_special_sections \
elf_x86_64_special_sections
#define elf_backend_additional_program_headers \
elf_x86_64_additional_program_headers
-#define elf_backend_hash_symbol \
- elf_x86_64_hash_symbol
-#define elf_backend_omit_section_dynsym \
- ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
-#define elf_backend_fixup_symbol \
- elf_x86_64_fixup_symbol
-#define elf_backend_parse_gnu_properties \
- elf_x86_64_parse_gnu_properties
-#define elf_backend_merge_gnu_properties \
- elf_x86_64_merge_gnu_properties
#define elf_backend_setup_gnu_properties \
elf_x86_64_link_setup_gnu_properties
@@ -8132,8 +7471,6 @@ elf32_x86_64_nacl_elf_object_p (bfd *abfd)
elf_x86_64_mkobject
#define bfd_elf32_get_synthetic_symtab \
elf_x86_64_get_synthetic_symtab
-#define bfd_elf32_bfd_link_check_relocs \
- elf_x86_64_link_check_relocs
#undef elf_backend_object_p
#define elf_backend_object_p \