]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Emit CAPINIT relocations for dynamically linked PDE's
authorMatthew Malcomson <matthew.malcomson@arm.com>
Fri, 1 Jul 2022 10:48:53 +0000 (11:48 +0100)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Fri, 1 Jul 2022 10:48:53 +0000 (11:48 +0100)
Until now CAPINIT relocations were only emitted for position independent
code.  For a data relocation against a symbol in some other shared
object this was problematic since we don't know the address that said
symbol will be at.  We ended up emitting a broken RELATIVE relocation.

This also happened to be problematic for function pointers, since a
CAPINIT relocation did not ensure that a PLT entry was created in this
binary.  When a PLT entry was not created we again had a broken RELATIVE
relocation.

We could have fixed the problem with function pointers by ensuring that
a CAPINIT relocation caused a PLT entry to be emitted and the RELATIVE
relocation hence to point to that PLT entry.  Here we choose to always
emit a CAPINIT relocation and let the dynamic linker resolve that to a
local PLT entry if one exists, but if one does not exist let the dynamic
linker resolve it to the actual function in some other shared library.

Alongside this change we ensure that we leave 0 as the value in the
fragment for a CAPINIT relocation.  The dynamic linker already has to
decide which symbol to use, and it would have the value of the local
symbol available if it chooses to use it.  Hence there is no reason for
the static linker to leave the value of one option in the fragment of
this CAPINIT relocation.

This patch also introduces quite a few new testcases.
These are to check that we should only add a special PLT entry as the
canonical address for pointer equality when a function pointer is
accessed via code relocations -- and we ensure this does not happen for
accessing data pointers or accesses via CAPINIT data relocations.

Outside of the new testcases, we also adjust
emit-relocs-morello-3{,-a64c}.d.  These testcases checked for a CAPINIT
relocation in a shared object.  Now we no longer populate that fragment
we need to adjust the testcase accordingly.

19 files changed:
bfd/elfnn-aarch64.c
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/emit-relocs-morello-3-a64c.d
ld/testsuite/ld-aarch64/emit-relocs-morello-3.d
ld/testsuite/ld-aarch64/morello-dataptr-code-and-data.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dataptr-code-and-data.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dataptr-in-code.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dataptr-in-code.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dataptr-through-data-pie.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dataptr-through-data.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dataptr-through-data.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-dynamic-relocs-lib.s
ld/testsuite/ld-aarch64/morello-funcptr-code-and-data.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-funcptr-code-and-data.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-funcptr-in-code.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-funcptr-in-code.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-funcptr-through-data-pie.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-funcptr-through-data.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-funcptr-through-data.s [new file with mode: 0644]

index 16447f15b05af3165b8bb2354437aa337ea3e304..dd1c28ad7e4352d9407b1b7a1d863a0cb293a9a4 100644 (file)
@@ -7611,36 +7611,53 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
          if (outrel.r_offset & 0xf)
            return bfd_reloc_overflow;
 
-         bfd_reloc_status_type ret;
-
-         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;
-
          outrel.r_addend = signed_addend;
-         value |= (h != NULL ? h->target_internal : sym->st_target_internal);
 
-         /* Emit a dynamic relocation if we are building PIC.  */
+         /* Emit a dynamic relocation if we are handling a symbol which the
+            dynamic linker will be told about.  */
          if (h != NULL
              && h->dynindx != -1
-             && bfd_link_pic (info)
+             && globals->root.dynamic_sections_created
              && !SYMBOL_REFERENCES_LOCAL (info, h))
-           outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
+           {
+             outrel.r_info = ELFNN_R_INFO (h->dynindx, r_type);
+             /* Dynamic symbols will be handled by the dynamic loader.  Hence
+                there is no need to fill a fragment with a value even if there
+                is a value that we would use assuming no interception.  */
+             value = 0;
+           }
          else
