diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp index 54b0a84e52137..71a1b1111e429 100644 --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -165,6 +165,8 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s, case R_AARCH64_ADR_GOT_PAGE: case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: return R_AARCH64_GOT_PAGE_PC; + case R_AARCH64_GOTPCREL32: + return R_GOT_PC; case R_AARCH64_NONE: return R_NONE; default: @@ -374,6 +376,7 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel, write32(loc, val); break; case R_AARCH64_PLT32: + case R_AARCH64_GOTPCREL32: checkInt(loc, val, 32, rel); write32(loc, val); break; diff --git a/lld/test/ELF/aarch64-reloc-gotpcrel32.s b/lld/test/ELF/aarch64-reloc-gotpcrel32.s new file mode 100644 index 0000000000000..4d007776a86a7 --- /dev/null +++ b/lld/test/ELF/aarch64-reloc-gotpcrel32.s @@ -0,0 +1,27 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +// RUN: ld.lld %t.o -o %t.so -shared --noinhibit-exec 2>&1 | FileCheck %s --check-prefix=WARN +// RUN: llvm-readelf -S %t.so | FileCheck --check-prefix=SEC %s +// RUN: llvm-objdump --no-print-imm-hex -s -d %t.so | FileCheck %s + +// SEC: .got PROGBITS 0000000000020390 + + .section .data + .globl bar +bar: + + .globl _start +_start: // PC = 0x303a0 +// bar@GOTPCREL = 0x20390 (got entry for `bar`) - 0x303a0 (.) = 0xf0fffeff +// bar@GOTPCREL+4 = 0x20390 (got entry for `bar`) - 0x303a4 (.) + 4 = 0xf0fffeff +// bar@GOTPCREL-4 = 0x20390 (got entry for `bar`) - 0x303a8 (.) - 4 = 0xe4fffeff +// CHECK: Contents of section .data: +// CHECK-NEXT: {{.*}} f0fffeff f0fffeff e4fffeff + .word bar@GOTPCREL + .word bar@GOTPCREL+4 + .word bar@GOTPCREL-4 + +// WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz' +// WARN: relocation R_AARCH64_GOTPCREL32 out of range: {{.*}} is not in [-2147483648, 2147483647]; references 'baz' + .word baz@GOTPCREL+0xffffffff + .word baz@GOTPCREL-0xffffffff diff --git a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def index 30375de420e30..5fb3fa4aeb7be 100644 --- a/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def +++ b/llvm/include/llvm/BinaryFormat/ELFRelocs/AArch64.def @@ -59,6 +59,7 @@ ELF_RELOC(R_AARCH64_ADR_GOT_PAGE, 0x137) ELF_RELOC(R_AARCH64_LD64_GOT_LO12_NC, 0x138) ELF_RELOC(R_AARCH64_LD64_GOTPAGE_LO15, 0x139) ELF_RELOC(R_AARCH64_PLT32, 0x13a) +ELF_RELOC(R_AARCH64_GOTPCREL32, 0x13b) ELF_RELOC(R_AARCH64_TLSGD_ADR_PREL21, 0x200) ELF_RELOC(R_AARCH64_TLSGD_ADR_PAGE21, 0x201) ELF_RELOC(R_AARCH64_TLSGD_ADD_LO12_NC, 0x202) diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp index 496ab18e9b195..6e074b6a63c41 100644 --- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp +++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64ELFObjectWriter.cpp @@ -120,7 +120,8 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, assert((!Target.getSymA() || Target.getSymA()->getKind() == MCSymbolRefExpr::VK_None || - Target.getSymA()->getKind() == MCSymbolRefExpr::VK_PLT) && + Target.getSymA()->getKind() == MCSymbolRefExpr::VK_PLT || + Target.getSymA()->getKind() == MCSymbolRefExpr::VK_GOTPCREL) && "Should only be expression-level modifiers here"); assert((!Target.getSymB() || @@ -206,7 +207,10 @@ unsigned AArch64ELFObjectWriter::getRelocType(MCContext &Ctx, case FK_Data_2: return R_CLS(ABS16); case FK_Data_4: - return R_CLS(ABS32); + return (!IsILP32 && + Target.getAccessVariant() == MCSymbolRefExpr::VK_GOTPCREL) + ? ELF::R_AARCH64_GOTPCREL32 + : R_CLS(ABS32); case FK_Data_8: if (IsILP32) { Ctx.reportError(Fixup.getLoc(), diff --git a/llvm/test/MC/AArch64/elf-reloc-gotpcrel32.s b/llvm/test/MC/AArch64/elf-reloc-gotpcrel32.s new file mode 100644 index 0000000000000..afbcaad9e1dfd --- /dev/null +++ b/llvm/test/MC/AArch64/elf-reloc-gotpcrel32.s @@ -0,0 +1,14 @@ +// RUN: llvm-mc -triple=aarch64 -filetype=obj %s -o - | \ +// RUN: llvm-readobj -r - | FileCheck %s + + .section .data +this: + .word this@GOTPCREL + .word extern_sym@GOTPCREL+4 + .word negative_offset@GOTPCREL-4 + +// CHECK: Section ({{.*}}) .rela.data +// CHECK-NEXT: 0x0 R_AARCH64_GOTPCREL32 this 0x0 +// CHECK-NEXT: 0x4 R_AARCH64_GOTPCREL32 extern_sym 0x4 +// CHECK-NEXT: 0x8 R_AARCH64_GOTPCREL32 negative_offset 0xFFFFFFFFFFFFFFFC +// CHECK-NEXT: }