On Wed, 4 Sep 2024, Martin Storsjö wrote:
On Wed, 4 Sep 2024, Evgeny Karpov wrote:
Monday, September 4, 2024
Martin Storsjö <mar...@martin.st> wrote:
Let's consider the following example, when symbol is located at 3072.
1. Example without the fix
compilation time
adrp x0, (3072 + 256) & ~0xFFF // x0 = 0
add x0, x0, (3072 + 256) & 0xFFF // x0 = 3328
linking time when symbol is relocated with offset 896
adrp x0, (0 + 896) & ~0xFFF // x0 = 0
Why did the 3072 suddenly become 0 here?
The test case which will be compiled.
adrp x0, symbol + 256
add x0, x0, symbol + 256
The numbers which are presented in the example help to clarify
relocation steps.
symbol is located at 3072.
compilation time
adrp x0, symbol + 256
90000000 adrp x0, 0
This is your first error.
As the symbol offset is 256, you will need to encode the offset "256" in
the instruction immediate field. Not "256 >> 12". This is the somewhat
non-obvious part here, but this is the only way symbol offsets can work.
This is how MS tools handle immediates in IMAGE_REL_ARM64_PAGEBASE_REL21,
and LLVM has replicated this bit.
See
https://github.com/llvm/llvm-project/commit/0b7bf7a2e3cb34086d6a05419319fd35ae8dd9a8#diff-502793e1256bca6339a09f5756111a947a2aeb5c600cdd22b2e1679db5ec48b0R162
for the case where I implemented this bit in LLVM.
To show this in action:
$ cat adrp.s
adrp x0, symbol + 256
add x0, x0, :lo12:symbol + 256
$ clang -target aarch64-windows -c adrp.s
$ llvm-objdump -d -r adrp.o
adrp.o: file format coff-arm64
Disassembly of section .text:
0000000000000000 <.text>:
0: 90000800 adrp x0, 0x100000 <.text+0x100000>
0000000000000000: IMAGE_REL_ARM64_PAGEBASE_REL21 symbol
4: 91040000 add x0, x0, #0x100
0000000000000004: IMAGE_REL_ARM64_PAGEOFFSET_12A symbol
The disassembly tool doesn't interpret the immediate correctly (it's not
0x100000, it's 0x100), but the opcode and relocation info is correct.
// Martin