From 36b6002396dc0898b6f7097bca4589fefabaac87 Mon Sep 17 00:00:00 2001 From: Matthew Malcomson Date: Thu, 13 Oct 2022 11:19:47 +0100 Subject: [PATCH] Various fixes for capability IFUNCs 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/elfnn-aarch64.c | 399 ++++++++++++++++-- ld/testsuite/ld-aarch64/aarch64-elf.exp | 21 +- ld/testsuite/ld-aarch64/c64-ifunc-2-local.d | 25 +- ld/testsuite/ld-aarch64/c64-ifunc-2.d | 16 +- ld/testsuite/ld-aarch64/c64-ifunc-3a.d | 23 +- ld/testsuite/ld-aarch64/morello-ifunc-a.d | 111 +++++ ld/testsuite/ld-aarch64/morello-ifunc-b.d | 104 +++++ .../ld-aarch64/morello-ifunc-dynlink-pie.d | 20 + .../ld-aarch64/morello-ifunc-dynlink.d | 20 + .../ld-aarch64/morello-ifunc-dynlink.s | 23 + .../ld-aarch64/morello-ifunc-shared.s | 23 + ld/testsuite/ld-aarch64/morello-ifunc.d | 138 ++++++ ld/testsuite/ld-aarch64/morello-ifunc.s | 52 +++ ld/testsuite/ld-aarch64/morello-ifunc1-a.d | 100 +++++ ld/testsuite/ld-aarch64/morello-ifunc1-b.d | 100 +++++ ld/testsuite/ld-aarch64/morello-ifunc1-c.d | 97 +++++ ld/testsuite/ld-aarch64/morello-ifunc1.d | 113 +++++ ld/testsuite/ld-aarch64/morello-ifunc1.s | 51 +++ ld/testsuite/ld-aarch64/morello-ifunc2-b.d | 82 ++++ ld/testsuite/ld-aarch64/morello-ifunc2.d | 92 ++++ ld/testsuite/ld-aarch64/morello-ifunc2.s | 46 ++ ld/testsuite/ld-aarch64/morello-ifunc3.d | 4 + ld/testsuite/ld-aarch64/morello-ifunc3.s | 43 ++ ld/testsuite/ld-aarch64/morello-ifunc4.d | 176 ++++++++ ld/testsuite/ld-aarch64/morello-ifunc4.s | 56 +++ ld/testsuite/ld-aarch64/morello-ifunc4a.d | 161 +++++++ ld/testsuite/ld-aarch64/morello-ifunc4a.s | 51 +++ 27 files changed, 2102 insertions(+), 45 deletions(-) create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc-a.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc-b.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc-dynlink-pie.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc-dynlink.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc-dynlink.s create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc-shared.s create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc.s create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc1-a.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc1-b.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc1-c.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc1.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc1.s create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc2-b.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc2.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc2.s create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc3.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc3.s create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc4.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc4.s create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc4a.d create mode 100644 ld/testsuite/ld-aarch64/morello-ifunc4a.s diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 4dce36d8148..be4c735753d 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -3049,6 +3049,13 @@ struct elf_c64_tls_data_stub_hash_entry 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. */ @@ -3357,6 +3364,11 @@ struct elf_aarch64_link_hash_table 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. */ @@ -3543,6 +3555,55 @@ c64_tls_stub_find (struct elf_link_hash_entry *h, 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 @@ -3685,6 +3746,11 @@ elfNN_aarch64_link_hash_table_free (bfd *obfd) 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); } @@ -3734,6 +3800,16 @@ elfNN_aarch64_link_hash_table_create (bfd *abfd) 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, @@ -7133,6 +7209,26 @@ c64_symbol_adjust (struct elf_link_hash_entry *h, 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. */ @@ -7263,6 +7359,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, 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) { @@ -7280,9 +7377,29 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, 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; @@ -7300,17 +7417,57 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, 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 { @@ -7318,8 +7475,21 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, 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, @@ -7356,6 +7526,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, if (base_got == NULL) abort (); + value |= h->target_internal; if (off == (bfd_vma) -1) { bfd_vma plt_index; @@ -9950,6 +10121,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -10040,6 +10212,7 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, 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)) @@ -10384,6 +10557,13 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *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) @@ -10398,6 +10578,49 @@ elfNN_aarch64_check_relocs (bfd *abfd, struct bfd_link_info *info, 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; @@ -10751,12 +10974,22 @@ elfNN_aarch64_output_arch_local_syms (bfd *output_bfd, } /* 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); @@ -10892,7 +11125,9 @@ elfNN_aarch64_allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) 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++; @@ -11161,12 +11396,29 @@ elfNN_aarch64_allocate_ifunc_dynrelocs (struct elf_link_hash_entry *h, 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; } @@ -11189,6 +11441,34 @@ elfNN_aarch64_allocate_local_ifunc_dynrelocs (void **slot, void *inf) 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 ! */ @@ -11345,6 +11625,14 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd, 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) @@ -11426,7 +11714,8 @@ elfNN_aarch64_size_dynamic_sections (bfd *output_bfd, /* 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 @@ -11640,12 +11929,32 @@ elfNN_aarch64_create_small_pltn_entry (struct elf_link_hash_entry *h, { /* 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 { @@ -11807,11 +12116,37 @@ elfNN_aarch64_finish_dynamic_symbol (bfd *output_bfd, 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; } } diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 2c372e24138..73c414ad7b4 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -106,7 +106,7 @@ proc aarch64_page_plus_decimal_offset { page offset } { # 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"]; } @@ -312,6 +312,25 @@ if { [check_shared_lib_support] 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] diff --git a/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d b/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d index c85443fe71a..6f00498390b 100644 --- a/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d +++ b/ld/testsuite/ld-aarch64/c64-ifunc-2-local.d @@ -1,13 +1,30 @@ #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 diff --git a/ld/testsuite/ld-aarch64/c64-ifunc-2.d b/ld/testsuite/ld-aarch64/c64-ifunc-2.d index 2954f67b0c5..1214c310639 100644 --- a/ld/testsuite/ld-aarch64/c64-ifunc-2.d +++ b/ld/testsuite/ld-aarch64/c64-ifunc-2.d @@ -1,18 +1,28 @@ #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_ADDR : #... [ \t0-9a-f]+:[ \t0-9a-f]+bl[ \t0-9a-f]+<\*ABS\*\+0xFOO_LOC@plt> [ \t0-9a-f]+:[ \t0-9a-f]+adrp[ \t]+c0, 0 <.*> diff --git a/ld/testsuite/ld-aarch64/c64-ifunc-3a.d b/ld/testsuite/ld-aarch64/c64-ifunc-3a.d index 7690b42edd5..905612ccec2 100644 --- a/ld/testsuite/ld-aarch64/c64-ifunc-3a.d +++ b/ld/testsuite/ld-aarch64/c64-ifunc-3a.d @@ -2,14 +2,27 @@ #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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc-a.d b/ld/testsuite/ld-aarch64/morello-ifunc-a.d new file mode 100644 index 00000000000..f36b0945cb5 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc-a.d @@ -0,0 +1,111 @@ +# 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]+ : +#... + +[0-9a-f]+ : +#... + +#record: FOO_ADDR +([0-9a-f]+) : + *[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc-b.d b/ld/testsuite/ld-aarch64/morello-ifunc-b.d new file mode 100644 index 00000000000..c6938e0eb58 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc-b.d @@ -0,0 +1,104 @@ +# 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]+ : +#... + +[0-9a-f]+ : +#... + +#check: FOO_ADDRESS format %x [expr "0x$PCC_START + 0x$RESOLVER_ADDEND - 1"] +([0-9a-f]+) : + *[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc-dynlink-pie.d b/ld/testsuite/ld-aarch64/morello-ifunc-dynlink-pie.d new file mode 100644 index 00000000000..e139f02770a --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc-dynlink-pie.d @@ -0,0 +1,20 @@ +# 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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc-dynlink.d b/ld/testsuite/ld-aarch64/morello-ifunc-dynlink.d new file mode 100644 index 00000000000..328fe047e03 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc-dynlink.d @@ -0,0 +1,20 @@ +# 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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc-dynlink.s b/ld/testsuite/ld-aarch64/morello-ifunc-dynlink.s new file mode 100644 index 00000000000..a6a7e4085ed --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc-dynlink.s @@ -0,0 +1,23 @@ + .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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc-shared.s b/ld/testsuite/ld-aarch64/morello-ifunc-shared.s new file mode 100644 index 00000000000..61c2f5a026e --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc-shared.s @@ -0,0 +1,23 @@ + .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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc.d b/ld/testsuite/ld-aarch64/morello-ifunc.d new file mode 100644 index 00000000000..11ad08d9a2f --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc.d @@ -0,0 +1,138 @@ +# 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]+ : + *[0-9a-f]+: 52800020 mov w0, #0x1 // #1 + *[0-9a-f]+: c2c253c0 ret c30 + +[0-9a-f]+ : + *[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 : + *[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc.s b/ld/testsuite/ld-aarch64/morello-ifunc.s new file mode 100644 index 00000000000..08efcb3c212 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc.s @@ -0,0 +1,52 @@ + .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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc1-a.d b/ld/testsuite/ld-aarch64/morello-ifunc1-a.d new file mode 100644 index 00000000000..062973bab00 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc1-a.d @@ -0,0 +1,100 @@ +# 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]+ : +#... + +[0-9a-f]+ : +#... + +#record: FOO_ADDR +([0-9a-f]+) : + *[0-9a-f]+: .* mov x1, #0x2a // #42 + *[0-9a-f]+: .* tst x0, x1 + *[0-9a-f]+: .* b\.ne .* // 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 .* + +[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc1-b.d b/ld/testsuite/ld-aarch64/morello-ifunc1-b.d new file mode 100644 index 00000000000..062973bab00 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc1-b.d @@ -0,0 +1,100 @@ +# 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]+ : +#... + +[0-9a-f]+ : +#... + +#record: FOO_ADDR +([0-9a-f]+) : + *[0-9a-f]+: .* mov x1, #0x2a // #42 + *[0-9a-f]+: .* tst x0, x1 + *[0-9a-f]+: .* b\.ne .* // 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 .* + +[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc1-c.d b/ld/testsuite/ld-aarch64/morello-ifunc1-c.d new file mode 100644 index 00000000000..741fb50ec45 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc1-c.d @@ -0,0 +1,97 @@ +# 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]+ : +#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]+ : +#... + +[0-9a-f]+ : +#... + +#record: FOO_ADDR +([0-9a-f]+) : + *[0-9a-f]+: .* mov x1, #0x2a // #42 + *[0-9a-f]+: .* tst x0, x1 + *[0-9a-f]+: .* b\.ne .* // 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 .* + +[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc1.d b/ld/testsuite/ld-aarch64/morello-ifunc1.d new file mode 100644 index 00000000000..c205f15a304 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc1.d @@ -0,0 +1,113 @@ +# 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]+ : +#... + +[0-9a-f]+ : +#... + +#check: FOO_ADDR format %016x [expr "0x$PCC_START + (0x$IREL_ADDEND & ~1)"] +FOO_ADDR : + *[0-9a-f]+: .* mov x1, #0x2a // #42 + *[0-9a-f]+: .* tst x0, x1 + *[0-9a-f]+: .* b\.ne .* // 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 .* + +[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 + diff --git a/ld/testsuite/ld-aarch64/morello-ifunc1.s b/ld/testsuite/ld-aarch64/morello-ifunc1.s new file mode 100644 index 00000000000..9e088b5c135 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc1.s @@ -0,0 +1,51 @@ +// 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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc2-b.d b/ld/testsuite/ld-aarch64/morello-ifunc2-b.d new file mode 100644 index 00000000000..773274b9990 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc2-b.d @@ -0,0 +1,82 @@ +# 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]+ : + *[0-9a-f]+: 52800020 mov w0, #0x1 // #1 + *[0-9a-f]+: c2c253c0 ret c30 + +[0-9a-f]+ : + *[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 : + *[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 .* + +[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc2.d b/ld/testsuite/ld-aarch64/morello-ifunc2.d new file mode 100644 index 00000000000..b706f0f1718 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc2.d @@ -0,0 +1,92 @@ +# 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]+ : + *[0-9a-f]+: 52800020 mov w0, #0x1 // #1 + *[0-9a-f]+: c2c253c0 ret c30 + +[0-9a-f]+ : + *[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 : + *[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 .* + +[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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc2.s b/ld/testsuite/ld-aarch64/morello-ifunc2.s new file mode 100644 index 00000000000..cc111f99626 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc2.s @@ -0,0 +1,46 @@ +// 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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc3.d b/ld/testsuite/ld-aarch64/morello-ifunc3.d new file mode 100644 index 00000000000..6eaea611499 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc3.d @@ -0,0 +1,4 @@ +#as: -march=morello+c64 +#ld: +#error: .*: relocation R_AARCH64_ABS64 against a C64 STT_GNU_IFUNC symbol `foo' +#error: .*: dangerous relocation: unsupported relocation diff --git a/ld/testsuite/ld-aarch64/morello-ifunc3.s b/ld/testsuite/ld-aarch64/morello-ifunc3.s new file mode 100644 index 00000000000..f6702f1690c --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc3.s @@ -0,0 +1,43 @@ +#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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc4.d b/ld/testsuite/ld-aarch64/morello-ifunc4.d new file mode 100644 index 00000000000..ceb213b2114 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc4.d @@ -0,0 +1,176 @@ +# 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]+ : +#... + +[0-9a-f]+ : +#... + +#check: FOO_ADDR format %016x [expr "0x$PCC_START + (0x$IREL_ADDEND & ~1)"] +FOO_ADDR : + *[0-9a-f]+: .* mov x1, #0x2a // #42 + *[0-9a-f]+: .* tst x0, x1 + *[0-9a-f]+: .* b\.ne .* // 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 .* + +#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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc4.s b/ld/testsuite/ld-aarch64/morello-ifunc4.s new file mode 100644 index 00000000000..5040f9a4717 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc4.s @@ -0,0 +1,56 @@ + .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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc4a.d b/ld/testsuite/ld-aarch64/morello-ifunc4a.d new file mode 100644 index 00000000000..fd6020d6f20 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc4a.d @@ -0,0 +1,161 @@ +# 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]+ : +#... + +[0-9a-f]+ : +#... + +#check: FOO_ADDR format %016x [expr "0x$PCC_START + (0x$IREL_ADDEND & ~1)"] +FOO_ADDR : + *[0-9a-f]+: .* mov x1, #0x2a // #42 + *[0-9a-f]+: .* tst x0, x1 + *[0-9a-f]+: .* b\.ne .* // 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 .* + +#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 diff --git a/ld/testsuite/ld-aarch64/morello-ifunc4a.s b/ld/testsuite/ld-aarch64/morello-ifunc4a.s new file mode 100644 index 00000000000..64c3facc6b8 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-ifunc4a.s @@ -0,0 +1,51 @@ + .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 -- 2.39.5