From: Matthew Malcomson Date: Mon, 7 Feb 2022 16:54:56 +0000 (+0000) Subject: Provide default permissions if section has no permission flags X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e10c835d8438317ae2f55648dfc14c11be8030f6;p=thirdparty%2Fbinutils-gdb.git Provide default permissions if section has no permission flags 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__used` symbols defined with `_NL_CURRENT_DEFINE` in the locale/lc-.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. --- diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 8b69c03c4a2..0a455763fae 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 9168a810fc5..01f65dc934d 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 00000000000..e907f7de72e --- /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 00000000000..4a42962a675 --- /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 00000000000..fa12fb43b4e --- /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