]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commit
Account for weak undefined symbols in Morello
authorMatthew Malcomson <matthew.malcomson@arm.com>
Fri, 1 Jul 2022 10:48:54 +0000 (11:48 +0100)
committerJohn Baldwin <jhb@FreeBSD.org>
Thu, 1 Sep 2022 23:10:29 +0000 (16:10 -0700)
commit4e308470a2c5a07fcb4c7223b732362b2da90c2e
treebb4d7f3c1801cce2f72e88c0629fd6811e026e46
parent0a22ef87678ba0a564ee54c02803a0d73765ac37
Account for weak undefined symbols in Morello

Originally we believed we had accounted for these symbols within the
existing if conditional.  It turns out that with `-pie
--no-dynamic-linker` on the command line (which causes the `link_info`
member `dynamic_undefined_weak` to be set to 0) such symbols can bypass
elfNN_aarch64_allocate_dynrelocs putting these symbols into the dynamic
symbol table.  Hence we can have such symbols without a dynamic index
and our existing conditionals need to be adjusted.

On further inspection we notice that GOT entries for *hidden* undefined
weak symbols were still getting RELATIVE relocations.  This is quite
unnecessary since it's known that the entry should be the NULL
capability, but on top of that it relies on the runtime to have a
special case to not add the load displacement to RELATIVE relocations
with completely zero fragments.

We make two logical adjustments.
The first is that in our handling of CAPINIT relocations we add a
clause to avoid emitting a relocation for any undefined weak symbol
which we know for certain should end up with the NULL capability at
runtime.  In this clause we ensure that the fragment is completely zero.

The second is around handling GOT entries.  For these we ensure that
elfNN_aarch64_allocate_dynrelocs does not allocate a dynamic relocation
for the GOT entry of such symbols and that
elfNN_aarch64_final_link_relocate leaves the GOT entry empty and without
any relocation.

N.b. in implementing this change the conditionals became quite
confusing.  We split them up quite unnecessarily into different else/if
statements for clarity at the expense of verbosity.

We also add tests to check the behaviour of undefined weak symbols for
dynamically linked PDE's/PIE's/static executables/shared objects.

N.b.2 We also add an extra assert in final_link_relocate.  This function
deals with GOT entries for symbols both in the internal hash table and
not in the hash table.  Binutils decides whether symbols should be in
the hash table or not based on their binding.  WEAK binding symbols are
put in the hash table.  That said, final_link_relocate has a
`weak_undef_p` local flag to describe whether a given symbol is weak
undefined or not.  This flag is defined for both symbols in the hash
table and symbols not in the hash table.

I believe that the only time we have weak_undef_p set in
final_link_relocate when the relevant symbol is not in the hash table is
when we have "removed" a relocation from our work list by modifying it
to be a R_AARCH64_NONE relocation against the STN_UNDEF symbol (e.g.
during TLS relaxation).

Such cases would not fall into the GOT relocation clause.  Hence I don't
think we can ever see weak_undef_p symbols which are not in the hash
table in this clause.  It's worth an assertion to catch the possibility
that this is wrong.
bfd/elfnn-aarch64.c
ld/testsuite/ld-aarch64/aarch64-elf.exp
ld/testsuite/ld-aarch64/morello-undefweak-relocs-PDE.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-undefweak-relocs-PIE.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-undefweak-relocs-no-dyn-linker.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-undefweak-relocs-static-relocs.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-undefweak-relocs-static.d [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-undefweak-relocs.s [new file with mode: 0644]
ld/testsuite/ld-aarch64/morello-weakdefinitions.s [new file with mode: 0644]