aarch64: Add support for GNU indirect functions.

Add support for STT_GNU_IFUNC symbols to the AArch64 bfd backend. The tests
are ported from the ld-ifunc tests but are enabled for cross builds so can
be run easily without hardware or a simulator.

bfd/ChangeLog:

2013-06-07  Will Newton  <will.newton@linaro.org>

	* configure: Regenerate.
	* configure.in: Build elf-ifunc.o for AArch64.
	* elf64-aarch64.c: Include objalloc.h.
	(elf64_aarch64_howto_dynrelocs): Add R_AARCH64_IRELATIVE howto.
	(struct elf64_aarch64_link_hash_table): Add members for handling
	R_AARCH64_IRELATIVE relocations.
	(elf_aarch64_local_htab_hash): New function.
	(elf_aarch64_local_htab_eq): New function.
	(elf_aarch64_get_local_sym_hash): New function.
	(elf64_aarch64_link_hash_table_create): Initialize local STT_GNU_IFUNC
	symbol hash.
	(elf64_aarch64_hash_table_free): Free local STT_GNU_IFUNC symbol hash.
	(elf64_aarch64_final_link_relocate): Add sym argument.  Add support
	for handling STT_GNU_IFUNC symbols.
	(elf64_aarch64_gc_sweep_hook): Add support for garbage collecting
	references to STT_GNU_IFUNC symbols.
	(elf64_aarch64_adjust_dynamic_symbol): Add support for handling
	STT_GNU_IFUNC symbols.
	(elf64_aarch64_check_relocs): Add support for handling STT_GNU_IFUNC
	symbols.  Ensure we don't increase plt.refcount from -1 to 0.
	(elf64_aarch64_post_process_headers): Call _bfd_elf_set_osabi.
	(elf64_aarch64_is_function_type): Remove function.
	(elf64_aarch64_allocate_dynrelocs): Call
	_bfd_elf_allocate_ifunc_dyn_relocs for STT_GNU_IFUNC symbols.
	(elf_aarch64_allocate_local_dynrelocs): New function.
	(elf64_aarch64_size_dynamic_sections): Call
	elf_aarch64_allocate_local_dynrelocs.  Initialize next_irelative_index.
	(elf64_aarch64_create_small_pltn_entry): Add info argument.
	Add support for creating .iplt entries for STT_GNU_IFUNC symbols.
	(elf64_aarch64_finish_dynamic_symbol): Add support for handling
	STT_GNU_IFUNC symbols and .iplt.
	(elf_aarch64_finish_local_dynamic_symbol): New function.
	(elf64_aarch64_finish_dynamic_sections): Call
	elf_aarch64_finish_local_dynamic_symbol.
	(elf64_aarch64_add_symbol_hook): New function.

include/elf/ChangeLog:

2013-06-07  Will Newton  <will.newton@linaro.org>

	* aarch64.h: Add R_AARCH64_IRELATIVE reloc.

ld/ChangeLog:

2013-06-07  Will Newton  <will.newton@linaro.org>

	* emulparams/aarch64elf.sh: Add IREL_IN_PLT.

ld/testsuite/ChangeLog:

2013-06-07  Will Newton  <will.newton@linaro.org>

	* ld-ifunc/ifunc.exp: Enable ifunc tests for AArch64.
	* ld-aarch64/aarch64-elf.exp: Add ifunc tests.
	* ld-aarch64/ifunc-1-local.d: New file.
	* ld-aarch64/ifunc-1-local.s: Likewise.
	* ld-aarch64/ifunc-1.d: Likewise.
	* ld-aarch64/ifunc-1.s: Likewise.
	* ld-aarch64/ifunc-10.d: Likewise.
	* ld-aarch64/ifunc-10.s: Likewise.
	* ld-aarch64/ifunc-11.d: Likewise.
	* ld-aarch64/ifunc-11.s: Likewise.
	* ld-aarch64/ifunc-12.d: Likewise.
	* ld-aarch64/ifunc-12.s: Likewise.
	* ld-aarch64/ifunc-13.d: Likewise.
	* ld-aarch64/ifunc-13a.s: Likewise.
	* ld-aarch64/ifunc-13b.s: Likewise.
	* ld-aarch64/ifunc-14a.d: Likewise.
	* ld-aarch64/ifunc-14a.s: Likewise.
	* ld-aarch64/ifunc-14b.d: Likewise.
	* ld-aarch64/ifunc-14b.s: Likewise.
	* ld-aarch64/ifunc-14c.d: Likewise.
	* ld-aarch64/ifunc-14c.s: Likewise.
	* ld-aarch64/ifunc-14d.d: Likewise.
	* ld-aarch64/ifunc-14e.d: Likewise.
	* ld-aarch64/ifunc-14f.d: Likewise.
	* ld-aarch64/ifunc-15.d: Likewise.
	* ld-aarch64/ifunc-15.s: Likewise.
	* ld-aarch64/ifunc-16.d: Likewise.
	* ld-aarch64/ifunc-16.s: Likewise.
	* ld-aarch64/ifunc-17a.d: Likewise.
	* ld-aarch64/ifunc-17a.s: Likewise.
	* ld-aarch64/ifunc-17b.d: Likewise.
	* ld-aarch64/ifunc-17b.s: Likewise.
	* ld-aarch64/ifunc-18a.d: Likewise.
	* ld-aarch64/ifunc-18a.s: Likewise.
	* ld-aarch64/ifunc-18b.d: Likewise.
	* ld-aarch64/ifunc-18b.s: Likewise.
	* ld-aarch64/ifunc-19a.d: Likewise.
	* ld-aarch64/ifunc-19a.s: Likewise.
	* ld-aarch64/ifunc-19b.d: Likewise.
	* ld-aarch64/ifunc-19b.s: Likewise.
	* ld-aarch64/ifunc-2-local.d: Likewise.
	* ld-aarch64/ifunc-2-local.s: Likewise.
	* ld-aarch64/ifunc-2.d: Likewise.
	* ld-aarch64/ifunc-2.s: Likewise.
	* ld-aarch64/ifunc-20.d: Likewise.
	* ld-aarch64/ifunc-20.s: Likewise.
	* ld-aarch64/ifunc-3.s: Likewise.
	* ld-aarch64/ifunc-3a.d: Likewise.
	* ld-aarch64/ifunc-3b.d: Likewise.
	* ld-aarch64/ifunc-4.d: Likewise.
	* ld-aarch64/ifunc-4.s: Likewise.
	* ld-aarch64/ifunc-4a.d: Likewise.
	* ld-aarch64/ifunc-5-local.s: Likewise.
	* ld-aarch64/ifunc-5.s: Likewise.
	* ld-aarch64/ifunc-5a-local.d: Likewise.
	* ld-aarch64/ifunc-5a.d: Likewise.
	* ld-aarch64/ifunc-5b-local.d: Likewise.
	* ld-aarch64/ifunc-5b.d: Likewise.
	* ld-aarch64/ifunc-5r-local.d: Likewise.
	* ld-aarch64/ifunc-6.s: Likewise.
	* ld-aarch64/ifunc-6a.d: Likewise.
	* ld-aarch64/ifunc-6b.d: Likewise.
	* ld-aarch64/ifunc-7.s: Likewise.
	* ld-aarch64/ifunc-7a.d: Likewise.
	* ld-aarch64/ifunc-7b.d: Likewise.
	* ld-aarch64/ifunc-8.d: Likewise.
	* ld-aarch64/ifunc-8a.s: Likewise.
	* ld-aarch64/ifunc-8b.s: Likewise.
	* ld-aarch64/ifunc-9.d: Likewise.
	* ld-aarch64/ifunc-9.s: Likewise.
This commit is contained in:
Will Newton 2013-06-07 18:57:03 +00:00
parent 4ec7020176
commit 692e2b8bcd
78 changed files with 1545 additions and 82 deletions

View File

