Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -42,6 +42,7 @@ llvm::StringRef Sysroot; std::string RPath; std::vector SearchPaths; + std::vector Undefined; bool AllowMultipleDefinition; bool AsNeeded = false; bool Bsymbolic; Index: lld/trunk/ELF/Driver.cpp =================================================================== --- lld/trunk/ELF/Driver.cpp +++ lld/trunk/ELF/Driver.cpp @@ -155,6 +155,9 @@ Config->SoName = getString(Args, OPT_soname); Config->Sysroot = getString(Args, OPT_sysroot); + for (auto *Arg : Args.filtered(OPT_undefined)) + Config->Undefined.push_back(Arg->getValue()); + for (auto *Arg : Args.filtered(OPT_z)) if (Arg->getValue() == StringRef("now")) Config->ZNow = true; @@ -225,8 +228,8 @@ for (std::unique_ptr &F : Files) Symtab.addFile(std::move(F)); - for (auto *Arg : Args.filtered(OPT_undefined)) - Symtab.addUndefinedOpt(Arg->getValue()); + for (auto &U : Config->Undefined) + Symtab.addUndefinedOpt(U); if (Config->OutputFile.empty()) Config->OutputFile = "a.out"; Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -43,6 +43,7 @@ void readAsNeeded(); void readEntry(); + void readExtern(); void readGroup(); void readInclude(); void readOutput(); @@ -63,6 +64,8 @@ continue; if (Tok == "ENTRY") { readEntry(); + } else if (Tok == "EXTERN") { + readExtern(); } else if (Tok == "GROUP" || Tok == "INPUT") { readGroup(); } else if (Tok == "INCLUDE") { @@ -181,6 +184,16 @@ expect(")"); } +void LinkerScript::readExtern() { + expect("("); + for (;;) { + StringRef Tok = next(); + if (Tok == ")") + return; + Config->Undefined.push_back(Tok); + } +} + void LinkerScript::readGroup() { expect("("); for (;;) { Index: lld/trunk/test/elf2/linkerscript.s =================================================================== --- lld/trunk/test/elf2/linkerscript.s +++ lld/trunk/test/elf2/linkerscript.s @@ -6,6 +6,10 @@ # RUN: rm -f %t.dir/libxyz.a # RUN: llvm-ar rcs %t.dir/libxyz.a %t2.o +# RUN: echo "EXTERN( undef undef2 )" > %t.script +# RUN: ld.lld2 %t -o %t2 %t.script +# RUN: llvm-readobj %t2 > /dev/null + # RUN: echo "GROUP(" %t ")" > %t.script # RUN: ld.lld2 -o %t2 %t.script # RUN: llvm-readobj %t2 > /dev/null Index: lld/trunk/test/elf2/undefined-opt.s =================================================================== --- lld/trunk/test/elf2/undefined-opt.s +++ lld/trunk/test/elf2/undefined-opt.s @@ -37,6 +37,10 @@ # TWO-UNDEFINED: Name: bar # TWO-UNDEFINED: Name: zed # TWO-UNDEFINED: ] +# Now the same logic but linker script is used to set undefines +# RUN: echo "EXTERN( bar abs )" > %t.script +# RUN: ld.lld2 -o %t3 %t.o %tar.a %t.script +# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TWO-UNDEFINED %s # Added undefined symbol may be left undefined without error, but # shouldn't show up in the dynamic table.