Index: lld/ELF/Symbols.h =================================================================== --- lld/ELF/Symbols.h +++ lld/ELF/Symbols.h @@ -352,7 +352,8 @@ 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; }; Index: lld/ELF/Symbols.cpp =================================================================== --- lld/ELF/Symbols.cpp +++ lld/ELF/Symbols.cpp @@ -38,6 +38,7 @@ 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) { Index: lld/ELF/Writer.cpp =================================================================== --- lld/ELF/Writer.cpp +++ lld/ELF/Writer.cpp @@ -911,7 +911,8 @@ if (Config->Relocatable || needsInterpSection()) return; StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; - addOptionalRegular(S, In.RelaIplt, 0, STV_HIDDEN, STB_WEAK); + ElfSym::RelaIpltStart = + addOptionalRegular(S, In.RelaIplt, 0, STV_HIDDEN, STB_WEAK); S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; ElfSym::RelaIpltEnd = @@ -949,8 +950,19 @@ ElfSym::GlobalOffsetTable->Section = GotSection; } - if (ElfSym::RelaIpltEnd) - ElfSym::RelaIpltEnd->Value = In.RelaIplt->getSize(); + // .rela_iplt_{start,end} mark the start and the end of .rela.plt section. + if (ElfSym::RelaIpltStart) { + uint64_t Size = In.RelaIplt->getSize(); + ElfSym::RelaIpltEnd->Value = Size; + + // If .rela.plt does not exist, use a dummy section value. The loader + // reads data between the start and the end symbols, so as long as the two + // symbols point to the same location, their actual locations don't matter. + if (Size == 0) { + ElfSym::RelaIpltStart->Section = Out::ElfHeader; + ElfSym::RelaIpltEnd->Section = Out::ElfHeader; + } + } PhdrEntry *Last = nullptr; PhdrEntry *LastRO = nullptr; Index: lld/test/ELF/gnu-ifunc-empty.s =================================================================== --- /dev/null +++ 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