summaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorRui Ueyama <ruiu@google.com>2019-01-15 18:30:23 +0000
committerRui Ueyama <ruiu@google.com>2019-01-15 18:30:23 +0000
commit7f3ef733bb5a0f3317355a10e732381e59d9da4d (patch)
tree17a17afdc88e434273a00c64328532854f7ef1a8 /lld
parent5b8ba49c7546077b495695930127f94d7343092b (diff)
Do not emit a corrupt symbol table entry for .rela_iplt_{start,end}.
If .rela.iplt does not exist, we used to emit a corrupt symbol table that contains two symbols, .rela_iplt_{start,end}, pointing to a nonexisting section. This patch fixes the issue by setting section index 0 to the symbols if .rel.iplt section does not exist. Differential Revision: https://reviews.llvm.org/D56623
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Symbols.cpp1
-rw-r--r--lld/ELF/Symbols.h3
-rw-r--r--lld/ELF/Writer.cpp22
-rw-r--r--lld/test/ELF/gnu-ifunc-empty.s16
4 files changed, 35 insertions, 7 deletions
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index da7fdb5dc43..a713ec539d8 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -38,6 +38,7 @@ Defined *ElfSym::GlobalOffsetTable;
Defined *ElfSym::MipsGp;
Defined *ElfSym::MipsGpDisp;
Defined *ElfSym::MipsLocalGp;
+Defined *ElfSym::RelaIpltStart;
Defined *ElfSym::RelaIpltEnd;
static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
diff --git a/lld/ELF/Symbols.h b/lld/ELF/Symbols.h
index 803cb80dd85..4d55405d893 100644
--- a/lld/ELF/Symbols.h
+++ b/lld/ELF/Symbols.h
@@ -352,7 +352,8 @@ struct ElfSym {
static Defined *MipsGpDisp;
static Defined *MipsLocalGp;
- // __rela_iplt_end or __rel_iplt_end
+ // __rel{,a}_iplt_{start,end} symbols.
+ static Defined *RelaIpltStart;
static Defined *RelaIpltEnd;
};
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 2f6a0bf0a91..17f4c7961d3 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -910,12 +910,18 @@ void PhdrEntry::add(OutputSection *Sec) {
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
if (Config->Relocatable || needsInterpSection())
return;
- StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
- addOptionalRegular(S, In.RelaIplt, 0, STV_HIDDEN, STB_WEAK);
- S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
- ElfSym::RelaIpltEnd =
- addOptionalRegular(S, In.RelaIplt, 0, STV_HIDDEN, STB_WEAK);
+ // By default, __rela_iplt_{start,end} belong to a dummy section 0
+ // because .rela.plt might be empty and thus removed from output.
+ // We'll override Out::ElfHeader with In.RelaIplt later when we are
+ // sure that .rela.plt exists in output.
+ ElfSym::RelaIpltStart = addOptionalRegular(
+ Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start",
+ Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK);
+
+ ElfSym::RelaIpltEnd = addOptionalRegular(
+ Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end",
+ Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK);
}
template <class ELFT>
@@ -949,8 +955,12 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
ElfSym::GlobalOffsetTable->Section = GotSection;
}
- if (ElfSym::RelaIpltEnd)
+ // .rela_iplt_{start,end} mark the start and the end of .rela.plt section.
+ if (ElfSym::RelaIpltStart && !In.RelaIplt->empty()) {
+ ElfSym::RelaIpltStart->Section = In.RelaIplt;
+ ElfSym::RelaIpltEnd->Section = In.RelaIplt;
ElfSym::RelaIpltEnd->Value = In.RelaIplt->getSize();
+ }
PhdrEntry *Last = nullptr;
PhdrEntry *LastRO = nullptr;
diff --git a/lld/test/ELF/gnu-ifunc-empty.s b/lld/test/ELF/gnu-ifunc-empty.s
new file mode 100644
index 00000000000..90798532f97
--- /dev/null
+++ b/lld/test/ELF/gnu-ifunc-empty.s
@@ -0,0 +1,16 @@
+// REQUIRES: x86
+
+// Verifies that .rela_iplt_{start,end} point to a dummy section
+// if .rela.iplt does not exist.
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld -static %t.o -o %t.exe
+// RUN: llvm-objdump -syms %t.exe | FileCheck %s
+
+// CHECK: 0000000000200000 .text 00000000 .hidden __rela_iplt_end
+// CHECK: 0000000000200000 .text 00000000 .hidden __rela_iplt_start
+
+.globl _start
+_start:
+ movl $__rela_iplt_start, %edx
+ movl $__rela_iplt_end, %edx