-           outrel.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE));
-
-         /* Symbols without size information get bounds to the
-            whole section: adjust the base of the capability to the
-            start of the section and set the addend to obtain the
-            correct address for the symbol.  */
-         bfd_vma new_value;
-         if (c64_symbol_adjust (h, value, sym_sec, info, &new_value))
            {
-             outrel.r_addend += (value - new_value);
-             value = new_value;
+             /* This relocation will point into the object we are building
+                (either because this is a statically linked executable and
+                hence there is only one object it could point at, or because
+                we know it will resolve locally even though this is
+                dynamically linked).
+
+                Hence we want to emit a RELATIVE relocation rather than a
+                CAPINIT one.  */
+             bfd_reloc_status_type ret;
+
+             value |= (h != NULL ? h->target_internal : sym->st_target_internal);
+             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;
+
+             outrel.r_info = ELFNN_R_INFO (0, MORELLO_R (RELATIVE));
+
+             /* Symbols without size information get bounds to the
+                whole section: adjust the base of the capability to the
+                start of the section and set the addend to obtain the
+                correct address for the symbol.  */
+             bfd_vma new_value;
+             if (c64_symbol_adjust (h, value, sym_sec, info, &new_value))
+               {
+                 outrel.r_addend += (value - new_value);
+                 value = new_value;
+               }
            }
 
          asection *s = globals->srelcaps;
index 19070408e990abbe50050b1cba183a6e4bf24934..235df2872084b5115239b671c5107b56a36b446f 100644 (file)
@@ -91,6 +91,15 @@ proc aarch64_required_func_addend { base result } {
   return [format %x [expr "0x$result + 1 - 0x$base"]];
 }
 
