X-Git-Url: https://git.efficios.com/?a=blobdiff_plain;f=bfd%2Felfnn-aarch64.c;h=8f1e5e1e456abbfa8b8eb9ae219d76f1f49c0cab;hb=ad8464f799a4c96c7ab8bdfec3f95846cf54f9b0;hp=6f3bd0d5650818e5429fc64775593a160ccee844;hpb=fd3619828e94a24a92cddec42cbc0ab33352eeb4;p=deliverable%2Fbinutils-gdb.git diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 6f3bd0d565..8f1e5e1e45 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -1,5 +1,5 @@ /* AArch64-specific support for NN-bit ELF. - Copyright (C) 2009-2019 Free Software Foundation, Inc. + Copyright (C) 2009-2020 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of BFD, the Binary File Descriptor library. @@ -144,6 +144,7 @@ #include "objalloc.h" #include "elf/aarch64.h" #include "elfxx-aarch64.h" +#include "cpu-aarch64.h" #define ARCH_SIZE NN @@ -2569,9 +2570,6 @@ struct elf_aarch64_link_hash_entry { struct elf_link_hash_entry root; - /* Track dynamic relocs copied for this symbol. */ - struct elf_dyn_relocs *dyn_relocs; - /* Since PLT entries have variable size, we need to record the index into .got.plt instead of recomputing it from the PLT offset. */ @@ -2684,20 +2682,9 @@ struct elf_aarch64_link_hash_table /* JUMP_SLOT relocs for variant PCS symbols may be present. */ int variant_pcs; - /* 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 number of bytes in the PLT enty for the TLS descriptor. */ bfd_size_type tlsdesc_plt_entry_size; - /* The GOT offset for the lazy trampoline. Communicated to the - loader via DT_TLSDESC_GOT. The magic value (bfd_vma) -1 - indicates an offset is not allocated. */ - bfd_vma dt_tlsdesc_got; - /* Used by local STT_GNU_IFUNC symbols. */ htab_t loc_hash_table; void * loc_hash_memory; @@ -2727,7 +2714,6 @@ elfNN_aarch64_link_hash_newfunc (struct bfd_hash_entry *entry, table, string)); if (ret != NULL) { - ret->dyn_relocs = NULL; ret->got_type = GOT_UNKNOWN; ret->plt_got_offset = (bfd_vma) - 1; ret->stub_cache = NULL; @@ -2854,37 +2840,6 @@ elfNN_aarch64_copy_indirect_symbol (struct bfd_link_info *info, edir = (struct elf_aarch64_link_hash_entry *) dir; eind = (struct elf_aarch64_link_hash_entry *) ind; - 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) { /* Copy over PLT info. */ @@ -2946,7 +2901,7 @@ static struct bfd_link_hash_table * elfNN_aarch64_link_hash_table_create (bfd *abfd) { struct elf_aarch64_link_hash_table *ret; - bfd_size_type amt = sizeof (struct elf_aarch64_link_hash_table); + size_t amt = sizeof (struct elf_aarch64_link_hash_table); ret = bfd_zmalloc (amt); if (ret == NULL) @@ -2966,7 +2921,7 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd) ret->plt_entry = elfNN_aarch64_small_plt_entry; ret->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE; ret->obfd = abfd; - ret->dt_tlsdesc_got = (bfd_vma) - 1; + ret->root.tlsdesc_got = (bfd_vma) - 1; if (!bfd_hash_table_init (&ret->stub_hash_table, stub_hash_newfunc, sizeof (struct elf_aarch64_stub_hash_entry))) @@ -3277,7 +3232,7 @@ _bfd_aarch64_add_stub_entry_after (const char *stub_name, static bfd_boolean aarch64_build_one_stub (struct bfd_hash_entry *gen_entry, - void *in_arg ATTRIBUTE_UNUSED) + void *in_arg) { struct elf_aarch64_stub_hash_entry *stub_entry; asection *stub_sec; @@ -3290,10 +3245,22 @@ aarch64_build_one_stub (struct bfd_hash_entry *gen_entry, unsigned int template_size; const uint32_t *template; unsigned int i; + struct bfd_link_info *info; /* Massage our args to the form they really have. */ stub_entry = (struct elf_aarch64_stub_hash_entry *) gen_entry; + info = (struct bfd_link_info *) in_arg; + + /* Fail if the target section could not be assigned to an output + section. The user should fix his linker script. */ + if (stub_entry->target_section->output_section == NULL + && info->non_contiguous_regions) + info->callbacks->einfo (_("%F%P: Could not assign '%pA' to an output section. " + "Retry without " + "--enable-non-contiguous-regions.\n"), + stub_entry->target_section); + stub_sec = stub_entry->stub_sec; /* Make a note of the offset within the stubs for this entry. */ @@ -3455,7 +3422,7 @@ elfNN_aarch64_setup_section_lists (bfd *output_bfd, unsigned int top_id, top_index; asection *section; asection **input_list, **list; - bfd_size_type amt; + size_t amt; struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info); @@ -3533,7 +3500,7 @@ elfNN_aarch64_next_input_section (struct bfd_link_info *info, asection *isec) { asection **list = htab->input_list + isec->output_section->index; - if (*list != bfd_abs_section_ptr) + if (*list != bfd_abs_section_ptr && (isec->flags & SEC_CODE) != 0) { /* Steal the link_sec pointer for our list. */ /* This happens to make the list in reverse order, @@ -3554,67 +3521,96 @@ elfNN_aarch64_next_input_section (struct bfd_link_info *info, asection *isec) static void group_sections (struct elf_aarch64_link_hash_table *htab, bfd_size_type stub_group_size, - bfd_boolean stubs_always_before_branch) + bfd_boolean stubs_always_after_branch) { - asection **list = htab->input_list + htab->top_index; + asection **list = htab->input_list; do { asection *tail = *list; + asection *head; if (tail == bfd_abs_section_ptr) continue; + /* Reverse the list: we must avoid placing stubs at the + beginning of the section because the beginning of the text + section may be required for an interrupt vector in bare metal + code. */ +#define NEXT_SEC PREV_SEC + head = NULL; while (tail != NULL) + { + /* Pop from tail. */ + asection *item = tail; + tail = PREV_SEC (item); + + /* Push on head. */ + NEXT_SEC (item) = head; + head = item; + } + + while (head != NULL) { asection *curr; - asection *prev; - bfd_size_type total; + asection *next; + bfd_vma stub_group_start = head->output_offset; + bfd_vma end_of_next; - curr = tail; - total = tail->size; - while ((prev = PREV_SEC (curr)) != NULL - && ((total += curr->output_offset - prev->output_offset) - < stub_group_size)) - curr = prev; + curr = head; + while (NEXT_SEC (curr) != NULL) + { + next = NEXT_SEC (curr); + end_of_next = next->output_offset + next->size; + if (end_of_next - stub_group_start >= stub_group_size) + /* End of NEXT is too far from start, so stop. */ + break; + /* Add NEXT to the group. */ + curr = next; + } - /* OK, the size from the start of CURR to the end is less + /* OK, the size from the start to the start of CURR is less than stub_group_size and thus can be handled by one stub - section. (Or the tail section is itself larger than + section. (Or the head section is itself larger than stub_group_size, in which case we may be toast.) We should really be keeping track of the total size of stubs added here, as stubs contribute to the final output section size. */ do { - prev = PREV_SEC (tail); + next = NEXT_SEC (head); /* Set up this stub group. */ - htab->stub_group[tail->id].link_sec = curr; + htab->stub_group[head->id].link_sec = curr; } - while (tail != curr && (tail = prev) != NULL); + while (head != curr && (head = next) != NULL); /* But wait, there's more! Input sections up to stub_group_size - bytes before the stub section can be handled by it too. */ - if (!stubs_always_before_branch) + bytes after the stub section can be handled by it too. */ + if (!stubs_always_after_branch) { - total = 0; - while (prev != NULL - && ((total += tail->output_offset - prev->output_offset) - < stub_group_size)) + stub_group_start = curr->output_offset + curr->size; + + while (next != NULL) { - tail = prev; - prev = PREV_SEC (tail); - htab->stub_group[tail->id].link_sec = curr; + end_of_next = next->output_offset + next->size; + if (end_of_next - stub_group_start >= stub_group_size) + /* End of NEXT is too far from stubs, so stop. */ + break; + /* Add NEXT to the stub group. */ + head = next; + next = NEXT_SEC (head); + htab->stub_group[head->id].link_sec = curr; } } - tail = prev; + head = next; } } - while (list-- != htab->input_list); + while (list++ != htab->input_list + htab->top_index); free (htab->input_list); } +#undef PREV_SEC #undef PREV_SEC #define AARCH64_BITS(x, pos, n) (((x) >> (pos)) & ((1 << (n)) - 1)) @@ -4312,9 +4308,15 @@ elfNN_aarch64_size_stubs (bfd *output_bfd, for (input_bfd = info->input_bfds; input_bfd != NULL; input_bfd = input_bfd->link.next) - if (!_bfd_aarch64_erratum_835769_scan (input_bfd, info, - &num_erratum_835769_fixes)) - return FALSE; + { + if (!is_aarch64_elf (input_bfd) + || (input_bfd->flags & BFD_LINKER_CREATED) != 0) + continue; + + if (!_bfd_aarch64_erratum_835769_scan (input_bfd, info, + &num_erratum_835769_fixes)) + return FALSE; + } _bfd_aarch64_resize_stubs (htab); (*htab->layout_sections_again) (); @@ -4330,6 +4332,10 @@ elfNN_aarch64_size_stubs (bfd *output_bfd, { asection *section; + if (!is_aarch64_elf (input_bfd) + || (input_bfd->flags & BFD_LINKER_CREATED) != 0) + continue; + for (section = input_bfd->sections; section != NULL; section = section->next) @@ -4352,6 +4358,10 @@ elfNN_aarch64_size_stubs (bfd *output_bfd, asection *section; Elf_Internal_Sym *local_syms = NULL; + if (!is_aarch64_elf (input_bfd) + || (input_bfd->flags & BFD_LINKER_CREATED) != 0) + continue; + /* We'll need the symbol table in a second. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; if (symtab_hdr->sh_info == 0) @@ -4614,7 +4624,7 @@ elfNN_aarch64_size_stubs (bfd *output_bfd, return TRUE; -error_ret_free_local: + error_ret_free_local: return FALSE; } @@ -5438,6 +5448,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, bfd_vma orig_value = value; bfd_boolean resolved_to_zero; bfd_boolean abs_symbol_p; + bfd_boolean via_plt_p; globals = elf_aarch64_hash_table (info); @@ -5459,6 +5470,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, : bfd_is_und_section (sym_sec)); abs_symbol_p = h != NULL && bfd_is_abs_symbol (&h->root); + via_plt_p = (globals->root.splt != NULL && h != NULL + && h->plt.offset != (bfd_vma) - 1); /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined in a non-shared object. */ @@ -5506,7 +5519,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, switch (bfd_r_type) { default: -bad_ifunc_reloc: + bad_ifunc_reloc: if (h->root.root.string) name = h->root.root.string; else @@ -5794,12 +5807,23 @@ bad_ifunc_reloc: value += signed_addend; break; + case BFD_RELOC_AARCH64_BRANCH19: + case BFD_RELOC_AARCH64_TSTBR14: + /* A conditional branch to an undefined weak symbol is converted to a + branch to itself. */ + if (weak_undef_p && !via_plt_p) + { + value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type, + place, value, + signed_addend, + weak_undef_p); + break; + } + /* Fall through. */ case BFD_RELOC_AARCH64_CALL26: case BFD_RELOC_AARCH64_JUMP26: { asection *splt = globals->root.splt; - bfd_boolean via_plt_p = - splt != NULL && h != NULL && h->plt.offset != (bfd_vma) - 1; /* A call to an undefined weak symbol is converted to a jump to the next instruction unless a PLT entry will be created. @@ -5887,7 +5911,6 @@ bad_ifunc_reloc: case BFD_RELOC_AARCH64_32: #endif case BFD_RELOC_AARCH64_ADD_LO12: - case BFD_RELOC_AARCH64_BRANCH19: case BFD_RELOC_AARCH64_LDST128_LO12: case BFD_RELOC_AARCH64_LDST16_LO12: case BFD_RELOC_AARCH64_LDST32_LO12: @@ -5903,7 +5926,6 @@ bad_ifunc_reloc: case BFD_RELOC_AARCH64_MOVW_G2_NC: case BFD_RELOC_AARCH64_MOVW_G2_S: case BFD_RELOC_AARCH64_MOVW_G3: - case BFD_RELOC_AARCH64_TSTBR14: value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type, place, value, signed_addend, weak_undef_p); @@ -7317,23 +7339,6 @@ elfNN_aarch64_print_private_bfd_data (bfd *abfd, void *ptr) return TRUE; } -/* Find dynamic relocs for H that apply to read-only sections. */ - -static asection * -readonly_dynrelocs (struct elf_link_hash_entry *h) -{ - struct elf_dyn_relocs *p; - - for (p = elf_aarch64_hash_entry (h)->dyn_relocs; p != NULL; p = p->next) - { - asection *s = p->sec->output_section; - - if (s != NULL && (s->flags & SEC_READONLY) != 0) - return p->sec; - } - return NULL; -} - /* Return true if we need copy relocation against EH. */ static bfd_boolean @@ -7342,7 +7347,7 @@ need_copy_relocation_p (struct elf_aarch64_link_hash_entry *eh) struct elf_dyn_relocs *p; asection *s; - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = eh->root.dyn_relocs; p != NULL; p = p->next) { /* If there is any pc-relative reference, we need to keep copy relocation to avoid propagating the relocation into runtime that current glibc @@ -7821,9 +7826,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, relocations we need for this symbol. */ if (h != NULL) { - struct elf_aarch64_link_hash_entry *eh; - eh = (struct elf_aarch64_link_hash_entry *) h; - head = &eh->dyn_relocs; + head = &h->dyn_relocs; } else { @@ -7852,7 +7855,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, p = *head; if (p == NULL || p->sec != sec) { - bfd_size_type amt = sizeof *p; + size_t amt = sizeof *p; p = ((struct elf_dyn_relocs *) bfd_zalloc (htab->root.dynobj, amt)); if (p == NULL) @@ -7966,6 +7969,8 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, break; } + case BFD_RELOC_AARCH64_BRANCH19: + case BFD_RELOC_AARCH64_TSTBR14: case BFD_RELOC_AARCH64_CALL26: case BFD_RELOC_AARCH64_JUMP26: /* If this is a local symbol then we resolve it @@ -7998,122 +8003,43 @@ elfNN_aarch64_is_target_special_symbol (bfd *abfd ATTRIBUTE_UNUSED, BFD_AARCH64_SPECIAL_SYM_TYPE_ANY); } -/* This is a version of _bfd_elf_find_function() from dwarf2.c except that - AArch64 mapping symbols are ignored when looking for function names. */ - -static bfd_boolean -aarch64_elf_find_function (bfd * abfd, - asymbol ** symbols, - asection * section, - bfd_vma offset, - const char ** filename_ptr, - const char ** functionname_ptr) -{ - const char *filename = NULL; - asymbol *func = NULL; - bfd_vma low_func = 0; - asymbol **p; - - if (symbols == NULL) - return FALSE; - - if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) - return FALSE; +/* If the ELF symbol SYM might be a function in SEC, return the + function size and set *CODE_OFF to the function's entry point, + otherwise return zero. */ - for (p = symbols; *p != NULL; p++) - { - elf_symbol_type *q; +static bfd_size_type +elfNN_aarch64_maybe_function_sym (const asymbol *sym, asection *sec, + bfd_vma *code_off) +{ + bfd_size_type size; - q = (elf_symbol_type *) * p; + if ((sym->flags & (BSF_SECTION_SYM | BSF_FILE | BSF_OBJECT + | BSF_THREAD_LOCAL | BSF_RELC | BSF_SRELC)) != 0 + || sym->section != sec) + return 0; - switch (ELF_ST_TYPE (q->internal_elf_sym.st_info)) - { - default: - break; - case STT_FILE: - filename = bfd_asymbol_name (&q->symbol); - break; + if (!(sym->flags & BSF_SYNTHETIC)) + switch (ELF_ST_TYPE (((elf_symbol_type *) sym)->internal_elf_sym.st_info)) + { case STT_FUNC: case STT_NOTYPE: - /* Skip mapping symbols. */ - if ((q->symbol.flags & BSF_LOCAL) - && (bfd_is_aarch64_special_symbol_name - (q->symbol.name, BFD_AARCH64_SPECIAL_SYM_TYPE_ANY))) - continue; - /* Fall through. */ - if (bfd_asymbol_section (&q->symbol) == section - && q->symbol.value >= low_func && q->symbol.value <= offset) - { - func = (asymbol *) q; - low_func = q->symbol.value; - } break; - } - } - - if (func == NULL) - return FALSE; - - if (filename_ptr) - *filename_ptr = filename; - if (functionname_ptr) - *functionname_ptr = bfd_asymbol_name (func); - - return TRUE; -} - - -/* Find the nearest line to a particular section and offset, for error - reporting. This code is a duplicate of the code in elf.c, except - that it uses aarch64_elf_find_function. */ - -static bfd_boolean -elfNN_aarch64_find_nearest_line (bfd *abfd, - asymbol **symbols, - asection *section, - bfd_vma offset, - const char **filename_ptr, - const char **functionname_ptr, - unsigned int *line_ptr, - unsigned int *discriminator_ptr) -{ - bfd_boolean found = FALSE; - - if (_bfd_dwarf2_find_nearest_line (abfd, symbols, NULL, section, offset, - filename_ptr, functionname_ptr, - line_ptr, discriminator_ptr, - dwarf_debug_sections, - &elf_tdata (abfd)->dwarf2_find_line_info)) - { - if (!*functionname_ptr) - aarch64_elf_find_function (abfd, symbols, section, offset, - *filename_ptr ? NULL : filename_ptr, - functionname_ptr); - - return TRUE; - } - - /* Skip _bfd_dwarf1_find_nearest_line since no known AArch64 - toolchain uses DWARF1. */ - - if (!_bfd_stab_section_find_nearest_line (abfd, symbols, section, offset, - &found, filename_ptr, - functionname_ptr, line_ptr, - &elf_tdata (abfd)->line_info)) - return FALSE; - - if (found && (*functionname_ptr || *line_ptr)) - return TRUE; - - if (symbols == NULL) - return FALSE; + default: + return 0; + } - if (!aarch64_elf_find_function (abfd, symbols, section, offset, - filename_ptr, functionname_ptr)) - return FALSE; + if ((sym->flags & BSF_LOCAL) + && bfd_is_aarch64_special_symbol_name (sym->name, + BFD_AARCH64_SPECIAL_SYM_TYPE_ANY)) + return 0; - *line_ptr = 0; - return TRUE; + *code_off = sym->value; + size = 0; + if (!(sym->flags & BSF_SYNTHETIC)) + size = ((elf_symbol_type *) sym)->internal_elf_sym.st_size; + if (size == 0) + size = 1; + return size; } static bfd_boolean @@ -8130,16 +8056,17 @@ elfNN_aarch64_find_inliner_info (bfd *abfd, } -static void -elfNN_aarch64_post_process_headers (bfd *abfd, - struct bfd_link_info *link_info) +static bfd_boolean +elfNN_aarch64_init_file_header (bfd *abfd, struct bfd_link_info *link_info) { Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */ + if (!_bfd_elf_init_file_header (abfd, link_info)) + return FALSE; + i_ehdrp = elf_elfheader (abfd); i_ehdrp->e_ident[EI_ABIVERSION] = AARCH64_ELF_ABI_VERSION; - - _bfd_elf_post_process_headers (abfd, link_info); + return TRUE; } static enum elf_reloc_type_class @@ -8496,7 +8423,7 @@ elfNN_aarch64_new_section_hook (bfd *abfd, asection *sec) if (!sec->used_by_bfd) { _aarch64_elf_section_data *sdata; - bfd_size_type amt = sizeof (*sdata); + size_t amt = sizeof (*sdata); sdata = bfd_zalloc (abfd, amt); if (sdata == NULL) @@ -8744,7 +8671,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) type. */ /* TLSDESC PLT is now needed, but not yet determined. */ - htab->tlsdesc_plt = (bfd_vma) - 1; + htab->root.tlsdesc_plt = (bfd_vma) - 1; } if (got_type & GOT_TLS_GD) @@ -8760,7 +8687,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) h->got.offset = (bfd_vma) - 1; } - if (eh->dyn_relocs == NULL) + if (h->dyn_relocs == NULL) return TRUE; /* In the shared -Bsymbolic case, discard space allocated for @@ -8781,7 +8708,7 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) { struct elf_dyn_relocs **pp; - for (pp = &eh->dyn_relocs; (p = *pp) != NULL;) + for (pp = &h->dyn_relocs; (p = *pp) != NULL;) { p->count -= p->pc_count; p->pc_count = 0; @@ -8794,11 +8721,11 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) /* Also discard relocs on undefined weak syms with non-default visibility. */ - if (eh->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) + if (h->dyn_relocs != NULL && h->root.type == bfd_link_hash_undefweak) { if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT || UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)) - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; /* Make sure undefined weak symbols are output as a dynamic symbol in PIEs. */ @@ -8837,13 +8764,13 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) goto keep; } - eh->dyn_relocs = NULL; + h->dyn_relocs = NULL; keep:; } /* Finally, allocate space. */ - for (p = eh->dyn_relocs; p != NULL; p = p->next) + for (p = h->dyn_relocs; p != NULL; p = p->next) { asection *sreloc; @@ -8866,7 +8793,6 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, { struct bfd_link_info *info; struct elf_aarch64_link_hash_table *htab; - struct elf_aarch64_link_hash_entry *eh; /* An example of a bfd_link_hash_indirect symbol is versioned symbol. For example: __gxx_personality_v0(bfd_link_hash_indirect) @@ -8886,15 +8812,12 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, info = (struct bfd_link_info *) inf; htab = elf_aarch64_hash_table (info); - eh = (struct elf_aarch64_link_hash_entry *) h; - /* Since STT_GNU_IFUNC symbol must go through PLT, we handle it here if it is defined and referenced in a non-shared object. */ if (h->type == STT_GNU_IFUNC && h->def_regular) return _bfd_elf_allocate_ifunc_dyn_relocs (info, h, - &eh->dyn_relocs, - NULL, + &h->dyn_relocs, htab->plt_entry_size, htab->plt_header_size, GOT_ENTRY_SIZE, @@ -8921,33 +8844,6 @@ elfNN_aarch64_allocate_local_ifunc_dynrelocs (void **slot, void *inf) return elfNN_aarch64_allocate_ifunc_dynrelocs (h, inf); } -/* Set DF_TEXTREL if we find any dynamic relocs that apply to - read-only sections. */ - -static bfd_boolean -maybe_set_textrel (struct elf_link_hash_entry *h, void *info_p) -{ - asection *sec; - - if (h->root.type == bfd_link_hash_indirect) - return TRUE; - - sec = readonly_dynrelocs (h); - if (sec != NULL) - { - struct bfd_link_info *info = (struct bfd_link_info *) info_p; - - info->flags |= DF_TEXTREL; - info->callbacks->minfo - (_("%pB: dynamic relocation against `%pT' in read-only section `%pA'\n"), - sec->owner, h->root.root.string, sec); - - /* Not an error, just cut short the traversal. */ - return FALSE; - } - return TRUE; -} - /* This is the most important function of all . Innocuosly named though ! */ @@ -9060,7 +8956,7 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, { htab->root.srelplt->size += RELOC_SIZE (htab); /* Note RELOC_COUNT not incremented here! */ - htab->tlsdesc_plt = (bfd_vma) - 1; + htab->root.tlsdesc_plt = (bfd_vma) - 1; } if (got_type & GOT_TLS_GD) @@ -9103,19 +8999,21 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, if (htab->root.srelplt) htab->sgotplt_jump_table_size = aarch64_compute_jump_table_size (htab); - if (htab->tlsdesc_plt) + if (htab->root.tlsdesc_plt) { if (htab->root.splt->size == 0) htab->root.splt->size += htab->plt_header_size; /* If we're not using lazy TLS relocations, don't generate the GOT and PLT entry required. */ - if (!(info->flags & DF_BIND_NOW)) + if ((info->flags & DF_BIND_NOW)) + htab->root.tlsdesc_plt = 0; + else { - htab->tlsdesc_plt = htab->root.splt->size; + htab->root.tlsdesc_plt = htab->root.splt->size; htab->root.splt->size += htab->tlsdesc_plt_entry_size; - htab->dt_tlsdesc_got = htab->root.sgot->size; + htab->root.tlsdesc_got = htab->root.sgot->size; htab->root.sgot->size += GOT_ENTRY_SIZE; } } @@ -9203,30 +9101,15 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, #define add_dynamic_entry(TAG, VAL) \ _bfd_elf_add_dynamic_entry (info, TAG, VAL) - if (bfd_link_executable (info)) - { - if (!add_dynamic_entry (DT_DEBUG, 0)) - return FALSE; - } + if (!_bfd_elf_add_dynamic_tags (output_bfd, info, relocs)) + return FALSE; if (htab->root.splt->size != 0) { - if (!add_dynamic_entry (DT_PLTGOT, 0) - || !add_dynamic_entry (DT_PLTRELSZ, 0) - || !add_dynamic_entry (DT_PLTREL, DT_RELA) - || !add_dynamic_entry (DT_JMPREL, 0)) - return FALSE; - if (htab->variant_pcs && !add_dynamic_entry (DT_AARCH64_VARIANT_PCS, 0)) return FALSE; - if (htab->tlsdesc_plt - && !(info->flags & DF_BIND_NOW) - && (!add_dynamic_entry (DT_TLSDESC_PLT, 0) - || !add_dynamic_entry (DT_TLSDESC_GOT, 0))) - return FALSE; - if ((elf_aarch64_tdata (output_bfd)->plt_type == PLT_BTI_PAC) && (!add_dynamic_entry (DT_AARCH64_BTI_PLT, 0) || !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0))) @@ -9240,25 +9123,6 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED, && !add_dynamic_entry (DT_AARCH64_PAC_PLT, 0)) return FALSE; } - - if (relocs) - { - if (!add_dynamic_entry (DT_RELA, 0) - || !add_dynamic_entry (DT_RELASZ, 0) - || !add_dynamic_entry (DT_RELAENT, RELOC_SIZE (htab))) - return FALSE; - - /* If any dynamic relocs apply to a read-only section, - then we need a DT_TEXTREL entry. */ - if ((info->flags & DF_TEXTREL) == 0) - elf_link_hash_traverse (&htab->root, maybe_set_textrel, info); - - if ((info->flags & DF_TEXTREL) != 0) - { - if (!add_dynamic_entry (DT_TEXTREL, 0)) - return FALSE; - } - } } #undef add_dynamic_entry @@ -9559,7 +9423,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, } else { -do_glob_dat: + do_glob_dat: BFD_ASSERT ((h->got.offset & 1) == 0); bfd_put_NN (output_bfd, (bfd_vma) 0, htab->root.sgot->contents + h->got.offset); @@ -9730,14 +9594,14 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, case DT_TLSDESC_PLT: s = htab->root.splt; dyn.d_un.d_ptr = s->output_section->vma + s->output_offset - + htab->tlsdesc_plt; + + htab->root.tlsdesc_plt; break; case DT_TLSDESC_GOT: s = htab->root.sgot; - BFD_ASSERT (htab->dt_tlsdesc_got != (bfd_vma)-1); + BFD_ASSERT (htab->root.tlsdesc_got != (bfd_vma)-1); dyn.d_un.d_ptr = s->output_section->vma + s->output_offset - + htab->dt_tlsdesc_got; + + htab->root.tlsdesc_got; break; } @@ -9755,11 +9619,11 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, this_hdr.sh_entsize = htab->plt_entry_size; - if (htab->tlsdesc_plt && !(info->flags & DF_BIND_NOW)) + if (htab->root.tlsdesc_plt && !(info->flags & DF_BIND_NOW)) { - BFD_ASSERT (htab->dt_tlsdesc_got != (bfd_vma)-1); + BFD_ASSERT (htab->root.tlsdesc_got != (bfd_vma)-1); bfd_put_NN (output_bfd, (bfd_vma) 0, - htab->root.sgot->contents + htab->dt_tlsdesc_got); + htab->root.sgot->contents + htab->root.tlsdesc_got); const bfd_byte *entry = elfNN_aarch64_tlsdesc_small_plt_entry; htab->tlsdesc_plt_entry_size = PLT_TLSDESC_ENTRY_SIZE; @@ -9770,13 +9634,14 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, entry = elfNN_aarch64_tlsdesc_small_plt_bti_entry; } - memcpy (htab->root.splt->contents + htab->tlsdesc_plt, + memcpy (htab->root.splt->contents + htab->root.tlsdesc_plt, entry, htab->tlsdesc_plt_entry_size); { bfd_vma adrp1_addr = htab->root.splt->output_section->vma - + htab->root.splt->output_offset + htab->tlsdesc_plt + 4; + + htab->root.splt->output_offset + + htab->root.tlsdesc_plt + 4; bfd_vma adrp2_addr = adrp1_addr + 4; @@ -9788,10 +9653,10 @@ elfNN_aarch64_finish_dynamic_sections (bfd *output_bfd, htab->root.sgotplt->output_section->vma + htab->root.sgotplt->output_offset; - bfd_vma dt_tlsdesc_got = got_addr + htab->dt_tlsdesc_got; + bfd_vma dt_tlsdesc_got = got_addr + htab->root.tlsdesc_got; bfd_byte *plt_entry = - htab->root.splt->contents + htab->tlsdesc_plt; + htab->root.splt->contents + htab->root.tlsdesc_plt; /* First instruction in BTI enabled PLT stub is a BTI instruction so skip it. */ @@ -10121,9 +9986,6 @@ const struct elf_size_info elfNN_aarch64_size_info = #define bfd_elfNN_find_inliner_info \ elfNN_aarch64_find_inliner_info -#define bfd_elfNN_find_nearest_line \ - elfNN_aarch64_find_nearest_line - #define bfd_elfNN_get_synthetic_symtab \ elfNN_aarch64_get_synthetic_symtab @@ -10168,11 +10030,14 @@ const struct elf_size_info elfNN_aarch64_size_info = #define elf_backend_output_arch_local_syms \ elfNN_aarch64_output_arch_local_syms +#define elf_backend_maybe_function_sym \ + elfNN_aarch64_maybe_function_sym + #define elf_backend_plt_sym_val \ elfNN_aarch64_plt_sym_val -#define elf_backend_post_process_headers \ - elfNN_aarch64_post_process_headers +#define elf_backend_init_file_header \ + elfNN_aarch64_init_file_header #define elf_backend_relocate_section \ elfNN_aarch64_relocate_section