Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -140,7 +140,8 @@ Type = Target->getPltRefReloc(Type); } else if (Target->relocNeedsGot(Type, Body)) { SymVA = Out::Got->getEntryAddr(Body); - Type = Body.isTLS() ? Target->getTlsGotReloc() : Target->getGotRefReloc(); + Type = Body.isTLS() ? Target->getTlsGotReloc() + : Target->getGotRefReloc(Type); } else if (Target->relocPointsToGot(Type)) { SymVA = Out::Got->getVA(); Type = Target->getPCRelReloc(); Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -27,7 +27,6 @@ unsigned getPCRelReloc() const { return PCRelReloc; } unsigned getGotReloc() const { return GotReloc; } unsigned getPltReloc() const { return PltReloc; } - unsigned getGotRefReloc() const { return GotRefReloc; } unsigned getRelativeReloc() const { return RelativeReloc; } unsigned getTlsGotReloc() const { return TlsGotReloc; } unsigned getTlsPcRelGotReloc() const { return TlsPcRelGotReloc; } @@ -44,6 +43,7 @@ bool supportsLazyRelocations() const { return LazyRelocations; } unsigned getGotHeaderEntriesNum() const { return GotHeaderEntriesNum; } unsigned getGotPltHeaderEntriesNum() const { return GotPltHeaderEntriesNum; } + virtual unsigned getGotRefReloc(unsigned Type) const; virtual unsigned getPltRefReloc(unsigned Type) const; virtual void writeGotHeaderEntries(uint8_t *Buf) const; virtual void writeGotPltHeaderEntries(uint8_t *Buf) const; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -94,6 +94,7 @@ class AArch64TargetInfo final : public TargetInfo { public: AArch64TargetInfo(); + unsigned getGotRefReloc(unsigned Type) const override; unsigned getPltRefReloc(unsigned Type) const override; void writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const override; void writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr, @@ -153,6 +154,8 @@ return false; } +unsigned TargetInfo::getGotRefReloc(unsigned Type) const { return GotRefReloc; } + unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; } bool TargetInfo::relocPointsToGot(uint32_t Type) const { return false; } @@ -608,12 +611,15 @@ } AArch64TargetInfo::AArch64TargetInfo() { + GotReloc = R_AARCH64_GLOB_DAT; PltReloc = R_AARCH64_JUMP_SLOT; LazyRelocations = true; PltEntrySize = 16; PltZeroEntrySize = 32; } +unsigned AArch64TargetInfo::getGotRefReloc(unsigned Type) const { return Type; } + unsigned AArch64TargetInfo::getPltRefReloc(unsigned Type) const { return Type; } void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const { @@ -663,7 +669,13 @@ bool AArch64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const { - return relocNeedsPlt(Type, S); + switch (Type) { + default: + return relocNeedsPlt(Type, S); + case R_AARCH64_ADR_GOT_PAGE: + case R_AARCH64_LD64_GOT_LO12_NC: + return true; + } } bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type, @@ -724,10 +736,14 @@ updateAArch64Adr(Loc, X & 0x1FFFFF); break; } + case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_ADR_PREL_PG_HI21: { uint64_t X = getAArch64Page(SA) - getAArch64Page(P); - if (!isInt<33>(X)) + if (!isInt<33>(X)) { + if (Type == R_AARCH64_ADR_GOT_PAGE) + error("Relocation R_AARCH64_ADR_GOT_PAGE out of range"); error("Relocation R_AARCH64_ADR_PREL_PG_HI21 out of range"); + } updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12] break; } @@ -746,6 +762,12 @@ // No overflow check needed. or32le(Loc, (SA & 0xFFC) << 8); break; + case R_AARCH64_LD64_GOT_LO12_NC: + if (SA & 0x7) + error("Relocation R_AARCH64_LD64_GOT_LO12_NC not aligned"); + // No overflow check needed. + or32le(Loc, (SA & 0xFF8) << 7); + break; case R_AARCH64_LDST64_ABS_LO12_NC: // No overflow check needed. or32le(Loc, (SA & 0xFF8) << 7); Index: test/ELF/got-aarch64.s =================================================================== --- /dev/null +++ test/ELF/got-aarch64.s @@ -0,0 +1,40 @@ +// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t.so +// RUN: llvm-readobj -s -r %t.so | FileCheck %s +// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s +// REQUIRES: aarch64 + +// CHECK: Name: .got +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_WRITE +// CHECK-NEXT: ] +// CHECK-NEXT: Address: 0x2098 +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 8 +// CHECK-NEXT: Link: 0 +// CHECK-NEXT: Info: 0 +// CHECK-NEXT: AddressAlignment: 8 + +// CHECK: Relocations [ +// CHECK-NEXT: Section ({{.*}}) .rela.dyn { +// CHECK-NEXT: 0x2098 R_AARCH64_GLOB_DAT dat 0x0 +// CHECK-NEXT: } +// CHECK-NEXT: ] + +// Page(0x2098) - Page(0x1000) = 0x1000 = 4096 +// 0x2098 & 0xff8 = 0x98 = 152 + +// DISASM: main: +// DISASM-NEXT: 1000: {{.*}} adrp x0, #4096 +// DISASM-NEXT: 1004: {{.*}} ldr x0, [x0, #152] + +.global main,foo,dat +.text +main: + adrp x0, :got:dat + ldr x0, [x0, :got_lo12:dat] +.data +dat: + .word 42