diff options
author | Matthew Malcomson <matthew.malcomson@arm.com> | 2022-04-28 09:50:31 +0100 |
---|---|---|
committer | Matthew Malcomson <matthew.malcomson@arm.com> | 2022-04-28 09:52:47 +0100 |
commit | 8f5baae3d15888c9c4aa40ccc0683045d40513f7 (patch) | |
tree | 445e9aa447ac963c9a61ce0c645761cd75570982 | |
parent | d9f4f6fc896adcb8abec896598ac42154bafc3a5 (diff) | |
download | binutils-gdb-8f5baae3d15888c9c4aa40ccc0683045d40513f7.tar.gz |
Morello do not create RELATIVE relocs for dynamic GOT entries
For dynamic symbol GOT entries, the linker emits relocations for that
entry in finish_dynamic_symbol.
Since Morello capabilities always need dynamic relocations to initialise
GOT entries at runtime, we need to emit relocations for any capability
GOT entries. Two examples which are not needed for non-Morello linking
are static linking and for global symbols defined and referenced in a
PDE.
In order to ensure we emit those relocations we catch them in the
existing clause of final_link_relocate that looks for GOT entries that
require relocations which are not handled by finish_dynamic_symbol.
Before this patch, the clause under which those relocations were emitted
would include dynamic GOT entries in dynamically linked position
dependent executables.
These symbols hence had RELATIVE relocations emitted to initialise them
in the executables GOT by final_link_relocate, and GLOB_DAT relocations
emitted to initialise them by finish_dynamic_symbol.
The RELATIVE relocation is incorrect to use, since the static linker
does not know the value of this symbol at runtime (i.e. it does not know
the location in memory that the the shared library will be loaded).
This patch ensures that the clause in final_link_relocate does not
catch such dynamic GOT entries by ensuring that we only catch symbols
when we would not otherwise call finish_dynamic_symbol.
N.b. we also add an assertion in the condition-guarded block, partly to
catch similar problems earlier, but mainly to make it clear that
`relative_reloc` should not be set when finish_dynamic_symbol will be
called.
N.b.2 The bfd_link_pic check is a little awkward to understand.
Due to the definition of WILL_CALL_FINISH_DYNAMIC_SYMBOL, the only time
that `!bfd_link_pic (info) && !WILL_CALL_FINISH_DYNAMIC_SYMBOL` is false
and
`!WILL_CALL_FINISH_DYNAMIC_SYMBOL (is_dynamic, bfd_link_pic (info), h)`
is true is when the below holds:
is_dynamic && !h->forced_local && h->dynindx == -1
This clause is looking for local GOT relocations that are not in the
dynamic symbol table, in a binary that will have dynamic sections.
This situation is the case that this clause was originally added to
handle (before the Morello specific code was added). It is the case
when we need a RELATIVE relocation because we have a PIC object, but
finish_dynamic_symbol would not be called on the symbol.
Since all capability GOT entries need relocations to initialise them it
would seem unnecessary to include the bfd_link_pic check in our Morello
clause. However the existing clause handling these relocations for
AArch64 specifically avoids adding a relocation for
bfd_link_hash_undefweak symbols. By keeping the `!bfd_link_pic (info)`
clause in the Morello part of this condition we ensure such undefweak
symbols are still avoided.
I do not believe it is possible to trigger the above case that requires
this `bfd_link_pic` clause (where we have a GOT relocation against a
symbol satisfying):
h->dynindx == -1 && !h->forced_local
&& h->root.type == bfd_link_hash_undefweak
&& bfd_link_pic (info) && bfd_link_executable (info)
I believe this is because when creating an undefweak symbol that has a
GOT reference we hit the clause in elfNN_aarch64_allocate_dynrelocs
which ensures that such symbols are put in `.dynsym` (and hence have a
`h->dynindx != -1`). A useful commit to reference for understanding
this is ff07562f1e.
Hence there is no testcase for this part. We do add some code that
exercises the relevant case (but does not exercise this particular
clause) into the morello-dynamic-link-rela-dyn testcase.
-rw-r--r-- | bfd/elfnn-aarch64.c | 21 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/aarch64-elf.exp | 1 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn.s | 3 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn2.d | 14 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/morello-dynamic-relocs.d | 16 | ||||
-rw-r--r-- | ld/testsuite/ld-aarch64/morello-dynamic-relocs.s | 15 |
6 files changed, 62 insertions, 8 deletions
diff --git a/bfd/elfnn-aarch64.c b/bfd/elfnn-aarch64.c index 88573828da7..76216f8f001 100644 --- a/bfd/elfnn-aarch64.c +++ b/bfd/elfnn-aarch64.c @@ -7244,17 +7244,28 @@ elfNN_aarch64_final_link_relocate (reloc_howto_type *howto, should only generate one RELATIVE relocation for that symbol. Therefore, check GOT offset mark first. - NOTE2: Symbol references via GOT in C64 static binaries without - PIC should always have relative relocations, so we do that here - early. */ + NOTE2: Symbol references via GOT in C64 should always have + relocations of some kind. Here we try to catch any such GOT + reference which would not otherwise be caught by + finish_dynamic_symbol. */ if (((h->dynindx == -1 && !h->forced_local && h->root.type != bfd_link_hash_undefweak && bfd_link_pic (info)) - || (!bfd_link_pic (info) && bfd_link_executable (info) - && c64_reloc)) + || (!bfd_link_pic (info) + && !WILL_CALL_FINISH_DYNAMIC_SYMBOL + (is_dynamic, bfd_link_pic (info), h) + && bfd_link_executable (info) && c64_reloc)) && !symbol_got_offset_mark_p (input_bfd, h, r_symndx)) { + /* If we would call finish_dynamic_symbol for this symbol then we + should not be introducing a relocation for the GOT entry + (that function handles creating relocations for the GOT entry + in the usual case, this bit of code is to handle special + cases where the relocation would not otherwise be generated). + */ + BFD_ASSERT (!WILL_CALL_FINISH_DYNAMIC_SYMBOL + (is_dynamic, bfd_link_pic (info), h)); relative_reloc = TRUE; c64_needs_frag_fixup = c64_reloc ? TRUE : FALSE; } diff --git a/ld/testsuite/ld-aarch64/aarch64-elf.exp b/ld/testsuite/ld-aarch64/aarch64-elf.exp index ba0b65a8aba..19070408e99 100644 --- a/ld/testsuite/ld-aarch64/aarch64-elf.exp +++ b/ld/testsuite/ld-aarch64/aarch64-elf.exp @@ -278,6 +278,7 @@ run_dump_test_lp64 "c64-ehdr-sized-reloc" # we need to specify different `ld` command lines for different objects. if { [ld_assemble_flags $as -march=morello+c64 $srcdir/$subdir/morello-dynamic-relocs-lib.s tmpdir/morello-dynamic-relocs-lib.o] && [ld_link $ld tmpdir/morello-dynamic-relocs.so "--shared tmpdir/morello-dynamic-relocs-lib.o"] } { + run_dump_test_lp64 "morello-dynamic-relocs" 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" diff --git a/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn.s b/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn.s index 3cffb35a8b8..cf6f0bfea61 100644 --- a/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn.s +++ b/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn.s @@ -6,6 +6,8 @@ _start: .LFB0: .cfi_startproc purecap + adrp c0, :got:undefweakval + ldr c0, [c0, #:got_lo12:undefweakval] adrp c0, :got:weakval ldr c0, [c0, #:got_lo12:weakval] adrp c0, :got:globval @@ -39,3 +41,4 @@ weakval: .byte 0x1 .byte 0x1 .size weakval, .-weakval + .weak undefweakval diff --git a/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn2.d b/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn2.d index 9de0c5f4f36..dcdd02606c3 100644 --- a/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn2.d +++ b/ld/testsuite/ld-aarch64/morello-dynamic-link-rela-dyn2.d @@ -3,12 +3,20 @@ #source: morello-dynamic-link-rela-dyn.s #as: -march=morello+c64 #ld: tmpdir/morello-dynamic-relocs.so -#readelf: --relocs +#readelf: --relocs --dyn-sym -Relocation section '\.rela\.dyn' at offset .* contains 5 entries: +Relocation section '\.rela\.dyn' at offset .* contains 6 entries: Offset Info Type Sym\. Value Sym\. Name \+ Addend .* 00000000e803 R_MORELLO_RELATIV 0 .* 00000000e803 R_MORELLO_RELATIV 0 .* 00000000e803 R_MORELLO_RELATIV 0 .* 00000000e803 R_MORELLO_RELATIV 0 -.* 00010000e801 R_MORELLO_GLOB_DA 0000000000000000 var \+ 0 +.* 00010000e801 R_MORELLO_GLOB_DA 0000000000000000 undefweakval \+ 0 +.* 00020000e801 R_MORELLO_GLOB_DA 0000000000000000 var \+ 0 + +Symbol table '\.dynsym' contains [34] entries: + Num: Value Size Type Bind Vis Ndx Name + 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND + 1: 0000000000000000 0 NOTYPE WEAK DEFAULT UND undefweakval + 2: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND var +#pass diff --git a/ld/testsuite/ld-aarch64/morello-dynamic-relocs.d b/ld/testsuite/ld-aarch64/morello-dynamic-relocs.d new file mode 100644 index 00000000000..c7cfbd91626 --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-dynamic-relocs.d @@ -0,0 +1,16 @@ +# Test here is to ensure that we only emit one relocation into the GOT for the +# one use of a GOT entry. This is already checked by the fact that the last +# linker command would hit an assertion failure if it were not the case. +# We check that there is only one relocation in the resulting binary anway, +# since double-checking is always nice. +# +# N.b. aarch64-elf.exp compiles a shared libary for this test under +# tmpdir/morello-dynamic-relocs.so. We use that shared library for the test in +# the `ld` command below. +#as: -march=morello+c64 +#ld: tmpdir/morello-dynamic-relocs.so +#readelf: --relocs + +Relocation section '\.rela\.dyn' at offset 0x[0-9a-f]+ contains 1 entry: + Offset Info Type Sym\. Value Sym\. Name \+ Addend +[0-9a-f]+ [0-9a-f]+ R_MORELLO_GLOB_DA 0000000000000000 var \+ 0 diff --git a/ld/testsuite/ld-aarch64/morello-dynamic-relocs.s b/ld/testsuite/ld-aarch64/morello-dynamic-relocs.s new file mode 100644 index 00000000000..6a4e862471b --- /dev/null +++ b/ld/testsuite/ld-aarch64/morello-dynamic-relocs.s @@ -0,0 +1,15 @@ + .arch morello+crc+c64 + .text + .align 2 + .global _start + .type _start, %function +_start: +.LFB0: + .cfi_startproc purecap + adrp c0, :got:var + ldr c0, [c0, #:got_lo12:var] + str wzr, [c0] + ret + .cfi_endproc +.LFE0: + .size _start, .-_start |