Closed PiJoules closed 9 months ago
LGTM as well -- merging as I'm the second to look at it.
Thanks for the addition. I think another advantage introducing the data relocation is that: -shared -fpic -fexperimental-relative-c++-abi-vtables
builds will not create PLT entries for functions in the vtables, as long as they are not directly called.
I don't understand the equation for this relocation G(GDAT(S+A)) - P
. Section 5.7.33 Relocation operations says:
GDAT(S+A)
represents a pointer-sized entry in theGOT
for addressS+A
. The entry will be relocated at run time with relocationR_<CLS>_GLOB_DAT(S+A)
Based on the LLD implementation of this relocation though (https://github.com/llvm/llvm-project/pull/72584), it seems the addend is applied to the place of the relocation, not the GOT entry. See the added test case for what I mean. The relocations in the object file are:
$ bin/llvm-readelf -rW tools/lld/test/ELF/Output/aarch64-reloc-gotpcrel32.s.tmp.o
Relocation section '.rela.data' at offset 0xd0 contains 5 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000000000 000000020000013b R_AARCH64_GOTPCREL32 0000000000000000 bar + 0
0000000000000004 000000020000013b R_AARCH64_GOTPCREL32 0000000000000000 bar + 4
0000000000000008 000000020000013b R_AARCH64_GOTPCREL32 0000000000000000 bar - 4
000000000000000c 000000040000013b R_AARCH64_GOTPCREL32 0000000000000000 baz + ffffffff
0000000000000010 000000040000013b R_AARCH64_GOTPCREL32 0000000000000000 baz - ffffffff
The relocations in the output SO are:
$ bin/llvm-readelf -rW tools/lld/test/ELF/Output/aarch64-reloc-gotpcrel32.s.tmp.so
Relocation section '.rela.dyn' at offset 0x2c0 contains 2 entries:
Offset Info Type Symbol's Value Symbol's Name + Addend
0000000000020398 0000000100000401 R_AARCH64_GLOB_DAT 0000000000000000 baz + 0
0000000000020390 0000000200000401 R_AARCH64_GLOB_DAT 00000000000303a0 bar + 0
So the addend isn't propagated to the dynamic relocations, which GDAT(S+A)
would imply in my reading. Instead, I believe the equation should be:
G(GDAT(S)) + A - P
This also better matches R_X86_64_GOTPCREL
, which is defined as G + GOT + A - P
, where G
is the GOT offset for the symbol and GOT
is the GOT address. I belive R_ARM_GOT_PREL
is the AArch32 equivalent, and that's also defined as GOT(S) + A - P
, where GOT(S)
is the address of the GOT entry for S. Am I missing something?
I don't understand the equation for this relocation
G(GDAT(S+A)) - P
. Section 5.7.33 Relocation operations says:
GDAT(S+A)
represents a pointer-sized entry in theGOT
for addressS+A
. The entry will be relocated at run time with relocationR_<CLS>_GLOB_DAT(S+A)
Based on the LLD implementation of this relocation though (llvm/llvm-project#72584), it seems the addend is applied to the place of the relocation, not the GOT entry. See the added test case for what I mean. The relocations in the object file are:
$ bin/llvm-readelf -rW tools/lld/test/ELF/Output/aarch64-reloc-gotpcrel32.s.tmp.o Relocation section '.rela.data' at offset 0xd0 contains 5 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000000000 000000020000013b R_AARCH64_GOTPCREL32 0000000000000000 bar + 0 0000000000000004 000000020000013b R_AARCH64_GOTPCREL32 0000000000000000 bar + 4 0000000000000008 000000020000013b R_AARCH64_GOTPCREL32 0000000000000000 bar - 4 000000000000000c 000000040000013b R_AARCH64_GOTPCREL32 0000000000000000 baz + ffffffff 0000000000000010 000000040000013b R_AARCH64_GOTPCREL32 0000000000000000 baz - ffffffff
The relocations in the output SO are:
$ bin/llvm-readelf -rW tools/lld/test/ELF/Output/aarch64-reloc-gotpcrel32.s.tmp.so Relocation section '.rela.dyn' at offset 0x2c0 contains 2 entries: Offset Info Type Symbol's Value Symbol's Name + Addend 0000000000020398 0000000100000401 R_AARCH64_GLOB_DAT 0000000000000000 baz + 0 0000000000020390 0000000200000401 R_AARCH64_GLOB_DAT 00000000000303a0 bar + 0
So the addend isn't propagated to the dynamic relocations, which
GDAT(S+A)
would imply in my reading. Instead, I believe the equation should be:G(GDAT(S)) + A - P
This also better matches
R_X86_64_GOTPCREL
, which is defined asG + GOT + A - P
, whereG
is the GOT offset for the symbol andGOT
is the GOT address. I beliveR_ARM_GOT_PREL
is the AArch32 equivalent, and that's also defined asGOT(S) + A - P
, whereGOT(S)
is the address of the GOT entry for S. Am I missing something?
No you're correct. The addend should be applied to where the relocation is located, not to symbol we're taking the GOT entry for. The relocation is intended to be similar to R_X86_64_GOTPCREL
as you said. I'll send out a followup fix. Sorry for the confusion.
Thanks for the confirmation and follow-up!
Apologies for the delayed response, just come back from vacation.
It is worth mentioning that there is a generic ABI issue with how GOT relative addends are represented in the AArch64 ABI https://github.com/ARM-software/abi-aa/issues/217 it looks like this instance may fall into that category. To summarise it looks like neither LLD, Mold, Gold or GNU ld implement GDAT(S+A)
as written in the spec. Moreover they don't implement it in a consistent way either, with lld doing GDAT(S) + A
and GNU ld just ignoring the A
.
So far there hasn't been a satisfactory resolution as it's not clear what all the linker's can support. Probably best leave any further comments on https://github.com/ARM-software/abi-aa/issues/217
I'll leave a comment in https://github.com/ARM-software/abi-aa/pull/247 too
This introduces a new relocation_GOTREL32”, but instead evaluates to the 32-bit offset between a GOT entry for a given symbol and the current location where the relocation is applied, so its equation would be “G(GDAT(S+A))- P”.
R\_<CLS>\_GOTPCREL32
which follows the existing wording to “R_