Monday, September 2, 2024
Martin Storsjö <mar...@martin.st> wrote:

> The only non-obvious thing, is that for IMAGE_REL_ARM64_PAGEBASE_REL21,
> i.e. "adrp" instructions, the immediate that gets stored in the
> instruction, is the byte offset to the symbol.
>
> After linking, when the instruction is interpreted at execution time, the
> immediate in an adrp instruction denotes the offset in units of 2^12 bytes
> - but in relocatable object files, the unit of the immediate is in single
> bytes.

This is exactly the reason why the fix was introduced, and it resolves
the issues detected during testing.
Here is a more detailed explanation.

1. the code without the fix
adrp        x0, symbol + 256
add         x0, x0, symbol + 256

2. the code with the fix
adrp        x0, symbol
add         x0, x0, symbol
add         x0, x0, 256


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
add         x0, x0, (3328 + 896) & 0xFFF; // x0 = 128
which is wrong. it should be x0 = 3072 + 896 + 256 = 4224

2. Example with the fix
compilation time
adrp        x0, 3072 & ~0xFFF // x0 = 0
add         x0, x0, 3072 & 0xFFF // x0 = 3072
add         x0, x0, 256 // x0 = 3328

linking time when symbol is relocated with offset 896
adrp        x0, (0 + 896) & ~0xFFF // x0 = 0
add         x0, x0, (3072 + 896) & 0xFFF // x0 = 3968
add         x0, x0, 256 // x0 = 4224
x0 contains expected result.

Theoretically, the issue can be solved by changing the alignment of segments
to 4096. It might require further investigation and a follow-up patch if it 
works.
Even if it works, it has a downside as it increases the segment sizes.

Regards,
Evgeny

Reply via email to