diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2017-08-28 06:23:25 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2017-08-29 12:58:51 -0700 |
commit | 0afcef5384c656b69706fed61d91f6d886c4c0f1 (patch) | |
tree | 5b28bd844807ef807fd4a179558c8beb0d1a62de /bfd/elf64-x86-64.c | |
parent | 823cb06774ad6a2aee0afcf6f011c3a134f25747 (diff) | |
download | gdb-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.c | 1143 |
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 \ |