Index: ELF/Relocations.cpp =================================================================== --- ELF/Relocations.cpp +++ ELF/Relocations.cpp @@ -678,8 +678,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; 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