normally RELA relocs in BFD should not consider the contents of the
relocated place. The aarch64 psABI is even stricter, it specifies
(section 5.7.16) that all RELA relocs _must_ be idempotent.
Since the inception of the aarch64 BFD backend all the relocs have a
non-zero src_mask, and hence break this invariant. It's normally not
a very visible problem as one can see it only when the relocated place
already contains a non-zero value, which usually only happens sometimes
when using 'ld -r' (or as in the testcase when jumping through hoops to
generate the relocations). Or with alternative toolchains that do encode
stuff in the relocated places with the assumption that a relocation
to that place ignores whatever is there (as they can according to
the psABI).
Golang is such a toolchain and https://github.com/golang/go/issues/39927
is ultimately caused by this problem: the testcase testGCData failing
is caused by the garbage collection data-structure to describe a type
containing pointers to be wrong. It's wrong because a field that's
supposed to contain a file-relative offset (to some gcbits) has a
relocation applied and that relocation has an addend which also is
already part of the go-produced object file (so the addend is
implicitely applied twice).
bfd/
PR ld/30437
* elfnn-aarch64.c (elfNN_aarch64_howto_table): Clear src_mask
if all relocation descriptors.
ld/
* testsuite/ld-aarch64/rela-idempotent.s: New testcase.
* testsuite/ld-aarch64/rela-idempotent.d: New.
* testsuite/ld-aarch64/aarch64-elf.exp: Run it.