diff options
author | Rui Ueyama <ruiu@google.com> | 2019-01-15 18:30:23 +0000 |
---|---|---|
committer | Rui Ueyama <ruiu@google.com> | 2019-01-15 18:30:23 +0000 |
commit | 7f3ef733bb5a0f3317355a10e732381e59d9da4d (patch) | |
tree | 17a17afdc88e434273a00c64328532854f7ef1a8 | |
parent | 5b8ba49c7546077b495695930127f94d7343092b (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
-rw-r--r-- | lld/ELF/Symbols.cpp | 1 | ||||
-rw-r--r-- | lld/ELF/Symbols.h | 3 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 22 | ||||
-rw-r--r-- | lld/test/ELF/gnu-ifunc-empty.s | 16 |
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 |