Index: ELF/Driver.h =================================================================== --- ELF/Driver.h +++ ELF/Driver.h @@ -27,8 +27,8 @@ class LinkerDriver { public: void main(ArrayRef Args, bool CanExitEarly); - void addFile(StringRef Path, bool WithLOption); - void addLibrary(StringRef Name); + bool addFile(StringRef Path, bool WithLOption); + bool addLibrary(StringRef Name); private: void readConfigs(llvm::opt::InputArgList &Args); Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -154,29 +154,29 @@ } // Opens a file and create a file object. Path has to be resolved already. -void LinkerDriver::addFile(StringRef Path, bool WithLOption) { +bool LinkerDriver::addFile(StringRef Path, bool WithLOption) { using namespace sys::fs; Optional Buffer = readFile(Path); if (!Buffer.hasValue()) - return; + return false; MemoryBufferRef MBRef = *Buffer; if (InBinary) { Files.push_back(make(MBRef)); - return; + return true; } switch (identify_magic(MBRef.getBuffer())) { case file_magic::unknown: readLinkerScript(MBRef); - return; + return true; case file_magic::archive: { // Handle -whole-archive. if (InWholeArchive) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(createObjectFile(P.first, Path, P.second)); - return; + return true; } std::unique_ptr File = @@ -189,17 +189,17 @@ if (!File->isEmpty() && !File->hasSymbolTable()) { for (const auto &P : getArchiveMembers(MBRef)) Files.push_back(make(P.first, Path, P.second)); - return; + return true; } // Handle the regular case. Files.push_back(make(std::move(File))); - return; + return true; } case file_magic::elf_shared_object: if (Config->Relocatable) { error("attempted static link of dynamic object " + Path); - return; + return true; } // DSOs usually have DT_SONAME tags in their ELF headers, and the @@ -214,21 +214,23 @@ // compatible with GNU. Files.push_back( createSharedFile(MBRef, WithLOption ? path::filename(Path) : Path)); - return; + return true; default: if (InLib) Files.push_back(make(MBRef, "", 0)); else Files.push_back(createObjectFile(MBRef)); } + + return true; } // Add a given library by searching it from input search paths. -void LinkerDriver::addLibrary(StringRef Name) { +bool LinkerDriver::addLibrary(StringRef Name) { if (Optional Path = searchLibrary(Name)) - addFile(*Path, /*WithLOption=*/true); - else - error("unable to find library -l" + Name); + return addFile(*Path, /*WithLOption=*/true); + error("unable to find library -l" + Name); + return false; } // This function is called on startup. We need this for LTO since Index: ELF/ScriptParser.cpp =================================================================== --- ELF/ScriptParser.cpp +++ ELF/ScriptParser.cpp @@ -54,7 +54,7 @@ void readDynamicList(); private: - void addFile(StringRef Path); + bool addFile(StringRef Path); OutputSection *checkSection(OutputSectionCommand *Cmd, StringRef Loccation); void readAsNeeded(); @@ -248,42 +248,45 @@ } } -void ScriptParser::addFile(StringRef S) { +bool ScriptParser::addFile(StringRef S) { if (IsUnderSysroot && S.startswith("/")) { SmallString<128> PathData; StringRef Path = (Config->Sysroot + S).toStringRef(PathData); - if (sys::fs::exists(Path)) { - Driver->addFile(Saver.save(Path), /*WithLOption=*/false); - return; - } + if (sys::fs::exists(Path)) + return Driver->addFile(Saver.save(Path), /*WithLOption=*/false); } - if (S.startswith("/")) { - Driver->addFile(S, /*WithLOption=*/false); - } else if (S.startswith("=")) { + if (S.startswith("/")) + return Driver->addFile(S, /*WithLOption=*/false); + + if (S.startswith("=")) { if (Config->Sysroot.empty()) - Driver->addFile(S.substr(1), /*WithLOption=*/false); - else - Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)), - /*WithLOption=*/false); - } else if (S.startswith("-l")) { - Driver->addLibrary(S.substr(2)); - } else if (sys::fs::exists(S)) { - Driver->addFile(S, /*WithLOption=*/false); - } else { - if (Optional Path = findFromSearchPaths(S)) - Driver->addFile(Saver.save(*Path), /*WithLOption=*/true); - else - setError("unable to find " + S); + return Driver->addFile(S.substr(1), /*WithLOption=*/false); + return Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)), + /*WithLOption=*/false); } + + if (S.startswith("-l")) + return Driver->addLibrary(S.substr(2)); + + if (sys::fs::exists(S)) + return Driver->addFile(S, /*WithLOption=*/false); + + if (Optional Path = findFromSearchPaths(S)) + return Driver->addFile(Saver.save(*Path), /*WithLOption=*/true); + + return false; } void ScriptParser::readAsNeeded() { expect("("); bool Orig = Config->AsNeeded; Config->AsNeeded = true; - while (!Error && !consume(")")) - addFile(unquote(next())); + while (!Error && !consume(")")) { + StringRef File = unquote(next()); + if (!addFile(File)) + setError("unable to find " + File); + } Config->AsNeeded = Orig; } @@ -305,10 +308,14 @@ void ScriptParser::readGroup() { expect("("); while (!Error && !consume(")")) { - if (consume("AS_NEEDED")) + if (consume("AS_NEEDED")) { readAsNeeded(); - else - addFile(unquote(next())); + continue; + } + + StringRef File = unquote(next()); + if (!addFile(File)) + setError("unable to find " + File); } } Index: test/ELF/linkerscript/group.s =================================================================== --- test/ELF/linkerscript/group.s +++ test/ELF/linkerscript/group.s @@ -51,6 +51,20 @@ # RUN: ld.lld -o %t2 %t.script # RUN: llvm-readobj %t2 > /dev/null +# RUN: echo "INPUT(/no_such_file)" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>&1 | FileCheck -check-prefix=ERR %s +# ERR: cannot open {{.*}}no_such_file: {{[Nn]}}o such file or directory +# ERR: {{.*}}.script:1: unable to find /no_such_file + +# RUN: echo "INPUT(AS_NEEDED(/no_such_file))" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>&1 | FileCheck -check-prefix=ERR %s + +# RUN: echo "GROUP(/no_such_file)" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>&1 | FileCheck -check-prefix=ERR %s + +# RUN: echo "GROUP(AS_NEEDED(/no_such_file))" > %t.script +# RUN: not ld.lld -o %t2 %t.script 2>&1 | FileCheck -check-prefix=ERR %s + .globl _start _start: ret