diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 6afbe62e5ec7..c8ea821ec522 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -26,6 +26,7 @@ #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Path.h" +#include "llvm/Support/TarWriter.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include @@ -51,6 +52,7 @@ bool elf::link(ArrayRef Args, bool CanExitEarly, ErrorCount = 0; ErrorOS = &Error; Argv0 = Args[0]; + Tar = nullptr; Config = make(); Driver = make(); @@ -170,25 +172,6 @@ void LinkerDriver::addFile(StringRef Path) { } } -Optional LinkerDriver::readFile(StringRef Path) { - if (Config->Verbose) - outs() << Path << "\n"; - - auto MBOrErr = MemoryBuffer::getFile(Path); - if (auto EC = MBOrErr.getError()) { - error(EC, "cannot open " + Path); - return None; - } - std::unique_ptr &MB = *MBOrErr; - MemoryBufferRef MBRef = MB->getMemBufferRef(); - make>(std::move(MB)); // take MB ownership - - if (Tar) - Tar->append(relativeToRoot(Path), MBRef.getBuffer()); - - return MBRef; -} - // Add a given library by searching it from input search paths. void LinkerDriver::addLibrary(StringRef Name) { if (Optional Path = searchLibrary(Name)) @@ -313,9 +296,10 @@ void LinkerDriver::main(ArrayRef ArgsArr, bool CanExitEarly) { Expected> ErrOrWriter = TarWriter::create(Path, path::stem(Path)); if (ErrOrWriter) { - Tar = std::move(*ErrOrWriter); + Tar = ErrOrWriter->get(); Tar->append("response.txt", createResponseFile(Args)); Tar->append("version.txt", getLLDVersion() + "\n"); + make>(std::move(*ErrOrWriter)); } else { error(Twine("--reproduce: failed to open ") + Path + ": " + toString(ErrOrWriter.takeError())); diff --git a/lld/ELF/Driver.h b/lld/ELF/Driver.h index dadee5eef355..8bb2093e86ca 100644 --- a/lld/ELF/Driver.h +++ b/lld/ELF/Driver.h @@ -17,7 +17,6 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Option/ArgList.h" -#include "llvm/Support/TarWriter.h" #include "llvm/Support/raw_ostream.h" namespace lld { @@ -30,11 +29,9 @@ public: void main(ArrayRef Args, bool CanExitEarly); void addFile(StringRef Path); void addLibrary(StringRef Name); - std::unique_ptr Tar; // for reproduce private: std::vector getArchiveMembers(MemoryBufferRef MB); - llvm::Optional readFile(StringRef Path); void readConfigs(llvm::opt::InputArgList &Args); void createFiles(llvm::opt::InputArgList &Args); void inferMachineType(); diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index abe90445b6bf..c33ff0f66f75 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -8,7 +8,6 @@ //===----------------------------------------------------------------------===// #include "InputFiles.h" -#include "Driver.h" #include "Error.h" #include "InputSection.h" #include "LinkerScript.h" @@ -26,6 +25,7 @@ #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/Path.h" +#include "llvm/Support/TarWriter.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; @@ -36,6 +36,8 @@ using namespace llvm::sys::fs; using namespace lld; using namespace lld::elf; +TarWriter *elf::Tar; + namespace { // In ELF object file all section addresses are zero. If we have multiple // .text sections (when using -ffunction-section or comdat group) then @@ -53,6 +55,24 @@ public: }; } +Optional elf::readFile(StringRef Path) { + if (Config->Verbose) + outs() << Path << "\n"; + + auto MBOrErr = MemoryBuffer::getFile(Path); + if (auto EC = MBOrErr.getError()) { + error(EC, "cannot open " + Path); + return None; + } + std::unique_ptr &MB = *MBOrErr; + MemoryBufferRef MBRef = MB->getMemBufferRef(); + make>(std::move(MB)); // take MB ownership + + if (Tar) + Tar->append(relativeToRoot(Path), MBRef.getBuffer()); + return MBRef; +} + template void elf::ObjectFile::initializeDwarfLine() { std::unique_ptr Obj = check(object::ObjectFile::createObjectFile(this->MB), @@ -524,9 +544,8 @@ ArchiveFile::getMember(const Archive::Symbol *Sym) { "could not get the buffer for the member defining symbol " + Sym->getName()); - if (C.getParent()->isThin() && Driver->Tar) - Driver->Tar->append(relativeToRoot(check(C.getFullName())), - Ret.getBuffer()); + if (C.getParent()->isThin() && Tar) + Tar->append(relativeToRoot(check(C.getFullName())), Ret.getBuffer()); if (C.getParent()->isThin()) return {Ret, 0}; return {Ret, C.getChildOffset()}; diff --git a/lld/ELF/InputFiles.h b/lld/ELF/InputFiles.h index 8b188348199f..73dda7b566b8 100644 --- a/lld/ELF/InputFiles.h +++ b/lld/ELF/InputFiles.h @@ -29,6 +29,7 @@ namespace llvm { class DWARFDebugLine; +class TarWriter; namespace lto { class InputFile; } @@ -49,6 +50,13 @@ using llvm::object::Archive; class Lazy; class SymbolBody; +// If -reproduce option is given, all input files are written +// to this tar archive. +extern llvm::TarWriter *Tar; + +// Opens a given file. +llvm::Optional readFile(StringRef Path); + // The root class of input files. class InputFile { public: diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index ccc1059949db..e26ab8ccbf3c 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -1143,20 +1143,21 @@ void ScriptParser::readGroup() { void ScriptParser::readInclude() { StringRef Tok = unquote(next()); + // https://sourceware.org/binutils/docs/ld/File-Commands.html: // The file will be searched for in the current directory, and in any // directory specified with the -L option. - auto MBOrErr = MemoryBuffer::getFile(Tok); - if (!MBOrErr) - if (Optional Path = findFromSearchPaths(Tok)) - MBOrErr = MemoryBuffer::getFile(*Path); - if (!MBOrErr) { - setError("cannot open " + Tok); + if (sys::fs::exists(Tok)) { + if (Optional MB = readFile(Tok)) + tokenize(*MB); return; } - MemoryBufferRef MBRef = (*MBOrErr)->getMemBufferRef(); - make>(std::move(*MBOrErr)); // take MB ownership - tokenize(MBRef); + if (Optional Path = findFromSearchPaths(Tok)) { + if (Optional MB = readFile(*Path)) + tokenize(*MB); + return; + } + setError("cannot open " + Tok); } void ScriptParser::readOutput() { diff --git a/lld/test/ELF/reproduce-linkerscript.s b/lld/test/ELF/reproduce-linkerscript.s index 1938e2b6cf94..2b0081501a62 100644 --- a/lld/test/ELF/reproduce-linkerscript.s +++ b/lld/test/ELF/reproduce-linkerscript.s @@ -4,10 +4,13 @@ # RUN: mkdir -p %t.dir/build # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build/foo.o # RUN: echo "INPUT(\"%t.dir/build/foo.o\")" > %t.dir/build/foo.script +# RUN: echo "INCLUDE \"%t.dir/build/bar.script\"" >> %t.dir/build/foo.script +# RUN: echo "/* empty */" > %t.dir/build/bar.script # RUN: cd %t.dir # RUN: ld.lld build/foo.script -o bar --reproduce repro.tar # RUN: tar xf repro.tar # RUN: diff build/foo.script repro/%:t.dir/build/foo.script +# RUN: diff build/bar.script repro/%:t.dir/build/bar.script # RUN: diff build/foo.o repro/%:t.dir/build/foo.o .globl _start