Page MenuHomePhabricator

[LLD][ELF][AArch64] Add support for R_AARCH64_LD64_GOTPAGE_LO15 relocation
Needs ReviewPublic

Authored by zatrazz on Wed, Jan 13, 9:35 AM.



It is not used by LLVM, but GCC might generates it when compiling
with -fpie, as indicated by PR#40357 [1].

The testcase depends on to parse
gotpage_lo15 and to set the correct
placement of _GLOBAL_OFFSET_TABLE_ as expected by gcc.

Besides the regression check, I build a llvm (clang;clang-tools-extra;
compiler-rt;lld) with -fpie and -DLLVM_ENABLE_PIC=OFF with
gcc9 with DLLVM_ENABLE_LLD=ON to check if the
R_AARCH64_LD64_GOTPAGE_LO15 is handled correctly on large

The resulted build generates about 445619
R_AARCH64_LD64_GOTPAGE_LO15 relocations and the resulting
llvm shows no regression on check-all.


Diff Detail

Event Timeline

zatrazz created this revision.Wed, Jan 13, 9:35 AM
zatrazz requested review of this revision.Wed, Jan 13, 9:35 AM
Herald added a project: Restricted Project. · View Herald TranscriptWed, Jan 13, 9:35 AM
psmith added a subscriber: psmith.Thu, Jan 14, 8:10 AM

Thanks for working on this. It will be very useful for people using GCC yet using LLD as a linker on AArch64. Will try and take a look later today, if not then I should have some time tomorrow morning.

psmith added inline comments.Thu, Jan 14, 9:31 AM

I think that this should be

return getAArch64Page(sym.getGotVA() + a) - getAArch64Page(>getVA());

From the expression is: G(GDAT(S+A))-Page(GOT)
Where GOT is "GOT is the address of the Global Offset Table"
Page(p) will be the same as Page(GOT) for many entries close to the start of the GOT.

IIUC the intent is to get an offset from the base of the GOT so that the same register can hold the base of the GOT for the whole function.

ldr x1, [x0, #:gotpage_lo15:foo]
ldr x2, [x0, #:gotpage_lo15:bar]

This particular test won't catch the case where Page(GOT) != Page(P). Perhaps something like a linker script that puts the GOT at the last 8-bytes of a page (I think .got is 8 byte aligned on AArch64)

.got (0x10000 - 8) : { *.got }

This would put the first entry in the same page as Page(GOT) but the second entry should be in the second page. This should be visible in the ldr disassembly.

I will update the patch, since it is incomplete and requires .


Indeed it misses the addend in the account. I am not sure if G() should be page aligned as well, the AArch64 ABI is only explict about Page() operation, gold at least does not seem to align it. I think the correct formula is in fact:

return sym.getGotVA() + a - getAArch64Page(>getVA());
zatrazz updated this revision to Diff 317019.Fri, Jan 15, 10:33 AM
zatrazz edited the summary of this revision. (Show Details)

Patch updated from comments, main changes are:

  • Fixed getRelocTargetVA fomula.
  • Fixed some lint issue.
  • Add a got displacement on .got for the test.