The permissions that a capability to an object should end up with is based on the section it should point into. With symbols that point into SHN_ABS sections we have nothing to base the permissions on (since these sections don't have associated permission flags).
For the moment we are making a default of choosing Read-Write permissions and warning the user about it. The permissions match what Morello LLD currently does (from observation). When Morello linkers use the symbol type to determine whether a capability should have executable permissions or not, this should end up being able to handle all uses (since STT_FUNC would get RX perms while everything else gets RW perms).
In the only case we know of in the GNU team the symbol ends up with zero-size anyway, so the choice of Read-Write doesn't seem too lax. (Having zero-size is fine for the use-case we know of in glibc, since that use case simply checks if the address of the symbol is non-zero. Hence we have no need as yet to dereference the symbol).
The use case we know about are the `_nl_current_<LANG>_used` symbols defined with `_NL_CURRENT_DEFINE` in the locale/lc-<lang>.c files in statically linked glibc. If any case that requires non-zero size or different permissions becomes important then something more will be required across the toolchain.
############### Attachment also inlined for ease of reply ###############
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 8b69c03c4a2f66a7f3d4a6dc88494c00ac72646b..0a455763faebf2d0c1e3cbe689d5b82163bfa43e 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -6364,7 +6364,7 @@ aarch64_relocation_aginst_gp_p (bfd_reloc_code_real_type reloc) /* Build capability meta data, i.e. size and permissions for a capability. */
static bfd_vma -cap_meta (size_t size, const asection *sec) +cap_meta (size_t size, const asection *sec, bfd_boolean *guessed) {
if (size >= (1ULL << 56)) @@ -6386,10 +6386,20 @@ cap_meta (size_t size, const asection *sec) else if (sec->flags & SEC_ALLOC) flags = 2;
- /* We should always be able to derive a valid set of permissions - from the section flags. */ + /* We should usually be able to derive a valid set of permissions + from the section flags. We know that when a relocation is against an + SHN_ABS symbol the section has no associated flags and we must guess. + + As it stands we don't know of any other instances where we do not have + permission flags on a section. We choose to allow instances that we do + not know of rather than abort on them so that if the guess is correct we + don't hamper anyone progressing. */ if (flags == 0) - abort (); + { + flags = 2; + *guessed = TRUE; + } + return size | (flags << 56); }
@@ -6451,15 +6461,18 @@ c64_symbol_section_adjustment (struct elf_link_hash_entry *h, bfd_vma value,
static bfd_reloc_status_type c64_fixup_frag (bfd *input_bfd, struct bfd_link_info *info, - Elf_Internal_Sym *sym, struct elf_link_hash_entry *h, - asection *sym_sec, bfd_byte *frag_loc, bfd_vma value, - bfd_signed_vma addend) + bfd_reloc_code_real_type bfd_r_type, Elf_Internal_Sym *sym, + struct elf_link_hash_entry *h, asection *sym_sec, + asection *reloc_sec, bfd_byte *frag_loc, bfd_vma value, + bfd_signed_vma addend, bfd_vma r_offset) { BFD_ASSERT (h || sym); bfd_vma size = sym ? sym->st_size : h->size; asection *perm_sec = sym_sec; bfd_boolean bounds_ok = FALSE;
+ const int aarch64_reloc_idx = bfd_r_type - BFD_RELOC_AARCH64_RELOC_START; + const char *reloc_name = elfNN_aarch64_howto_table[aarch64_reloc_idx].name; const char *sym_name;
if (sym) @@ -6534,11 +6547,22 @@ c64_fixup_frag (bfd *input_bfd, struct bfd_link_info *info,
if (perm_sec != NULL) { - bfd_vma frag = cap_meta (size, perm_sec); + bfd_boolean permissions_guessed = FALSE; + bfd_vma frag = cap_meta (size, perm_sec, &permissions_guessed);
if (frag == (bfd_vma) -1) return bfd_reloc_outofrange;
+ if (permissions_guessed) + { + _bfd_error_handler (_("%pB(%pA+%#" PRIx64 "): " + "warning: relocation %s against symbol '%s' in " + "section without permission flags '%s'. " + "Assuming Read-Write."), + input_bfd, reloc_sec, r_offset, reloc_name, + sym_name, perm_sec->name); + } + bfd_put_64 (input_bfd, frag, frag_loc); }
@@ -7304,9 +7328,9 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, { bfd_reloc_status_type ret;
- ret = c64_fixup_frag (input_bfd, info, sym, h, - sym_sec, base_got->contents + off + 8, - orig_value, 0); + ret = c64_fixup_frag (input_bfd, info, bfd_r_type, sym, h, + sym_sec, s, base_got->contents + off + 8, + orig_value, 0, off);
if (ret != bfd_reloc_continue) return ret; @@ -7509,8 +7533,9 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
bfd_reloc_status_type ret;
- ret = c64_fixup_frag (input_bfd, info, sym, h, sym_sec, - hit_data + 8, value, signed_addend); + ret = c64_fixup_frag (input_bfd, info, bfd_r_type, sym, h, sym_sec, + input_section, hit_data + 8, value, + signed_addend, rel->r_offset);
if (ret != bfd_reloc_continue) return ret; diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 9168a810fc57783dd122ce40b6385dddc6888042..01f65dc934de3f012b6e134ff2ccebd1f4207650 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -249,6 +249,7 @@ run_dump_test_lp64 "emit-relocs-morello-5" run_dump_test_lp64 "emit-relocs-morello-6" run_dump_test_lp64 "emit-relocs-morello-6b" run_dump_test_lp64 "emit-relocs-morello-7" +run_dump_test_lp64 "emit-relocs-morello-8" run_dump_test_lp64 "emit-morello-reloc-markers-1" run_dump_test_lp64 "emit-morello-reloc-markers-2" run_dump_test_lp64 "emit-morello-reloc-markers-3" diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-8.d b/ld/testsuite/ld-aarch64/emit-relocs-morello-8.d new file mode 100644 index 0000000000000000000000000000000000000000..e907f7de72e084263acd208374c09e91d6bd065f --- /dev/null +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-8.d @@ -0,0 +1,18 @@ +#source: emit-relocs-morello-8.s +#source: emit-relocs-morello-8b.s +#as: -march=morello+c64 +#ld: -static -pie +#objdump: -DR -j .data.rel.ro +#warning: .*relocation R_MORELLO_CAPINIT against symbol 'absolute_sym' in section without permission flags '*ABS*'. Assuming Read-Write. + +.*: file format .* + + +Disassembly of section .data.rel.ro: + +0.* <.LC1>: + .*: 00001000 udf #4096 + 101e0: R_MORELLO_RELATIVE *ABS* + .*: 00000000 udf #0 + .*: 00000004 udf #4 + .*: 02000000 add c0, c0, #0x0 diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-8.s b/ld/testsuite/ld-aarch64/emit-relocs-morello-8.s new file mode 100644 index 0000000000000000000000000000000000000000..4a42962a67534e13217a18048daf7279a89201b4 --- /dev/null +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-8.s @@ -0,0 +1,16 @@ + .arch morello+crc+c64 + .text + .align 2 + .global _start +_start: + adrp c0, .LC1 + add c0, c0, :lo12:.LC1 + ldr c0, [c0] + + .section .data.rel.ro.local,"aw" + .align 4 + .type .LC1, %object + .size .LC1, 16 +.LC1: + .chericap absolute_sym + .ident "GCC: (unknown) 11.0.0 20200826 (experimental)" diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-8b.s b/ld/testsuite/ld-aarch64/emit-relocs-morello-8b.s new file mode 100644 index 0000000000000000000000000000000000000000..fa12fb43b4e349c0949bb08b9648935032368110 --- /dev/null +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-8b.s @@ -0,0 +1,5 @@ + .arch morello+crc+c64 + .text + .global absolute_sym +absolute_sym = 0x1000 + .size absolute_sym, 4
gnu-morello@op-lists.linaro.org