@ -1,3 +1,41 @@
2013-06-07 Will Newton <will.newton@linaro.org>
* configure: Regenerate.
* configure.in: Build elf-ifunc.o for AArch64.
* elf64-aarch64.c: Include objalloc.h.
(elf64_aarch64_howto_dynrelocs): Add R_AARCH64_IRELATIVE howto.
(struct elf64_aarch64_link_hash_table): Add members for handling
R_AARCH64_IRELATIVE relocations.
(elf_aarch64_local_htab_hash): New function.
(elf_aarch64_local_htab_eq): New function.
(elf_aarch64_get_local_sym_hash): New function.
(elf64_aarch64_link_hash_table_create): Initialize local STT_GNU_IFUNC
symbol hash.
(elf64_aarch64_hash_table_free): Free local STT_GNU_IFUNC symbol hash.
(elf64_aarch64_final_link_relocate): Add sym argument. Add support
for handling STT_GNU_IFUNC symbols.
(elf64_aarch64_gc_sweep_hook): Add support for garbage collecting
references to STT_GNU_IFUNC symbols.
(elf64_aarch64_adjust_dynamic_symbol): Add support for handling
STT_GNU_IFUNC symbols.
(elf64_aarch64_check_relocs): Add support for handling STT_GNU_IFUNC
symbols. Ensure we don't increase plt.refcount from -1 to 0.
(elf64_aarch64_post_process_headers): Call _bfd_elf_set_osabi.
(elf64_aarch64_is_function_type): Remove function.
(elf64_aarch64_allocate_dynrelocs): Call
_bfd_elf_allocate_ifunc_dyn_relocs for STT_GNU_IFUNC symbols.
(elf_aarch64_allocate_local_dynrelocs): New function.
(elf64_aarch64_size_dynamic_sections): Call
elf_aarch64_allocate_local_dynrelocs. Initialize next_irelative_index.
(elf64_aarch64_create_small_pltn_entry): Add info argument.
Add support for creating .iplt entries for STT_GNU_IFUNC symbols.
(elf64_aarch64_finish_dynamic_symbol): Add support for handling
STT_GNU_IFUNC symbols and .iplt.
(elf_aarch64_finish_local_dynamic_symbol): New function.
(elf64_aarch64_finish_dynamic_sections): Call
elf_aarch64_finish_local_dynamic_symbol.
(elf64_aarch64_add_symbol_hook): New function.
2013-06-03 Alan Modra <amodra@gmail.com>
* syms.c (_bfd_stab_section_find_nearest_line): Add last_str

4
bfd/configure vendored
View File

@ -15364,7 +15364,7 @@ do
bfd_elf32_xtensa_be_vec) tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;;
bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_alpha_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_bigaarch64_vec) tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_bigaarch64_vec) tb="$tb elf64-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_hppa_linux_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
@ -15373,7 +15373,7 @@ do
bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_little_vec) tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_vms_vec) tb="$tb elf64-ia64-vms.lo elf64-ia64.lo elfxx-ia64.lo elf64.lo vms-lib.lo vms-misc.lo $elf"; target_size=64 ;;
bfd_elf64_littleaarch64_vec)tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_littleaarch64_vec)tb="$tb elf64-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_mmix_vec) tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;;

View File

@ -859,7 +859,7 @@ do
bfd_elf32_xtensa_be_vec) tb="$tb xtensa-isa.lo xtensa-modules.lo elf32-xtensa.lo elf32.lo $elf" ;;
bfd_elf64_alpha_freebsd_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_alpha_vec) tb="$tb elf64-alpha.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_bigaarch64_vec) tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_bigaarch64_vec) tb="$tb elf64-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_big_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_bigmips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_hppa_linux_vec) tb="$tb elf64-hppa.lo elf64.lo $elf"; target_size=64 ;;
@ -868,7 +868,7 @@ do
bfd_elf64_ia64_hpux_big_vec) tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_little_vec) tb="$tb elf64-ia64.lo elfxx-ia64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_ia64_vms_vec) tb="$tb elf64-ia64-vms.lo elf64-ia64.lo elfxx-ia64.lo elf64.lo vms-lib.lo vms-misc.lo $elf"; target_size=64 ;;
bfd_elf64_littleaarch64_vec)tb="$tb elf64-aarch64.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_littleaarch64_vec)tb="$tb elf64-aarch64.lo elf-ifunc.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_little_generic_vec) tb="$tb elf64-gen.lo elf64.lo $elf"; target_size=64 ;;
bfd_elf64_littlemips_vec) tb="$tb elf64-mips.lo elf64.lo elfxx-mips.lo elf-vxworks.lo elf32.lo $elf ecofflink.lo"; target_size=64 ;;
bfd_elf64_mmix_vec) tb="$tb elf64-mmix.lo elf64.lo $elf" target_size=64 ;;

View File

