/* AArch64-specific support for NN-bit ELF.
- Copyright (C) 2009-2019 Free Software Foundation, Inc.
+ Copyright (C) 2009-2021 Free Software Foundation, Inc.
Contributed by ARM Ltd.
This file is part of BFD, the Binary File Descriptor library.
#include "objalloc.h"
#include "elf/aarch64.h"
#include "elfxx-aarch64.h"
+#include "cpu-aarch64.h"
#define ARCH_SIZE NN
{
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. */
/* The bytes of the subsequent PLT entry. */
const bfd_byte *plt_entry;
- /* Small local sym cache. */
- struct sym_cache sym_cache;
-
/* For convenience in allocate_dynrelocs. */
bfd *obfd;
/* 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;
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;
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. */
static void
elfNN_aarch64_merge_symbol_attribute (struct elf_link_hash_entry *h,
- const Elf_Internal_Sym *isym,
+ unsigned int st_other,
bfd_boolean definition ATTRIBUTE_UNUSED,
bfd_boolean dynamic ATTRIBUTE_UNUSED)
{
- unsigned int isym_sto = isym->st_other & ~ELF_ST_VISIBILITY (-1);
+ unsigned int isym_sto = st_other & ~ELF_ST_VISIBILITY (-1);
unsigned int h_sto = h->other & ~ELF_ST_VISIBILITY (-1);
if (isym_sto == h_sto)
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)
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)))
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;
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. */
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);
{
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,
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))
sec_data = elf_aarch64_section_data (section);
- qsort (sec_data->map, sec_data->mapcount,
- sizeof (elf_aarch64_section_map), elf_aarch64_compare_mapping);
+ if (sec_data->mapcount)
+ qsort (sec_data->map, sec_data->mapcount,
+ sizeof (elf_aarch64_section_map), elf_aarch64_compare_mapping);
for (span = 0; span < sec_data->mapcount; span++)
{
sec_data = elf_aarch64_section_data (section);
- qsort (sec_data->map, sec_data->mapcount,
- sizeof (elf_aarch64_section_map), elf_aarch64_compare_mapping);
+ if (sec_data->mapcount)
+ qsort (sec_data->map, sec_data->mapcount,
+ sizeof (elf_aarch64_section_map), elf_aarch64_compare_mapping);
for (span = 0; span < sec_data->mapcount; span++)
{
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) ();
{
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)
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)
return TRUE;
-error_ret_free_local:
+ error_ret_free_local:
return FALSE;
}
switch (bfd_r_type)
{
default:
-bad_ifunc_reloc:
+ bad_ifunc_reloc:
if (h->root.root.string)
name = h->root.root.string;
else
bfd_set_error (bfd_error_bad_value);
return bfd_reloc_notsupported;
}
+ value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
+ place, value,
+ signed_addend,
+ weak_undef_p);
+ break;
+
+ case BFD_RELOC_AARCH64_BRANCH19:
+ case BFD_RELOC_AARCH64_TSTBR14:
+ if (h && h->root.type == bfd_link_hash_undefined)
+ {
+ _bfd_error_handler
+ /* xgettext:c-format */
+ (_("%pB: conditional branch to undefined symbol `%s' "
+ "not allowed"), input_bfd, h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return bfd_reloc_notsupported;
+ }
/* Fall through. */
case BFD_RELOC_AARCH64_16:
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:
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);
Try to catch this situation here and provide a more helpful
error message to the user. */
- if (addend & ((1 << howto->rightshift) - 1)
+ if (addend & (((bfd_vma) 1 << howto->rightshift) - 1)
/* FIXME: Are we testing all of the appropriate reloc
types here ? */
&& (real_r_type == BFD_RELOC_AARCH64_LD_LO19_PCREL
containing valid data. */
/* xgettext:c-format */
- fprintf (file, _("private flags = %lx:"), elf_elfheader (abfd)->e_flags);
+ fprintf (file, _("private flags = 0x%lx:"), elf_elfheader (abfd)->e_flags);
if (flags)
- fprintf (file, _("<Unrecognised flag bits set>"));
+ fprintf (file, _(" <Unrecognised flag bits set>"));
fputc ('\n', file);
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
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
if (r_symndx < symtab_hdr->sh_info)
{
/* A local symbol. */
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ isym = bfd_sym_from_r_symndx (&htab->root.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
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
{
asection *s;
void **vpp;
- isym = bfd_sym_from_r_symndx (&htab->sym_cache,
+ isym = bfd_sym_from_r_symndx (&htab->root.sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
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)
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
}
-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
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)
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)
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
{
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;
/* 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. */
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;
{
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)
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,
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 ! */
{
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)
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;
}
}
#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)))
&& !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
}
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);
memcpy (htab->root.splt->contents, htab->plt0_entry,
htab->plt_header_size);
- elf_section_data (htab->root.splt->output_section)->this_hdr.sh_entsize =
- htab->plt_header_size;
+
+ /* PR 26312: Explicitly set the sh_entsize to 0 so that
+ consumers do not think that the section contains fixed
+ sized objects. */
+ elf_section_data (htab->root.splt->output_section)->this_hdr.sh_entsize = 0;
plt_got_2nd_ent = (htab->root.sgotplt->output_section->vma
+ htab->root.sgotplt->output_offset
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;
}
{
elfNN_aarch64_init_small_plt0_entry (output_bfd, htab);
- elf_section_data (htab->root.splt->output_section)->
- 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;
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;
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. */
#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
#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