]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Provide default permissions if section has no permission flags
authorMatthew Malcomson <matthew.malcomson@arm.com>
Mon, 7 Feb 2022 16:54:56 +0000 (16:54 +0000)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Wed, 9 Feb 2022 10:35:00 +0000 (10:35 +0000)
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.

bfd/elfnn-aarch64.c
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/emit-relocs-morello-8.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/emit-relocs-morello-8.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/emit-relocs-morello-8b.s [new file with mode: 0644]

index 8b69c03c4a2f66a7f3d4a6dc88494c00ac72646b..0a455763faebf2d0c1e3cbe689d5b82163bfa43e 100644 (file)
@@ -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;
index 9168a810fc57783dd122ce40b6385dddc6888042..01f65dc934de3f012b6e134ff2ccebd1f4207650 100644 (file)
@@ -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 (file)
index 0000000..e907f7d
--- /dev/null
@@ -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 (file)
index 0000000..4a42962
--- /dev/null
@@ -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 (file)
index 0000000..fa12fb4
--- /dev/null
@@ -0,0 +1,5 @@
+       .arch morello+crc+c64
+       .text
+       .global absolute_sym
+absolute_sym = 0x1000
+       .size absolute_sym, 4