[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