+# Return the hexadecimal addition of the two given values.  Values should be
+# provided in hexadecimal without the leading 0x prefix.
+#
+# Used in a testsuite to check that the combination of some ADRP/ADD constants
+# do indeed point at a variable later on in the dump.
+proc aarch64_page_plus_offset { page offset } {
+  return [format %x [expr "0x$page + 0x$offset"] ];
+}
+
 set eh-frame-merge-lp64 [list [list "EH Frame merge" \
                              [concat "-m " [aarch64_choose_lp64_emul] \
                                      " -Ttext 0x8000"] \
@@ -282,6 +291,14 @@ if { [ld_assemble_flags $as -march=morello+c64 $srcdir/$subdir/morello-dynamic-r
   run_dump_test_lp64 "morello-dynamic-link-rela-dyn"
   run_dump_test_lp64 "morello-dynamic-link-rela-dyn2"
   run_dump_test_lp64 "morello-dynamic-local-got"
+  run_dump_test_lp64 "morello-funcptr-in-code"
+  run_dump_test_lp64 "morello-funcptr-through-data"
+  run_dump_test_lp64 "morello-funcptr-through-data-pie"
+  run_dump_test_lp64 "morello-funcptr-code-and-data"
+  run_dump_test_lp64 "morello-dataptr-in-code"
+  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-static-got"
index d596a53df90e6a73ee950e91187ecf72c86d7e13..f57aa48ca3feb1ab75d6162bb4c882ef0c86309f 100644 (file)
@@ -36,12 +36,9 @@ Disassembly of section .data:
 .*:    00000000        .*
 
 .* <cap>:
-.*:    [0-9a-f]+       .*
+       \.\.\.
                        .*: R_MORELLO_CAPINIT   str
-.*:    00000000        .*
-.*:    0000001b        .*
-.*:    02000000        .*
 
 .* <cap2>:
-       ...
+       \.\.\.
                        .*: R_MORELLO_CAPINIT   str2
index fe248be367e98bc0720042b0c2ed9bab76427c86..7266ca94469966d71ef5fc3e6104f02125a74a08 100644 (file)
@@ -36,12 +36,9 @@ Disassembly of section .data:
 .*:    00000000        .*
 
 .* <cap>:
-.*:    [0-9a-f]+       .*
+       \.\.\.
                        .*: R_MORELLO_CAPINIT   str
-.*:    00000000        .*
-.*:    0000001b        .*
-.*:    02000000        .*
 
 .* <cap2>:
-       ...
+       \.\.\.
                        .*: R_MORELLO_CAPINIT   str2
diff --git a/ld/testsuite/ld-aarch64/morello-dataptr-code-and-data.d b/ld/testsuite/ld-aarch64/morello-dataptr-code-and-data.d
new file mode 100644 (file)
index 0000000..6d19f23
--- /dev/null
@@ -0,0 +1,35 @@
+# Want to double-check that when creating a PDE which loads a data pointer
+# in an external library using an adrp/ldr code sequence and also via a CAPINIT
+# relocation, we generate both a COPY relocation and a CAPINIT relocation.
+#
+# We want to make sure the COPY relocation is used by the text.  We can not
+# check that the dynamic loader would initialize the CAPINIT relocation with
+# the address of that COPY relocation, so that's left.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .data -j .bss -j .text
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+.* <_start>:
+#record: PAGE
+.*:    .*      adrp    c0, ([0-9a-f]*).*
+#record: OFFSET
+.*:    .*      add     c0, c0, #0x([0-9a-f]*)
+.*:    .*      ldr     w0, \[c0\]
+.*:    .*      ret     c30
+
+Disassembly of section \.data:
+#...
+                       .*: R_MORELLO_CAPINIT   var
+
+Disassembly of section \.bss:
+
+#check: VAR_LOCATION aarch64_page_plus_offset $PAGE $OFFSET
+0*VAR_LOCATION <var>:
+       \.\.\.
+                       VAR_LOCATION: R_AARCH64_COPY    var
+
diff --git a/ld/testsuite/ld-aarch64/morello-dataptr-code-and-data.s b/ld/testsuite/ld-aarch64/morello-dataptr-code-and-data.s
new file mode 100644 (file)
index 0000000..85ae06b
--- /dev/null
@@ -0,0 +1,16 @@
+       .arch morello+crc+c64
+       .text
+       .p2align 4,,11
+       .global _start
+       .type   _start, %function
+_start:
+       .cfi_startproc purecap
+       adrp    c0, var
+       add     c0, c0, #:lo12:var
+       ldr     w0, [c0]
+       ret
+       .cfi_endproc
+       .size   _start, .-_start
+       .data
+varptr:
+       .chericap var
diff --git a/ld/testsuite/ld-aarch64/morello-dataptr-in-code.d b/ld/testsuite/ld-aarch64/morello-dataptr-in-code.d
new file mode 100644 (file)
index 0000000..4f54626
--- /dev/null
@@ -0,0 +1,31 @@
+# Want to double-check that when creating a PDE which references a data pointer
+# in an external library in code with an adrp/add, we generate a COPY
+# relocation and access that the data said relocation will initialize.
+#
+# We check this by ensuring that there is a new `var` symbol in the .bss of the
+# PDE, that the adrp/add addresses point to that symbol, and that there is a
+# COPY relocation at that symbol for its initialisation.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .bss -j .text
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+.* <_start>:
+#record: PAGE
+.*:    .*      adrp    c0, ([0-9a-f]*).*
+#record: OFFSET
+.*:    .*      add     c0, c0, #0x([0-9a-f]*)
+.*:    .*      ldr     w0, \[c0\]
+.*:    .*      ret     c30
+
+Disassembly of section \.bss:
+
+#check: VAR_LOCATION aarch64_page_plus_offset $PAGE $OFFSET
+0*VAR_LOCATION <var>:
+       \.\.\.
+                       VAR_LOCATION: R_AARCH64_COPY    var
+
diff --git a/ld/testsuite/ld-aarch64/morello-dataptr-in-code.s b/ld/testsuite/ld-aarch64/morello-dataptr-in-code.s
new file mode 100644 (file)
index 0000000..9babed4
--- /dev/null
@@ -0,0 +1,13 @@
+       .arch morello+crc+c64
+       .text
+       .p2align 4,,11
+       .global _start
+       .type   _start, %function
+_start:
+       .cfi_startproc purecap
+       adrp    c0, var
+       add     c0, c0, #:lo12:var
+       ldr     w0, [c0]
+       ret
+       .cfi_endproc
+       .size   _start, .-_start
diff --git a/ld/testsuite/ld-aarch64/morello-dataptr-through-data-pie.d b/ld/testsuite/ld-aarch64/morello-dataptr-through-data-pie.d
new file mode 100644 (file)
index 0000000..2270c33
--- /dev/null
@@ -0,0 +1,12 @@
+# Want to double-check that when creating a PIE which loads a data pointer
+# in an external library using a CAPINIT relocation we end up with a
+# straight-forward CAPINIT relocation in the final binary requesting the
+# dynamic loader to provide a capability pointing to that bit of data.
+#source: morello-dataptr-through-data.s
+#as: -march=morello+c64
+#ld: -pie tmpdir/morello-dynamic-relocs.so
+#readelf: --relocs
+
+Relocation section '\.rela\.dyn' at offset .* contains 1 entry:
+  Offset          Info           Type           Sym\. Value    Sym\. Name \+ Addend
+.*  .* R_MORELLO_CAPINIT .* var \+ 0
diff --git a/ld/testsuite/ld-aarch64/morello-dataptr-through-data.d b/ld/testsuite/ld-aarch64/morello-dataptr-through-data.d
new file mode 100644 (file)
index 0000000..0c42017
--- /dev/null
@@ -0,0 +1,11 @@
+# Want to double-check that when creating a PDE which loads a data pointer
+# in an external library using a CAPINIT relocation we end up with a
+# straight-forward CAPINIT relocation in the final binary requesting the
+# dynamic loader to provide a capability pointing to that bit of data.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#readelf: --relocs
+
+Relocation section '\.rela\.dyn' at offset .* contains 1 entry:
+  Offset          Info           Type           Sym\. Value    Sym\. Name \+ Addend
+.*  .* R_MORELLO_CAPINIT .* var \+ 0
diff --git a/ld/testsuite/ld-aarch64/morello-dataptr-through-data.s b/ld/testsuite/ld-aarch64/morello-dataptr-through-data.s
new file mode 100644 (file)
index 0000000..9b56a25
--- /dev/null
@@ -0,0 +1,13 @@
+       .arch morello+crc+c64
+       .text
+       .p2align 4,,11
+       .global _start
+       .type   _start, %function
+_start:
+       .cfi_startproc purecap
+       ret
+       .cfi_endproc
+       .size   _start, .-_start
+       .data
+varptr:
+       .chericap var
index 80e84e5bc847a99b21c1da515749a3362842a641..2b4e058cc0383e0dbb98ca8fdf7e97fab92bb3da 100644 (file)
@@ -1,5 +1,11 @@
        .arch morello+crc+c64
        .text
+       .p2align 4,,11
+       .global memcpy
+       .type   memcpy,%function
+memcpy:
+       ret
+       .size memcpy, .-memcpy
        .global var
        .bss
        .align  2
diff --git a/ld/testsuite/ld-aarch64/morello-funcptr-code-and-data.d b/ld/testsuite/ld-aarch64/morello-funcptr-code-and-data.d
new file mode 100644 (file)
index 0000000..c8cfff8
--- /dev/null
@@ -0,0 +1,26 @@
+# Want to double-check that when creating a PDE which references a function
+# pointer in an external library with a CAPINIT and also references the
+# function pointer in code with an adrp/add, we generate a CAPINIT
+# entry in that PDE and also generate a PLT entry.
+# We check this by ensuring that there is a memcpy@plt entry in the PLT, that
+# there is the associated MORELLO jump slot relocation in the .got.plt, and
+# there is a CAPINIT relocation.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .data -j .got.plt
+
+.*:     file format .*
+
+Disassembly of section \.plt:
+#...
+.* <memcpy@plt>:
+#...
+Disassembly of section \.got\.plt:
+#...
+.*: R_MORELLO_JUMP_SLOT        memcpy
+#...
+Disassembly of section \.data:
+
+.* <p>:
+       \.\.\.
+       .*: R_MORELLO_CAPINIT   memcpy
diff --git a/ld/testsuite/ld-aarch64/morello-funcptr-code-and-data.s b/ld/testsuite/ld-aarch64/morello-funcptr-code-and-data.s
new file mode 100644 (file)
index 0000000..489fa7c
--- /dev/null
@@ -0,0 +1,21 @@
+       .arch morello+crc+c64
+       .text
+       .p2align 4,,11
+       .global _start
+       .type   _start, %function
+_start:
+       .cfi_startproc purecap
+       adrp    c0, memcpy
+       ldr     c0, [c0, #:lo12:memcpy]
+       ldr     w0, [c0]
+       ret
+       .cfi_endproc
+       .size   _start, .-_start
+       .global p
+       .section        .data.rel,"aw"
+       .align  4
+       .type   p, %object
+       .size   p, 16
+p:
+       .chericap       memcpy
+
diff --git a/ld/testsuite/ld-aarch64/morello-funcptr-in-code.d b/ld/testsuite/ld-aarch64/morello-funcptr-in-code.d
new file mode 100644 (file)
index 0000000..9bcb7d3
--- /dev/null
@@ -0,0 +1,21 @@
+# Want to double-check that when creating a PDE which loads a function pointer
+# in an external library using an adrp/ldr code sequence, we generate a PLT
+# entry in that PDE and use that PLT entry as the address that is loaded in the
+# code.
+# We check this by ensuring that there is a memcpy@plt entry in the PLT, and
+# that the .got.plt has a MORELLO jump slot relocation in it.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .got.plt
+
+.*:     file format .*
+
+
+Disassembly of section \.plt:
+#...
+.* <memcpy@plt>:
+#...
+Disassembly of section \.got\.plt:
+#...
+.*: R_MORELLO_JUMP_SLOT        memcpy
+#pass
diff --git a/ld/testsuite/ld-aarch64/morello-funcptr-in-code.s b/ld/testsuite/ld-aarch64/morello-funcptr-in-code.s
new file mode 100644 (file)
index 0000000..6bc38a1
--- /dev/null
@@ -0,0 +1,13 @@
+       .text
+       .p2align 4,,11
+       .global _start
+       .type   _start, %function
+_start:
+       .cfi_startproc purecap
+       adrp    c0, memcpy
+       add     c0, c0, #:lo12:memcpy
+       ldr     w0, [c0]
+       ret
+       .cfi_endproc
+       .size   _start, .-_start
+
diff --git a/ld/testsuite/ld-aarch64/morello-funcptr-through-data-pie.d b/ld/testsuite/ld-aarch64/morello-funcptr-through-data-pie.d
new file mode 100644 (file)
index 0000000..5f5b201
--- /dev/null
@@ -0,0 +1,19 @@
+# Want to double-check that when creating a PIE which references a function
+# pointer in an external library with a CAPINIT and does not reference the
+# function pointer in code with an adrp/add, we generate a CAPINIT
+# entry in that PIE and do not generate a PLT entry.
+# We check this by ensuring that there is no memcpy@plt entry in the PLT, and
+# by checking there is a CAPINIT relocation.
+#source: morello-funcptr-through-data.s
+#as: -march=morello+c64
+#ld: -pie tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .data
+
+.*:     file format .*
+
+Disassembly of section \.data:
+
+.* <p>:
+       \.\.\.
+       .*: R_MORELLO_CAPINIT   memcpy
+
diff --git a/ld/testsuite/ld-aarch64/morello-funcptr-through-data.d b/ld/testsuite/ld-aarch64/morello-funcptr-through-data.d
new file mode 100644 (file)
index 0000000..1b0d13f
--- /dev/null
@@ -0,0 +1,17 @@
+# Want to double-check that when creating a PDE which references a function
+# pointer in an external library with a CAPINIT and does not reference the
+# function pointer in code with an adrp/add, we generate a CAPINIT
+# entry in that PDE and do not generate a PLT entry.
+# We check this by ensuring that there is no memcpy@plt entry in the PLT, and
+# by checking there is a CAPINIT relocation.
+#as: -march=morello+c64
+#ld: tmpdir/morello-dynamic-relocs.so
+#objdump: -dR -j .plt -j .data
+
+.*:     file format .*
+
+Disassembly of section \.data:
+
+.* <p>:
+       \.\.\.
+       .*: R_MORELLO_CAPINIT   memcpy
diff --git a/ld/testsuite/ld-aarch64/morello-funcptr-through-data.s b/ld/testsuite/ld-aarch64/morello-funcptr-through-data.s
new file mode 100644 (file)
index 0000000..1782a7f
--- /dev/null
@@ -0,0 +1,18 @@
+       .arch morello+crc+c64
+       .text
+       .p2align 4,,11
+       .global _start
+       .type   _start, %function
+_start:
+       .cfi_startproc purecap
+       ret
+       .cfi_endproc
+       .size   _start, .-_start
+       .global p
+       .section        .data.rel,"aw"
+       .align  4
+       .type   p, %object
+       .size   p, 16
+p:
+       .chericap       memcpy
+