]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Account for LSB in more relocations
authorMatthew Malcomson <matthew.malcomson@arm.com>
Mon, 7 Mar 2022 18:10:52 +0000 (18:10 +0000)
committerMatthew Malcomson <matthew.malcomson@arm.com>
Mon, 7 Mar 2022 18:10:52 +0000 (18:10 +0000)
The LSB on STT_FUNC symbols was missed in a few different places.

1) Absolute relocations coming from .xword, .word, and .hword
   directives and the lowest bit MOVW relocations did not account for
   the LSB at all.
2) Relocations for the ADR instruction only added the LSB on local
   symbols.

Here we account for these by adding the LSB in each clause in
elfNN_aarch64_final_link_relocate.
The change under the BFD_RELOC_AARCH64_NN clause handles absolute 64 bit
relocations, the change for BFD_RELOC_AARCH64_ADR_LO21_PCREL handles the
relocation on ADR instructions, and the extra relocations checked
against in the clause including BFD_RELOC_AARCH64_ADD_LO12 ore the
remaining items.

N.b. we noticed the MOVW relocation problem because glibc's start.S was
using these direct MOV relocations to access the value of `main`.  Since
`main` is a function we need to include the LSB in the resulting
relocation value.  These relocations did not include the LSB from
STT_FUNC symbols.

Others were found from inspection of each relocation in turn.

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

index 4814e4ac06f88e5e7dcac89a7ed7c3576f08600c..5e7f0324dd89838a56eda2b87cd2b439ba52b796 100644 (file)
@@ -6900,6 +6900,11 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
       return bfd_reloc_ok;
 
     case BFD_RELOC_AARCH64_NN:
+      /* If we are relocating against a C64 symbol, then the value can't
+        already have the LSB set (since STT_FUNC symbols are code labels and
+        they will be aligned).  Hence it's safe just to or-equal in order
+        to ensure the LSB is set in that case.  */
+      value |= to_c64 ? 1 : 0;
 
       /* When generating a shared object or relocatable executable, these
         relocations are copied into the output file to be resolved at
@@ -7115,8 +7120,7 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
                                                   signed_addend,
                                                   weak_undef_p);
 
-      if (bfd_r_type == BFD_RELOC_AARCH64_ADR_LO21_PCREL && isym != NULL
-         && isym->st_target_internal & ST_BRANCH_TO_C64)
+      if (bfd_r_type == BFD_RELOC_AARCH64_ADR_LO21_PCREL && to_c64)
        value |= 1;
       break;
 
@@ -7172,8 +7176,13 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto,
       value = _bfd_aarch64_elf_resolve_relocation (input_bfd, bfd_r_type,
                                                   place, value,
                                                   signed_addend, weak_undef_p);
-      if (bfd_r_type == BFD_RELOC_AARCH64_ADD_LO12 && isym != NULL
-         && isym->st_target_internal & ST_BRANCH_TO_C64)
+      if ((bfd_r_type == BFD_RELOC_AARCH64_ADD_LO12
+          || bfd_r_type == BFD_RELOC_AARCH64_MOVW_G0
+          || bfd_r_type == BFD_RELOC_AARCH64_MOVW_G0_S
+          || bfd_r_type == BFD_RELOC_AARCH64_MOVW_G0_NC
+          || bfd_r_type == BFD_RELOC_AARCH64_32
+          || bfd_r_type == BFD_RELOC_AARCH64_16)
+         && to_c64)
        value |= 1;
 
       break;
index 9352db42e9913021d17a8e5dd8d7d8cf2125fe29..49b2e70adca947b61294bf1d589ce366b81da569 100644 (file)
@@ -250,6 +250,7 @@ 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-relocs-morello-9"
 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-9.d b/ld/testsuite/ld-aarch64/emit-relocs-morello-9.d
new file mode 100644 (file)
index 0000000..a9e1c3f
--- /dev/null
@@ -0,0 +1,33 @@
+#source: emit-relocs-morello-9.s
+#as: -march=morello+c64
+#ld: -static -Ttext-segment 0x0
+#objdump: -d -j .data -j .text
+
+.*:     file format .*
+
+
+Disassembly of section \.text:
+
+0000000000000000 <_start>:
+   0:  f2800020        movk    x0, #0x1
+   4:  f2800020        movk    x0, #0x1
+   8:  30ffffc0        adr     c0, 1 <_start\+0x1>
+   c:  30ffffa0        adr     c0, 1 <_start\+0x1>
+  10:  02000400        add     c0, c0, #0x1
+  14:  02000400        add     c0, c0, #0x1
+  18:  d2800020        mov     x0, #0x1                        // #1
+  1c:  d2800020        mov     x0, #0x1                        // #1
+  20:  f2800020        movk    x0, #0x1
+  24:  f2800020        movk    x0, #0x1
+
+Disassembly of section \.data:
+
+.* <val>:
+   .*: 00000001        .word   0x00000001
+   .*: 00000001        .word   0x00000001
+   .*: 00000001        .word   0x00000001
+   .*: 00000000        .word   0x00000000
+   .*: 00000001        .word   0x00000001
+   .*: 00000001        .word   0x00000001
+   .*: 00000001        .word   0x00000001
+   .*: 00000000        .word   0x00000000
diff --git a/ld/testsuite/ld-aarch64/emit-relocs-morello-9.s b/ld/testsuite/ld-aarch64/emit-relocs-morello-9.s
new file mode 100644 (file)
index 0000000..854482c
--- /dev/null
@@ -0,0 +1,42 @@
+# Attempting to check that the LSB is set on all relocations to a function
+# symbol.
+#
+# This should only happen for those relocations which load an address into a
+# register, since relocations that jump to a PC relative address like `bl`
+# should not include the LSB.
+.text
+.global _start
+.type _start,@function
+.type otherstart,@function
+_start:
+otherstart:
+       movk    x0, #:abs_g0_nc:_start
+       movk    x0, #:abs_g0_nc:otherstart
+       adr     c0, _start
+       adr     c0, otherstart
+       add     c0, c0, :lo12:_start
+       add     c0, c0, :lo12:otherstart
+       # The below are not as much of a worry if they go wrong since they
+       # check overflow, and the likelyhood of there being a function which
+       # fits in the lowest 16 bits of an address is low.  However, we can
+       # still test it in our testsuite with arguments to the linker, so we
+       # still get to check this edge case.
+       movz    x0, #:abs_g0_s:_start
+       movz    x0, #:abs_g0_s:otherstart
+       movk    x0, #:abs_g0:_start
+       movk    x0, #:abs_g0:otherstart
+.data
+.align 4
+.global val
+val:
+       # LSB should be included in the value of function symbols even if they
+       # are just added via absolute relocations.
+       .hword _start
+       .hword 0
+       .word _start
+       .xword _start
+       .hword otherstart
+       .hword 0
+       .word otherstart
+       .xword otherstart
+       .size val, .-val