lld dynamic relocation creation issue

Hi all,

Working on lld aarch64 support I came across an issue where I am not sure which
would be best design approach to solve.

The aarch64 R_AARCH64_ABS64 relocation for PIC/PIE build requires a dynamic
relocation (R_AARCH64_RELATIVE) with the value set as the addend of the
relocation. For instance, when linking the crtbeginS.o which contains:

Relocation section '.rela.init_array' at offset 0xd28 contains 1 entries:
  Offset Info Type Sym. Value Sym. Name + Addend
000000000000 000200000101 R_AARCH64_ABS64 0000000000000000 .text + d4

The resulting dynamic relocation on the shared object should be:

Relocation section '.rela.dyn' at offset 0x548 contains 10 entries:
  Offset Info Type Sym. Value Sym. Name + Addend
000000010dc0 000000000403 R_AARCH64_RELATIV 7a8

Where 0x7a8 (dynamic relocation r_addend) points to a function at
.text segment (in this case frame_dummy).

I am trying to made this on lld, but current step sequence is:

- Write::run
  \_ Write::createSections
     \_ Write::scanRelocs
        \_ Write::addReloc // Dynamic Relocation creation
  \_ Write::writeSections
     \_ OutputSectionBase::writeTo
        \_ InputSection::writeTo
           \_ InputSection::relocate
              \_ TargetInfo::relocateOne

The problem is only at TargetInfo::relocate the target (aarch64) will see
that the relocation is a R_AARCH64_ABS64 one and thus will need to create
a dynamic R_AARCH64_RELATIVE relocation.

Also from comments at ELF/Writer.cpp:243 I noted that scanRelocs is done
early as a design choice. So I am not sure if it would be best to follow
the second idea of the comment (and do the scan later *after* the relocations
is computed) or if it would be better to allow the TargetInfo add a scan
phase to handle such things (as other linker does).

Suggestions, tips, advices?

We are refactoring the relocation generation code, but currently Writer::scanReloc adds relocation entries for the dynamic relocations. If “Out::RelaDyn->addReloc({&C, &RI});” is not called for your relocation, then no dynamic relocation will be created for that.

What do you currently get? You didn’t see any dynamic relocations for R_AACH_ABS64 relocs, do you?

We are refactoring the relocation generation code, but currently Writer::scanReloc adds relocation entries for the dynamic relocations. If "Out<ELFT>::RelaDyn->addReloc({&C, &RI});" is not called for your relocation, then no dynamic relocation will be created for that.

What do you currently get? You didn't see any dynamic relocations for R_AACH_ABS64 relocs, do you?

Current there is no dynamic relocation creation for R_AARCH64_ABS64, which leads
to invalid shared objects due invalid relocation against .{init,fini}_array.

If I specifically set needsDynRelative to return true for R_AARCH64_ABS64 in
PIC/PIE and set RelativeRel to the expected type (R_AARCH64_RELATIVE) I do see
dynamic relocation being generated, with wrong target:

Relocation section '.rela.dyn' at offset 0x4d8 contains 10 entries:
  Offset Info Type Sym. Value Sym. Name + Addend
000000002000 000000000403 R_AARCH64_RELATIV 0

Disassembly of section .init_array:

0000000000002000 <__frame_dummy_init_array_entry>:
    2000: 000010e8 .word 0x000010e8
    2004: 00000000 .word 0x00000000

00000000000010e8 <frame_dummy>:
    10e8: a9bf7bfd stp x29, x30, [sp,#-16]!

The R_AARCH64_ABS64 relocation will be place in '.init_array' section, but its
value '0x10e8' (which points to the frame_dummy) should be used instead as the
r_addend of the R_AARCH64_RELATIVE (because libc itself does not consider the
value of the relocation itself, just the map address plus the dynamic relocation
addend value).

That's why I need to instruct a dynamic creation not in scanRolocs, but rather
in relocateOne with the correct value of R_AARCH64_ABS64 to use it as the
addend of the dynamic R_AARCH64_RELATIVE. And my doubt is exactly on how to
design it on lld, where all the dynamic relocation are only create before
any actual relocation computation.

My first idea is to add a method 'InputSectionBase<ELFT>::addDynamicReloc'
and then pass the InputSection on TargetInfo::relocateOne, but I am not
sure if it would desirable.

r259829 should hopefully make this easier for you.

Note that a similar issues exists in other ABIs. With x86_64, a file with just

foo:
.quad foo

will create a .o that has

  0x0 R_X86_64_64 .text 0x0

and running "ld.lld test.o -o test.so -shared" creates a .so file with

    0x1000 R_X86_64_RELATIVE - 0x1000

Cheers,
Rafael