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

Reply via email to