|
|
|
|
@@ -2706,6 +2706,19 @@ struct elf_aarch64_link_hash_table
|
|
|
|
|
/* Used by local STT_GNU_IFUNC symbols. */
|
|
|
|
|
htab_t loc_hash_table;
|
|
|
|
|
void * loc_hash_memory;
|
|
|
|
|
|
|
|
|
|
/* Array of relative relocs to be emitted in DT_RELR format. */
|
|
|
|
|
bfd_size_type relr_alloc;
|
|
|
|
|
bfd_size_type relr_count;
|
|
|
|
|
struct relr_entry
|
|
|
|
|
{
|
|
|
|
|
asection *sec;
|
|
|
|
|
bfd_vma off;
|
|
|
|
|
} *relr;
|
|
|
|
|
/* Sorted output addresses of above relative relocs. */
|
|
|
|
|
bfd_vma *relr_sorted;
|
|
|
|
|
/* Layout recomputation count. */
|
|
|
|
|
bfd_size_type relr_layout_iter;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Create an entry in an AArch64 ELF linker hash table. */
|
|
|
|
|
@@ -5971,6 +5984,18 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
|
|
|
|
|
|| !(bfd_link_pie (info) || SYMBOLIC_BIND (info, h))
|
|
|
|
|
|| !h->def_regular))
|
|
|
|
|
outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
|
|
|
|
|
else if (info->enable_dt_relr
|
|
|
|
|
&& input_section->alignment_power != 0
|
|
|
|
|
&& rel->r_offset % 2 == 0)
|
|
|
|
|
{
|
|
|
|
|
/* Don't emit a relative relocation that is packed, only
|
|
|
|
|
apply the addend. */
|
|
|
|
|
if (globals->no_apply_dynamic_relocs)
|
|
|
|
|
return bfd_reloc_ok;
|
|
|
|
|
return _bfd_final_link_relocate (howto, input_bfd, input_section,
|
|
|
|
|
contents, rel->r_offset, value,
|
|
|
|
|
signed_addend);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int symbol;
|
|
|
|
|
@@ -6237,7 +6262,8 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
|
|
|
|
|
addend, weak_undef_p);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (relative_reloc)
|
|
|
|
|
/* Emit relative relocations, but not if they are packed (DT_RELR). */
|
|
|
|
|
if (relative_reloc && !info->enable_dt_relr)
|
|
|
|
|
{
|
|
|
|
|
asection *s;
|
|
|
|
|
Elf_Internal_Rela outrel;
|
|
|
|
|
@@ -9169,6 +9195,363 @@ elfNN_aarch64_allocate_local_ifunc_dynrelocs (void **slot, void *inf)
|
|
|
|
|
return elfNN_aarch64_allocate_ifunc_dynrelocs (h, inf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Record a relative relocation that will be emitted packed (DT_RELR).
|
|
|
|
|
Called after relocation sections are sized, so undo the size accounting
|
|
|
|
|
for this relocation. */
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
record_relr (struct elf_aarch64_link_hash_table *htab, asection *sec,
|
|
|
|
|
bfd_vma off, asection *sreloc)
|
|
|
|
|
{
|
|
|
|
|
/* Undo the relocation section size accounting. */
|
|
|
|
|
BFD_ASSERT (sreloc->size >= RELOC_SIZE (htab));
|
|
|
|
|
sreloc->size -= RELOC_SIZE (htab);
|
|
|
|
|
/* The packing format uses the last bit of the address so that
|
|
|
|
|
must be aligned. We don't pack relocations that may not be
|
|
|
|
|
aligned even though the final output address could end up
|
|
|
|
|
aligned, to avoid complex sizing logic for a rare case. */
|
|
|
|
|
BFD_ASSERT (off % 2 == 0 && sec->alignment_power > 0);
|
|
|
|
|
if (htab->relr_count >= htab->relr_alloc)
|
|
|
|
|
{
|
|
|
|
|
if (htab->relr_alloc == 0)
|
|
|
|
|
htab->relr_alloc = 4096;
|
|
|
|
|
else
|
|
|
|
|
htab->relr_alloc *= 2;
|
|
|
|
|
htab->relr = bfd_realloc (htab->relr,
|
|
|
|
|
htab->relr_alloc * sizeof (*htab->relr));
|
|
|
|
|
if (htab->relr == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
htab->relr[htab->relr_count].sec = sec;
|
|
|
|
|
htab->relr[htab->relr_count].off = off;
|
|
|
|
|
htab->relr_count++;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Follow elfNN_aarch64_allocate_dynrelocs, but only record relative
|
|
|
|
|
relocations against the GOT and undo their previous size accounting. */
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
record_relr_dyn_got_relocs (struct elf_link_hash_entry *h, void *inf)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
if (h->root.type == bfd_link_hash_indirect)
|
|
|
|
|
return true;
|
|
|
|
|
if (h->root.type == bfd_link_hash_warning)
|
|
|
|
|
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
|
|
|
if (h->type == STT_GNU_IFUNC && h->def_regular)
|
|
|
|
|
return true;
|
|
|
|
|
if (h->got.refcount <= 0)
|
|
|
|
|
return true;
|
|
|
|
|
if (elf_aarch64_hash_entry (h)->got_type != GOT_NORMAL)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
struct bfd_link_info *info = (struct bfd_link_info *) inf;
|
|
|
|
|
struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
|
|
|
|
|
|
|
|
|
|
if ((ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
|
|
|
|
|| h->root.type != bfd_link_hash_undefweak)
|
|
|
|
|
&& bfd_link_pic (info)
|
|
|
|
|
/* Undefined weak symbol in static PIE resolves to 0 without
|
|
|
|
|
any dynamic relocations. */
|
|
|
|
|
&& !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h))
|
|
|
|
|
{
|
|
|
|
|
bool relative_reloc = SYMBOL_REFERENCES_LOCAL (info, h)
|
|
|
|
|
&& !bfd_is_abs_symbol (&h->root);
|
|
|
|
|
if (relative_reloc)
|
|
|
|
|
if (!record_relr (htab, htab->root.sgot, h->got.offset,
|
|
|
|
|
htab->root.srelgot))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Record packed relative relocs against the GOT for local symbols.
|
|
|
|
|
Undo the size accounting of elfNN_aarch64_late_size_sections. */
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
record_relr_local_got_relocs (bfd *input_bfd, struct bfd_link_info *info)
|
|
|
|
|
{
|
|
|
|
|
struct elf_aarch64_local_symbol *locals;
|
|
|
|
|
Elf_Internal_Shdr *symtab_hdr;
|
|
|
|
|
struct elf_aarch64_link_hash_table *htab;
|
|
|
|
|
|
|
|
|
|
if (!bfd_link_pic (info))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
locals = elf_aarch64_locals (input_bfd);
|
|
|
|
|
if (locals == NULL)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
symtab_hdr = &elf_symtab_hdr (input_bfd);
|
|
|
|
|
htab = elf_aarch64_hash_table (info);
|
|
|
|
|
for (unsigned int i = 0; i < symtab_hdr->sh_info; i++)
|
|
|
|
|
{
|
|
|
|
|
bfd_vma off = locals[i].got_offset;
|
|
|
|
|
if (locals[i].got_refcount <= 0)
|
|
|
|
|
continue;
|
|
|
|
|
if ((locals[i].got_type & GOT_NORMAL) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
/* FIXME: If the local symbol is in SHN_ABS then emitting
|
|
|
|
|
a relative relocation is not correct, but it seems to
|
|
|
|
|
be wrong in elfNN_aarch64_final_link_relocate too. */
|
|
|
|
|
if (!record_relr (htab, htab->root.sgot, off, htab->root.srelgot))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Follows the logic of elfNN_aarch64_relocate_section to decide which
|
|
|
|
|
relocations will become relative and possible to pack. Ignore
|
|
|
|
|
relocations against the GOT, those are handled separately per-symbol.
|
|
|
|
|
Undo the size accounting of the packed relocations and record them
|
|
|
|
|
so the relr section can be sized later. */
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
record_relr_non_got_relocs (bfd *input_bfd, struct bfd_link_info *info,
|
|
|
|
|
asection *sec)
|
|
|
|
|
{
|
|
|
|
|
const Elf_Internal_Rela *relocs;
|
|
|
|
|
const Elf_Internal_Rela *rel;
|
|
|
|
|
const Elf_Internal_Rela *rel_end;
|
|
|
|
|
asection *sreloc;
|
|
|
|
|
struct elf_aarch64_link_hash_table *htab;
|
|
|
|
|
Elf_Internal_Shdr *symtab_hdr;
|
|
|
|
|
struct elf_link_hash_entry **sym_hashes;
|
|
|
|
|
|
|
|
|
|
if (sec->reloc_count == 0)
|
|
|
|
|
return true;
|
|
|
|
|
if ((sec->flags & (SEC_RELOC | SEC_ALLOC | SEC_DEBUGGING))
|
|
|
|
|
!= (SEC_RELOC | SEC_ALLOC))
|
|
|
|
|
return true;
|
|
|
|
|
if (sec->alignment_power == 0)
|
|
|
|
|
return true;
|
|
|
|
|
sreloc = elf_section_data (sec)->sreloc;
|
|
|
|
|
if (sreloc == NULL)
|
|
|
|
|
return true;
|
|
|
|
|
htab = elf_aarch64_hash_table (info);
|
|
|
|
|
symtab_hdr = &elf_symtab_hdr (input_bfd);
|
|
|
|
|
sym_hashes = elf_sym_hashes (input_bfd);
|
|
|
|
|
relocs = _bfd_elf_link_info_read_relocs (input_bfd, info, sec, NULL, NULL,
|
|
|
|
|
info->keep_memory);
|
|
|
|
|
BFD_ASSERT (relocs != NULL);
|
|
|
|
|
rel_end = relocs + sec->reloc_count;
|
|
|
|
|
for (rel = relocs; rel < rel_end; rel++)
|
|
|
|
|
{
|
|
|
|
|
unsigned int r_symndx = ELFNN_R_SYM (rel->r_info);
|
|
|
|
|
unsigned int r_type = ELFNN_R_TYPE (rel->r_info);
|
|
|
|
|
|
|
|
|
|
bfd_reloc_code_real_type bfd_r_type
|
|
|
|
|
= elfNN_aarch64_bfd_reloc_from_type (input_bfd, r_type);
|
|
|
|
|
/* Handle relocs that can become R_AARCH64_RELATIVE,
|
|
|
|
|
but not ones against the GOT as those are handled
|
|
|
|
|
separately per-symbol. */
|
|
|
|
|
if (bfd_r_type != BFD_RELOC_AARCH64_NN)
|
|
|
|
|
continue;
|
|
|
|
|
/* Can only pack relocation against an aligned address. */
|
|
|
|
|
if (rel->r_offset % 2 != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
struct elf_link_hash_entry *h = NULL;
|
|
|
|
|
asection *def_sec = NULL;
|
|
|
|
|
bool resolved_to_zero = false;
|
|
|
|
|
if (r_symndx < symtab_hdr->sh_info)
|
|
|
|
|
{
|
|
|
|
|
/* A local symbol. */
|
|
|
|
|
Elf_Internal_Sym *isym;
|
|
|
|
|
isym = bfd_sym_from_r_symndx (&htab->root.sym_cache,
|
|
|
|
|
input_bfd, r_symndx);
|
|
|
|
|
BFD_ASSERT (isym != NULL);
|
|
|
|
|
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
|
|
|
|
|
continue;
|
|
|
|
|
def_sec = bfd_section_from_elf_index (input_bfd, isym->st_shndx);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
|
|
|
|
|
while (h->root.type == bfd_link_hash_indirect
|
|
|
|
|
|| h->root.type == bfd_link_hash_warning)
|
|
|
|
|
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
|
|
|
|
|
|
|
|
|
/* Filter out symbols that cannot have a relative reloc. */
|
|
|
|
|
if (h->dyn_relocs == NULL)
|
|
|
|
|
continue;
|
|
|
|
|
if (bfd_is_abs_symbol (&h->root))
|
|
|
|
|
continue;
|
|
|
|
|
if (h->type == STT_GNU_IFUNC)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (h->root.type == bfd_link_hash_defined
|
|
|
|
|
|| h->root.type == bfd_link_hash_defweak)
|
|
|
|
|
def_sec = h->root.u.def.section;
|
|
|
|
|
resolved_to_zero = UNDEFWEAK_NO_DYNAMIC_RELOC (info, h);
|
|
|
|
|
}
|
|
|
|
|
if (def_sec != NULL && discarded_section (def_sec))
|
|
|
|
|
continue;
|
|
|
|
|
/* Same logic as in elfNN_aarch64_final_link_relocate.
|
|
|
|
|
Except conditionals trimmed that cannot result a reltive reloc. */
|
|
|
|
|
if (bfd_link_pic (info)
|
|
|
|
|
&& (h == NULL
|
|
|
|
|
|| (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
|
|
|
|
&& !resolved_to_zero)
|
|
|
|
|
|| h->root.type != bfd_link_hash_undefweak))
|
|
|
|
|
{
|
|
|
|
|
if (h != NULL
|
|
|
|
|
&& h->dynindx != -1
|
|
|
|
|
&& (!(bfd_link_pie (info) || SYMBOLIC_BIND (info, h))
|
|
|
|
|
|| !h->def_regular))
|
|
|
|
|
continue;
|
|
|
|
|
if (!record_relr (htab, sec, rel->r_offset, sreloc))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
cmp_relr_addr (const void *p, const void *q)
|
|
|
|
|
{
|
|
|
|
|
const bfd_vma *a = p;
|
|
|
|
|
const bfd_vma *b = q;
|
|
|
|
|
return *a < *b ? -1 : *a > *b ? 1 : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Produce a malloc'd sorted array of reloc addresses in htab->relr_sorted.
|
|
|
|
|
Returns false on allocation failure. */
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
sort_relr (struct bfd_link_info *info,
|
|
|
|
|
struct elf_aarch64_link_hash_table *htab)
|
|
|
|
|
{
|
|
|
|
|
if (htab->relr_count == 0)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
bfd_vma *addr = htab->relr_sorted;
|
|
|
|
|
if (addr == NULL)
|
|
|
|
|
{
|
|
|
|
|
addr = bfd_malloc (htab->relr_count * sizeof (*addr));
|
|
|
|
|
if (addr == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
htab->relr_sorted = addr;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (bfd_size_type i = 0; i < htab->relr_count; i++)
|
|
|
|
|
{
|
|
|
|
|
bfd_vma off = _bfd_elf_section_offset (info->output_bfd, info,
|
|
|
|
|
htab->relr[i].sec,
|
|
|
|
|
htab->relr[i].off);
|
|
|
|
|
addr[i] = htab->relr[i].sec->output_section->vma
|
|
|
|
|
+ htab->relr[i].sec->output_offset
|
|
|
|
|
+ off;
|
|
|
|
|
}
|
|
|
|
|
qsort (addr, htab->relr_count, sizeof (*addr), cmp_relr_addr);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Size .relr.dyn whenever the layout changes, the number of packed
|
|
|
|
|
relocs are unchanged but the packed representation can. */
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
elfNN_aarch64_size_relative_relocs (struct bfd_link_info *info,
|
|
|
|
|
bool *need_layout)
|
|
|
|
|
{
|
|
|
|
|
struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
|
|
|
|
|
asection *srelrdyn = htab->root.srelrdyn;
|
|
|
|
|
*need_layout = false;
|
|
|
|
|
|
|
|
|
|
if (!sort_relr (info, htab))
|
|
|
|
|
return false;
|
|
|
|
|
bfd_vma *addr = htab->relr_sorted;
|
|
|
|
|
|
|
|
|
|
BFD_ASSERT (srelrdyn != NULL);
|
|
|
|
|
bfd_size_type oldsize = srelrdyn->size;
|
|
|
|
|
srelrdyn->size = 0;
|
|
|
|
|
for (bfd_size_type i = 0; i < htab->relr_count; )
|
|
|
|
|
{
|
|
|
|
|
bfd_vma base = addr[i];
|
|
|
|
|
i++;
|
|
|
|
|
srelrdyn->size += 8;
|
|
|
|
|
base += 8;
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
bfd_size_type start_i = i;
|
|
|
|
|
while (i < htab->relr_count
|
|
|
|
|
&& addr[i] - base < 63 * 8
|
|
|
|
|
&& (addr[i] - base) % 8 == 0)
|
|
|
|
|
i++;
|
|
|
|
|
if (i == start_i)
|
|
|
|
|
break;
|
|
|
|
|
srelrdyn->size += 8;
|
|
|
|
|
base += 63 * 8;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (srelrdyn->size != oldsize)
|
|
|
|
|
{
|
|
|
|
|
*need_layout = true;
|
|
|
|
|
/* Stop after a few iterations in case the layout does not converge,
|
|
|
|
|
we can do this when the size would shrink. */
|
|
|
|
|
if (htab->relr_layout_iter++ > 5 && srelrdyn->size < oldsize)
|
|
|
|
|
{
|
|
|
|
|
srelrdyn->size = oldsize;
|
|
|
|
|
*need_layout = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Emit the .relr.dyn section after it is sized and the layout is fixed. */
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
elfNN_aarch64_finish_relative_relocs (struct bfd_link_info *info)
|
|
|
|
|
{
|
|
|
|
|
struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
|
|
|
|
|
asection *srelrdyn = htab->root.srelrdyn;
|
|
|
|
|
bfd *dynobj = htab->root.dynobj;
|
|
|
|
|
|
|
|
|
|
if (srelrdyn == NULL || srelrdyn->size == 0)
|
|
|
|
|
return true;
|
|
|
|
|
srelrdyn->contents = bfd_alloc (dynobj, srelrdyn->size);
|
|
|
|
|
if (srelrdyn->contents == NULL)
|
|
|
|
|
return false;
|
|
|
|
|
bfd_vma *addr = htab->relr_sorted;
|
|
|
|
|
bfd_byte *loc = srelrdyn->contents;
|
|
|
|
|
for (bfd_size_type i = 0; i < htab->relr_count; )
|
|
|
|
|
{
|
|
|
|
|
bfd_vma base = addr[i];
|
|
|
|
|
i++;
|
|
|
|
|
bfd_put_64 (dynobj, base, loc);
|
|
|
|
|
loc += 8;
|
|
|
|
|
base += 8;
|
|
|
|
|
for (;;)
|
|
|
|
|
{
|
|
|
|
|
bfd_vma bits = 0;
|
|
|
|
|
while (i < htab->relr_count)
|
|
|
|
|
{
|
|
|
|
|
bfd_vma delta = addr[i] - base;
|
|
|
|
|
if (delta >= 63 * 8 || delta % 8 != 0)
|
|
|
|
|
break;
|
|
|
|
|
bits |= (bfd_vma) 1 << (delta / 8);
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
if (bits == 0)
|
|
|
|
|
break;
|
|
|
|
|
bfd_put_64 (dynobj, (bits << 1) | 1, loc);
|
|
|
|
|
loc += 8;
|
|
|
|
|
base += 63 * 8;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free (addr);
|
|
|
|
|
htab->relr_sorted = NULL;
|
|
|
|
|
/* Pad any excess with 1's, a do-nothing encoding. */
|
|
|
|
|
while (loc < srelrdyn->contents + srelrdyn->size)
|
|
|
|
|
{
|
|
|
|
|
bfd_put_64 (dynobj, 1, loc);
|
|
|
|
|
loc += 8;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This is the most important function of all . Innocuosly named
|
|
|
|
|
though ! */
|
|
|
|
|
|
|
|
|
|
@@ -9344,6 +9727,27 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Record the relative relocations that will be packed and undo the
|
|
|
|
|
size allocation for them in .rela.*. The size of .relr.dyn will be
|
|
|
|
|
computed later iteratively since it depends on the final layout. */
|
|
|
|
|
if (info->enable_dt_relr && !bfd_link_relocatable (info))
|
|
|
|
|
{
|
|
|
|
|
elf_link_hash_traverse (&htab->root, record_relr_dyn_got_relocs, info);
|
|
|
|
|
|
|
|
|
|
for (ibfd = info->input_bfds; ibfd != NULL; ibfd = ibfd->link.next)
|
|
|
|
|
{
|
|
|
|
|
if (!is_aarch64_elf (ibfd))
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
for (s = ibfd->sections; s != NULL; s = s->next)
|
|
|
|
|
if (!record_relr_non_got_relocs (ibfd, info, s))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (!record_relr_local_got_relocs (ibfd, info))
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Init mapping symbols information to use later to distingush between
|
|
|
|
|
code and data while scanning for errata. */
|
|
|
|
|
if (htab->fix_erratum_835769 || htab->fix_erratum_843419)
|
|
|
|
|
@@ -9383,6 +9787,19 @@ elfNN_aarch64_late_size_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|
|
|
|
if (s != htab->root.srelplt)
|
|
|
|
|
s->reloc_count = 0;
|
|
|
|
|
}
|
|
|
|
|
else if (s == htab->root.srelrdyn)
|
|
|
|
|
{
|
|
|
|
|
/* Remove .relr.dyn based on relr_count, not size, since
|
|
|
|
|
it is not sized yet. */
|
|
|
|
|
if (htab->relr_count == 0)
|
|
|
|
|
s->flags |= SEC_EXCLUDE;
|
|
|
|
|
else
|
|
|
|
|
/* Force dynamic tags for relocs even if there are no
|
|
|
|
|
.rela* relocs, required for setting DT_TEXTREL. */
|
|
|
|
|
relocs = true;
|
|
|
|
|
/* Allocate contents later. */
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* It's not one of our sections, so don't allocate space. */
|
|
|
|
|
@@ -9741,6 +10158,9 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
|
|
|
|
|
if (!(h->def_regular || ELF_COMMON_DEF_P (h)))
|
|
|
|
|
return false;
|
|
|
|
|
BFD_ASSERT ((h->got.offset & 1) != 0);
|
|
|
|
|
/* Don't emit relative relocs if they are packed. */
|
|
|
|
|
if (info->enable_dt_relr)
|
|
|
|
|
goto skip_got_reloc;
|
|
|
|
|
rela.r_info = ELFNN_R_INFO (0, AARCH64_R (RELATIVE));
|
|
|
|
|
rela.r_addend = (h->root.u.def.value
|
|
|
|
|
+ h->root.u.def.section->output_section->vma
|
|
|
|
|
@@ -9760,6 +10180,7 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd,
|
|
|
|
|
loc += htab->root.srelgot->reloc_count++ * RELOC_SIZE (htab);
|
|
|
|
|
bfd_elfNN_swap_reloca_out (output_bfd, &rela, loc);
|
|
|
|
|
}
|
|
|
|
|
skip_got_reloc:
|
|
|
|
|
|
|
|
|
|
if (h->needs_copy)
|
|
|
|
|
{
|
|
|
|
|
@@ -10395,6 +10816,12 @@ const struct elf_size_info elfNN_aarch64_size_info =
|
|
|
|
|
#define elf_backend_merge_gnu_properties \
|
|
|
|
|
elfNN_aarch64_merge_gnu_properties
|
|
|
|
|
|
|
|
|
|
#define elf_backend_size_relative_relocs \
|
|
|
|
|
elfNN_aarch64_size_relative_relocs
|
|
|
|
|
|
|
|
|
|
#define elf_backend_finish_relative_relocs \
|
|
|
|
|
elfNN_aarch64_finish_relative_relocs
|
|
|
|
|
|
|
|
|
|
#define elf_backend_can_refcount 1
|
|
|
|
|
#define elf_backend_can_gc_sections 1
|
|
|
|
|
#define elf_backend_plt_readonly 1
|
|
|
|
|
|