Add linker-script-included files to reproduce tar files.

Previously, files added using INCLUDE directive weren't added
to reproduce archives. In this patch, I defined a function to
open a file and use that from Driver and LinkerScript.

llvm-svn: 291413
This commit is contained in:
Rui Ueyama 2017-01-09 01:42:02 +00:00
parent 7950d82ab5
commit ec1c75e059
6 changed files with 48 additions and 36 deletions

View File

@ -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 <cstdlib>
@ -51,6 +52,7 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
ErrorCount = 0;
ErrorOS = &Error;
Argv0 = Args[0];
Tar = nullptr;
Config = make<Configuration>();
Driver = make<LinkerDriver>();
@ -170,25 +172,6 @@ void LinkerDriver::addFile(StringRef Path) {
}
}
Optional<MemoryBufferRef> 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<MemoryBuffer> &MB = *MBOrErr;
MemoryBufferRef MBRef = MB->getMemBufferRef();
make<std::unique_ptr<MemoryBuffer>>(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<std::string> Path = searchLibrary(Name))
@ -313,9 +296,10 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr, bool CanExitEarly) {
Expected<std::unique_ptr<TarWriter>> 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::unique_ptr<TarWriter>>(std::move(*ErrOrWriter));
} else {
error(Twine("--reproduce: failed to open ") + Path + ": " +
toString(ErrOrWriter.takeError()));

View File

@ -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<const char *> Args, bool CanExitEarly);
void addFile(StringRef Path);
void addLibrary(StringRef Name);
std::unique_ptr<llvm::TarWriter> Tar; // for reproduce
private:
std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
void readConfigs(llvm::opt::InputArgList &Args);
void createFiles(llvm::opt::InputArgList &Args);
void inferMachineType();

View File

@ -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<MemoryBufferRef> 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<MemoryBuffer> &MB = *MBOrErr;
MemoryBufferRef MBRef = MB->getMemBufferRef();
make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership
if (Tar)
Tar->append(relativeToRoot(Path), MBRef.getBuffer());
return MBRef;
}
template <class ELFT> void elf::ObjectFile<ELFT>::initializeDwarfLine() {
std::unique_ptr<object::ObjectFile> 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()};

View File

@ -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<MemoryBufferRef> readFile(StringRef Path);
// The root class of input files.
class InputFile {
public:

View File

@ -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<std::string> Path = findFromSearchPaths(Tok))
MBOrErr = MemoryBuffer::getFile(*Path);
if (!MBOrErr) {
setError("cannot open " + Tok);
if (sys::fs::exists(Tok)) {
if (Optional<MemoryBufferRef> MB = readFile(Tok))
tokenize(*MB);
return;
}
MemoryBufferRef MBRef = (*MBOrErr)->getMemBufferRef();
make<std::unique_ptr<MemoryBuffer>>(std::move(*MBOrErr)); // take MB ownership
tokenize(MBRef);
if (Optional<std::string> Path = findFromSearchPaths(Tok)) {
if (Optional<MemoryBufferRef> MB = readFile(*Path))
tokenize(*MB);
return;
}
setError("cannot open " + Tok);
}
void ScriptParser::readOutput() {

View File

@ -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