diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index cb9e5f132cca2d360b8bd2cf2e2eb1fbbf1695f0..a33aea0eab02ac97cb605cac677d8ac27a475967 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -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; diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index 9352db42e9913021d17a8e5dd8d7d8cf2125fe29..49b2e70adca947b61294bf1d589ce366b81da569 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -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 index 0000000000000000000000000000000000000000..a9e1c3f37485df9d0ea9f2a52edab97cc9edf355 --- /dev/null +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-9.d @@ -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: + +.* : + .*: 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 index 0000000000000000000000000000000000000000..854482cd027dd853aecd41465c1b2238bbbedb7d --- /dev/null +++ b/ld/testsuite/ld-aarch64/emit-relocs-morello-9.s @@ -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