summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2016-05-05 19:41:49 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2016-05-05 19:41:49 +0000
commit66434562e7cdb4671821cbe50ec8c15fe5fff078 (patch)
treef22f73e817e8a48ef70e84d26c618001f504a9a8
parent188a7c5f9e3ed9a40740bc0f878fb3b2908c1863 (diff)
downloadbcm5719-llvm-66434562e7cdb4671821cbe50ec8c15fe5fff078.tar.gz
bcm5719-llvm-66434562e7cdb4671821cbe50ec8c15fe5fff078.zip
Fix copy relocations in pie.
We were creating the copy relocations just fine, but then thinking that the .bss position could be preempted and creating a dynamic relocation to it, which would crash at runtime since that memory is read only. llvm-svn: 268668
-rw-r--r--lld/ELF/Symbols.cpp6
-rw-r--r--lld/ELF/Writer.cpp7
-rw-r--r--lld/test/ELF/Inputs/copy-rel-pie.s9
-rw-r--r--lld/test/ELF/copy-rel-pie.s44
-rw-r--r--lld/test/ELF/mips-got-and-copy.s18
-rw-r--r--lld/test/ELF/relro.s2
6 files changed, 72 insertions, 14 deletions
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index 2768f1865a2..798e8c6d17a 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -113,9 +113,11 @@ bool SymbolBody::isPreemptible() const {
if (isLocal())
return false;
- // Shared symbols resolve to the definition in the DSO.
+ // Shared symbols resolve to the definition in the DSO. The exceptions are
+ // symbols with copy relocations (which resolve to .bss) or preempt plt
+ // entries (which resolve to that plt entry).
if (isShared())
- return true;
+ return !NeedsCopyOrPltAddr;
// That's all that can be preempted in a non-DSO.
if (!Config->Shared)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 6937dd59f88..dfb99d4b8b4 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -606,13 +606,10 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
if (Offset == (uintX_t)-1)
continue;
+ bool Preemptible = Body.isPreemptible();
Expr = adjustExpr(Body, IsWrite, Expr, Type);
if (HasError)
continue;
- bool Preemptible = Body.isPreemptible();
- if (auto *B = dyn_cast<SharedSymbol<ELFT>>(&Body))
- if (B->needsCopy())
- Preemptible = false;
// This relocation does not require got entry, but it is relative to got and
// needs it to be created. Here we request for that.
@@ -711,7 +708,7 @@ void Writer<ELFT>::scanRelocs(InputSectionBase<ELFT> &C, ArrayRef<RelTy> Rels) {
continue;
}
- if (Preemptible) {
+ if (Body.isPreemptible()) {
// We don't know anything about the finaly symbol. Just ask the dynamic
// linker to handle the relocation for us.
AddDyn({Target->getDynRel(Type), C.OutSec, Offset, false, &Body, Addend});
diff --git a/lld/test/ELF/Inputs/copy-rel-pie.s b/lld/test/ELF/Inputs/copy-rel-pie.s
new file mode 100644
index 00000000000..6cd681fcecb
--- /dev/null
+++ b/lld/test/ELF/Inputs/copy-rel-pie.s
@@ -0,0 +1,9 @@
+.global foo
+.type foo, @object
+.size foo, 4
+foo:
+.long 0
+
+.global bar
+.type bar, @function
+bar:
diff --git a/lld/test/ELF/copy-rel-pie.s b/lld/test/ELF/copy-rel-pie.s
new file mode 100644
index 00000000000..be7d5acaeba
--- /dev/null
+++ b/lld/test/ELF/copy-rel-pie.s
@@ -0,0 +1,44 @@
+// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
+// RUN: ld.lld %t2.o -o %t2.so -shared
+// RUN: ld.lld %t.o %t2.so -o %t.exe -pie
+// RUN: llvm-readobj -s -r %t.exe | FileCheck %s
+// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s
+
+.global _start
+_start:
+ call bar
+ call foo
+
+// CHECK: Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1010
+
+// CHECK: Name: .bss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x3020
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section (4) .rela.dyn {
+// CHECK-NEXT: 0x3020 R_X86_64_COPY foo 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Section (5) .rela.plt {
+// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// (0x1010 + 0x10) - 0x1005 = 27
+// 0x3020 - 0x100a = 8214
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 1000: e8 1b 00 00 00 callq 27
+// DISASM-NEXT: 1005: e8 16 20 00 00 callq 8214 <foo>
diff --git a/lld/test/ELF/mips-got-and-copy.s b/lld/test/ELF/mips-got-and-copy.s
index 8501bd623e6..846bc245bc0 100644
--- a/lld/test/ELF/mips-got-and-copy.s
+++ b/lld/test/ELF/mips-got-and-copy.s
@@ -23,15 +23,21 @@
# CHECK-NEXT: Reserved entries [
# CHECK: ]
# CHECK-NEXT: Local entries [
-# CHECK-NEXT: ]
-# CHECK-NEXT: Global entries [
# CHECK-NEXT: Entry {
-# CHECK: Section: .bss
-# CHECK-NEXT: Name: data0
+# CHECK-NEXT: Address: 0x30008
+# CHECK-NEXT: Access: -32744
+# CHECK-NEXT: Initial: 0x40010
# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: Global entries [
# CHECK-NEXT: Entry {
-# CHECK: Section: .bss
-# CHECK-NEXT: Name: data1
+# CHECK-NEXT: Address: 0x3000C
+# CHECK-NEXT: Access: -32740
+# CHECK-NEXT: Initial: 0x40010
+# CHECK-NEXT: Value: 0x40010
+# CHECK-NEXT: Type: Object (0x1)
+# CHECK-NEXT: Section: .bss (0xC)
+# CHECK-NEXT: Name: data1@ (7)
# CHECK-NEXT: }
# CHECK-NEXT: ]
# CHECK-NEXT: Number of TLS and multi-GOT entries: 0
diff --git a/lld/test/ELF/relro.s b/lld/test/ELF/relro.s
index 692d6b271cf..d3554874000 100644
--- a/lld/test/ELF/relro.s
+++ b/lld/test/ELF/relro.s
@@ -232,7 +232,7 @@
.global _start
_start:
.long bar
- jmp *bar@GOTPCREL(%rip)
+ jmp *bar2@GOTPCREL(%rip)
.section .data,"aw"
.quad 0
OpenPOWER on IntegriCloud