@ -142,6 +142,7 @@
#include "bfd_stdint.h"
#include "elf-bfd.h"
#include "bfdlink.h"
#include "objalloc.h"
#include "elf/aarch64.h"
static bfd_reloc_status_type
@ -398,6 +399,20 @@ static reloc_howto_type elf64_aarch64_howto_dynrelocs[] =
ALL_ONES, /* dst_mask */
FALSE), /* pcrel_offset */
HOWTO (R_AARCH64_IRELATIVE, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
64, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_bitfield, /* complain_on_overflow */
bfd_elf_generic_reloc, /* special_function */
"R_AARCH64_IRELATIVE", /* name */
FALSE, /* partial_inplace */
0, /* src_mask */
ALL_ONES, /* dst_mask */
FALSE), /* pcrel_offset */
};
/* Note: code such as elf64_aarch64_reloc_type_lookup expect to use e.g.
@ -1864,6 +1879,15 @@ struct elf64_aarch64_link_hash_table
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;
/* The index of the next R_AARCH64_JUMP_SLOT entry in .rela.plt. */
bfd_vma next_jump_slot_index;
/* The index of the next R_AARCH64_IRELATIVE entry in .rela.plt. */
bfd_vma next_irelative_index;
};
@ -1973,6 +1997,72 @@ stub_hash_newfunc (struct bfd_hash_entry *entry,
return entry;
}
/* 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_aarch64_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_aarch64_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;
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_aarch64_get_local_sym_hash (struct elf64_aarch64_link_hash_table *htab,
bfd *abfd, const Elf_Internal_Rela *rel,
bfd_boolean create)
{
struct elf64_aarch64_link_hash_entry e, *ret;
asection *sec = abfd->sections;
hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id,
ELF32_R_SYM (rel->r_info));
void **slot;
e.root.indx = sec->id;
e.root.dynstr_index = ELF32_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 elf64_aarch64_link_hash_entry *) *slot;
return &ret->root;
}
ret = (struct elf64_aarch64_link_hash_entry *)
objalloc_alloc ((struct objalloc *) htab->loc_hash_memory,
sizeof (struct elf64_aarch64_link_hash_entry));
if (ret)
{
memset (ret, 0, sizeof (*ret));
ret->root.indx = sec->id;
ret->root.dynstr_index = ELF32_R_SYM (rel->r_info);
ret->root.dynindx = -1;
*slot = ret;
}
return &ret->root;
}
/* Copy the extra info we tack onto an elf_link_hash_entry. */
@ -2062,6 +2152,17 @@ elf64_aarch64_link_hash_table_create (bfd *abfd)
return NULL;
}
ret->loc_hash_table = htab_try_create (1024,
elf_aarch64_local_htab_hash,
elf_aarch64_local_htab_eq,
NULL);
ret->loc_hash_memory = objalloc_create ();
if (!ret->loc_hash_table || !ret->loc_hash_memory)
{
free (ret);
return NULL;
}
return &ret->root.root;
}
@ -2073,6 +2174,11 @@ elf64_aarch64_hash_table_free (struct bfd_link_hash_table *hash)
struct elf64_aarch64_link_hash_table *ret
= (struct elf64_aarch64_link_hash_table *) hash;
if (ret->loc_hash_table)
htab_delete (ret->loc_hash_table);
if (ret->loc_hash_memory)
objalloc_free ((struct objalloc *) ret->loc_hash_memory);
bfd_hash_table_free (&ret->stub_hash_table);
_bfd_elf_link_hash_table_free (hash);
}
@ -3770,8 +3876,10 @@ elf64_aarch64_final_link_relocate (reloc_howto_type *howto,
struct elf_link_hash_entry *h,
bfd_boolean *unresolved_reloc_p,
bfd_boolean save_addend,
bfd_vma *saved_addend)
bfd_vma *saved_addend,
Elf_Internal_Sym *sym)
{
Elf_Internal_Shdr *symtab_hdr;
unsigned int r_type = howto->type;
unsigned long r_symndx;
bfd_byte *hit_data = contents + rel->r_offset;
@ -3782,6 +3890,8 @@ elf64_aarch64_final_link_relocate (reloc_howto_type *howto,
globals = elf64_aarch64_hash_table (info);
symtab_hdr = &elf_symtab_hdr (input_bfd);
BFD_ASSERT (is_aarch64_elf (input_bfd));
r_symndx = ELF64_R_SYM (rel->r_info);
@ -3803,6 +3913,181 @@ elf64_aarch64_final_link_relocate (reloc_howto_type *howto,
weak_undef_p = (h ? h->root.type == bfd_link_hash_undefweak
: bfd_is_und_section (sym_sec));
/* Since STT_GNU_IFUNC symbol must go through PLT, we handle
it here if it is defined in a non-shared object. */
if (h != NULL
&& h->type == STT_GNU_IFUNC
&& h->def_regular)
{
asection *plt;
const char *name;
asection *base_got;
bfd_vma off;
if ((input_section->flags & SEC_ALLOC) == 0
|| h->plt.offset == (bfd_vma) -1)
abort ();
/* STT_GNU_IFUNC symbol must go through PLT. */
plt = globals->root.splt ? globals->root.splt : globals->root.iplt;
value = (plt->output_section->vma + plt->output_offset + h->plt.offset);
switch (r_type)
{
default:
if (h->root.root.string)
name = h->root.root.string;
else
name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
NULL);
(*_bfd_error_handler)
(_("%B: relocation %s against STT_GNU_IFUNC "
"symbol `%s' isn't handled by %s"), input_bfd,
howto->name, name, __FUNCTION__);
bfd_set_error (bfd_error_bad_value);
return FALSE;
case R_AARCH64_ABS64:
if (rel->r_addend != 0)
{
if (h->root.root.string)
name = h->root.root.string;
else
name = bfd_elf_sym_name (input_bfd, symtab_hdr,
sym, NULL);
(*_bfd_error_handler)
(_("%B: relocation %s against STT_GNU_IFUNC "
"symbol `%s' has non-zero addend: %d"),
input_bfd, howto->name, name, rel->r_addend);
bfd_set_error (bfd_error_bad_value);
return FALSE;
}
/* Generate dynamic relocation only when there is a
non-GOT reference in a shared object. */
if (info->shared && h->non_got_ref)
{
Elf_Internal_Rela outrel;
asection *sreloc;
/* Need a dynamic relocation to get the real function
address. */
outrel.r_offset = _bfd_elf_section_offset (output_bfd,
info,
input_section,
rel->r_offset);
if (outrel.r_offset == (bfd_vma) -1
|| outrel.r_offset == (bfd_vma) -2)
abort ();
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
if (h->dynindx == -1
|| h->forced_local
|| info->executable)
{
/* This symbol is resolved locally. */
outrel.r_info = ELF64_R_INFO (0, R_AARCH64_IRELATIVE);
outrel.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
}
else
{
outrel.r_info = ELF64_R_INFO (h->dynindx, r_type);
outrel.r_addend = 0;
}
sreloc = globals->root.irelifunc;
elf_append_rela (output_bfd, sreloc, &outrel);
/* If this reloc is against an external symbol, we
do not want to fiddle with the addend. Otherwise,
we need to include the symbol value so that it
becomes an addend for the dynamic reloc. For an
internal symbol, we have updated addend. */
return bfd_reloc_ok;
}
/* FALLTHROUGH */
case R_AARCH64_JUMP26:
case R_AARCH64_CALL26:
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
signed_addend);
case R_AARCH64_LD64_GOT_LO12_NC:
case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_GOT_LD_PREL19:
base_got = globals->root.sgot;
off = h->got.offset;
if (base_got == NULL)
abort ();
if (off == (bfd_vma) -1)
{
bfd_vma plt_index;
/* We can't use h->got.offset here to save state, or
even just remember the offset, as finish_dynamic_symbol
would use that as offset into .got. */
if (globals->root.splt != NULL)
{
plt_index = h->plt.offset / globals->plt_entry_size - 1;
off = (plt_index + 3) * GOT_ENTRY_SIZE;
base_got = globals->root.sgotplt;
}
else
{
plt_index = h->plt.offset / globals->plt_entry_size;
off = plt_index * GOT_ENTRY_SIZE;
base_got = globals->root.igotplt;
}
if (h->dynindx == -1
|| h->forced_local
|| info->symbolic)
{
/* This references the local defitionion. We must
initialize this entry in the global offset table.
Since the offset must always be a multiple of 8,
we use the least significant bit to record
whether we have initialized it already.
When doing a dynamic link, we create a .rela.got
relocation entry to initialize the value. This
is done in the finish_dynamic_symbol routine. */
if ((off & 1) != 0)
off &= ~1;
else
{
bfd_put_64 (output_bfd, value,
base_got->contents + off);
/* Note that this is harmless for the GOTPLT64
case, as -1 | 1 still is -1. */
h->got.offset |= 1;
}
}
value = (base_got->output_section->vma
+ base_got->output_offset + off);
}
else
value = aarch64_calculate_got_entry_vma (h, globals, info,
value, output_bfd,
unresolved_reloc_p);
value = aarch64_resolve_relocation (r_type, place, value,
0, weak_undef_p);
return _bfd_final_link_relocate (howto, input_bfd, input_section,
contents, rel->r_offset, value,
signed_addend);
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_ADD_ABS_LO12_NC:
break;
}
}
switch (r_type)
{
case R_AARCH64_NONE:
@ -3829,11 +4114,6 @@ elf64_aarch64_final_link_relocate (reloc_howto_type *howto,
*unresolved_reloc_p = FALSE;
sreloc = _bfd_elf_get_dynamic_reloc_section (input_bfd,
input_section, 1);
if (sreloc == NULL)
return bfd_reloc_notsupported;
skip = FALSE;
relocate = FALSE;
@ -3870,10 +4150,14 @@ elf64_aarch64_final_link_relocate (reloc_howto_type *howto,
outrel.r_addend += value;
}
loc = sreloc->contents + sreloc->reloc_count++ * RELOC_SIZE (htab);
sreloc = elf_section_data (input_section)->sreloc;
if (sreloc == NULL || sreloc->contents == NULL)
return bfd_reloc_notsupported;
loc = sreloc->contents + sreloc->reloc_count++ * RELOC_SIZE (globals);
bfd_elf64_swap_reloca_out (output_bfd, &outrel, loc);
if (sreloc->reloc_count * RELOC_SIZE (htab) > sreloc->size)
if (sreloc->reloc_count * RELOC_SIZE (globals) > sreloc->size)
{
/* Sanity to check that we have previously allocated
sufficient space in the relocation section for the
@ -4284,6 +4568,20 @@ elf64_aarch64_relocate_section (bfd *output_bfd,
}
relocation = _bfd_elf_rela_local_sym (output_bfd, sym, &sec, rel);
/* Relocate against local STT_GNU_IFUNC symbol. */
if (!info->relocatable
&& ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
{
h = elf_aarch64_get_local_sym_hash (globals, input_bfd,
rel, FALSE);
if (h == NULL)
abort ();
/* Set STT_GNU_IFUNC symbol value. */
h->root.u.def.value = sym->st_value;
h->root.u.def.section = sec;
}
}
else
{
@ -4373,7 +4671,7 @@ elf64_aarch64_relocate_section (bfd *output_bfd,
input_section, contents, rel,
relocation, info, sec,
h, &unresolved_reloc,
save_addend, &addend);
save_addend, &addend, sym);
switch (r_type)
{
@ -4850,38 +5148,46 @@ elf64_aarch64_gc_sweep_hook (bfd *abfd,
struct elf_link_hash_entry *h = NULL;
r_symndx = ELF64_R_SYM (rel->r_info);
if (r_symndx >= symtab_hdr->sh_info)
{
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;
}
else
{
/* A local symbol. */
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
/* Check relocation against local STT_GNU_IFUNC symbol. */
if (isym != NULL
&& ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
h = elf_aarch64_get_local_sym_hash (htab, abfd, rel, FALSE);
if (h == NULL)
abort ();
}
}
if (h)
{
struct elf64_aarch64_link_hash_entry *eh;
struct elf_dyn_relocs **pp;
struct elf_dyn_relocs *p;
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;
eh = (struct elf64_aarch64_link_hash_entry *) h;
for (pp = &eh->dyn_relocs; (p = *pp) != NULL; pp = &p->next)
{
if (p->sec == sec)
{
/* Everything must go for SEC. */
*pp = p->next;
break;
}
}
}
else
{
Elf_Internal_Sym *isym;
/* A local symbol. */
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
if (p->sec == sec)
{
/* Everything must go for SEC. */
*pp = p->next;
break;
}
}
r_type = ELF64_R_TYPE (rel->r_info);
@ -4910,6 +5216,12 @@ elf64_aarch64_gc_sweep_hook (bfd *abfd,
{
if (h->got.refcount > 0)
h->got.refcount -= 1;
if (h->type == STT_GNU_IFUNC)
{
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
}
}
else if (locals != NULL)
{
@ -4940,7 +5252,7 @@ elf64_aarch64_gc_sweep_hook (bfd *abfd,
break;
case R_AARCH64_ABS64:
if (h != NULL && info->executable)
if (h != NULL)
{
if (h->plt.refcount > 0)
h->plt.refcount -= 1;
@ -4971,12 +5283,13 @@ elf64_aarch64_adjust_dynamic_symbol (struct bfd_link_info *info,
/* If this is a function, put it in the procedure linkage table. We
will fill in the contents of the procedure linkage table later,
when we know the address of the .got section. */
if (h->type == STT_FUNC || h->needs_plt)
if (h->type == STT_FUNC || h->type == STT_GNU_IFUNC || h->needs_plt)
{
if (h->plt.refcount <= 0
|| SYMBOL_CALLS_LOCAL (info, h)
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
&& h->root.type == bfd_link_hash_undefweak))
|| (h->type != STT_GNU_IFUNC
&& (SYMBOL_CALLS_LOCAL (info, h)
|| (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT
&& h->root.type == bfd_link_hash_undefweak))))
{
/* This case can occur if we saw a CALL26 reloc in
an input file, but the symbol wasn't referred to
@ -5105,6 +5418,7 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
struct elf_link_hash_entry *h;
unsigned long r_symndx;
unsigned int r_type;
Elf_Internal_Sym *isym;
r_symndx = ELF64_R_SYM (rel->r_info);
r_type = ELF64_R_TYPE (rel->r_info);
@ -5117,7 +5431,31 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
}
if (r_symndx < symtab_hdr->sh_info)
h = NULL;
{
/* A local symbol. */
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
if (isym == NULL)
return FALSE;
/* Check relocation against local STT_GNU_IFUNC symbol. */
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
{
h = elf_aarch64_get_local_sym_hash (htab, abfd, rel,
TRUE);
if (h == NULL)
return FALSE;
/* Fake a STT_GNU_IFUNC symbol. */
h->type = STT_GNU_IFUNC;
h->def_regular = 1;
h->ref_regular = 1;
h->forced_local = 1;
h->root.type = bfd_link_hash_defined;
}
else
h = NULL;
}
else
{
h = sym_hashes[r_symndx - symtab_hdr->sh_info];
@ -5130,6 +5468,37 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
h->root.non_ir_ref = 1;
}
if (h != NULL)
{
/* Create the ifunc sections for static executables. If we
never see an indirect function symbol nor we are building
a static executable, those sections will be empty and
won't appear in output. */
switch (r_type)
{
default:
break;
case R_AARCH64_ABS64:
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
case R_AARCH64_LD64_GOT_LO12_NC:
case R_AARCH64_ADR_GOT_PAGE:
case R_AARCH64_GOT_LD_PREL19:
case R_AARCH64_ADR_PREL_PG_HI21:
case R_AARCH64_ADD_ABS_LO12_NC:
if (htab->root.dynobj == NULL)
htab->root.dynobj = abfd;
if (!_bfd_elf_create_ifunc_sections (htab->root.dynobj, info))
return FALSE;
break;
}
/* It is referenced by a non-shared object. */
h->ref_regular = 1;
h->root.non_ir_ref = 1;
}
/* Could be done earlier, if h were already available. */
r_type = aarch64_tls_transition (abfd, info, r_type, h, r_symndx);
@ -5191,7 +5560,6 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
asection *s;
void **vpp;
Elf_Internal_Sym *isym;
isym = bfd_sym_from_r_symndx (&htab->sym_cache,
abfd, r_symndx);
@ -5341,7 +5709,10 @@ elf64_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info,
continue;
h->needs_plt = 1;
h->plt.refcount += 1;
if (h->plt.refcount <= 0)
h->plt.refcount = 1;
else
h->plt.refcount += 1;
break;
}
}
@ -5485,14 +5856,14 @@ elf64_aarch64_find_inliner_info (bfd *abfd,
static void
elf64_aarch64_post_process_headers (bfd *abfd,
struct bfd_link_info *link_info
ATTRIBUTE_UNUSED)
struct bfd_link_info *link_info)
{
Elf_Internal_Ehdr *i_ehdrp; /* ELF file header, internal form. */
i_ehdrp = elf_elfheader (abfd);
i_ehdrp->e_ident[EI_OSABI] = 0;
i_ehdrp->e_ident[EI_ABIVERSION] = AARCH64_ELF_ABI_VERSION;
_bfd_elf_set_osabi (abfd, link_info);
}
static enum elf_reloc_type_class
@ -5884,12 +6255,6 @@ elf64_aarch64_bfd_free_cached_info (bfd *abfd)
return _bfd_free_cached_info (abfd);
}
static bfd_boolean
elf64_aarch64_is_function_type (unsigned int type)
{
return type == STT_FUNC;
}
/* Create dynamic sections. This is different from the ARM backend in that
the got, plt, gotplt and their relocation sections are all created in the
standard part of the bfd elf backend. */
@ -5956,7 +6321,18 @@ elf64_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
info = (struct bfd_link_info *) inf;
htab = elf64_aarch64_hash_table (info);
if (htab->root.dynamic_sections_created && h->plt.refcount > 0)
eh = (struct elf64_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,
htab->plt_entry_size,
htab->plt_header_size,
GOT_ENTRY_SIZE);
else if (htab->root.dynamic_sections_created && h->plt.refcount > 0)
{
/* Make sure this symbol is output as a dynamic symbol.
Undefined weak syms won't yet be marked as dynamic. */
@ -6027,7 +6403,6 @@ elf64_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
h->needs_plt = 0;
}
eh = (struct elf64_aarch64_link_hash_entry *) h;
eh->tlsdesc_got_jump_table_offset = (bfd_vma) - 1;
if (h->got.refcount > 0)
@ -6212,6 +6587,24 @@ elf64_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
}
/* Allocate space in .plt, .got and associated reloc sections for
local dynamic relocs. */
static bfd_boolean
elf_aarch64_allocate_local_dynrelocs (void **slot, void *inf)
{
struct elf_link_hash_entry *h
= (struct elf_link_hash_entry *) *slot;
if (h->type != STT_GNU_IFUNC
|| !h->def_regular
|| !h->ref_regular
|| !h->forced_local
|| h->root.type != bfd_link_hash_defined)
abort ();
return elf64_aarch64_allocate_dynrelocs (h, inf);
}
/* This is the most important function of all . Innocuosly named
@ -6351,6 +6744,10 @@ elf64_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
elf_link_hash_traverse (&htab->root, elf64_aarch64_allocate_dynrelocs,
info);
/* Allocate .plt and .got entries, and space for local symbols. */
htab_traverse (htab->loc_hash_table,
elf_aarch64_allocate_local_dynrelocs,
info);
/* For every jump slot reserved in the sgotplt, reloc_count is
incremented. However, when we reserve space for TLS descriptors,
@ -6359,7 +6756,12 @@ elf64_aarch64_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
slot size. */
if (htab->root.srelplt)
htab->sgotplt_jump_table_size = aarch64_compute_jump_table_size (htab);
{
htab->sgotplt_jump_table_size = aarch64_compute_jump_table_size (htab);
htab->next_irelative_index = htab->root.srelplt->reloc_count - 1;
}
else if (htab->root.irelplt)
htab->next_irelative_index = htab->root.irelplt->reloc_count - 1;
if (htab->tlsdesc_plt)
{
@ -6506,7 +6908,8 @@ elf64_aarch64_update_plt_entry (bfd *output_bfd,
static void
elf64_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
struct elf64_aarch64_link_hash_table
*htab, bfd *output_bfd)
*htab, bfd *output_bfd,
struct bfd_link_info *info)
{
bfd_byte *plt_entry;
bfd_vma plt_index;
@ -6515,17 +6918,50 @@ elf64_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
bfd_vma plt_entry_address;
Elf_Internal_Rela rela;
bfd_byte *loc;
asection *plt, *gotplt, *relplt;
plt_index = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size;
/* When building a static executable, use .iplt, .igot.plt and
.rela.iplt sections for STT_GNU_IFUNC symbols. */
if (htab->root.splt != NULL)
{
plt = htab->root.splt;
gotplt = htab->root.sgotplt;
relplt = htab->root.srelplt;
}
else
{
plt = htab->root.iplt;
gotplt = htab->root.igotplt;
relplt = htab->root.irelplt;
}
/* Offset in the GOT is PLT index plus got GOT headers(3)
times 8. */
got_offset = (plt_index + 3) * GOT_ENTRY_SIZE;
plt_entry = htab->root.splt->contents + h->plt.offset;
plt_entry_address = htab->root.splt->output_section->vma
+ htab->root.splt->output_section->output_offset + h->plt.offset;
gotplt_entry_address = htab->root.sgotplt->output_section->vma +
htab->root.sgotplt->output_offset + got_offset;
/* Get the index in the procedure linkage table which
corresponds to this symbol. This is the index of this symbol
in all the symbols for which we are making plt entries. The
first entry in the procedure linkage table is reserved.
Get the offset into the .got table of the entry that
corresponds to this function. Each .got entry is GOT_ENTRY_SIZE
bytes. The first three are reserved for the dynamic linker.
For static executables, we don't reserve anything. */
if (plt == htab->root.splt)
{
got_offset = (h->plt.offset - htab->plt_header_size) / htab->plt_entry_size;
got_offset = (got_offset + 3) * GOT_ENTRY_SIZE;
}
else
{
got_offset = h->plt.offset / htab->plt_entry_size;
got_offset = got_offset * GOT_ENTRY_SIZE;
}
plt_entry = plt->contents + h->plt.offset;
plt_entry_address = plt->output_section->vma
+ plt->output_section->output_offset + h->plt.offset;
gotplt_entry_address = gotplt->output_section->vma +
gotplt->output_offset + got_offset;
/* Copy in the boiler-plate for the PLTn entry. */
memcpy (plt_entry, elf64_aarch64_small_plt_entry, PLT_SMALL_ENTRY_SIZE);
@ -6549,19 +6985,38 @@ elf64_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h,
/* All the GOTPLT Entries are essentially initialized to PLT0. */
bfd_put_64 (output_bfd,
(htab->root.splt->output_section->vma
+ htab->root.splt->output_offset),
htab->root.sgotplt->contents + got_offset);
plt->output_section->vma + plt->output_offset,
gotplt->contents + got_offset);
/* Fill in the entry in the .rela.plt section. */
rela.r_offset = gotplt_entry_address;
rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_JUMP_SLOT);
rela.r_addend = 0;
if (h->dynindx == -1
|| ((info->executable
|| ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
&& h->def_regular
&& h->type == STT_GNU_IFUNC))
{
/* If an STT_GNU_IFUNC symbol is locally defined, generate
R_AARCH64_IRELATIVE instead of R_AARCH64_JUMP_SLOT. */
rela.r_info = ELF64_R_INFO (0, R_AARCH64_IRELATIVE);
rela.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
/* R_AARCH64_IRELATIVE comes last. */
plt_index = htab->next_irelative_index--;
}
else
{
/* Fill in the entry in the .rela.plt section. */
rela.r_info = ELF64_R_INFO (h->dynindx, R_AARCH64_JUMP_SLOT);
rela.r_addend = 0;
plt_index = htab->next_jump_slot_index++;
}
/* Compute the relocation entry to used based on PLT index and do
not adjust reloc_count. The reloc_count has already been adjusted
to account for this entry. */
loc = htab->root.srelplt->contents + plt_index * RELOC_SIZE (htab);
loc = relplt->contents + plt_index * RELOC_SIZE (htab);
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
}
@ -6621,15 +7076,38 @@ elf64_aarch64_finish_dynamic_symbol (bfd *output_bfd,
if (h->plt.offset != (bfd_vma) - 1)
{
asection *plt, *gotplt, *relplt;
/* This symbol has an entry in the procedure linkage table. Set
it up. */
if (h->dynindx == -1
|| htab->root.splt == NULL
|| htab->root.sgotplt == NULL || htab->root.srelplt == NULL)
/* When building a static executable, use .iplt, .igot.plt and
.rela.iplt sections for STT_GNU_IFUNC symbols. */
if (htab->root.splt != NULL)
{
plt = htab->root.splt;
gotplt = htab->root.sgotplt;
relplt = htab->root.srelplt;
}
else
{
plt = htab->root.iplt;
gotplt = htab->root.igotplt;
relplt = htab->root.irelplt;
}
/* This symbol has an entry in the procedure linkage table. Set
it up. */
if ((h->dynindx == -1
&& !((h->forced_local || info->executable)
&& h->def_regular
&& h->type == STT_GNU_IFUNC))
|| plt == NULL
|| gotplt == NULL
|| relplt == NULL)
abort ();
elf64_aarch64_create_small_pltn_entry (h, htab, output_bfd);
elf64_aarch64_create_small_pltn_entry (h, htab, output_bfd, info);
if (!h->def_regular)
{
/* Mark the symbol as undefined, rather than as defined in
@ -6714,6 +7192,21 @@ elf64_aarch64_finish_dynamic_symbol (bfd *output_bfd,
return TRUE;
}
/* Finish up local dynamic symbol handling. We set the contents of
various dynamic sections here. */
static bfd_boolean
elf_aarch64_finish_local_dynamic_symbol (void **slot, void *inf)
{
struct elf_link_hash_entry *h
= (struct elf_link_hash_entry *) *slot;
struct bfd_link_info *info
= (struct bfd_link_info *) inf;
return elf64_aarch64_finish_dynamic_symbol (info->output_bfd,
info, h, NULL);
}
static void
elf64_aarch64_init_small_plt0_entry (bfd *output_bfd ATTRIBUTE_UNUSED,
struct elf64_aarch64_link_hash_table
@ -6956,6 +7449,11 @@ elf64_aarch64_finish_dynamic_sections (bfd *output_bfd,
elf_section_data (htab->root.sgot->output_section)->this_hdr.sh_entsize
= GOT_ENTRY_SIZE;
/* Fill PLT and GOT entries for local STT_GNU_IFUNC symbols. */
htab_traverse (htab->loc_hash_table,
elf_aarch64_finish_local_dynamic_symbol,
info);
return TRUE;
}
@ -6969,6 +7467,24 @@ elf64_aarch64_plt_sym_val (bfd_vma i, const asection *plt,
return plt->vma + PLT_ENTRY_SIZE + i * PLT_SMALL_ENTRY_SIZE;
}
/* Hook called by the linker routine which adds symbols from an object
file. */
static bfd_boolean
elf64_aarch64_add_symbol_hook (bfd *abfd, struct bfd_link_info *info,
Elf_Internal_Sym *sym,
const char **namep ATTRIBUTE_UNUSED,
flagword *flagsp ATTRIBUTE_UNUSED,
asection **secp ATTRIBUTE_UNUSED,
bfd_vma *valp ATTRIBUTE_UNUSED)
{
if ((abfd->flags & DYNAMIC) == 0
&& (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
|| ELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE))
elf_tdata (info->output_bfd)->has_gnu_symbols = TRUE;
return TRUE;
}
/* We use this so we can override certain functions
(though currently we don't). */
@ -7075,9 +7591,6 @@ const struct elf_size_info elf64_aarch64_size_info =
#define elf_backend_init_index_section \
_bfd_elf_init_2_index_sections
#define elf_backend_is_function_type \
elf64_aarch64_is_function_type
#define elf_backend_finish_dynamic_sections \
elf64_aarch64_finish_dynamic_sections
@ -7117,6 +7630,9 @@ const struct elf_size_info elf64_aarch64_size_info =
#define elf_backend_size_info \
elf64_aarch64_size_info
#define elf_backend_add_symbol_hook \
elf64_aarch64_add_symbol_hook
#define elf_backend_can_refcount 1
#define elf_backend_can_gc_sections 1
#define elf_backend_plt_readonly 1

View File

@ -1,3 +1,7 @@
2013-06-07 Will Newton <will.newton@linaro.org>
* aarch64.h: Add R_AARCH64_IRELATIVE reloc.
2013-06-06 Maciej W. Rozycki <macro@codesourcery.com>
* mips.h (ELF_ST_SET_MIPS_PIC): Clear any STO_MIPS16 setting.

View File

@ -208,7 +208,8 @@ RELOC_NUMBER (R_AARCH64_TLS_DTPMOD64, 1028)
RELOC_NUMBER (R_AARCH64_TLS_DTPREL64, 1029)
RELOC_NUMBER (R_AARCH64_TLS_TPREL64, 1030)
RELOC_NUMBER (R_AARCH64_TLSDESC, 1031)
FAKE_RELOC (R_AARCH64_dyn_max, 1032)
RELOC_NUMBER (R_AARCH64_IRELATIVE, 1032)
FAKE_RELOC (R_AARCH64_dyn_max, 1033)
END_RELOC_NUMBERS (R_AARCH64_end)

View File

@ -1,3 +1,7 @@
2013-06-07 Will Newton <will.newton@linaro.org>
* emulparams/aarch64elf.sh: Add IREL_IN_PLT.
2013-06-07 Nick Clifton <nickc@redhat.com>
* ld.texinfo (SEGMENT_START): Rephrase to indicate that a -T

View File

@ -1,3 +1,76 @@
2013-06-07 Will Newton <will.newton@linaro.org>
* ld-ifunc/ifunc.exp: Enable ifunc tests for AArch64.
* ld-aarch64/aarch64-elf.exp: Add ifunc tests.
* ld-aarch64/ifunc-1-local.d: New file.
* ld-aarch64/ifunc-1-local.s: Likewise.
* ld-aarch64/ifunc-1.d: Likewise.
* ld-aarch64/ifunc-1.s: Likewise.
* ld-aarch64/ifunc-10.d: Likewise.
* ld-aarch64/ifunc-10.s: Likewise.
* ld-aarch64/ifunc-11.d: Likewise.
* ld-aarch64/ifunc-11.s: Likewise.
* ld-aarch64/ifunc-12.d: Likewise.
* ld-aarch64/ifunc-12.s: Likewise.
* ld-aarch64/ifunc-13.d: Likewise.
* ld-aarch64/ifunc-13a.s: Likewise.
* ld-aarch64/ifunc-13b.s: Likewise.
* ld-aarch64/ifunc-14a.d: Likewise.
* ld-aarch64/ifunc-14a.s: Likewise.
* ld-aarch64/ifunc-14b.d: Likewise.
* ld-aarch64/ifunc-14b.s: Likewise.
* ld-aarch64/ifunc-14c.d: Likewise.
* ld-aarch64/ifunc-14c.s: Likewise.
* ld-aarch64/ifunc-14d.d: Likewise.
* ld-aarch64/ifunc-14e.d: Likewise.
* ld-aarch64/ifunc-14f.d: Likewise.
* ld-aarch64/ifunc-15.d: Likewise.
* ld-aarch64/ifunc-15.s: Likewise.
* ld-aarch64/ifunc-16.d: Likewise.
* ld-aarch64/ifunc-16.s: Likewise.
* ld-aarch64/ifunc-17a.d: Likewise.
* ld-aarch64/ifunc-17a.s: Likewise.
* ld-aarch64/ifunc-17b.d: Likewise.
* ld-aarch64/ifunc-17b.s: Likewise.
* ld-aarch64/ifunc-18a.d: Likewise.
* ld-aarch64/ifunc-18a.s: Likewise.
* ld-aarch64/ifunc-18b.d: Likewise.
* ld-aarch64/ifunc-18b.s: Likewise.
* ld-aarch64/ifunc-19a.d: Likewise.
* ld-aarch64/ifunc-19a.s: Likewise.
* ld-aarch64/ifunc-19b.d: Likewise.
* ld-aarch64/ifunc-19b.s: Likewise.
* ld-aarch64/ifunc-2-local.d: Likewise.
* ld-aarch64/ifunc-2-local.s: Likewise.
* ld-aarch64/ifunc-2.d: Likewise.
* ld-aarch64/ifunc-2.s: Likewise.
* ld-aarch64/ifunc-20.d: Likewise.
* ld-aarch64/ifunc-20.s: Likewise.
* ld-aarch64/ifunc-3.s: Likewise.
* ld-aarch64/ifunc-3a.d: Likewise.
* ld-aarch64/ifunc-3b.d: Likewise.
* ld-aarch64/ifunc-4.d: Likewise.
* ld-aarch64/ifunc-4.s: Likewise.
* ld-aarch64/ifunc-4a.d: Likewise.
* ld-aarch64/ifunc-5-local.s: Likewise.
* ld-aarch64/ifunc-5.s: Likewise.
* ld-aarch64/ifunc-5a-local.d: Likewise.
* ld-aarch64/ifunc-5a.d: Likewise.
* ld-aarch64/ifunc-5b-local.d: Likewise.
* ld-aarch64/ifunc-5b.d: Likewise.
* ld-aarch64/ifunc-5r-local.d: Likewise.
* ld-aarch64/ifunc-6.s: Likewise.
* ld-aarch64/ifunc-6a.d: Likewise.
* ld-aarch64/ifunc-6b.d: Likewise.
* ld-aarch64/ifunc-7.s: Likewise.
* ld-aarch64/ifunc-7a.d: Likewise.
* ld-aarch64/ifunc-7b.d: Likewise.
* ld-aarch64/ifunc-8.d: Likewise.
* ld-aarch64/ifunc-8a.s: Likewise.
* ld-aarch64/ifunc-8b.s: Likewise.
* ld-aarch64/ifunc-9.d: Likewise.
* ld-aarch64/ifunc-9.s: Likewise.
2013-06-04 Roland McGrath <mcgrathr@google.com>
* ld-size/size.exp: For *-*-nacl* targets, use options_regsub(ld)

View File

@ -114,3 +114,43 @@ run_dump_test "gc-tls-relocs"
run_dump_test "gc-plt-relocs"
run_dump_test "gc-relocs-257-dyn"
run_dump_test "gc-relocs-257"
# ifunc tests
run_dump_test "ifunc-1"
run_dump_test "ifunc-1-local"
run_dump_test "ifunc-2"
run_dump_test "ifunc-2-local"
run_dump_test "ifunc-3a"
run_dump_test "ifunc-3b"
run_dump_test "ifunc-4"
run_dump_test "ifunc-4a"
run_dump_test "ifunc-5a"
run_dump_test "ifunc-5b"
run_dump_test "ifunc-5a-local"
run_dump_test "ifunc-5b-local"
run_dump_test "ifunc-5r-local"
run_dump_test "ifunc-6a"
run_dump_test "ifunc-6b"
run_dump_test "ifunc-7a"
run_dump_test "ifunc-7b"
run_dump_test "ifunc-8"
run_dump_test "ifunc-9"
run_dump_test "ifunc-10"
run_dump_test "ifunc-11"
run_dump_test "ifunc-12"
run_dump_test "ifunc-13"
run_dump_test "ifunc-14a"
run_dump_test "ifunc-14b"
run_dump_test "ifunc-14c"
run_dump_test "ifunc-14d"
run_dump_test "ifunc-14e"
run_dump_test "ifunc-14f"
run_dump_test "ifunc-15"
run_dump_test "ifunc-16"
run_dump_test "ifunc-17a"
run_dump_test "ifunc-17b"
run_dump_test "ifunc-18a"
run_dump_test "ifunc-18b"
run_dump_test "ifunc-19a"
run_dump_test "ifunc-19b"
run_dump_test "ifunc-20"

View File

@ -0,0 +1,7 @@
#ld: -shared
#objdump: -dw
#target: aarch64-*-*
#...
[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2a0@plt>
#pass

View File

@ -0,0 +1,13 @@
.type foo, %gnu_indirect_function
.set __GI_foo, foo
.text
.type foo, @function
foo:
ret
.size foo, .-foo
.globl bar
.type bar, @function
bar:
bl __GI_foo
ret
.size bar, .-bar

View File

@ -0,0 +1,7 @@
#ld: -shared
#objdump: -dw
#target: aarch64-*-*
#...
[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2c0@plt>
#pass

View File

@ -0,0 +1,16 @@
.type foo, %gnu_indirect_function
.global __GI_foo
.hidden __GI_foo
.set __GI_foo, foo
.text
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.globl bar
.type bar, @function
bar:
bl __GI_foo
ret
.size bar, .-bar

View File

@ -0,0 +1,5 @@
#ld: -e bar --gc-sections
#readelf: -r --wide
#target: aarch64-*-*
There are no relocations in this file.

View File

@ -0,0 +1,25 @@
.section .text.foo,"ax",@progbits
.type foo, @function
foo:
.global foo
adrp x0, :got:ifunc
ldr x0, [x0, #:got_lo12:ifunc]
bl ifunc
adrp x0, xxx
add x0, x0, :lo12:xxx
ret
.section .text.bar,"ax",@progbits
.type bar, @function
bar:
.global bar
ret
.section .text.ifunc,"ax",@progbits
.type ifunc, @gnu_indirect_function
ifunc:
ret
.section .data.foo,"aw",@progbits
xxx:
.quad ifunc

View File

@ -0,0 +1,5 @@
#ld: -e bar --gc-sections
#readelf: -r --wide
#target: aarch64-*-*
There are no relocations in this file.

View File

@ -0,0 +1,26 @@
.section .text.foo,"ax",@progbits
.type foo, @function
foo:
.global foo
adrp x0, :got:ifunc
ldr x0, [x0, #:got_lo12:ifunc]
bl ifunc
adrp x0, xxx
add x0, x0, :lo12:xxx
ret
.section .text.bar,"ax",@progbits
.type bar, @function
bar:
.global bar
ret
.section .text.ifunc,"ax",@progbits
.type ifunc, @gnu_indirect_function
.global ifunc
ifunc:
ret
.section .data.foo,"aw",@progbits
xxx:
.quad ifunc

View File

@ -0,0 +1,5 @@
#ld: -shared -e bar --gc-sections
#readelf: -r --wide
#target: aarch64-*-*
There are no relocations in this file.

View File

@ -0,0 +1,24 @@
.section .text.foo,"ax",@progbits
.type foo, @function
foo:
adrp x0, :got:ifunc
ldr x0, [x0, #:got_lo12:ifunc]
bl ifunc
adrp x0, xxx
add x0, x0, :lo12:xxx
ret
.section .text.bar,"ax",@progbits
.type bar, @function
bar:
.global bar
ret
.section .text.ifunc,"ax",@progbits
.type ifunc, @gnu_indirect_function
ifunc:
ret
.section .data.foo,"aw",@progbits
xxx:
.quad ifunc

View File

@ -0,0 +1,13 @@
#source: ifunc-13a.s
#source: ifunc-13b.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.ifunc' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_ABS64[ ]+ifunc\(\)[ ]+ifunc \+ 0
Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0

View File

@ -0,0 +1,11 @@
.text
.type foo, @function
.global foo
foo:
adrp x0, xxx
add x0, x0, :lo12:xxx
ret
.data
xxx:
.quad ifunc

View File

@ -0,0 +1,5 @@
.text
.type ifunc, @gnu_indirect_function
.globl ifunc
ifunc:
ret

View File

@ -0,0 +1,10 @@
#source: ifunc-14a.s
#source: ifunc-14b.s
#ld: -shared -z nocombreloc
#readelf: -d
#target: aarch64-*-*
#failif
#...
.*\(TEXTREL\).*
#...

View File

@ -0,0 +1,7 @@
.text
.globl bar
.type bar, @function
bar:
bl foo
.size bar, .-bar
.hidden foo

View File

@ -0,0 +1,10 @@
#source: ifunc-14b.s
#source: ifunc-14a.s
#ld: -shared -z nocombreloc
#readelf: -d
#target: aarch64-*-*
#failif
#...
.*\(TEXTREL\).*
#...

View File

@ -0,0 +1,5 @@
.type foo, %gnu_indirect_function
.globl foo
foo:
ret
.size foo, .-foo

View File

@ -0,0 +1,10 @@
#source: ifunc-14a.s
#source: ifunc-14b.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
#failif
#...
.* +R_AARCH64_NONE +.*
#...

View File

@ -0,0 +1,7 @@
.text
.globl xxx
.type xxx, @function
xxx:
bl foo
.size xxx, .-xxx
.hidden foo

View File

@ -0,0 +1,10 @@
#source: ifunc-14b.s
#source: ifunc-14a.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
#failif
#...
.* +R_AARCH64_NONE +.*
#...

View File

@ -0,0 +1,11 @@
#source: ifunc-14a.s
#source: ifunc-14c.s
#source: ifunc-14b.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
#failif
#...
.* +R_AARCH64_NONE +.*
#...

View File

@ -0,0 +1,11 @@
#source: ifunc-14a.s
#source: ifunc-14b.s
#source: ifunc-14c.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
#failif
#...
.* +R_AARCH64_NONE +.*
#...

View File

@ -0,0 +1,12 @@
#source: ifunc-15.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.got' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_GLOB_DAT[ ]+ifunc\(\)[ ]+ifunc \+ 0
Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0

View File

@ -0,0 +1,11 @@
.text
.type foo, @function
.global foo
foo:
adrp x0, :got:ifunc
ldr x0, [x0, #:got_lo12:ifunc]
ret
.type ifunc, @gnu_indirect_function
.globl ifunc
ifunc:
ret

View File

@ -0,0 +1,9 @@
#source: ifunc-16.s
#ld: -shared
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+0+[ ]+ifunc \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,17 @@
.text
.globl fct
.type fct, @gnu_indirect_function
.set fct,resolve
.hidden int_fct
.globl int_fct
.set int_fct,fct
.p2align 4,,15
.type resolve, @function
resolve:
bl ifunc
.size resolve, .-resolve
.globl g
.type g, @function
g:
bl int_fct
.size g, .-g

View File

@ -0,0 +1,9 @@
#source: ifunc-17a.s
#source: ifunc-17b.s
#ld: -static
#readelf: -s --wide
#target: aarch64-*-*
#...
+[0-9]+: +[0-9a-f]+ +4 +OBJECT +GLOBAL +DEFAULT +[1-9] foo
#pass

View File

@ -0,0 +1,11 @@
.globl main
.globl start
.globl _start
.globl __start
.text
main:
start:
_start:
__start:
.byte 0
.common foo,4,4

View File

@ -0,0 +1,9 @@
#source: ifunc-17b.s
#source: ifunc-17a.s
#ld: -static
#readelf: -s --wide
#target: aarch64-*-*
#...
+[0-9]+: +[0-9a-f]+ +4 +OBJECT +GLOBAL +DEFAULT +[1-9] foo
#pass

View File

@ -0,0 +1,6 @@
.weak foo
.type foo, %gnu_indirect_function
.size foo,1
.text
foo:
.byte 1

View File

@ -0,0 +1,14 @@
#source: ifunc-18a.s
#source: ifunc-18b.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.ifunc' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,5 @@
.section .data.rel,"aw",@progbits
.globl foo_ptrt
.type foo_ptr, @object
foo_ptr:
.dc.a foo

View File

@ -0,0 +1,14 @@
#source: ifunc-18b.s
#source: ifunc-18a.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.ifunc' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,15 @@
.text
.type foo, %gnu_indirect_function
.hidden foo
.globl foo
foo:
ret
.size foo, .-foo
.globl bar
bar:
bl foo1
ret
.size bar, .-bar
.hidden foo1
.globl foo1
foo1 = foo

View File

@ -0,0 +1,13 @@
#source: ifunc-19a.s
#source: ifunc-19b.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.ifunc' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,5 @@
.section .data.rel,"aw",@progbits
.globl foo_ptrt
.type foo_ptr, @object
foo_ptr:
.dc.a foo1

View File

@ -0,0 +1,13 @@
#source: ifunc-19b.s
#source: ifunc-19a.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.ifunc' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,15 @@
.text
.type foo, %gnu_indirect_function
.hidden foo
.globl foo
foo:
ret
.size foo, .-foo
.globl bar
bar:
bl foo1
ret
.size bar, .-bar
.hidden foo1
.globl foo1
foo1 = foo

View File

@ -0,0 +1,9 @@
#ld: -shared
#objdump: -dw
#target: aarch64-*-*
#...
[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2c0@plt>
[ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+x0, 0 <_GLOBAL_OFFSET_TABLE_>
[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+x0, x0, #0x2b0
#pass

View File

@ -0,0 +1,18 @@
.type foo, %gnu_indirect_function
.global __GI_foo
.hidden __GI_foo
.set __GI_foo, foo
.text
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.globl bar
.type bar, @function
bar:
bl __GI_foo
adrp x0, __GI_foo
add x0, x0, :lo12:__GI_foo
ret
.size bar, .-bar

View File

@ -0,0 +1,9 @@
#ld: -shared
#objdump: -dw
#target: aarch64-*-*
#...
[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2c0@plt>
[ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+x0, 0 <_GLOBAL_OFFSET_TABLE_>
[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+x0, x0, #0x2b0
#pass

View File

@ -0,0 +1,18 @@
.type foo, %gnu_indirect_function
.global __GI_foo
.hidden __GI_foo
.set __GI_foo, foo
.text
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.globl bar
.type bar, @function
bar:
bl __GI_foo
adrp x0, __GI_foo
add x0, x0, :lo12:__GI_foo
ret
.size bar, .-bar

View File

@ -0,0 +1,12 @@
#source: ifunc-20.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.ifunc' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_ABS64[ ]+ifunc\(\)[ ]+ifunc \+ 0
Relocation section '.rela.plt' at offset 0x[0-9a-f]+ contains 1 entries:
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+ifunc\(\)[ ]+ifunc \+ 0

View File

@ -0,0 +1,16 @@
.section .data.rel,"aw",@progbits
.globl ifunc_ptrt
.type ifunc_ptr, @object
ifunc_ptr:
.dc.a ifunc
.text
.type ifunc, @gnu_indirect_function
.globl ifunc
ifunc:
ret
.size ifunc, .-ifunc
.type bar, @function
.globl bar
bar:
bl ifunc
.size bar, .-bar

View File

@ -0,0 +1,16 @@
.type foo, %gnu_indirect_function
.global __GI_foo
.protected __GI_foo
.set __GI_foo, foo
.text
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.globl bar
.type bar, @function
bar:
bl __GI_foo
ret
.size bar, .-bar

View File

@ -0,0 +1,8 @@
#source: ifunc-3.s
#ld: -shared
#objdump: -dw
#target: aarch64-*-*
#...
[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x2e0@plt>
#pass

View File

@ -0,0 +1,8 @@
#source: ifunc-3.s
#ld: -shared
#readelf: -r --wide
#target: aarch64-*-*
#...
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_[_0-9A-Z]+_IRELATIVE[ ]*[0-9a-f]*
#pass

View File

@ -0,0 +1,7 @@
#ld:
#readelf: -r --wide
#target: aarch64-*-*
#...
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_[_0-9A-Z]+_IRELATIVE[ ]*[0-9a-f]*
#pass

View File

@ -0,0 +1,18 @@
.text
.type foo, %gnu_indirect_function
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.type start,"function"
.global start
start:
.type _start,"function"
.global _start
_start:
.type __start,"function"
.global __start
__start:
.type __start,"function"
bl foo

View File

@ -0,0 +1,8 @@
#ld: -s
#readelf: -r --wide
#target: aarch64-*-*
#source: ifunc-4.s
#...
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_[_0-9A-Z]+_IRELATIVE[ ]*[0-9a-f]*
#pass

View File

@ -0,0 +1,19 @@
.text
.type foo, %gnu_indirect_function
.type foo, @function
foo:
ret
.size foo, .-foo
.type start,"function"
.global start
start:
.type _start,"function"
.global _start
_start:
.type __start,"function"
.global __start
__start:
.type __start,"function"
bl foo
adrp x0, :got:foo
ldr x0, [x0, #:got_lo12:foo]

View File

@ -0,0 +1,20 @@
.text
.type foo, %gnu_indirect_function
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.type start,"function"
.global start
start:
.type _start,"function"
.global _start
_start:
.type __start,"function"
.global __start
__start:
.type __start,"function"
bl foo
adrp x0, :got:foo
ldr x0, [x0, #:got_lo12:foo]

View File

@ -0,0 +1,8 @@
#source: ifunc-5-local.s
#ld:
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,8 @@
#source: ifunc-5.s
#ld:
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,8 @@
#source: ifunc-5-local.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,12 @@
#source: ifunc-5.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.got' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_GLOB_DAT[ ]+foo\(\)[ ]+foo \+ 0
#...
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_JUMP_SLOT[ ]+foo\(\)[ ]+foo \+ 0

View File

@ -0,0 +1,10 @@
#source: ifunc-5-local.s
#ld: -r
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.text' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_CALL26[ ]+foo\(\)[ ]+foo \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_ADR_GOT_PAGE[ ]+foo\(\)[ ]+foo \+ 0
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_LD64_GOT_LO1[ ]+foo\(\)[ ]+foo \+ 0

View File

@ -0,0 +1,21 @@
.text
.type foo, %gnu_indirect_function
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.protected foo
.type start,"function"
.global start
start:
.type _start,"function"
.global _start
_start:
.type __start,"function"
.global __start
__start:
.type __start,"function"
bl foo
adrp x0, :got:foo
ldr x0, [x0, #:got_lo12:foo]

View File

@ -0,0 +1,8 @@
#source: ifunc-6.s
#ld:
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,12 @@
#source: ifunc-6.s
#ld: -shared -z nocombreloc
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.got' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_GLOB_DAT[ ]+foo\(\)[ ]+foo \+ 0
#...
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,21 @@
.text
.type foo, %gnu_indirect_function
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.hidden foo
.type start,"function"
.global start
start:
.type _start,"function"
.global _start
_start:
.type __start,"function"
.global __start
__start:
.type __start,"function"
bl foo
adrp x0, :got:foo
ldr x0, [x0, #:got_lo12:foo]

View File

@ -0,0 +1,8 @@
#source: ifunc-7.s
#ld:
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,8 @@
#source: ifunc-7.s
#ld: -shared
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,9 @@
#source: ifunc-8a.s
#source: ifunc-8b.s
#ld:
#readelf: -r --wide
#target: aarch64-*-*
Relocation section '.rela.plt' at .*
[ ]+Offset[ ]+Info[ ]+Type[ ]+.*
[0-9a-f]+[ ]+[0-9a-f]+[ ]+R_AARCH64_IRELATIVE[ ]+[0-9a-f]*

View File

@ -0,0 +1,13 @@
.text
.type start,"function"
.global start
start:
.type _start,"function"
.global _start
_start:
.type __start,"function"
.global __start
__start:
.type __start,"function"
adrp x0, :got:foo
ldr x0, [x0, #:got_lo12:foo]

View File

@ -0,0 +1,7 @@
.text
.type foo, %gnu_indirect_function
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo

View File

@ -0,0 +1,3 @@
#ld: --export-dynamic
#error: .*dynamic STT_GNU_IFUNC symbol `foo' with pointer equality in `.*.o' can not be used when making an executable; recompile with -fPIE and relink with -pie
#target: aarch64-*-*

View File

@ -0,0 +1,23 @@
.text
.type foo, %gnu_indirect_function
.globl foo
.type foo, @function
foo:
ret
.size foo, .-foo
.type start,"function"
.global start
start:
.type _start,"function"
.global _start
_start:
.type __start,"function"
.global __start
__start:
.type __start,"function"
adrp x0, .LANCHOR0
add x0, x0, :lo12:.LANCHOR0
.data
.align 3
.LANCHOR0 = . + 0
.xword foo

View File

@ -24,10 +24,11 @@
# IFUNC support has only been implemented for the ix86, x86_64, powerpc,
# and sparc so far.
# aarch64 and sparc so far.
if {!(([istarget "i?86-*-*"]
|| [istarget "x86_64-*-*"]
|| [istarget "powerpc*-*-*"]
|| [istarget "aarch64-*-*"]
|| [istarget "sparc*-*-*"])
&& ([istarget "*-*-elf*"]
|| [istarget "*-*-nacl*"]