Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -128,6 +128,7 @@ bool ICF; bool MipsN32Abi = false; bool NoGnuUnique; + bool NoinhibitExec; bool NoUndefinedVersion; bool Nostdlib; bool OFormatBinary; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -647,6 +647,7 @@ Config->LTOPartitions = getInteger(Args, OPT_lto_partitions, 1); Config->MapFile = Args.getLastArgValue(OPT_Map); Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); + Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); Config->Nostdlib = Args.hasArg(OPT_nostdlib); Config->OFormatBinary = isOutputFormatBinary(Args); Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -535,6 +535,13 @@ In::RelaDyn->addReloc({Target->CopyRel, Sec, Off, false, SS, 0}); } +static void errorOrWarn(const Twine &Msg) { + if (!Config->NoinhibitExec) + error(Msg); + else + warn(Msg); +} + template static RelExpr adjustExpr(SymbolBody &Body, RelExpr Expr, uint32_t Type, const uint8_t *Data, InputSectionBase &S, @@ -609,8 +616,8 @@ return toPlt(Expr); } - error("symbol '" + toString(Body) + "' defined in " + toString(Body.File) + - " has no type"); + errorOrWarn("symbol '" + toString(Body) + "' defined in " + + toString(Body.File) + " has no type"); return Expr; } @@ -678,8 +685,7 @@ if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll) return; - bool CanBeExternal = Sym.symbol()->computeBinding() != STB_LOCAL && - Sym.getVisibility() == STV_DEFAULT; + bool CanBeExternal = Sym.symbol()->canBeExternal(); if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal) return; @@ -905,9 +911,10 @@ // We don't know anything about the finaly symbol. Just ask the dynamic // linker to handle the relocation for us. if (!Target->isPicRel(Type)) - error("relocation " + toString(Type) + - " cannot be used against shared object; recompile with -fPIC" + - getLocation(Sec, Body, Offset)); + errorOrWarn( + "relocation " + toString(Type) + + " cannot be used against shared object; recompile with -fPIC" + + getLocation(Sec, Body, Offset)); In::RelaDyn->addReloc( {Target->getDynRel(Type), &Sec, Offset, false, &Body, Addend}); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -369,6 +369,7 @@ unsigned InVersionScript : 1; bool includeInDynsym() const; + bool canBeExternal() const; uint8_t computeBinding() const; bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } Index: ELF/Symbols.cpp =================================================================== --- ELF/Symbols.cpp +++ ELF/Symbols.cpp @@ -141,10 +141,6 @@ if (isShared()) return !NeedsCopy && !NeedsPltAddr; - // That's all that can be preempted in a non-DSO. - if (!Config->Shared) - return false; - // Only symbols that appear in dynsym can be preempted. if (!symbol()->includeInDynsym()) return false; @@ -153,6 +149,12 @@ if (symbol()->Visibility != STV_DEFAULT) return false; + // Undefined external symbols in a non-DSO usually reported by linker and link + // fails, but together with --unresolved-symbols=ignore-all link succeeds and + // runtime linker should take care about them during execution. + if (!Config->Shared) + return isUndefined(); + // -Bsymbolic means that definitions are not preempted. if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc())) return !isDefined(); @@ -354,11 +356,21 @@ return Binding; } +bool Symbol::canBeExternal() const { + return computeBinding() != STB_LOCAL && + body()->getVisibility() == STV_DEFAULT; +} + bool Symbol::includeInDynsym() const { if (computeBinding() == STB_LOCAL) return false; - return ExportDynamic || body()->isShared() || - (body()->isUndefined() && Config->Shared); + if (ExportDynamic || body()->isShared()) + return true; + if (!body()->isUndefined()) + return false; + if (Config->Shared) + return true; + return canBeExternal() && !body()->symbol()->isWeak(); } // Print out a log message for --trace-symbol. Index: test/ELF/executable-undefined-ignoreall.s =================================================================== --- test/ELF/executable-undefined-ignoreall.s +++ test/ELF/executable-undefined-ignoreall.s @@ -0,0 +1,13 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: ld.lld %t -o %tout --unresolved-symbols=ignore-all -pie +# RUN: llvm-readobj -r %tout | FileCheck %s + +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.plt { +# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT foo 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +_start: +callq foo@PLT Index: test/ELF/no-inhibit-exec.s =================================================================== --- test/ELF/no-inhibit-exec.s +++ test/ELF/no-inhibit-exec.s @@ -6,7 +6,7 @@ # CHECK: Disassembly of section .text: # CHECK-NEXT: _start -# CHECK-NEXT: 201000: {{.*}} callq -2101253 +# CHECK-NEXT: 201000: {{.*}} callq 0 # next code will not link without noinhibit-exec flag # because of undefined symbol _bar