Index: ELF/Arch/X86.cpp =================================================================== --- ELF/Arch/X86.cpp +++ ELF/Arch/X86.cpp @@ -60,6 +60,15 @@ PltHeaderSize = 16; TlsGdRelaxSkip = 2; TrapInstr = 0xcccccccc; // 0xcc = INT3 + + // For position independent executable, the plt entry requires ebx to be set. + // This causes two problems: + // * If some code has a direct reference to a function, it was probably + // compiled without -fPIE/-fPIC and doesn't maintain ebx. + // * If a library definition gets preempted to the executable, it will have the + // wrong ebx value. + if (Config->Pie) + SupportsPltPreemption = false; } static bool hasBaseReg(uint8_t ModRM) { return (ModRM & 0xc7) != 0x5; } Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -875,6 +875,9 @@ // that points to the real function is a dedicated got entry used by the // plt. That is identified by special relocation types (R_X86_64_JUMP_SLOT, // R_386_JMP_SLOT, etc). + if (!Target->SupportsPltPreemption) + errorOrWarn("symbol '" + toString(Sym) + "' cannot be preempted" + + getLocation(Sec, Sym, Offset)); Sym.NeedsPltAddr = true; Expr = toPlt(Expr); Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -107,6 +107,8 @@ // executable OutputSections. uint32_t TrapInstr = 0; + bool SupportsPltPreemption = true; + virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, RelExpr Expr) const; virtual void relaxGot(uint8_t *Loc, uint64_t Val) const; Index: test/ELF/Inputs/i386-pic-plt.s =================================================================== --- /dev/null +++ test/ELF/Inputs/i386-pic-plt.s @@ -0,0 +1,4 @@ + .global foo + .type foo, @function +foo: + nop Index: test/ELF/i386-pic-plt.s =================================================================== --- /dev/null +++ test/ELF/i386-pic-plt.s @@ -0,0 +1,12 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %p/Inputs/i386-pic-plt.s -o %t2.o +// RUN: ld.lld -shared %t2.o -o %t2.so +// RUN: ld.lld %t.o %t2.so -o %t +// RUN: not ld.lld %t.o %t2.so -o %t -pie 2>&1 | FileCheck %s + +// CHECK: error: symbol 'foo' cannot be preempted + +.global _start +_start: + call foo