[lld] 723b5a1 - [lld][ELF][AArch64] Handle R_AARCH64_PLT32 relocation
Leonard Chan via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 23 16:10:26 PDT 2020
Author: Leonard Chan
Date: 2020-06-23T16:10:07-07:00
New Revision: 723b5a1785426245e3c56b4666ef526b32be84a9
URL: https://github.com/llvm/llvm-project/commit/723b5a1785426245e3c56b4666ef526b32be84a9
DIFF: https://github.com/llvm/llvm-project/commit/723b5a1785426245e3c56b4666ef526b32be84a9.diff
LOG: [lld][ELF][AArch64] Handle R_AARCH64_PLT32 relocation
This is the followup to D77647 which implements handling for the new
R_AARCH64_PLT32 relocation type in lld. This relocation would benefit the
PIC-friendly vtables feature described in D72959.
Differential Revision: https://reviews.llvm.org/D81184
Added:
lld/test/ELF/aarch64-range-thunk-extension-plt32.s
lld/test/ELF/aarch64-reloc-plt32.s
Modified:
lld/ELF/Arch/AArch64.cpp
lld/ELF/InputSection.cpp
lld/ELF/Thunks.cpp
lld/test/ELF/aarch64-undefined-weak.s
Removed:
################################################################################
diff --git a/lld/ELF/Arch/AArch64.cpp b/lld/ELF/Arch/AArch64.cpp
index 704ef1a84012..637046e90bbd 100644
--- a/lld/ELF/Arch/AArch64.cpp
+++ b/lld/ELF/Arch/AArch64.cpp
@@ -126,6 +126,7 @@ RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
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:
@@ -244,7 +245,8 @@ bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
// ELF for the ARM 64-bit architecture, section Call and Jump relocations
// only permits range extension thunks for R_AARCH64_CALL26 and
// R_AARCH64_JUMP26 relocation types.
- if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
+ if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26 &&
+ type != R_AARCH64_PLT32)
return false;
uint64_t dst = expr == R_PLT_PC ? s.getPltVA() : s.getVA(a);
return !inBranchRange(type, branchAddr, dst);
@@ -258,11 +260,13 @@ uint32_t AArch64::getThunkSectionSpacing() const {
}
bool AArch64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
- if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
+ if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26 &&
+ type != R_AARCH64_PLT32)
return true;
// The AArch64 call and unconditional branch instructions have a range of
- // +/- 128 MiB.
- uint64_t range = 128 * 1024 * 1024;
+ // +/- 128 MiB. The PLT32 relocation supports a range up to +/- 2 GiB.
+ uint64_t range =
+ type == R_AARCH64_PLT32 ? (UINT64_C(1) << 31) : (128 * 1024 * 1024);
if (dst > src) {
// Immediate of branch is signed.
range -= 4;
@@ -325,6 +329,10 @@ void AArch64::relocate(uint8_t *loc, const Relocation &rel,
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
index d439db0039db..33bad9fbb0ef 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -556,6 +556,7 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t type, uint64_t a,
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/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 6f0d16ae6796..744ceaf725cf 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -838,7 +838,8 @@ Thunk::Thunk(Symbol &d, int64_t a) : destination(d), addend(a), offset(0) {}
Thunk::~Thunk() = default;
static Thunk *addThunkAArch64(RelType type, Symbol &s, int64_t a) {
- if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
+ if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26 &&
+ type != R_AARCH64_PLT32)
fatal("unrecognized relocation type");
if (config->picThunk)
return make<AArch64ADRPThunk>(s, a);
diff --git a/lld/test/ELF/aarch64-range-thunk-extension-plt32.s b/lld/test/ELF/aarch64-range-thunk-extension-plt32.s
new file mode 100644
index 000000000000..20b497fcb67e
--- /dev/null
+++ b/lld/test/ELF/aarch64-range-thunk-extension-plt32.s
@@ -0,0 +1,36 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
+// RUN: echo 'SECTIONS { \
+// RUN: .text.1 0x10000 : { *(.text.1) } \
+// RUN: .text.2 0x200000000 : AT(0x20000) { *(.text.2) } \
+// RUN: } ' > %t.script
+// RUN: ld.lld --script %t.script %t.o -o %t
+// RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t | FileCheck %s
+
+// The word should be an offset to the range extension thunk.
+// CHECK-LABEL: <_start>:
+// CHECK-NEXT: 10000: 04 00 00 00 .word 0x00000004
+
+// The thunk redirects to the address of callee.
+// CHECK-LABEL: <__AArch64AbsLongThunk_callee>:
+// CHECK-NEXT: 10004: ldr x16, 0x1000c <$d>
+// CHECK-NEXT: 10008: br x16
+
+// CHECK-LABEL: <$d>:
+// CHECK-NEXT: 1000c: 00 00 00 00 .word 0x00000000
+// CHECK-NEXT: 10010: 02 00 00 00 .word 0x00000002
+
+// CHECK-LABEL: <callee>:
+// CHECK-NEXT: 200000000: ret
+
+ .section .text.1, "ax", %progbits
+ .global _start
+ .type _start, %function
+_start:
+ .word callee at PLT - .
+
+ .section .text.2, "ax", %progbits
+ .global callee
+ .type callee, %function
+callee:
+ ret
diff --git a/lld/test/ELF/aarch64-reloc-plt32.s b/lld/test/ELF/aarch64-reloc-plt32.s
new file mode 100644
index 000000000000..a7467562b2db
--- /dev/null
+++ b/lld/test/ELF/aarch64-reloc-plt32.s
@@ -0,0 +1,32 @@
+// 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.
+
+// 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
+/// 202160: S = 0x100, A = 0, P = 0x202160
+/// S + A - P = 0xffdfdfa0
+// CHECK-NEXT: 202158 ffffff7f 00000080 a0dfdfff
+
+// 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
+
+ .globl _start
+ _start:
+.data
+ .word foo at PLT - . + 2149589079
+ .word foo at PLT - . - 2145378212
+ .word foo at PLT - .
diff --git a/lld/test/ELF/aarch64-undefined-weak.s b/lld/test/ELF/aarch64-undefined-weak.s
index 839dd8d14d61..9a4b7c23aa7a 100644
--- a/lld/test/ELF/aarch64-undefined-weak.s
+++ b/lld/test/ELF/aarch64-undefined-weak.s
@@ -33,6 +33,8 @@ _start:
.xword target - .
// R_AARCH64_PREL16
.hword target - .
+// R_AARCH64_PLT32
+ .word target at PLT - .
// CHECK: Disassembly of section .text:
// CHECK-EMPTY:
@@ -47,4 +49,5 @@ _start:
// CHECK: 1001013c: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 10010140: 00 00 00 00 .word 0x00000000
// CHECK-NEXT: 10010144: 00 00 00 00 .word 0x00000000
-// CHECK-NEXT: 10010148: 00 00 .short 0x0000
+// CHECK-NEXT: 10010148: 00 00 00 00 .word 0x00000000
+// CHECK-NEXT: 1001014c: 00 00 .short 0x0000
More information about the llvm-commits
mailing list