1) Enable having a CAPINIT relocation against an IFUNC.
We update the `final_link_relocate` switch case around IFUNC's to
also handle CAPINIT relocations. The handling of CAPINIT relocations
is slightly different than for AARCH64_NN (i.e. ABS64) relocations
since we generally need to emit a dynamic relocation.
Handling this relocation also needs to manage the PDE case when a
hard-coded address has been put into code to satisfy something like
an `adrp`. In these cases the canonical address of the IFUNC becomes
its PLT stub rather than the result of the resolver. We then need to
use a RELATIVE relocation rather than an IRELATIVE one.
N.b. unlike the ABS64 relocation, since a CAPINIT will always emit a
dynamic relocation we do not require pointer equality adjustments on
a symbol from having seen a CAPINIT. That means we do not need to
request that the PLT stub of an IFUNC is treated as the canonical
address just from having seen a CAPINIT relocation.
A CAPINIT relocation against an IFUNC needs to be recorded internally
so that _bfd_elf_allocate_ifunc_dyn_relocs does not garbage collect
the PLT stub and associated IRELATIVE relocation.
See changes in the CAPINIT case of the IFUNC switch of
elfNN_aarch64_final_link_relocate, and in the CAPINIT case of
elfNN_aarch64_check_relocs.
2) Ensure that GOT relocations against an IFUNC have their fragment
populated with the LSB set.
For GOT relocations against a capability IFUNC we need to introduce a
relocation for the runtime to provide us with a valid capability.
See changes in the GOT cases of the IFUNC switch of
elfNN_aarch64_final_link_relocate, changes in the
elfNN_aarch64_allocate_ifunc_dynrelocs function, and changes around
handling an IFUNC GOT entry in elfNN_aarch64_finish_dynamic_symbol.
3) Ensure that mapping symbols are emitted for the .iplt. Without this
many of the testcases here are disassembled incorrectly.
See changes in elfNN_aarch64_output_arch_local_syms.
4) IRELATIVE relocations are against symbols which are not in the
dynamic symbol table, hence they need their fragment populated to
inform the dynamic linker the bounds and permissions to call the
associated resolver with.
See part of the CAPINIT IFUNC handling in
elfNN_aarch64_final_link_relocate, and the IRELATIVE handling in
elfNN_aarch64_create_small_pltn_entry.
5) Disallow an ABS64 relocation against a purecap IFUNC. Such a
relocation is expecting a 64-bit value but the function will return a
capability. Some handling could be implemented by some communication
method to the dynamic linker that this particular value should be
64-bit (maybe by emitting an AARCH64_IRELATIVE relocation rather than
a MORELLO_IRELATIVE one), but as yet GCC doesn't generate such a
relocation and we believe it's unlikely to be needed.
See new error check in AARCH64_NN clause of
elfNN_aarch64_final_link_relocate.
6) Ensure that for statically linked PDE's, we segregate IRELATIVE and
RELATIVE relocations. IRELATIVE relocs should be in the .rela.iplt
section, while RELATIVE relocs should be in the .rela.dyn section.
Correspondingly all RELATIVE relocations should be between the
__rela_dyn_{start,end} symbols, and all IRELATIVE relocations should
be between the __rela_iplt_{start,end} symbols.
This segregation is made based on dynamic relocation type rather than
static relocation that generates it. The segregation allows the
static libc to more easily handle relocations.
Update testcases accordingly.
We introduce some new testcases, morello-ifunc.s contains uses of an
IFUNC which has been referenced directly in code. When compiling a PDE
this triggers the pointer equality requirement and hence the canonical
address for this symbol becomes the PLT stub rather than the result of
the resolver.
morello-ifunc1.s does not use the IFUNC directly in code so that the
address used everywhere is the result of the resolver.
Both of these have testcases assembled and linked for static,
dynamically linked PDE, and PIE. The testcase without a hard-coded
access also has a testcase for -shared.
morello-ifunc2.s is written to check that a CAPINIT relocation does
indeed stop the garbage collection of an IFUNC's PLT and IRELATIVE
relocation.
morello-ifunc3.s tests that we error on an ABS64 relocation against a
C64 IFUNC.
morello-ifunc-dynlink.s tests that a CAPINIT relocation against an IFUNC
symbol defined in a shared library behaves the same way as one against a
FUNC symbol defined in a shared library.
Implementation note:
When segregating IRELATIVE and RELATIVE relocs the change for
relocations against IFUNC symbols populated in the GOT is
straightforward.
For CAPINIT relocations the change is not as straightforward. The
problem is that on sight of CAPINIT relocations in check_relocs we
immediately allocate space in the srelcaps section. In trying to
satisfy the above we need to know whether we're going to be emitting an
IRELATIVE relocation or RELATIVE one in order to know which section it
should go in. The determining factor between these two kinds of
relocations is whether there is a text relocation to this IFUNC symbol,
since that determines whether we need to make this CAPINIT relocation
a RELATIVE relocation pointing to the PLT stub (in order to satisfy
pointer equality) or an IRELATIVE relocation pointing to the resolver.
Whether such a relocation occurs is recorded against each symbol in the
pointer_equality_needed member. This can only be known after all
relocations have been seen in check_relocs. Hence, when coming across a
CAPINIT relocation in check_relocs we do not in general know whether
this CAPINIT relocation should end up as an IRELATIVE or RELATIVE
relocation.
This patch postpones the decision by recording the number of CAPINIT
relocations against a given symbol in a hash table while going through
check_relocs and allocating the relevant space in the required section
in size_dynamic_sections.
N.b. this is similar in purpose to the dyn_relocs linked list on a
symbol. We do not use that existing member which is on every symbol
since the structure does not allow any indication of what kind of
relocation triggered the need. Moreover the structure is used for
different purposes throughout the linker and disentangling the new
meaning from the existing ones seems overly confusing.
Overall, the decisions about which sections relocations against an IFUNC
should go in are:
CAPINIT relocations:
If this is a static PDE link, and the symbol does not need pointer
equality handling, then this should emit an IRELATIVE relocation and
that should go in the .rela.iplt section.
If this is a PIC link, then this should go in the .rela.ifunc
section (along with all other dynamic relocations against the IFUNC,
as commented in _bfd_elf_allocate_ifunc_dyn_relocs).
Otherwise this relocation should go in the srelcaps section (which
goes in .rela.dyn).
GOT relocations:
If this is a static PDE link, and the symbol does not need pointer
equality, then this should emit an IRELATIVE relocation into the
.rela.iplt section.
If this is a static PDE link, then this should emit a RELATIVE
relocation and that should go in the srelcaps section (which is in
.rela.dyn).
Otherwise this should go in .rela.got section.
bfd_boolean populated;
};
+struct elf_c64_ifunc_capinit_record
+{
+ struct elf_link_hash_entry *h;
+ /* Number of CAPINIT relocations this hash entry has against it. */
+ unsigned long count;
+};
+
/* Used to build a map of a section. This is required for mixed-endian
code/data. */
void **c64_sec_info;
unsigned min_output_section_id;
unsigned max_output_section_id;
+
+ /* Used for CAPINIT relocations on a STT_GNU_IFUNC symbols in a static PDE.
+ * */
+ htab_t c64_ifunc_capinit_hash_table;
+ void * c64_ifunc_capinit_memory;
};
/* Create an entry in an AArch64 ELF linker hash table. */
return (struct elf_c64_tls_data_stub_hash_entry *)ret;
}
+static hashval_t
+c64_ifunc_capinit_hash (const void *ptr)
+{
+ struct elf_c64_ifunc_capinit_record *entry
+ = (struct elf_c64_ifunc_capinit_record *) ptr;
+ return htab_hash_pointer (entry->h);
+}
+
+static int
+c64_ifunc_capinit_eq (const void *ptr1, const void *ptr2)
+{
+ struct elf_c64_ifunc_capinit_record *entry1
+ = (struct elf_c64_ifunc_capinit_record *) ptr1;
+ struct elf_c64_ifunc_capinit_record *entry2
+ = (struct elf_c64_ifunc_capinit_record *) ptr2;
+
+ return entry1->h == entry2->h;
+}
+
+static bfd_boolean
+c64_record_ifunc_capinit (struct elf_aarch64_link_hash_table *htab,
+ struct elf_link_hash_entry *h)
+{
+ BFD_ASSERT (h && h->type == STT_GNU_IFUNC);
+ struct elf_c64_ifunc_capinit_record e, *new_entry;
+ e.h = h;
+ void **slot = htab_find_slot (htab->c64_ifunc_capinit_hash_table, &e,
+ INSERT);
+ if (!slot)
+ return FALSE;
+ if (*slot)
+ {
+ ((struct elf_c64_ifunc_capinit_record *)*slot)->count += 1;
+ return TRUE;
+ }
+
+ new_entry = (struct elf_c64_ifunc_capinit_record *)
+ objalloc_alloc ((struct objalloc *) htab->c64_ifunc_capinit_memory,
+ sizeof (struct elf_c64_ifunc_capinit_record));
+ if (new_entry)
+ {
+ new_entry->h = h;
+ new_entry->count = 1;
+ *slot = new_entry;
+ return TRUE;
+ }
+ return FALSE;
+}
+
/* 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
if (ret->tls_data_stub_memory)
objalloc_free ((struct objalloc *) ret->tls_data_stub_memory);
+ if (ret->c64_ifunc_capinit_hash_table)
+ htab_delete (ret->c64_ifunc_capinit_hash_table);
+ if (ret->c64_ifunc_capinit_memory)
+ objalloc_free ((struct objalloc *) ret->c64_ifunc_capinit_memory);
+
bfd_hash_table_free (&ret->stub_hash_table);
_bfd_elf_link_hash_table_free (obfd);
}
return NULL;
}
+ ret->c64_ifunc_capinit_hash_table
+ = htab_try_create (256, c64_ifunc_capinit_hash, c64_ifunc_capinit_eq,
+ NULL);
+ ret->c64_ifunc_capinit_memory = objalloc_create ();
+ if (!ret->c64_ifunc_capinit_hash_table || !ret->c64_ifunc_capinit_memory)
+ {
+ elfNN_aarch64_link_hash_table_free (abfd);
+ return NULL;
+ }
+
ret->loc_hash_table = htab_try_create (1024,
elfNN_aarch64_local_htab_hash,
elfNN_aarch64_local_htab_eq,
return FALSE;
}
+static bfd_boolean
+c64_ifunc_reloc_static_irelative (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ return (static_pde (info) && !h->pointer_equality_needed);
+}
+
+static asection *
+c64_ifunc_got_reloc_section (struct bfd_link_info *info,
+ struct elf_link_hash_entry *h)
+{
+ struct elf_aarch64_link_hash_table *htab;
+ htab = elf_aarch64_hash_table (info);
+ if (c64_ifunc_reloc_static_irelative (info, h))
+ return htab->root.irelplt;
+ if (static_pde (info))
+ return htab->srelcaps;
+ return htab->root.srelgot;
+}
+
/* Perform a relocation as part of a final link. The input relocation type
should be TLS relaxed. */
bfd_set_error (bfd_error_bad_value);
return bfd_reloc_notsupported;
+ case BFD_RELOC_MORELLO_CAPINIT:
case BFD_RELOC_AARCH64_NN:
if (rel->r_addend != 0)
{
return bfd_reloc_notsupported;
}
- /* Generate dynamic relocation only when there is a
- non-GOT reference in a shared object. */
- if (bfd_link_pic (info) && h->non_got_ref)
+ /* N.b. Having an AARCH64_NN relocation (i.e. an ABS64
+ relocation) against a capability ifunc is not yet defined. */
+ if (globals->c64_rel && bfd_r_type == BFD_RELOC_AARCH64_NN)
+ {
+ 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 (_("%pB: relocation %s against a C64 "
+ "STT_GNU_IFUNC symbol `%s'"),
+ input_bfd, howto->name, name);
+ bfd_set_error (bfd_error_bad_value);
+ return bfd_reloc_notsupported;
+ }
+
+ /* Generate dynamic relocation for AArch64 only when there is a
+ non-GOT reference in a shared object.
+ Need a dynamic relocation for a CAPINIT whenever
+ c64_needs_relocation. */
+ if ((bfd_link_pic (info) && h->non_got_ref)
+ || (bfd_r_type == BFD_RELOC_MORELLO_CAPINIT
+ && c64_needs_relocation (info, h)))
{
Elf_Internal_Rela outrel;
asection *sreloc;
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
+
if (h->dynindx == -1
|| h->forced_local
|| bfd_link_executable (info))
{
- /* This symbol is resolved locally. */
- outrel.r_info = (globals->c64_rel
- ? ELFNN_R_INFO (0, MORELLO_R (IRELATIVE))
- : ELFNN_R_INFO (0, AARCH64_R (IRELATIVE)));
- outrel.r_addend = (h->root.u.def.value
- + h->root.u.def.section->output_section->vma
- + h->root.u.def.section->output_offset);
+ /* This symbol is resolved locally.
+ N.b. a MORELLO_IRELATIVE relocation is not suitable for
+ populating an 8-byte value. We don't handle ABS64
+ relocations against a capability IFUNC. */
+ bfd_vma resolver_loc = (h->root.u.def.value
+ + h->root.u.def.section->output_section->vma
+ + h->root.u.def.section->output_offset);
+
+ if (bfd_r_type == BFD_RELOC_MORELLO_CAPINIT)
+ {
+ bfd_vma frag_value = 0, value_tmp;
+ if (h->pointer_equality_needed && !bfd_link_pic (info))
+ {
+ outrel.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE));
+ /* Use the PLT as the canonical address. */
+ value_tmp = value;
+ }
+ else
+ {
+ outrel.r_info = ELFNN_R_INFO (0, MORELLO_R (IRELATIVE));
+ value_tmp = resolver_loc;
+ }
+ BFD_ASSERT (c64_symbol_adjust (h, value_tmp, sym_sec, info,
+ &frag_value));
+ outrel.r_addend
+ = (value_tmp | h->target_internal) - frag_value;
+ /* Can feel safe asserting things here since we've
+ created all of the values. I.e. nothing is coming
+ from the user and hence we don't need gracious error
+ handling. */
+ BFD_ASSERT (_bfd_aarch64_elf_put_addend (input_bfd,
+ hit_data,
+ bfd_r_type,
+ howto, frag_value)
+ == bfd_reloc_ok);
+ BFD_ASSERT (c64_fixup_frag (input_bfd, info, bfd_r_type,
+ sym, h, sym_sec,
+ input_section, hit_data + 8,
+ value_tmp, 0, rel->r_offset)
+ == bfd_reloc_continue);
+ }
+ else
+ {
+ outrel.r_info = ELFNN_R_INFO (0, AARCH64_R (IRELATIVE));
+ outrel.r_addend = resolver_loc;
+ }
}
else
{
outrel.r_addend = 0;
}
- sreloc = globals->root.irelifunc;
- elf_append_rela (output_bfd, sreloc, &outrel);
+ if (c64_ifunc_reloc_static_irelative (info, h))
+ {
+ /* In the same way as TLS descriptor PLT stubs, we want
+ IRELATIVE relocations coming from CAPINIT relocations to
+ be after all the relocations for PLT stub entries. */
+ BFD_ASSERT (bfd_r_type == BFD_RELOC_MORELLO_CAPINIT);
+ sreloc = globals->root.irelplt;
+ bfd_byte *loc = sreloc->contents
+ + sreloc->reloc_count++ * RELOC_SIZE (globals);
+ bfd_elfNN_swap_reloca_out (output_bfd, &outrel, loc);
+ }
+ else if (bfd_link_pic (info))
+ elf_append_rela (output_bfd, globals->root.irelifunc, &outrel);
+ else
+ elf_append_rela (output_bfd, globals->srelcaps, &outrel);
/* If this reloc is against an external symbol, we
do not want to fiddle with the addend. Otherwise,
if (base_got == NULL)
abort ();
+ value |= h->target_internal;
if (off == (bfd_vma) -1)
{
bfd_vma plt_index;
h->ref_regular = 1;
h->forced_local = 1;
h->root.type = bfd_link_hash_defined;
+ h->target_internal = isym->st_target_internal;
}
else
h = NULL;
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G0_NC:
case BFD_RELOC_AARCH64_MOVW_GOTOFF_G1:
case BFD_RELOC_AARCH64_NN:
+ case BFD_RELOC_MORELLO_CAPINIT:
if (htab->root.dynobj == NULL)
htab->root.dynobj = abfd;
if (!_bfd_elf_create_ifunc_sections (htab->root.dynobj, info))
/* If this symbol does not need a relocation, then there's no
reason to increase the srelcaps size for a relocation. */
break;
+ /* Always create srelcaps, even if there's the possibility that this
+ relocation will not end up in srelcaps (i.e. in the special case
+ that our CAPINIT relocation will end up as an IRELATIVE relocation
+ in .rela.iplt for static PDE). If we don't actually put anything
+ into this section it will be empty and won't appear in the output
+ (similar to how we use `_bfd_elf_create_ifunc_sections` above).
+ */
if (htab->srelcaps == NULL)
{
if (htab->root.dynobj == NULL)
htab->srelcaps = sreloc;
}
+
+ /* Mark any IFUNC symbol as requiring a PLT.
+ We do not want to use dyn_relocs since generic code ignores this
+ when not linking PIC but we need the dynamic relocation for
+ capabilities.
+ We would not benefit from using dyn_relocs since a CAPINIT
+ relocation will never be reduced to a hand-coded value and hence
+ can't be garbage collected (even if it may turn from a CAPINIT to
+ an IRELATIVE).
+ However, without dyn_relocs or a greater than zero plt.refcount,
+ _bfd_elf_allocate_ifunc_dyn_relocs would garbage collect the PLT
+ entry for this symbol believing that it is not used. */
+ if (h && h->type == STT_GNU_IFUNC)
+ {
+ h->needs_plt = 1;
+ h->plt.refcount = h->plt.refcount < 0
+ ? 1 : h->plt.refcount + 1;
+ /* The only time that a CAPINIT relocation should not trigger
+ some dynamic relocation in the srelcaps section of the output
+ binary is when the relocation is against an STT_GNU_IFUNC in
+ a static PDE. In this case we need to emit the relocations in
+ the .rela.iplt section. */
+ if (static_pde (info))
+ {
+ /* As yet we do not know whether this symbol needs pointer
+ equality or not. This means that we don't know which
+ symbols (either __rela_dyn_{start,end} or
+ __rela_iplt_{start,end}) we need to put this relocation
+ between.
+
+ This problem does not exist outside of a static_pde since
+ there the runtime reads all relocs rather than relying on
+ symbols to point to where relocations are. */
+ BFD_ASSERT (c64_record_ifunc_capinit (htab, h));
+ break;
+ }
+ else if (bfd_link_pic (info))
+ {
+ htab->root.irelifunc->size += RELOC_SIZE (htab);
+ break;
+ }
+ /* Otherwise put into the srelcaps section. */
+ }
htab->srelcaps->size += RELOC_SIZE (htab);
break;
}
/* Finally, output mapping symbols for the PLT. */
- if (!htab->root.splt || htab->root.splt->size == 0)
+ if ((!htab->root.splt || htab->root.splt->size == 0)
+ && (!htab->root.iplt || htab->root.iplt->size == 0))
return TRUE;
- osi.sec_shndx = _bfd_elf_section_from_bfd_section
- (output_bfd, htab->root.splt->output_section);
- osi.sec = htab->root.splt;
+ if (htab->root.splt && htab->root.splt->size != 0)
+ {
+ osi.sec_shndx = _bfd_elf_section_from_bfd_section
+ (output_bfd, htab->root.splt->output_section);
+ osi.sec = htab->root.splt;
+ }
+ else
+ {
+ osi.sec_shndx = _bfd_elf_section_from_bfd_section
+ (output_bfd, htab->root.iplt->output_section);
+ osi.sec = htab->root.iplt;
+ }
elfNN_aarch64_output_map_sym (&osi, (htab->c64_rel ? AARCH64_MAP_C64
: AARCH64_MAP_INSN), 0);
entries are placed by computing their PLT index (0
.. reloc_count). While other none PLT relocs are placed
at the slot indicated by reloc_count and reloc_count is
- updated. */
+ updated.
+ For reference, a similar abuse of the reloc_count is done for the
+ irelplt section for Morello CAPINIT relocations. */
htab->root.srelplt->reloc_count++;
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,
- &h->dyn_relocs,
- htab->plt_entry_size,
- htab->plt_header_size,
- GOT_ENTRY_SIZE (htab),
- FALSE);
+ {
+ bfd_boolean ret
+ = _bfd_elf_allocate_ifunc_dyn_relocs (info, h, &h->dyn_relocs,
+ htab->plt_entry_size,
+ htab->plt_header_size,
+ GOT_ENTRY_SIZE (htab), FALSE);
+ if (htab->c64_rel
+ && ret
+ && h->got.offset != (bfd_vma)-1
+ && !UNDEFWEAK_NO_DYNAMIC_RELOC (info, h)
+ && !bfd_link_pic (info)
+ && !bfd_link_relocatable (info))
+ /* got.offset is not -1 which indicates we have an entry in the got.
+ For non-capabilities we would manually populate the GOT with the
+ known location of the PLT in finish_dynamic_symbol, since this is a
+ non-PIC executable. For capabilities we need to emit a relocation
+ to populate that entry. */
+ {
+ asection *reloc_sec = c64_ifunc_got_reloc_section (info, h);
+ reloc_sec->size += RELOC_SIZE (htab);
+ }
+ return ret;
+ }
return TRUE;
}
return elfNN_aarch64_allocate_ifunc_dynrelocs (h, inf);
}
+/* Allocate space for CAPINIT relocations against IFUNC symbols in a static
+ PDE. This case is special since the IRELATIVE relocations and RELATIVE
+ relocations need to be placed in different sections, and the decision about
+ whether we need to emit an IRELATIVE or RELATIVE relocation is dependent on
+ whether there are *other* relocations. */
+static bfd_boolean
+c64_allocate_ifunc_capinit_static_relocs (void **slot, void *inf)
+{
+ struct elf_link_hash_entry *h;
+ struct elf_c64_ifunc_capinit_record *rec
+ = (struct elf_c64_ifunc_capinit_record *) *slot;
+ h = rec->h;
+
+ if (h->type != STT_GNU_IFUNC
+ || !h->def_regular
+ || !h->ref_regular
+ || h->root.type != bfd_link_hash_defined)
+ abort ();
+
+ struct bfd_link_info *info = (struct bfd_link_info *) inf;
+ struct elf_aarch64_link_hash_table *htab = elf_aarch64_hash_table (info);
+ if (c64_ifunc_reloc_static_irelative (info, h))
+ htab->root.irelplt->size += rec->count * RELOC_SIZE (htab);
+ else
+ htab->srelcaps->size += rec->count * RELOC_SIZE (htab);
+ return TRUE;
+}
+
/* This is the most important function of all . Innocuosly named
though ! */
elfNN_aarch64_allocate_local_ifunc_dynrelocs,
info);
+ if (static_pde (info))
+ {
+ htab_traverse (htab->c64_ifunc_capinit_hash_table,
+ c64_allocate_ifunc_capinit_static_relocs,
+ info);
+ htab_empty (htab->c64_ifunc_capinit_hash_table);
+ }
+
if (static_pde (info)
&& htab->srelcaps
&& htab->srelcaps->size > 0)
/* We use the reloc_count field as a counter if we need
to copy relocs into the output file. */
- if (s != htab->root.srelplt)
+ if (s != htab->root.srelplt
+ && s != htab->root.irelplt)
s->reloc_count = 0;
}
else
{
/* If an STT_GNU_IFUNC symbol is locally defined, generate
R_AARCH64_IRELATIVE instead of R_AARCH64_JUMP_SLOT. */
- rela.r_info = (htab->c64_rel
- ? ELFNN_R_INFO (0, MORELLO_R (IRELATIVE))
- : ELFNN_R_INFO (0, AARCH64_R (IRELATIVE)));
rela.r_addend = (h->root.u.def.value
+ h->root.u.def.section->output_section->vma
+ h->root.u.def.section->output_offset);
+ if (htab->c64_rel)
+ {
+ /* A MORELLO_IRELATIVE relocation is the only kind of relocation that
+ wants something other than PLT0 in the fragment. It requires the
+ PCC base with associated permissions and size information. */
+ bfd_vma frag_value = 0;
+ bfd_vma orig_value = rela.r_addend;
+ rela.r_info = ELFNN_R_INFO (0, MORELLO_R (IRELATIVE));
+ BFD_ASSERT (c64_symbol_adjust (h, orig_value, plt, info,
+ &frag_value));
+ rela.r_addend = (orig_value | 1) - frag_value;
+ bfd_put_NN (output_bfd, frag_value, gotplt->contents + got_offset);
+ BFD_ASSERT (c64_fixup_frag (output_bfd, info,
+ BFD_RELOC_MORELLO_CAPINIT,
+ NULL, h, plt, gotplt,
+ gotplt->contents + got_offset + 8,
+ orig_value, 0, rela.r_offset)
+ == bfd_reloc_continue);
+ }
+ else
+ {
+ rela.r_info = ELFNN_R_INFO (0, AARCH64_R (IRELATIVE));
+ }
}
else
{
contains the real function address if we need pointer
equality. We load the GOT entry with the PLT entry. */
plt = htab->root.splt ? htab->root.splt : htab->root.iplt;
- bfd_put_NN (output_bfd, (plt->output_section->vma
- + plt->output_offset
- + h->plt.offset),
- htab->root.sgot->contents
- + (h->got.offset & ~(bfd_vma) 1));
+
+ bfd_vma value = (plt->output_section->vma + plt->output_offset
+ + h->plt.offset);
+ bfd_vma got_offset = h->got.offset & ~(bfd_vma)1;
+ if (htab->c64_rel)
+ {
+ bfd_vma base_value = 0;
+ BFD_ASSERT (c64_symbol_adjust (h, value, plt, info,
+ &base_value));
+ rela.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE));
+ rela.r_addend = (value | h->target_internal) - base_value;
+ asection *s = c64_ifunc_got_reloc_section (info, h);
+ elf_append_rela (output_bfd, s, &rela);
+
+ /* N.b. we do not use c64_fixup_frag since in includes a
+ bunch of features we do not use like error checking the
+ size and ensuring figuring out whether we need to extend
+ things depending on the kind of symbol. We know these due
+ to the fact this is a STT_GNU_IFUNC symbol.
+ In order to implement those features it requires quite a
+ lot of arguments which we don't happen to have here. */
+ bfd_boolean guessed = FALSE;
+ bfd_vma meta = cap_meta (pcc_high - pcc_low, plt, &guessed);
+ BFD_ASSERT (!guessed);
+ bfd_put_NN (output_bfd, meta,
+ htab->root.sgot->contents + got_offset + 8);
+ value = base_value;
+ }
+
+ bfd_put_NN (output_bfd, value,
+ htab->root.sgot->contents + got_offset);
return TRUE;
}
}
# Return the 8-hexdigit truncation of an address.
proc aarch64_8digit_addr { addr { plusLSB 0 } } {
if { $plusLSB } {
- return [aarch64_8digit_addr [format %08x [expr "0x$addr + 1"]]];
+ return [format %08x [expr "0x$addr + 1"]];
}
return [format %08x "0x$addr"];
}
run_dump_test_lp64 "morello-dataptr-through-data"
run_dump_test_lp64 "morello-dataptr-through-data-pie"
run_dump_test_lp64 "morello-dataptr-code-and-data"
+ run_dump_test_lp64 "morello-ifunc-a"
+ run_dump_test_lp64 "morello-ifunc1-a"
+}
+run_dump_test_lp64 "morello-ifunc"
+run_dump_test_lp64 "morello-ifunc-b"
+run_dump_test_lp64 "morello-ifunc1"
+run_dump_test_lp64 "morello-ifunc1-b"
+run_dump_test_lp64 "morello-ifunc1-c"
+run_dump_test_lp64 "morello-ifunc2"
+run_dump_test_lp64 "morello-ifunc2-b"
+run_dump_test_lp64 "morello-ifunc3"
+run_dump_test_lp64 "morello-ifunc4"
+run_dump_test_lp64 "morello-ifunc4a"
+
+if { [check_shared_lib_support]
+ && [ld_assemble_flags $as -march=morello+c64 $srcdir/$subdir/morello-ifunc-shared.s tmpdir/morello-ifunc-shared.o]
+ && [ld_link $ld tmpdir/morello-ifunc-shared.so "--shared tmpdir/morello-ifunc-shared.o"] } {
+ run_dump_test_lp64 "morello-ifunc-dynlink"
+ run_dump_test_lp64 "morello-ifunc-dynlink-pie"
}
if { [check_shared_lib_support]
#target: [check_shared_lib_support]
#as: -march=morello+c64 --defsym C64MODE=1
#ld: -shared --hash-style=sysv
-#objdump: -dw
+#objdump: -dw --section-headers
#source: ifunc-2-local.s
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn Flags
+#record: PCC_START
+ 0 \.[^ ]* *[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*[0-9] CONTENTS, ALLOC, LOAD, READONLY, DATA
+#...
+Disassembly of section \.plt:
+
+#record: INDIRECT_LOC FOO_LOCATION
#...
-0+(110|180|1a0|1b8) <__GI_foo>:
+0+([0-9a-f]{3}).*0x([0-9a-f]+)@plt>:
+#...
+Disassembly of section \.text:
+
+#check: FOO_LOC string tolower $FOO_LOCATION
+#check: FOO_ADDR format %016x [expr "0x$PCC_START + 0x$FOO_LOCATION & ~1"]
+#check: INDIRECT_POS format %x [expr "0x$INDIRECT_LOC + 1"]
+FOO_ADDR <__GI_foo>:
#...
-[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0x(110|180|1a0|1b8)@plt>
+[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0xFOO_LOC@plt>
[ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+c0, 0 <.*>
-[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+c0, c0, #0x(101|171|191|1a9)
+[ \t0-9a-f]+:[ \t0-9a-f]+add[ \t]+c0, c0, #0xINDIRECT_POS
#pass
#target: [check_shared_lib_support]
#as: -march=morello+c64 --defsym C64MODE=1
#ld: -shared --hash-style=sysv
-#objdump: -dw
+#objdump: -dw --section-headers
#source: ifunc-2.s
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn Flags
+#record: PCC_START
+ 0 \.[^ ]* *[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*[0-9] CONTENTS, ALLOC, LOAD, READONLY, DATA
+#...
+Disassembly of section \.plt:
+
#record: INDIRECT_LOC FOO_LOCATION
#...
-0+([0-9a-f]{3}).*0x([0-9a-f]{3})@plt>:
+0+([0-9a-f]{3}).*0x([0-9a-f]+)@plt>:
#...
Disassembly of section \.text:
#check: FOO_LOC string tolower $FOO_LOCATION
+#check: FOO_ADDR format %016x [expr "0x$PCC_START + 0x$FOO_LOCATION & ~1"]
#check: INDIRECT_POS format %x [expr "0x$INDIRECT_LOC + 1"]
-0+FOO_LOC <foo>:
+FOO_ADDR <foo>:
#...
[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0xFOO_LOC@plt>
[ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+c0, 0 <.*>
#target: [check_shared_lib_support]
#as: -march=morello+c64
#ld: -shared --hash-style=sysv
-#objdump: -dw
+#objdump: -dw --section-headers
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn Flags
+#record: PCC_START
+ 0 \.[^ ]* *[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*[0-9] CONTENTS, ALLOC, LOAD, READONLY, DATA
+#...
+Disassembly of section \.plt:
+
+#record: INDIRECT_LOC FOO_LOCATION
+#...
+0+([0-9a-f]{3}).*0x([0-9a-f]+)@plt>:
#...
Disassembly of section \.text:
-#record: INDIRECT_FOO
-([0-9a-f]+) <__GI_foo>:
-#check: FOO_POS format %x 0x$INDIRECT_FOO
+#check: FOO_LOC string tolower $FOO_LOCATION
+#check: FOO_ADDR format %016x [expr "0x$PCC_START + 0x$FOO_LOCATION & ~1"]
+#check: INDIRECT_POS string tolower $INDIRECT_LOC
+FOO_ADDR <__GI_foo>:
#...
-[ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0xFOO_POS@plt>
+[ \t0-9a-f]+:[ \t0-9a-f]+bl\tINDIRECT_POS <\*ABS\*\+0xFOO_LOC@plt>
#pass
--- /dev/null
+# Checking that the introduction of a CAPINIT relocation against an IFUNC does
+# not change the behaviour of us requiring pointer equality, and checking that
+# the CAPINIT relocation respects that pointer equality requirement by pointing
+# at the PLT stub.
+#source: morello-ifunc.s
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -DR --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]* +[0-9a-f]* ([0-9a-f]+) .*
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt *([0-9a-f]+) ([0-9a-f]+) .*
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+Disassembly of section \.plt:
+
+#record: PLT0_ADDR
+([0-9a-f]+) <\.plt>:
+#...
+.*nop
+.*nop
+.*nop
+# Note that for a none-linux-gnu target we don't emit a symbol specific to the
+# PLT stub for an IFUNC, but for a none-elf target we do. That means we can't
+# generally check the offset in the symbols name matches the `foo` address
+# below.
+#?
+#?[0-9a-f]+ <\*ABS\*\+0x[0-9a-f]+@plt>:
+#record: PLTADDR PLTGOT_PAGE
+ *([0-9a-f]+): .* adrp c16, ([0-9a-f]+) .*
+#record: FOO_PLTGOT_OFFSET
+ *[0-9a-f]+: .* ldr c17, \[c16, #([0-9]+)\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: c2c21220 br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#record: FOO_ADDR
+([0-9a-f]+) <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .*
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* b .*
+
+[0-9a-f]+ <_start>:
+#check: PLTLOC string tolower $PLTADDR
+#check: PLT_PAGE format %x [expr "0x$PLTADDR & ~0xfff"]
+#check: FOO_PLT_OFF format %x [expr "(0x$PLTADDR & 0xfff) + 1"]
+ *[0-9a-f]+: .* bl PLTLOC .*
+#record: GOT_PAGE
+ *[0-9a-f]+: .* adrp c0, ([0-9a-f]+) .*
+#record: FOO_GOTOFF_DECIMAL
+ *[0-9a-f]+: .* ldr c0, \[c0, #([0-9]+)\]
+ *[0-9a-f]+: .* adrp c0, PLT_PAGE .*
+ *[0-9a-f]+: .* add c0, c0, #0xFOO_PLT_OFF
+ *[0-9a-f]+: .* ret c30
+
+#...
+Disassembly of section \.got:
+
+#check: PLT_ADDEND format %x [expr "0x$PLTADDR - 0x$PCC_START + 1"]
+#check: FRAGBASE format %08x 0x$PCC_START
+#check: FRAGSIZE format %08x [expr "0x$PCC_LAST_SIZE + 0x$PCC_LAST_START - 0x$PCC_START"]
+#check: FRAGMENT_LOC aarch64_page_plus_decimal_offset $GOT_PAGE $FOO_GOTOFF_DECIMAL
+#...
+ *FRAGMENT_LOC: FRAGBASE .*
+ [0-9a-f]+: R_MORELLO_RELATIVE \*ABS\*\+0xPLT_ADDEND
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+
+Disassembly of section \.got\.plt:
+
+#check: PLTGOTLOC aarch64_page_plus_decimal_offset $PLTGOT_PAGE $FOO_PLTGOT_OFFSET
+#check: FOO_OFFSET format %x [expr "0x$FOO_ADDR + 1 - 0x$PCC_START"]
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *PLTGOTLOC: FRAGBASE .*
+ PLTGOTLOC: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+ \.\.\.
+
+Disassembly of section \.data:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: FRAGBASE .*
+ .*: R_MORELLO_RELATIVE \*ABS\*\+0xPLT_ADDEND
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
--- /dev/null
+# Checking that the introduction of a CAPINIT relocation against an IFUNC does
+# not change the behaviour of us requiring pointer equality, and checking that
+# the CAPINIT relocation respects that pointer equality requirement by pointing
+# at the PLT stub.
+#source: morello-ifunc.s
+#as: -march=morello+c64
+#ld: -pie
+#objdump: -DR --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]* +[0-9a-f]* ([0-9a-f]+) .*
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt *([0-9a-f]+) ([0-9a-f]+) .*
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+Disassembly of section \.plt:
+
+#record: PLT0_ADDR
+([0-9a-f]+) <\.plt>:
+#...
+.*nop
+.*nop
+.*nop
+
+#record: RESOLVER_ADDEND
+[0-9a-f]+ <\*ABS\*\+0x([0-9a-f]+)@plt>:
+#record: PLTADDR PLTGOT_PAGE
+ *([0-9a-f]+): .* adrp c16, ([0-9a-f]+) .*
+#record: FOO_PLTGOT_OFFSET
+ *[0-9a-f]+: .* ldr c17, \[c16, #([0-9]+)\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: c2c21220 br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#check: FOO_ADDRESS format %x [expr "0x$PCC_START + 0x$RESOLVER_ADDEND - 1"]
+([0-9a-f]+) <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .*
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* b .*
+
+[0-9a-f]+ <_start>:
+#check: PLTLOC string tolower $PLTADDR
+#check: PLT_PAGE format %x [expr "0x$PLTADDR & ~0xfff"]
+#check: FOO_PLT_OFF format %x [expr "(0x$PLTADDR & 0xfff) + 1"]
+ *[0-9a-f]+: .* bl PLTLOC .*
+#record: GOT_PAGE
+ *[0-9a-f]+: .* adrp c0, ([0-9a-f]+) .*
+#record: FOO_GOTOFF_DECIMAL
+ *[0-9a-f]+: .* ldr c0, \[c0, #([0-9]+)\]
+ *[0-9a-f]+: .* adrp c0, PLT_PAGE .*
+ *[0-9a-f]+: .* add c0, c0, #0xFOO_PLT_OFF
+ *[0-9a-f]+: .* ret c30
+
+#...
+Disassembly of section \.got:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+:.*
+ \.\.\.
+
+Disassembly of section \.got\.plt:
+
+#check: PLT_ADDEND format %x [expr "0x$PLTADDR - 0x$PCC_START + 1"]
+#check: FRAGBASE format %08x 0x$PCC_START
+#check: FRAGSIZE format %08x [expr "0x$PCC_LAST_SIZE + 0x$PCC_LAST_START - 0x$PCC_START"]
+#check: FRAGMENT_LOC aarch64_page_plus_decimal_offset $GOT_PAGE $FOO_GOTOFF_DECIMAL
+#check: PLTGOTLOC aarch64_page_plus_decimal_offset $PLTGOT_PAGE $FOO_PLTGOT_OFFSET
+#check: FOO_OFFSET string tolower $RESOLVER_ADDEND
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *PLTGOTLOC: FRAGBASE .*
+ PLTGOTLOC: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#...
+Disassembly of section \.data:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: FRAGBASE .*
+ .*: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
--- /dev/null
+# Checking that the sharedfoo symbol is a FUNC and UNDEFINED symbol.
+# It should also have 0 as its value (so that we don't make the PLT stub the
+# canonical address).
+# Also checking that there is a CAPINIT relocation against the sharedfoo symbol
+# (i.e. that it has not been relaxed to some other relocation).
+#source: morello-ifunc-dynlink.s
+#as: -march=morello+c64
+#ld: -pie tmpdir/morello-ifunc-shared.so
+#readelf: --relocs --dyn-syms
+
+Relocation section '\.rela\.dyn' at offset 0x.* contains 1 entry:
+ Offset Info Type Sym\. Value Sym\. Name \+ Addend
+[0-9a-f]+ 00030000e800 R_MORELLO_CAPINIT 0000000000000000 sharedfoo \+ 0
+
+#...
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ Num: Value Size Type Bind Vis Ndx Name
+#...
+ +[0-9]+: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sharedfoo
+#pass
--- /dev/null
+# Checking that the sharedfoo symbol is a FUNC and UNDEFINED symbol.
+# It should also have 0 as its value (so that we don't make the PLT stub the
+# canonical address).
+# Also checking that there is a CAPINIT relocation against the sharedfoo symbol
+# (i.e. that it has not been relaxed to some other relocation).
+#source: morello-ifunc-dynlink.s
+#as: -march=morello+c64
+#ld: tmpdir/morello-ifunc-shared.so
+#readelf: --relocs --dyn-syms
+
+Relocation section '\.rela\.dyn' at offset 0x.* contains 1 entry:
+ Offset Info Type Sym\. Value Sym\. Name \+ Addend
+[0-9a-f]+ ............ R_MORELLO_CAPINIT 0000000000000000 sharedfoo \+ 0
+
+#...
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ Num: Value Size Type Bind Vis Ndx Name
+#...
+ +[0-9]+: 0000000000000000 0 FUNC GLOBAL DEFAULT UND sharedfoo
+#pass
--- /dev/null
+ .text
+ .p2align 4,,11
+#APP
+ .type foo, %gnu_indirect_function
+#NO_APP
+ .global foo
+ .type foo, @function
+foo:
+ ret
+ .size foo, .-foo
+
+ .global _start
+ .type _start,%function
+_start:
+ bl sharedfoo
+ ret
+ .size _start, .-_start
+ .data
+ .align 2
+ .type var, %object
+ .size var, 4
+var:
+ .chericap sharedfoo
--- /dev/null
+ .text
+ .p2align 4,,11
+#APP
+ .type sharedfoo, %gnu_indirect_function
+#NO_APP
+ .global sharedfoo
+ .type sharedfoo, @function
+sharedfoo:
+ ret
+ .size sharedfoo, .-sharedfoo
+
+ .global libfunc
+ .type libfunc,%function
+libfunc:
+ bl foo
+ ret
+ .size libfunc, .-libfunc
+ .data
+ .align 2
+ .type var, %object
+ .size var, 4
+var:
+ .chericap foo
--- /dev/null
+# Checking that GOT relocations against a PLT which requires pointer equality
+# use a GOT entry pointing to the PLT stub rather than just using the .got.plt
+# entry.
+#
+# Things we check are:
+# - __rela_dyn_{start,end} are around the RELATIVE relocation against FOO.
+# - That RELATIVE relocation initialises a GOT entry.
+# - The fragment in that GOT entry plus the addend of the RELATIVE
+# relocation total to point to the foo PLT stub.
+# - We emit a PLT stub which accesses a PLTGOT entry.
+#as: -march=morello+c64
+#ld:
+#objdump: -Dr --section-headers --syms
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ \t]* +[0-9a-f]* ([0-9a-f]+) .*
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: LAST_PCC_SEC_SIZE LAST_PCC_SEC_START
+#...
+ *[0-9]+ \.got\.plt *([0-9a-f]+) ([0-9a-f]+) .*
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+SYMBOL TABLE:
+#record: RELA_DYN_END
+#...
+([0-9a-f]+) l O \.rela\.dyn 0000000000000000 __rela_dyn_end
+#record: RELA_DYN_START
+([0-9a-f]+) l O \.rela\.dyn 0000000000000000 __rela_dyn_start
+#...
+Disassembly of section \.rela\.dyn:
+
+#check: RELA_START format %016x 0x$RELA_DYN_START
+RELA_START <__rela_dyn_start>:
+#record: CHERICAP_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e803 .*
+ *[0-9a-f]+: 00000000 .*
+#record: CHERICAP_ADDEND
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+#record: FOO_GOT
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e803 .*
+ *[0-9a-f]+: 00000000 .*
+#check: CHERICAP_ADDEND string tolower $CHERICAP_ADDEND
+ *[0-9a-f]+: CHERICAP_ADDEND .*
+#check: RELA_DYN_LAST format %x [expr "0x$RELA_DYN_END - 0x4"]
+ *RELA_DYN_LAST: 00000000 .*
+
+Disassembly of section \.rela\.plt:
+
+[0-9a-f]+ <.*>:
+#record: PLTGOT_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e804 .*
+ *[0-9a-f]+: 00000000 .*
+#record: PLTGOT_LOC_ADDEND
+ *[0-9a-f]+: ([0-9a-f]+) .*
+#...
+Disassembly of section \.plt:
+
+#check: FOO_PLT format %x [expr "0x$PCC_START + 0x$CHERICAP_ADDEND - 1"]
+#check: PLTGOT_PAGE format %x [expr "0x$PLTGOT_LOC & (~0xfff)"]
+#check: PLTGOT_DEC_OFF expr "0x$PLTGOT_LOC & 0xfff"
+([0-9a-f]+) <\.plt>:
+#...
+ *FOO_PLT: .* adrp c16, PLTGOT_PAGE .*
+ *[0-9a-f]+: .* ldr c17, \[c16, #PLTGOT_DEC_OFF\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: c2c21220 br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+ *[0-9a-f]+: 52800020 mov w0, #0x1 // #1
+ *[0-9a-f]+: c2c253c0 ret c30
+
+[0-9a-f]+ <foo_2>:
+ *[0-9a-f]+: 52800040 mov w0, #0x2 // #2
+ *[0-9a-f]+: c2c253c0 ret c30
+
+#check: RESOLVER_ADDRESS format %016x [expr "0x$PLTGOT_LOC_ADDEND + 0x$PCC_START - 1"]
+RESOLVER_ADDRESS <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .*
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* b .*
+
+#clearcheck:
+#check: FOO_PLT format %x [expr "0x$PCC_START + 0x$CHERICAP_ADDEND - 1"]
+#check: GOT_PAGE format %x [expr "0x$FOO_GOT & ~0xfff"]
+#check: FOO_GOTOFF expr "0x$FOO_GOT & 0xfff"
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: .* bl FOO_PLT .*
+ *[0-9a-f]+: .* adrp c0, GOT_PAGE .*
+ *[0-9a-f]+: .* ldr c0, \[c0, #FOO_GOTOFF\]
+#clearcheck:
+#check: PLT_PAGE format %x [expr "(0x$PCC_START + 0x$CHERICAP_ADDEND) & ~0xfff"]
+#check: FOO_PLT_OFF format %x [expr "(0x$PCC_START + 0x$CHERICAP_ADDEND) & 0xfff"]
+ *[0-9a-f]+: .* adrp c0, PLT_PAGE .*
+ *[0-9a-f]+: .* add c0, c0, #0xFOO_PLT_OFF
+ *[0-9a-f]+: .* ret c30
+
+#...
+Disassembly of section \.got:
+
+#clearcheck:
+#check: FRAGMENT_BASE aarch64_8digit_addr $PCC_START
+#check: FRAGMENT_SIZE format %08x [expr "0x$LAST_PCC_SEC_START + 0x$LAST_PCC_SEC_SIZE - 0x$PCC_START"]
+#check: FRAGMENT_LOC format %x 0x$FOO_GOT
+#...
+ *FRAGMENT_LOC: FRAGMENT_BASE .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGMENT_SIZE .*
+ *[0-9a-f]+: 04000000 .*
+
+Disassembly of section \.got\.plt:
+
+#check: PLTGOTLOC format %x 0x$PLTGOT_LOC
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *PLTGOTLOC: FRAGMENT_BASE .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGMENT_SIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
--- /dev/null
+ .text
+#APP
+ .type foo, %gnu_indirect_function
+#NO_APP
+ .align 2
+ .type foo_1, %function
+foo_1:
+ mov w0, 1
+ ret
+ .size foo_1, .-foo_1
+ .align 2
+ .type foo_2, %function
+foo_2:
+ mov w0, 2
+ ret
+ .size foo_2, .-foo_2
+ .align 2
+
+ .global foo
+ .type foo, %function
+foo:
+ mov x1, 42
+ tst x0, x1
+ bne .L5
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+.L4:
+ ret
+.L5:
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+ b .L4
+ .size foo, .-foo
+ .align 2
+
+ .global _start
+ .type _start, %function
+_start:
+ bl foo
+ adrp c0, :got:foo
+ ldr c0, [c0, #:got_lo12:foo]
+ // Adding direct relocation against `foo` to ensure that we need
+ // pointer equality. This should change the behaviour of the CAPINIT
+ // and GOT relocations.
+ adrp c0, foo
+ add c0, c0, :lo12:foo
+ ret
+ .size _start, .-_start
+
+ .data
+ .align 4
+ .chericap foo
--- /dev/null
+# Checking that when linking as standard, the BL and the GOT access both use
+# the PLT. This link does not do anything special to maintain pointer equality
+# since there is no access which directly uses the address.
+#
+# Things this testcase checks:
+# 1) Fragment of IRELATIVE relocation is PCC_START with bounds and
+# permissions of PCC.
+# 2) GOT access uses IRELATIVE relocation in the PLTGOT when no direct access
+# to address is used.
+# 3) BL to an IFUNC branches to a PLT stub which uses the a PLTGOT slot
+# initialised by an IRELATIVE relocation against our resolver.
+#source: morello-ifunc1.s
+#as: -march=morello+c64
+#ld: -pie
+#objdump: -DR --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]+ +[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt +([0-9a-f]+) ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+Disassembly of section \.plt:
+
+[0-9a-f]+ <\.plt>:
+#...
+.*nop
+.*nop
+.*nop
+# Note that for a none-linux-gnu target we don't emit a symbol specific to the
+# PLT stub for an IFUNC, but for a none-elf target we do. That means we can't
+# generally check the offset in the symbols name matches the `foo` address
+# below.
+#?
+#?[0-9a-f]+ <\*ABS\*\+0x[0-9a-f]+@plt>:
+#record: PLTADDR PLTGOT_PAGE
+ *([0-9a-f]+): .* adrp c16, ([0-9a-f]+) .*
+#record: PLTGOT_DEC_OFF
+ *[0-9a-f]+: .* ldr c17, \[c16, #([0-9]+)\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: .* br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#record: FOO_ADDR
+([0-9a-f]+) <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .* <foo\+0x18> // b\.any
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, .*
+ *[0-9a-f]+: .* b .* <foo\+0x14>
+
+[0-9a-f]+ <_start>:
+#check: PLTLOC string tolower $PLTADDR
+#check: PLTGOTPAGE string tolower $PLTGOT_PAGE
+#check: PLTGOT_DECOFF string tolower $PLTGOT_DEC_OFF
+ *[0-9a-f]+: .* bl PLTLOC .*
+ *[0-9a-f]+: .* adrp c0, PLTGOTPAGE .*
+ *[0-9a-f]+: .* ldr c0, \[c0, #PLTGOT_DECOFF\]
+ *[0-9a-f]+: .* ret c30
+#...
+Disassembly of section \.got\.plt:
+
+#check: GOTLOC aarch64_page_plus_decimal_offset $PLTGOT_PAGE $PLTGOT_DEC_OFF
+#check: FRAGBASE format %08x 0x$PCC_START
+#check: FRAGSIZE format %08x [expr "0x$PCC_LAST_SIZE + 0x$PCC_LAST_START - 0x$PCC_START"]
+#check: FOO_OFFSET format %x [expr "0x$FOO_ADDR + 1 - 0x$PCC_START"]
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *GOTLOC: FRAGBASE .*
+ GOTLOC: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#...
+Disassembly of section \.data:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: FRAGBASE .*
+ [0-9a-f]+: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
--- /dev/null
+# Checking that when linking as standard, the BL and the GOT access both use
+# the PLT. This link does not do anything special to maintain pointer equality
+# since there is no access which directly uses the address.
+#
+# Things this testcase checks:
+# 1) Fragment of IRELATIVE relocation is PCC_START with bounds and
+# permissions of PCC.
+# 2) GOT access uses IRELATIVE relocation in the PLTGOT when no direct access
+# to address is used.
+# 3) BL to an IFUNC branches to a PLT stub which uses the a PLTGOT slot
+# initialised by an IRELATIVE relocation against our resolver.
+#source: morello-ifunc1.s
+#as: -march=morello+c64
+#ld: -pie
+#objdump: -DR --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]+ +[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt +([0-9a-f]+) ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+Disassembly of section \.plt:
+
+[0-9a-f]+ <\.plt>:
+#...
+.*nop
+.*nop
+.*nop
+# Note that for a none-linux-gnu target we don't emit a symbol specific to the
+# PLT stub for an IFUNC, but for a none-elf target we do. That means we can't
+# generally check the offset in the symbols name matches the `foo` address
+# below.
+#?
+#?[0-9a-f]+ <\*ABS\*\+0x[0-9a-f]+@plt>:
+#record: PLTADDR PLTGOT_PAGE
+ *([0-9a-f]+): .* adrp c16, ([0-9a-f]+) .*
+#record: PLTGOT_DEC_OFF
+ *[0-9a-f]+: .* ldr c17, \[c16, #([0-9]+)\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: .* br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#record: FOO_ADDR
+([0-9a-f]+) <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .* <foo\+0x18> // b\.any
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, .*
+ *[0-9a-f]+: .* b .* <foo\+0x14>
+
+[0-9a-f]+ <_start>:
+#check: PLTLOC string tolower $PLTADDR
+#check: PLTGOTPAGE string tolower $PLTGOT_PAGE
+#check: PLTGOT_DECOFF string tolower $PLTGOT_DEC_OFF
+ *[0-9a-f]+: .* bl PLTLOC .*
+ *[0-9a-f]+: .* adrp c0, PLTGOTPAGE .*
+ *[0-9a-f]+: .* ldr c0, \[c0, #PLTGOT_DECOFF\]
+ *[0-9a-f]+: .* ret c30
+#...
+Disassembly of section \.got\.plt:
+
+#check: GOTLOC aarch64_page_plus_decimal_offset $PLTGOT_PAGE $PLTGOT_DEC_OFF
+#check: FRAGBASE format %08x 0x$PCC_START
+#check: FRAGSIZE format %08x [expr "0x$PCC_LAST_SIZE + 0x$PCC_LAST_START - 0x$PCC_START"]
+#check: FOO_OFFSET format %x [expr "0x$FOO_ADDR + 1 - 0x$PCC_START"]
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *GOTLOC: FRAGBASE .*
+ GOTLOC: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#...
+Disassembly of section \.data:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: FRAGBASE .*
+ [0-9a-f]+: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
--- /dev/null
+# Checking that when linking as standard, the BL and the GOT access both use
+# the PLT. This link does not do anything special to maintain pointer equality
+# since there is no access which directly uses the address.
+#
+# Things this testcase checks:
+# 1) Fragment of IRELATIVE relocation is PCC_START with bounds and
+# permissions of PCC.
+# 2) GOT access uses IRELATIVE relocation in the PLTGOT when no direct access
+# to address is used.
+# 3) BL to an IFUNC branches to a PLT stub which uses the a PLTGOT slot
+# initialised by an IRELATIVE relocation against our resolver.
+#source: morello-ifunc1.s
+#target: [check_shared_lib_support]
+#as: -march=morello+c64
+#ld: -shared
+#objdump: -DR --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]+ +[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt +([0-9a-f]+) ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+Disassembly of section \.plt:
+
+#record: PLT0_ADDR
+([0-9a-f]+) <\.plt>:
+#...
+.*nop
+.*nop
+.*nop
+
+[0-9a-f]+ <foo@plt>:
+#record: PLTADDR PLTGOT_PAGE
+ *([0-9a-f]+): .* adrp c16, ([0-9a-f]+) .*
+#record: PLTGOT_DEC_OFF
+ *[0-9a-f]+: .* ldr c17, \[c16, #([0-9]+)\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: .* br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#record: FOO_ADDR
+([0-9a-f]+) <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .* <foo\+0x18> // b\.any
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, .*
+ *[0-9a-f]+: .* b .* <foo\+0x14>
+
+[0-9a-f]+ <_start>:
+#check: PLTLOC string tolower $PLTADDR
+ *[0-9a-f]+: .* bl PLTLOC .*
+#record: GOT_PAGE
+ *[0-9a-f]+: .* adrp c0, ([0-9a-f]+) .*
+#record: GOT_DEC_OFF
+ *[0-9a-f]+: .* ldr c0, \[c0, #([0-9]+)\]
+ *[0-9a-f]+: .* ret c30
+#...
+Disassembly of section \.got:
+
+#check: GOTLOC aarch64_page_plus_decimal_offset $GOT_PAGE $GOT_DEC_OFF
+[0-9a-f]+ <.*>:
+#...
+ GOTLOC: R_MORELLO_GLOB_DAT foo
+#...
+Disassembly of section \.got\.plt:
+
+#check: PLTGOT_LOC aarch64_page_plus_decimal_offset $PLTGOT_PAGE $PLTGOT_DEC_OFF
+#check: FRAGBASE format %08x [expr "0x$PLT0_ADDR + 1"]
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *PLTGOT_LOC: FRAGBASE .*
+ PLTGOT_LOC: R_MORELLO_JUMP_SLOT foo
+#...
+Disassembly of section \.data:
+
+[0-9a-f]+ <.*>:
+ \.\.\.
+ [0-9a-f]+: R_MORELLO_CAPINIT foo
+#pass
--- /dev/null
+# Checking that when linking as standard, the BL and the GOT access both use
+# the PLT. This link does not do anything special to maintain pointer equality
+# since there is no access which directly uses the address.
+#
+# Things this testcase checks:
+# 1) Fragment of IRELATIVE relocation is PCC_START with bounds and
+# permissions of PCC.
+# 2) GOT access uses IRELATIVE relocation in the PLTGOT when no direct access
+# to address is used.
+# 3) BL to an IFUNC branches to a PLT stub which uses the a PLTGOT slot
+# initialised by an IRELATIVE relocation against our resolver.
+#as: -march=morello+c64
+#ld:
+#objdump: -Dr --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]+ +[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt +([0-9a-f]+) ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+
+Disassembly of section \.rela\.plt:
+
+[0-9a-f]+ <.*>:
+#record: PLTGOT_LOC
+ +[0-9a-f]+: ([0-9a-f]+) .*
+ +[0-9a-f]+: 00000000 .*
+ +[0-9a-f]+: 0000e804 .*
+ +[0-9a-f]+: 00000000 .*
+#record: IREL_ADDEND
+ +[0-9a-f]+: ([0-9a-f]+) .*
+ +[0-9a-f]+: 00000000 .*
+#record: CHERICAP_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e804 .*
+ *[0-9a-f]+: 00000000 .*
+#check: CHERICAP_ADDEND string tolower $IREL_ADDEND
+ *[0-9a-f]+: CHERICAP_ADDEND .*
+ *[0-9a-f]+: 00000000 .*
+
+Disassembly of section \.plt:
+
+#check: PLTGOT_PAGE format %x [expr "0x$PLTGOT_LOC & (~0xfff)"]
+#check: PLTGOT_DEC_OFF expr "0x$PLTGOT_LOC & 0xfff"
+[0-9a-f]+ <\.plt>:
+#record: PLTADDR
+ *([0-9a-f]+): .* adrp c16, PLTGOT_PAGE .*
+ *[0-9a-f]+: .* ldr c17, \[c16, #PLTGOT_DEC_OFF\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: .* br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#check: FOO_ADDR format %016x [expr "0x$PCC_START + (0x$IREL_ADDEND & ~1)"]
+FOO_ADDR <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .* <foo\+0x18> // b\.any
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, .*
+ *[0-9a-f]+: .* b .* <foo\+0x14>
+
+[0-9a-f]+ <_start>:
+#check: PLTLOC string tolower $PLTADDR
+ *[0-9a-f]+: .* bl PLTLOC .*
+ *[0-9a-f]+: .* adrp c0, PLTGOT_PAGE .*
+ *[0-9a-f]+: .* ldr c0, \[c0, #PLTGOT_DEC_OFF\]
+ *[0-9a-f]+: .* ret c30
+
+Disassembly of section \.got:
+
+[0-9a-f]+ <.*>:
+ \.\.\.
+
+Disassembly of section \.got\.plt:
+
+#check: GOTLOC format %x 0x$PLTGOT_LOC
+#check: FRAGBASE format %08x 0x$PCC_START
+#check: FRAGSIZE format %08x [expr "0x$PCC_LAST_SIZE + 0x$PCC_LAST_START - 0x$PCC_START"]
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *GOTLOC: FRAGBASE .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#...
+Disassembly of section \.data:
+
+#check: CHERICAPLOC format %x 0x$CHERICAP_LOC
+[0-9a-f]+ <.*>:
+ *CHERICAPLOC: FRAGBASE .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
+
--- /dev/null
+// Want to check that having a CAPINIT relocation on an IFUNC does not require
+// pointer equality (this would mean that a GOT relocation against the symbol
+// would end up using a GOT entry which refers to the PLT, but without
+// requiring pointer equality we end up using the PLTGOT entry that is already
+// around for the use of the PLT).
+#APP
+ .type foo, %gnu_indirect_function
+#NO_APP
+ .align 2
+ .type foo_1, %function
+foo_1:
+ mov w0, 1
+ ret
+ .size foo_1, .-foo_1
+ .align 2
+ .type foo_2, %function
+foo_2:
+ mov w0, 2
+ ret
+ .size foo_2, .-foo_2
+ .align 2
+
+ .global foo
+ .type foo, %function
+foo:
+ mov x1, 42
+ tst x0, x1
+ bne .L5
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+.L4:
+ ret
+.L5:
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+ b .L4
+ .size foo, .-foo
+ .align 2
+
+ .global _start
+ .type _start, %function
+_start:
+ bl foo
+ adrp c0, :got:foo
+ ldr c0, [c0, #:got_lo12:foo]
+ ret
+ .size _start, .-_start
+
+ .data
+ .align 4
+ .chericap foo
--- /dev/null
+# Checking that having a CAPINIT relocation against an IFUNC symbol stops the
+# garbage collection of the IFUNC's PLT.
+# In order to show that the PLT stub is indeed the one related to FOO we show
+# that the PLT stub loads from the PLTGOT, and that the entry in the PLTGOT it
+# loads is initialised with an IRELATIVE relocation pointing to the foo
+# resolver.
+#source: morello-ifunc2.s
+#as: -march=morello+c64
+#ld: -pie
+#objdump: -DR --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: TEXT_START
+.* .interp [0-9a-f]+ ([0-9a-f]+) .* .* 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: DATA_START
+#...
+.* .data 00000010 ([0-9a-f]+) .* .* 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+
+#...
+Disassembly of section \.plt:
+
+[0-9a-f]+ <\.plt>:
+#...
+ *[0-9a-f]+: d503201f nop
+ *[0-9a-f]+: d503201f nop
+ *[0-9a-f]+: d503201f nop
+
+#record: PLTSTUB_ADDR FOO_OFF
+([0-9a-f]+) <\*ABS\*\+0x([0-9a-f]+)@plt>:
+#record: PLTGOT_PAGE
+ *[0-9a-f]+: ........ adrp c16, ([0-9a-f]+) <.*
+#record: FOO_PLTGOT_OFF
+ *[0-9a-f]+: ........ ldr c17, \[c16, #([0-9]+)\]
+#check: FOO_PLTGOT_HEXOFF format %x $FOO_PLTGOT_OFF
+ *[0-9a-f]+: ........ add c16, c16, #0xFOO_PLTGOT_HEXOFF
+ *[0-9a-f]+: c2c21220 br c17
+#clearcheck:
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+ *[0-9a-f]+: 52800020 mov w0, #0x1 // #1
+ *[0-9a-f]+: c2c253c0 ret c30
+
+[0-9a-f]+ <foo_2>:
+ *[0-9a-f]+: 52800040 mov w0, #0x2 // #2
+ *[0-9a-f]+: c2c253c0 ret c30
+
+#check: FOO_LOC format %016x [expr "0x$TEXT_START + 0x$FOO_OFF - 1"]
+FOO_LOC <foo>:
+ *[0-9a-f]+: d2800541 mov x1, #0x2a // #42
+ *[0-9a-f]+: ea01001f tst x0, x1
+ *[0-9a-f]+: ........ b\.ne .*
+ *[0-9a-f]+: ........ adrp c0, .*
+ *[0-9a-f]+: ........ add c0, c0, .*
+ *[0-9a-f]+: c2c253c0 ret c30
+ *[0-9a-f]+: ........ adrp c0, .*
+ *[0-9a-f]+: ........ add c0, c0, .*
+ *[0-9a-f]+: 17fffffd b .* <foo\+0x14>
+
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: c2c253c0 ret c30
+
+#...
+Disassembly of section \.got\.plt:
+#check: PCC_START aarch64_8digit_addr $TEXT_START
+#check: PCC_SIZE format %08x [expr "0x$DATA_START - 0x$TEXT_START"]
+#check: FOO_OFFSET string tolower $FOO_OFF
+
+[0-9a-f]+ <.*>:
+ \.\.\.
+ *[0-9a-f]+: PCC_START .*
+ .*: R_MORELLO_IRELATIVE \*ABS\*\+0xFOO_OFFSET
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: PCC_SIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
--- /dev/null
+# Checking that having a CAPINIT relocation against an IFUNC symbol stops the
+# garbage collection of the IFUNC's PLT.
+# In order to show that the PLT stub is indeed the one related to FOO we show
+# that the PLT stub loads from the PLTGOT, and that the entry in the PLTGOT it
+# loads is initialised with an IRELATIVE relocation pointing to the foo
+# resolver.
+#as: -march=morello+c64
+#ld:
+#objdump: -Dr --section-headers
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: TEXT_START
+.* .[^ ]+ +[0-9a-f]+ ([0-9a-f]+) .* .* 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: DATA_START
+#...
+.* .data 00000010 ([0-9a-f]+) .* .* 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+
+#...
+Disassembly of section \.rela\.plt:
+
+[0-9a-f]+ <\.rela\.plt>:
+#record: PLTGOT_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e804 .*
+ *[0-9a-f]+: 00000000 .*
+#record: PLTGOT_IREL_ADDEND
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+#record: CAPINIT_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e804 .*
+ *[0-9a-f]+: 00000000 .*
+#check: CAPINIT_ADDEND string tolower $PLTGOT_IREL_ADDEND
+ *[0-9a-f]+: CAPINIT_ADDEND .*
+ *[0-9a-f]+: 00000000 .*
+
+
+Disassembly of section \.plt:
+
+#check: PLTGOT_PAGE format %x [expr "0x$PLTGOT_LOC & (~0xfff)"]
+#check: PLTGOT_DEC_OFF expr "0x$PLTGOT_LOC & 0xfff"
+[0-9a-f]+ <\.plt>:
+ *[0-9a-f]+: ........ adrp c16, PLTGOT_PAGE <.*
+ *[0-9a-f]+: ........ ldr c17, \[c16, #PLTGOT_DEC_OFF\]
+ *[0-9a-f]+: ........ add c16, c16, #0x.*
+ *[0-9a-f]+: c2c21220 br c17
+#clearcheck:
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+ *[0-9a-f]+: 52800020 mov w0, #0x1 // #1
+ *[0-9a-f]+: c2c253c0 ret c30
+
+[0-9a-f]+ <foo_2>:
+ *[0-9a-f]+: 52800040 mov w0, #0x2 // #2
+ *[0-9a-f]+: c2c253c0 ret c30
+
+#check: FOO_LOC format %016x [expr "0x$TEXT_START + 0x$PLTGOT_IREL_ADDEND - 1"]
+FOO_LOC <foo>:
+ *[0-9a-f]+: d2800541 mov x1, #0x2a // #42
+ *[0-9a-f]+: ea01001f tst x0, x1
+ *[0-9a-f]+: ........ b\.ne .*
+ *[0-9a-f]+: ........ adrp c0, .*
+ *[0-9a-f]+: ........ add c0, c0, .*
+ *[0-9a-f]+: c2c253c0 ret c30
+ *[0-9a-f]+: ........ adrp c0, .*
+ *[0-9a-f]+: ........ add c0, c0, .*
+ *[0-9a-f]+: 17fffffd b .* <foo\+0x14>
+
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: c2c253c0 ret c30
+
+#...
+Disassembly of section \.got\.plt:
+
+#check: PLTGOT_LOCATION format %x 0x$PLTGOT_LOC
+#check: PCC_START aarch64_8digit_addr $TEXT_START
+#check: PCC_SIZE format %08x [expr "0x$DATA_START - 0x$TEXT_START"]
+[0-9a-f]+ <.*>:
+ *PLTGOT_LOCATION: PCC_START .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: PCC_SIZE .*
+ *[0-9a-f]+: 04000000 .*
+#pass
--- /dev/null
+// Want to check that having a CAPINIT relocation on an IFUNC stops the garbage
+// collection of the IFUNC's PLT (so that the CAPINIT relocation has something
+// to point to).
+#APP
+ .type foo, %gnu_indirect_function
+#NO_APP
+ .align 2
+ .type foo_1, %function
+foo_1:
+ mov w0, 1
+ ret
+ .size foo_1, .-foo_1
+ .align 2
+ .type foo_2, %function
+foo_2:
+ mov w0, 2
+ ret
+ .size foo_2, .-foo_2
+ .align 2
+
+ .global foo
+ .type foo, %function
+foo:
+ mov x1, 42
+ tst x0, x1
+ bne .L5
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+.L4:
+ ret
+.L5:
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+ b .L4
+ .size foo, .-foo
+ .align 2
+
+ .global _start
+ .type _start, %function
+_start:
+ ret
+ .size _start, .-_start
+
+ .data
+ .align 4
+ .chericap foo
--- /dev/null
+#as: -march=morello+c64
+#ld:
+#error: .*: relocation R_AARCH64_ABS64 against a C64 STT_GNU_IFUNC symbol `foo'
+#error: .*: dangerous relocation: unsupported relocation
--- /dev/null
+#APP
+ .type foo, %gnu_indirect_function
+#NO_APP
+ .align 2
+ .type foo_1, %function
+foo_1:
+ mov w0, 1
+ ret
+ .size foo_1, .-foo_1
+ .align 2
+ .type foo_2, %function
+foo_2:
+ mov w0, 2
+ ret
+ .size foo_2, .-foo_2
+ .align 2
+
+ .global foo
+ .type foo, %function
+foo:
+ mov x1, 42
+ tst x0, x1
+ bne .L5
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+.L4:
+ ret
+.L5:
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+ b .L4
+ .size foo, .-foo
+ .align 2
+
+ .global _start
+ .type _start, %function
+_start:
+ ret
+ .size _start, .-_start
+
+ .data
+ .align 4
+ .xword foo
--- /dev/null
+# Checking that the IRELATIVE relocations which are added by CAPINIT
+# static relocations end up between the __rela_iplt_start and __rela_iplt_end
+# symbols and that RELATIVE relocations added by CAPINIT static relocations end
+# up between __rela_dyn_start and __rela_dyn_end.
+#as: -march=morello+c64
+#ld:
+#objdump: -Dzr --section-headers --syms
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]+ +[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt +([0-9a-f]+) ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+SYMBOL TABLE:
+#record: RELA_IPLT_END
+#...
+([0-9a-f]+) l \.rela\.plt 0000000000000000 __rela_iplt_end
+#record: RELA_IPLT_START
+([0-9a-f]+) l \.rela\.plt 0000000000000000 __rela_iplt_start
+#record: RELA_DYN_END
+([0-9a-f]+) l O \.rela\.dyn 0000000000000000 __rela_dyn_end
+#record: RELA_DYN_START
+([0-9a-f]+) l O \.rela\.dyn 0000000000000000 __rela_dyn_start
+#...
+
+Disassembly of section \.rela\.dyn:
+
+#check: RELA_START format %016x 0x$RELA_DYN_START
+RELA_START <__rela_dyn_start>:
+#record: CHERICAP_A_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e803 .*
+ *[0-9a-f]+: 00000000 .*
+#record: CHERICAP_ADDEND
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+# __rela_iplt_end and __rela_iplt_start relocations.
+# These were just added in order to get the symbols in the output binary.
+# There is nothing we want to check around them.
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+#check: CCAP_ADDEND string tolower $CHERICAP_ADDEND
+#record: CHERICAP_B_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e803 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: CCAP_ADDEND .*
+ *[0-9a-f]+: 00000000 .*
+#record: CHERICAP_C_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e803 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: CCAP_ADDEND .*
+ *[0-9a-f]+: 00000000 .*
+#record: GOT_IFUNC_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e803 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: CCAP_ADDEND .*
+#check: RELA_DYN_LAST format %x [expr "0x$RELA_DYN_END - 0x4"]
+ *RELA_DYN_LAST: 00000000 .*
+
+Disassembly of section \.rela\.plt:
+
+[0-9a-f]+ <__rela_iplt_start>:
+#record: PLTGOT_LOC
+ +[0-9a-f]+: ([0-9a-f]+) .*
+ +[0-9a-f]+: 00000000 .*
+ +[0-9a-f]+: 0000e804 .*
+ +[0-9a-f]+: 00000000 .*
+#record: IREL_ADDEND
+ +[0-9a-f]+: ([0-9a-f]+) .*
+ +[0-9a-f]+: 00000000 .*
+
+Disassembly of section \.plt:
+
+#check: PLTGOT_PAGE format %x [expr "0x$PLTGOT_LOC & (~0xfff)"]
+#check: PLTGOT_DEC_OFF expr "0x$PLTGOT_LOC & 0xfff"
+#check: PLTADDR_LOC format %x [expr "0x$PCC_START + (0x$CHERICAP_ADDEND & ~1)"]
+[0-9a-f]+ <\.plt>:
+ *PLTADDR_LOC: .* adrp c16, PLTGOT_PAGE .*
+ *[0-9a-f]+: .* ldr c17, \[c16, #PLTGOT_DEC_OFF\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: .* br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#check: FOO_ADDR format %016x [expr "0x$PCC_START + (0x$IREL_ADDEND & ~1)"]
+FOO_ADDR <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .* <foo\+0x18> // b\.any
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, .*
+ *[0-9a-f]+: .* b .* <foo\+0x14>
+
+#check: GOT_PAGE format %x [expr "0x$GOT_IFUNC_LOC & (~0xfff)"]
+#check: GOT_DEC_OFF expr "0x$GOT_IFUNC_LOC & 0xfff"
+#check: PLTADDR_PAGE format %x [expr "(0x$PCC_START + 0x$CHERICAP_ADDEND) & (~0xfff)"]
+#check: PLTADDR_OFF format %x [expr "(0x$PCC_START + 0x$CHERICAP_ADDEND) & 0xfff"]
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: .* bl PLTADDR_LOC .*
+ *[0-9a-f]+: .* adrp c0, GOT_PAGE .*
+ *[0-9a-f]+: .* ldr c0, \[c0, #GOT_DEC_OFF\]
+ *[0-9a-f]+: .* adrp c0, PLTADDR_PAGE .*
+ *[0-9a-f]+: .* add c0, c0, #0xPLTADDR_OFF
+ *[0-9a-f]+: .* ret c30
+
+Disassembly of section \.got:
+
+#check: GOTLOC format %x 0x$GOT_IFUNC_LOC
+#check: FRAGBASE format %08x 0x$PCC_START
+#check: FRAGSIZE format %08x [expr "0x$PCC_LAST_SIZE + 0x$PCC_LAST_START - 0x$PCC_START"]
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *GOTLOC: FRAGBASE .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+
+Disassembly of section \.got\.plt:
+
+#check: PLTGOT_ADDR format %x 0x$PLTGOT_LOC
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *PLTGOT_ADDR: FRAGBASE .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#...
+Disassembly of section \.data:
+#pass
--- /dev/null
+ .text
+#APP
+ .type foo, %gnu_indirect_function
+#NO_APP
+ .align 2
+ .type foo_1, %function
+foo_1:
+ mov w0, 1
+ ret
+ .size foo_1, .-foo_1
+ .align 2
+ .type foo_2, %function
+foo_2:
+ mov w0, 2
+ ret
+ .size foo_2, .-foo_2
+ .align 2
+
+ .global foo
+ .type foo, %function
+foo:
+ mov x1, 42
+ tst x0, x1
+ bne .L5
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+.L4:
+ ret
+.L5:
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+ b .L4
+ .size foo, .-foo
+ .align 2
+
+ .global _start
+ .type _start, %function
+_start:
+ bl foo
+ adrp c0, :got:foo
+ ldr c0, [c0, #:got_lo12:foo]
+ // Adding direct relocation against `foo` to ensure that we need
+ // pointer equality. This should change the behaviour of the CAPINIT
+ // and GOT relocations.
+ adrp c0, foo
+ add c0, c0, :lo12:foo
+ ret
+ .size _start, .-_start
+
+ .data
+ .align 4
+ .chericap foo
+ .chericap __rela_iplt_start
+ .chericap __rela_iplt_end
+ .chericap foo
+ .chericap foo
--- /dev/null
+# Checking that the IRELATIVE relocations which are added by CAPINIT
+# static relocations end up between the __rela_iplt_start and __rela_iplt_end
+# symbols and that RELATIVE relocations added by CAPINIT static relocations end
+# up between __rela_dyn_start and __rela_dyn_end.
+#as: -march=morello+c64
+#ld:
+#objdump: -Dzr --section-headers --syms
+
+.*: file format .*
+
+Sections:
+Idx Name Size VMA LMA File off Algn
+#record: PCC_START
+ 0 \.[^ ]+ +[0-9a-f]+ ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, READONLY, DATA
+#record: PCC_LAST_SIZE PCC_LAST_START
+#...
+ *[0-9]+ \.got\.plt +([0-9a-f]+) ([0-9a-f]+) [0-9a-f]+ [0-9a-f]+ 2\*\*.
+ CONTENTS, ALLOC, LOAD, DATA
+#...
+SYMBOL TABLE:
+#record: RELA_IPLT_END
+#...
+([0-9a-f]+) l \.rela\.plt 0000000000000000 __rela_iplt_end
+#record: RELA_IPLT_START
+([0-9a-f]+) l \.rela\.plt 0000000000000000 __rela_iplt_start
+#record: RELA_DYN_END
+([0-9a-f]+) l O \.rela\.dyn 0000000000000000 __rela_dyn_end
+#record: RELA_DYN_START
+([0-9a-f]+) l O \.rela\.dyn 0000000000000000 __rela_dyn_start
+#...
+
+Disassembly of section \.rela\.dyn:
+
+#check: RELA_START format %016x 0x$RELA_DYN_START
+RELA_START <__rela_dyn_start>:
+# __rela_iplt_end and __rela_iplt_start relocations.
+# These were just added in order to get the symbols in the output binary.
+# There is nothing we want to check around them.
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+ *[0-9a-f]+: ........ .*
+#check: RELA_DYN_LAST format %x [expr "0x$RELA_DYN_END - 0x4"]
+ *RELA_DYN_LAST: 00000000 .*
+
+Disassembly of section \.rela\.plt:
+
+[0-9a-f]+ <__rela_iplt_start>:
+#record: PLTGOT_LOC
+ +[0-9a-f]+: ([0-9a-f]+) .*
+ +[0-9a-f]+: 00000000 .*
+ +[0-9a-f]+: 0000e804 .*
+ +[0-9a-f]+: 00000000 .*
+#record: IREL_ADDEND
+ +[0-9a-f]+: ([0-9a-f]+) .*
+ +[0-9a-f]+: 00000000 .*
+#record: CHERICAP_A_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e804 .*
+ *[0-9a-f]+: 00000000 .*
+#check: CCAP_ADDEND string tolower $IREL_ADDEND
+ *[0-9a-f]+: CCAP_ADDEND .*
+ *[0-9a-f]+: 00000000 .*
+#record: CHERICAP_B_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e804 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: CCAP_ADDEND .*
+ *[0-9a-f]+: 00000000 .*
+#record: CHERICAP_C_LOC
+ *[0-9a-f]+: ([0-9a-f]+) .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 0000e804 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: CCAP_ADDEND .*
+#check: RELA_IPLT_LAST format %x [expr "0x$RELA_IPLT_END - 0x4"]
+ *RELA_IPLT_LAST: 00000000 .*
+
+Disassembly of section \.plt:
+
+#check: PLTGOT_PAGE format %x [expr "0x$PLTGOT_LOC & (~0xfff)"]
+#check: PLTGOT_DEC_OFF expr "0x$PLTGOT_LOC & 0xfff"
+[0-9a-f]+ <\.plt>:
+#record: PLTADDR
+ *([0-9a-f]+): .* adrp c16, PLTGOT_PAGE .*
+ *[0-9a-f]+: .* ldr c17, \[c16, #PLTGOT_DEC_OFF\]
+ *[0-9a-f]+: .* add c16, c16, #0x.*
+ *[0-9a-f]+: .* br c17
+
+Disassembly of section \.text:
+
+[0-9a-f]+ <foo_1>:
+#...
+
+[0-9a-f]+ <foo_2>:
+#...
+
+#check: FOO_ADDR format %016x [expr "0x$PCC_START + (0x$IREL_ADDEND & ~1)"]
+FOO_ADDR <foo>:
+ *[0-9a-f]+: .* mov x1, #0x2a // #42
+ *[0-9a-f]+: .* tst x0, x1
+ *[0-9a-f]+: .* b\.ne .* <foo\+0x18> // b\.any
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, c0, .*
+ *[0-9a-f]+: .* ret c30
+ *[0-9a-f]+: .* adrp c0, .*
+ *[0-9a-f]+: .* add c0, .*
+ *[0-9a-f]+: .* b .* <foo\+0x14>
+
+#check: GOT_PAGE format %x [expr "0x$PLTGOT_LOC & (~0xfff)"]
+#check: GOT_DEC_OFF expr "0x$PLTGOT_LOC & 0xfff"
+#check: PLT_LOC string tolower $PLTADDR
+[0-9a-f]+ <_start>:
+ *[0-9a-f]+: .* bl PLT_LOC .*
+ *[0-9a-f]+: .* adrp c0, GOT_PAGE .*
+ *[0-9a-f]+: .* ldr c0, \[c0, #GOT_DEC_OFF\]
+ *[0-9a-f]+: .* ret c30
+
+Disassembly of section \.got:
+
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+
+Disassembly of section \.got\.plt:
+
+#check: FRAGBASE format %08x 0x$PCC_START
+#check: FRAGSIZE format %08x [expr "0x$PCC_LAST_SIZE + 0x$PCC_LAST_START - 0x$PCC_START"]
+#check: PLTGOT_ADDR format %x 0x$PLTGOT_LOC
+[0-9a-f]+ <.*>:
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: 00000000 .*
+ *PLTGOT_ADDR: FRAGBASE .*
+ *[0-9a-f]+: 00000000 .*
+ *[0-9a-f]+: FRAGSIZE .*
+ *[0-9a-f]+: 04000000 .*
+#...
+Disassembly of section \.data:
+#pass
--- /dev/null
+ .text
+#APP
+ .type foo, %gnu_indirect_function
+#NO_APP
+ .align 2
+ .type foo_1, %function
+foo_1:
+ mov w0, 1
+ ret
+ .size foo_1, .-foo_1
+ .align 2
+ .type foo_2, %function
+foo_2:
+ mov w0, 2
+ ret
+ .size foo_2, .-foo_2
+ .align 2
+
+ .global foo
+ .type foo, %function
+foo:
+ mov x1, 42
+ tst x0, x1
+ bne .L5
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+.L4:
+ ret
+.L5:
+ adrp c0, foo_1
+ add c0, c0, :lo12:foo_1
+ b .L4
+ .size foo, .-foo
+ .align 2
+
+ .global _start
+ .type _start, %function
+_start:
+ bl foo
+ adrp c0, :got:foo
+ ldr c0, [c0, #:got_lo12:foo]
+ ret
+ .size _start, .-_start
+
+ .data
+ .align 4
+ .chericap foo
+ .chericap __rela_iplt_start
+ .chericap __rela_iplt_end
+ .chericap foo
+ .chericap foo