Closed statham-arm closed 2 months ago
I think we've got two possibilities.
Add special cases (like in the 32-bit ABI) for ADRP, MOV (wide immediate), MOVZ and MOVK instructions. I see that in the 32-bit ABI these clarifications were added in 2012, which is after the first release of the AArch64 ABI so it seems like we didn't consider the 64-bit ABI at the time, presumably as most implementations were using RELA.
The alternative is to interpret the following line strictly (https://github.com/ARM-software/abi-aa/blob/main/aaelf64/aaelf64.rst#572addends-and-pc-bias)
A RELA format relocation must be used if the initial addend cannot be encoded in the place.
And include addends for scaled immediates in ADRP and MOV (wide immediate), MOVZ and MOVK. An implementation would either need to use RELA relocations or always use a 0 addend and compensate with additional instructions.
I think the addition of a couple of special cases would make a fully SHT_REL implementation much more practical. Many existing open-source linkers cannot mix both REL and RELA relocations for the same section so converting individual relocations to RELA is not always practical.
Thanks. I've created #271 with some proposed wording.
Suppose I have an AArch64 ELF file containing:
For example:
What should the output be? There are two plausible interpretations:
mySymbol+0x123
four times, and each time, extracts a different 16-bit chunk of it to put into x0.mySymbol+0x123
; the next 16 bits ofmySymbol+0x1230000
; the next 16 bits ofmySymbol+0x12300000000
, and finally the high 16 bits ofmySymbol+0x123000000000000
.For the analogous case in AAELF32, this is reasonably clear. §5.6.1.1 "Addends and PC-bias compensation" says (my emphasis):
So in AAELF32, I'd expect that the analogous code would consistently compute
mySymbol+0x123
, and deliver the bottom and top 16 bits of that constant. This also seems sensible because that might plausibly be a thing I'd want. The other interpretation, of shifting each constant, would be useful if it allowed you to consistently relocate the whole instruction sequence to getmySymbol
plus an arbitrary full-width constant, but it doesn't allow that, because the relocations are processed independently, so a carry when adding to the low word can't be accounted for in the high word. So the way AAELF32 has defined it, it's possible to add a small constant to a symbol and load the result via MOVW+MOVT, without having to resort to SHT_RELA to specify a larger addend.But AAELF64 is not so clear. It says this about addends, in §5.7.2 "Addends and PC-bias" (again my emphasis):
It's clear that "scaled as required" should apply to things like branch offsets being interpreted as a multiple of 4 bytes. But it's not clear whether it also means you should scale up implicit addends in MOVK by 16, 32 or 48 bits, or in ADRP by 12 bits.
I think the most useful answer would be no: those addends should be taken to be applied unshifted to the symbol value, for the same reason as in AAELF32. But either way, I think the current wording is unclear.