diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp --- a/lld/ELF/Arch/AArch64.cpp +++ b/lld/ELF/Arch/AArch64.cpp @@ -126,6 +126,7 @@ case R_AARCH64_CONDBR19: case R_AARCH64_JUMP26: case R_AARCH64_TSTBR14: + case R_AARCH64_PLT32: return R_PLT_PC; case R_AARCH64_PREL16: case R_AARCH64_PREL32: @@ -325,6 +326,10 @@ checkIntUInt(loc, val, 32, rel); write32le(loc, val); break; + case R_AARCH64_PLT32: + checkInt(loc, val, 32, rel); + write32le(loc, val); + break; case R_AARCH64_ABS64: case R_AARCH64_PREL64: write64le(loc, val); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -556,6 +556,7 @@ case R_AARCH64_PREL64: case R_AARCH64_ADR_PREL_LO21: case R_AARCH64_LD_PREL_LO19: + case R_AARCH64_PLT32: return p + a; } llvm_unreachable("AArch64 pc-relative relocation expected\n"); diff --git a/lld/test/ELF/aarch64-plt32.s b/lld/test/ELF/aarch64-plt32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/aarch64-plt32.s @@ -0,0 +1,29 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs255.s -o %t255.o +// RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs256.s -o %t256.o +// RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/abs257.s -o %t257.o + +// Check for overflow with a R_AACH64_PLT32 relocation. + + .globl _start + _start: +.data + .word foo@PLT - . + 2149589079 + .word foo@PLT - . - 2145378212 + +// RUN: ld.lld -z max-page-size=4096 %t.o %t256.o -o %t2 +// RUN: llvm-objdump -s --section=.data %t2 | FileCheck %s + +// CHECK: Contents of section .data: +// 202158: S = 0x100, A = 0x80202057, P = 0x202158 +// S + A - P = 0xffffff7f +// 20215c: S = 0x100, A = -0x7fdfdfa4, P = 0x20215c +// S + A - P = 0x80000000 +// CHECK-NEXT: 202158 ffffff7f 00000080 + +// RUN: not ld.lld -z max-page-size=4096 %t.o %t255.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 +// OVERFLOW1: relocation R_AARCH64_PLT32 out of range: -2147483649 is not in [-2147483648, 2147483647]; references foo + +// RUN: not ld.lld -z max-page-size=4096 %t.o %t257.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW2 +// OVERFLOW2: relocation R_AARCH64_PLT32 out of range: 2147483648 is not in [-2147483648, 2147483647]; references foo diff --git a/lld/test/ELF/aarch64-undefined-weak-plt32.s b/lld/test/ELF/aarch64-undefined-weak-plt32.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/aarch64-undefined-weak-plt32.s @@ -0,0 +1,16 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +// RUN: ld.lld --image-base=0x10000000 %t.o -o %t +// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s + + .weak target + + .text + .global +_start: + .word target@PLT - . + +// CHECK: Disassembly of section .text: +// CHECK-EMPTY: +// CHECK-NEXT: 0000000010010120 <_start>: +// CHECK-NEXT: 10010120: 00 00 00 00 .word 0x00000000 diff --git a/lld/test/ELF/relocation-plt32-aarch64.s b/lld/test/ELF/relocation-plt32-aarch64.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/relocation-plt32-aarch64.s @@ -0,0 +1,19 @@ +// REQUIRES: aarch64 +// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +// RUN: ld.lld -shared %t.o -o %t.out +// RUN: llvm-objdump -s %t.out | FileCheck %s + +// Check that a PLT entry is generated for R_AARCH64_PLT32 and the caulculation is correct. + +// CHECK: Contents of section .plt: +// CHECK-NEXT: 10290 +// CHECK: Contents of section .data: +// CHECK: 30370 40fffdff +// The calculation is +// 0x10290 (foo@PLT) +// - 0x30370 (.data) +// --------- +// -0x200c0 -> 0xfffdff40 -> 0x40fffdff (little endian) + +.data + .word foo@PLT - .