Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -23,6 +23,7 @@ bool DiscardAll = false; bool DiscardLocals = false; bool ExportDynamic = false; + bool NoInhibitExec = false; }; extern Configuration *Config; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -91,6 +91,9 @@ if (Args.hasArg(OPT_export_dynamic)) Config->ExportDynamic = true; + if (Args.hasArg(OPT_noinhibit_exec)) + Config->NoInhibitExec = true; + // Create a list of input files. std::vector Inputs; Index: ELF/InputSection.cpp =================================================================== --- ELF/InputSection.cpp +++ ELF/InputSection.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "InputSection.h" +#include "Config.h" #include "Error.h" #include "InputFiles.h" #include "OutputSections.h" @@ -72,7 +73,8 @@ continue; break; case SymbolBody::UndefinedKind: - assert(Body->isWeak() && "Undefined symbol reached writer"); + assert((Config->NoInhibitExec || Body->isWeak()) && + "Undefined symbol reached writer"); SymVA = 0; break; case SymbolBody::LazyKind: Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -28,6 +28,10 @@ def alias_discard_locals: Flag<["-"], "X">, Alias; +def noinhibit_exec : Flag<["--"], "noinhibit-exec">, + HelpText<"Retain the executable output file whenever" + " it is still usable">; + //===----------------------------------------------------------------------===// /// Ignored options //===----------------------------------------------------------------------===// Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -303,11 +303,14 @@ if (&SymE > Syms.begin() && &SymE < Syms.end()) SymFile = F.get(); } - if (SymFile) - error(Twine("undefined symbol: ") + Sym.getName() + " in " + - SymFile->getName()); + + Twine Error = + Twine("undefined symbol: ") + + (SymFile ? (Sym.getName() + " in " + SymFile->getName()) : Sym.getName()); + if (Config->NoInhibitExec) + warning(Error); else - error(Twine("undefined symbol: ") + Sym.getName()); + error(Error); } // Create output section objects and add them to OutputSections. Index: test/elf2/no-inhibit-exec.s =================================================================== --- test/elf2/no-inhibit-exec.s +++ test/elf2/no-inhibit-exec.s @@ -0,0 +1,14 @@ +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: lld -flavor gnu2 %t --noinhibit-exec -o %t2 +# RUN: not lld -flavor gnu2 %t -o %t2 +# REQUIRES: x86 + +# next code will not link without noinhibit-exec flag +# because of undefined symbol _bar +.globl _start; +_start: + call _bar + mov $60, %rax + mov $0, %rdi + syscall +