[EXTERNAL] Re: [PATCH v2 0/3] aarch64: Relocation fixes and LTO
Martin Storsjö
martin@martin.st
Fri Dec 6 21:10:27 GMT 2024
On Fri, 6 Dec 2024, Evgeny Karpov wrote:
> The example below shows how changes affect the relocation tables.
>
> static int test_static(int* val)
> {
> return *val + 1;
> }
>
> int (*get_test_static(void))(int* val)
> {
> return test_static;
> }
>
> static int first __attribute__((section("section")));
> static int second __attribute__((section("section"))) = 10;
>
> int main() {
> if (get_test_static()(&second) != 11)
> return 1;
>
> return 0;
> }
>
> 1. Without applying the patch and introducing tc_fix_adjustable.
> test_static and second symbols are reduced to section names which leads
> to an increased offset value and the removal of information about the symbol
> that requires relocation.
>
> Offset Type Applied To Index Name
> -------- ---------------- ----------------- -------- ------
> 0000001C PAGEBASE_REL21 90000000 8 .text
> 00000020 PAGEOFFSET_12A 91000000 8 .text
> 00000038 BRANCH26 94000000 12 __main
> 0000003C BRANCH26 94000000 4 get_test_static
> 00000044 PAGEBASE_REL21 90000020 10 section
> 00000048 PAGEOFFSET_12A 91001000 10 section
>
> 2. Introducing tc_fix_adjustable and applying
> + if (S_GET_STORAGE_CLASS (sym) == C_STAT)
> + return false;
>
> RELOCATIONS #1
> Symbol Symbol
> Offset Type Applied To Index Name
> -------- ---------------- ----------------- -------- ------
> 0000001C PAGEBASE_REL21 90000000 0 test_static
> 00000020 PAGEOFFSET_12A 91000000 0 test_static
> 00000038 BRANCH26 94000000 12 __main
> 0000003C BRANCH26 94000000 4 get_test_static
> 00000044 PAGEBASE_REL21 90000020 10 section
> 00000048 PAGEOFFSET_12A 91001000 10 section
>
> 3. Introducing tc_fix_adjustable and applying
>
> + if (S_GET_STORAGE_CLASS (sym) == C_STAT)
> + return false;
> +
> + if (symbol_get_bfdsym (sym)->section->flags & (SEC_DATA | SEC_READONLY))
> + return false;
>
> RELOCATIONS #1
> Symbol Symbol
> Offset Type Applied To Index Name
> -------- ---------------- ----------------- -------- ------
> 0000001C PAGEBASE_REL21 90000000 0 test_static
> 00000020 PAGEOFFSET_12A 91000000 0 test_static
> 00000038 BRANCH26 94000000 15 __main
> 0000003C BRANCH26 94000000 5 get_test_static
> 00000044 PAGEBASE_REL21 90000000 8 second
> 00000048 PAGEOFFSET_12A 91000000 8 second
Thanks, I see!
So this only affects how things are assembled, not how things are linked -
and this prefers doing relocations against symbols rather than against
section+offset. That sounds like a very reasonable way to avoid the issues
around offsets being too large.
I tested this now with assembly input looking like this:
.globl func
func:
adrp x0, symbol
adrp x0, .Lnot_a_symbol
ret
.section .rdata
.word 1
symbol:
.word 2
.Lnot_a_symbol:
.word 3
Previously, I got the following output:
$ aarch64-w64-mingw32-nm aarch64-relocs.o
0000000000000000 t $x
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 T func
0000000000000000 r .rdata
0000000000000004 r symbol
0000000000000000 t .text
$ aarch64-w64-mingw32-objdump -d -r aarch64-relocs.o
0000000000000000 <func>:
0: 90000020 adrp x0, 4000 <symbol+0x3ffc>
0: IMAGE_REL_ARM64_PAGEBASE_REL21 .rdata
4: 90000040 adrp x0, 8000 <symbol+0x7ffc>
4: IMAGE_REL_ARM64_PAGEBASE_REL21 .rdata
8: d65f03c0 ret
Thus, "symbol" was emitted into the symbol table, while .Lnot_a_symbol
wasn't. But the relocations both pointed at the section. After this
change, we get this:
$ aarch64-w64-mingw32-nm aarch64-relocs.o
0000000000000000 t $x
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 T func
0000000000000008 r .Lnot_a_symbol
0000000000000000 r .rdata
0000000000000004 r symbol
0000000000000000 t .text
$ aarch64-w64-mingw32-objdump -d -r aarch64-relocs.o
0000000000000000 <func>:
0: 90000000 adrp x0, 4 <func+0x4>
0: IMAGE_REL_ARM64_PAGEBASE_REL21 symbol
4: 90000000 adrp x0, 8 <func+0x8>
4: IMAGE_REL_ARM64_PAGEBASE_REL21 .Lnot_a_symbol
8: d65f03c0 ret
Thus now both symbol and .Lnot_a_symbol are emitted into the symbol table,
and the relocations point directly at them.
For reference, if assembled with LLVM, I get the following output:
$ ~/binutils-aarch64-mingw/bin/aarch64-w64-mingw32-nm aarch64-relocs.o
0000000000000000 b .bss
0000000000000000 d .data
0000000000000000 T func
0000000000000000 r .rdata
0000000000000004 r symbol
0000000000000000 t .text
$ aarch64-w64-mingw32-objdump -d -r aarch64-relocs.o
0000000000000000 <func>:
0: 90000000 adrp x0, 4 <func+0x4>
0: IMAGE_REL_ARM64_PAGEBASE_REL21 symbol
4: 90000040 adrp x0, 8000 <symbol+0x7ffc>
4: IMAGE_REL_ARM64_PAGEBASE_REL21 .rdata
8: d65f03c0 ret
I.e. we only emit "symbol" but not ".Lnot_a_symbol" to the symbol table,
and we use "symbol" for the relocation, if possible, otherwise we use the
section symbol instead.
So all in all - I don't mind the solution in this patch; it will end up
emitting a lot of symbols into the symbol table that were only meant to be
temporary labels, but that's probably an acceptable compromise.
(In the case of LLVM, it instead generates extra symbols to use instead of
the base of the section, only when the section is too large, and only one
extra symbol per 1 MB interval.)
// Martin
More information about the Binutils
mailing list