summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Smith <peter.smith@linaro.org>2019-01-16 12:09:13 +0000
committerPeter Smith <peter.smith@linaro.org>2019-01-16 12:09:13 +0000
commit54fb3f658780179d46c8f12b79c1482887464a26 (patch)
tree3bb4916c6a6ae134045867e2f1cec614f7242322
parent87c4b3e0c47d5d178e8a9a4833d6171f2a8aa070 (diff)
[ELF] Implement option to force PIC compatible Thunks
By default LLD will generate position independent Thunks when the --pie or --shared option is used. Reference to absolute addresses is permitted in other cases. For some embedded systems position independent thunks are needed for code that executes before the MMU has been set up. The option --pic-veneer is used by ld.bfd to force position independent thunks. The patch adds --pic-veneer as the option is needed for the Linux kernel on Arm. fixes pr39886 Differential Revision: https://reviews.llvm.org/D55505
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/Driver.cpp1
-rw-r--r--lld/ELF/Options.td3
-rw-r--r--lld/ELF/Thunks.cpp10
-rw-r--r--lld/docs/ld.lld.12
-rw-r--r--lld/test/ELF/arm-force-pi-thunk.s87
6 files changed, 99 insertions, 5 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 8fb760e592e..60555f188fe 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -159,6 +159,7 @@ struct Configuration {
bool OFormatBinary;
bool Omagic;
bool OptRemarksWithHotness;
+ bool PicThunk;
bool Pie;
bool PrintGcSections;
bool PrintIcfSections;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 13b6119e2dc..2e2036310fb 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -1006,6 +1006,7 @@ static void setConfigs(opt::InputArgList &Args) {
Config->Endianness = Config->IsLE ? endianness::little : endianness::big;
Config->IsMips64EL = (K == ELF64LEKind && M == EM_MIPS);
Config->Pic = Config->Pie || Config->Shared;
+ Config->PicThunk = Args.hasArg(OPT_pic_veneer, Config->Pic);
Config->Wordsize = Config->Is64 ? 8 : 4;
// ELF defines two different ways to store relocation addends as shown below:
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index e43a21b923d..bc203193661 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -255,6 +255,9 @@ defm use_android_relr_tags: B<"use-android-relr-tags",
"Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
"Use SHT_RELR / DT_RELR* tags (default)">;
+def pic_veneer: F<"pic-veneer">,
+ HelpText<"Always generate position independent thunks (veneers)">;
+
defm pie: B<"pie",
"Create a position independent executable",
"Do not create a position independent executable (default)">;
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index 95b57dc0db4..7a31d36b0e9 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -722,7 +722,7 @@ Thunk::~Thunk() = default;
static Thunk *addThunkAArch64(RelType Type, Symbol &S) {
if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26)
fatal("unrecognized relocation type");
- if (Config->Pic)
+ if (Config->PicThunk)
return make<AArch64ADRPThunk>(S);
return make<AArch64ABSLongThunk>(S);
}
@@ -739,7 +739,7 @@ static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) {
case R_ARM_JUMP24:
case R_ARM_CALL:
case R_ARM_THM_CALL:
- if (Config->Pic)
+ if (Config->PicThunk)
return make<ARMV5PILongThunk>(S);
return make<ARMV5ABSLongThunk>(S);
}
@@ -794,13 +794,13 @@ static Thunk *addThunkArm(RelType Reloc, Symbol &S) {
case R_ARM_PLT32:
case R_ARM_JUMP24:
case R_ARM_CALL:
- if (Config->Pic)
+ if (Config->PicThunk)
return make<ARMV7PILongThunk>(S);
return make<ARMV7ABSLongThunk>(S);
case R_ARM_THM_JUMP19:
case R_ARM_THM_JUMP24:
case R_ARM_THM_CALL:
- if (Config->Pic)
+ if (Config->PicThunk)
return make<ThumbV7PILongThunk>(S);
return make<ThumbV7ABSLongThunk>(S);
}
@@ -820,7 +820,7 @@ static Thunk *addThunkPPC64(RelType Type, Symbol &S) {
if (S.isInPlt())
return make<PPC64PltCallStub>(S);
- if (Config->Pic)
+ if (Config->PicThunk)
return make<PPC64PILongBranchThunk>(S);
return make<PPC64PDLongBranchThunk>(S);
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index d1ce4a3517f..889d5feabe4 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -311,6 +311,8 @@ Write optimization remarks in YAML format to
.Ar file .
.It Fl -opt-remarks-with-hotness
Include hotness information in the optimization remarks file.
+.It Fl -pic-veneer
+Always generate position independent thunks.
.It Fl -pie
Create a position independent executable.
.It Fl -print-gc-sections
diff --git a/lld/test/ELF/arm-force-pi-thunk.s b/lld/test/ELF/arm-force-pi-thunk.s
new file mode 100644
index 00000000000..2c88de0424e
--- /dev/null
+++ b/lld/test/ELF/arm-force-pi-thunk.s
@@ -0,0 +1,87 @@
+// REQUIRES: arm
+// RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: echo "SECTIONS { \
+// RUN: . = SIZEOF_HEADERS; \
+// RUN: .text_low : { *(.text_low) *(.text_low2) } \
+// RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \
+// RUN: } " > %t.script
+// RUN: ld.lld --pic-veneer --script %t.script %t -o %t2 2>&1
+// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s
+
+// Test that we can force generation of position independent thunks even when
+// inputs are not pic.
+
+ .syntax unified
+ .section .text_low, "ax", %progbits
+ .thumb
+ .globl _start
+_start: bx lr
+ .globl low_target
+ .type low_target, %function
+low_target:
+ bl high_target
+ bl high_target2
+
+ .section .text_low2, "ax", %progbits
+ .thumb
+ .globl low_target2
+ .type low_target2, %function
+low_target2:
+ bl high_target
+ bl high_target2
+
+// CHECK: Disassembly of section .text_low:
+// CHECK-NEXT: _start:
+// CHECK-NEXT: 94: 70 47 bx lr
+// CHECK: low_target:
+// CHECK-NEXT: 96: 00 f0 03 f8 bl #6
+// CHECK-NEXT: 9a: 00 f0 07 f8 bl #14
+// CHECK-NEXT: 9e: d4 d4 bmi #-88
+// CHECK: __ThumbV7PILongThunk_high_target:
+// CHECK-NEXT: a0: 4f f6 55 7c movw r12, #65365
+// CHECK-NEXT: a4: c0 f2 ff 1c movt r12, #511
+// CHECK-NEXT: a8: fc 44 add r12, pc
+// CHECK-NEXT: aa: 60 47 bx r12
+// CHECK: __ThumbV7PILongThunk_high_target2:
+// CHECK-NEXT: ac: 4f f6 69 7c movw r12, #65385
+// CHECK-NEXT: b0: c0 f2 ff 1c movt r12, #511
+// CHECK-NEXT: b4: fc 44 add r12, pc
+// CHECK-NEXT: b6: 60 47 bx r12
+// CHECK: low_target2:
+// CHECK-NEXT: b8: ff f7 f2 ff bl #-28
+// CHECK-NEXT: bc: ff f7 f6 ff bl #-20
+
+
+ .section .text_high, "ax", %progbits
+ .thumb
+ .globl high_target
+ .type high_target, %function
+high_target:
+ bl low_target
+ bl low_target2
+
+ .section .text_high2, "ax", %progbits
+ .thumb
+ .globl high_target2
+ .type high_target2, %function
+high_target2:
+ bl low_target
+ bl low_target2
+
+// CHECK: Disassembly of section .text_high:
+// CHECK-NEXT: high_target:
+// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4
+// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12
+// CHECK: __ThumbV7PILongThunk_low_target:
+// CHECK-NEXT: 2000008: 40 f2 83 0c movw r12, #131
+// CHECK-NEXT: 200000c: cf f6 00 6c movt r12, #65024
+// CHECK-NEXT: 2000010: fc 44 add r12, pc
+// CHECK-NEXT: 2000012: 60 47 bx r12
+// CHECK: __ThumbV7PILongThunk_low_target2:
+// CHECK-NEXT: 2000014: 40 f2 99 0c movw r12, #153
+// CHECK-NEXT: 2000018: cf f6 00 6c movt r12, #65024
+// CHECK-NEXT: 200001c: fc 44 add r12, pc
+// CHECK-NEXT: 200001e: 60 47 bx r12
+// CHECK: high_target2:
+// CHECK-NEXT: 2000020: ff f7 f2 ff bl #-28
+// CHECK-NEXT: 2000024: ff f7 f6 ff bl #-20