ELF2: Define Driver::addFile() as a one-stop place to open a file.

Opening a file and dispatching to readLinkerScript() or createFile()
is a common operation. We want to use that at least from Driver and
from LinkerScript. In COFF, we had the same problem. This patch
resolves the problem in the same way as we did for COFF.

Now, if you have a path that you want to open, just call
Driver->addFile(StringRef). That function opens the file and handles
that as if that were given by command line. This function is the
only place we call identify_magic().

llvm-svn: 249023
This commit is contained in:
Rui Ueyama
2015-10-01 15:23:09 +00:00
parent 812f57e6dc
commit 983ed2b749
5 changed files with 44 additions and 60 deletions

View File

@@ -23,31 +23,15 @@ using namespace llvm;
using namespace lld;
using namespace lld::elf2;
namespace lld {
namespace elf2 {
Configuration *lld::elf2::Config;
LinkerDriver *lld::elf2::Driver;
Configuration *Config;
std::vector<std::unique_ptr<MemoryBuffer>> *MemoryBufferPool;
void link(ArrayRef<const char *> Args) {
void lld::elf2::link(ArrayRef<const char *> Args) {
Configuration C;
LinkerDriver D;
Config = &C;
std::vector<std::unique_ptr<MemoryBuffer>> V;
MemoryBufferPool = &V;
LinkerDriver().link(Args.slice(1));
}
// Opens a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
MemoryBufferRef openFile(StringRef Path) {
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(Path);
error(MBOrErr, Twine("cannot open ") + Path);
std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
MemoryBufferRef MBRef = MB->getMemBufferRef();
MemoryBufferPool->push_back(std::move(MB)); // transfer ownership
return MBRef;
}
}
Driver = &D;
Driver->link(Args.slice(1));
}
// Makes a path by concatenating Dir and File.
@@ -82,10 +66,29 @@ static std::string searchLibrary(StringRef Path) {
error(Twine("Unable to find library -l") + Path);
}
// Returns true if MB looks like a linker script.
static bool isLinkerScript(MemoryBufferRef MB) {
// Opens and parses a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
void LinkerDriver::addFile(StringRef Path) {
using namespace llvm::sys::fs;
return identify_magic(MB.getBuffer()) == file_magic::unknown;
auto MBOrErr = MemoryBuffer::getFile(Path);
error(MBOrErr, Twine("cannot open ") + Path);
std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
MemoryBufferRef MBRef = MB->getMemBufferRef();
OwningMBs.push_back(std::move(MB)); // take MB ownership
switch (identify_magic(MBRef.getBuffer())) {
case file_magic::unknown:
readLinkerScript(MBRef);
return;
case file_magic::archive:
Symtab.addFile(make_unique<ArchiveFile>(MBRef));
return;
case file_magic::elf_shared_object:
Symtab.addFile(createELFFile<SharedFile>(MBRef));
return;
default:
Symtab.addFile(createELFFile<ObjectFile>(MBRef));
}
}
void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
@@ -121,20 +124,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
Config->NoInhibitExec = Args.hasArg(OPT_noinhibit_exec);
Config->Shared = Args.hasArg(OPT_shared);
// Create a symbol table.
SymbolTable Symtab;
for (auto *Arg : Args.filtered(OPT_l, OPT_INPUT)) {
std::string Path = Arg->getValue();
if (Arg->getOption().getID() == OPT_l)
Path = searchLibrary(Path);
MemoryBufferRef MB = openFile(Path);
if (isLinkerScript(MB)) {
// readLinkerScript may add files to the symbol table.
readLinkerScript(&Symtab, MB);
continue;
StringRef Path = Arg->getValue();
if (Arg->getOption().getID() == OPT_l) {
addFile(searchLibrary(Path));
} else {
addFile(Path);
}
Symtab.addFile(createFile(MB));
}
if (Symtab.getObjectFiles().empty())

View File

@@ -10,6 +10,7 @@
#ifndef LLD_ELF_DRIVER_H
#define LLD_ELF_DRIVER_H
#include "SymbolTable.h"
#include "lld/Core/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Option/ArgList.h"
@@ -17,11 +18,7 @@
namespace lld {
namespace elf2 {
class SymbolTable;
// The owner of all opened files.
extern std::vector<std::unique_ptr<MemoryBuffer>> *MemoryBufferPool;
MemoryBufferRef openFile(StringRef Path);
extern class LinkerDriver *Driver;
// Entry point of the ELF linker.
void link(ArrayRef<const char *> Args);
@@ -38,9 +35,12 @@ private:
class LinkerDriver {
public:
void link(ArrayRef<const char *> Args);
void addFile(StringRef Path);
private:
SymbolTable Symtab;
ArgParser Parser;
std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
};
// Create enum with OPT_xxx values for each option in Options.td
@@ -52,7 +52,7 @@ enum {
};
// Parses a linker script. Calling this function updates the Symtab and Config.
void readLinkerScript(SymbolTable *Symtab, MemoryBufferRef MB);
void readLinkerScript(MemoryBufferRef MB);
} // namespace elf2
} // namespace lld

View File

@@ -21,15 +21,6 @@ using namespace llvm::sys::fs;
using namespace lld;
using namespace lld::elf2;
std::unique_ptr<InputFile> lld::elf2::createFile(MemoryBufferRef MB) {
file_magic Magic = identify_magic(MB.getBuffer());
if (Magic == file_magic::archive)
return make_unique<ArchiveFile>(MB);
if (Magic == file_magic::elf_shared_object)
return createELFFile<SharedFile>(MB);
return createELFFile<ObjectFile>(MB);
}
template <class ELFT> static uint16_t getEMachine(const ELFFileBase &B) {
bool IsShared = isa<SharedFileBase>(B);
if (IsShared)

View File

@@ -29,8 +29,6 @@ class InputFile;
class Lazy;
class SymbolBody;
std::unique_ptr<InputFile> createFile(MemoryBufferRef MB);
// The root class of input files.
class InputFile {
public:

View File

@@ -26,7 +26,7 @@ using namespace lld::elf2;
namespace {
class LinkerScript {
public:
LinkerScript(SymbolTable *T, StringRef S) : Symtab(T), Tokens(tokenize(S)) {}
LinkerScript(StringRef S) : Tokens(tokenize(S)) {}
void run();
private:
@@ -40,7 +40,6 @@ private:
void readGroup();
void readOutputFormat();
SymbolTable *Symtab;
std::vector<StringRef> Tokens;
size_t Pos = 0;
};
@@ -125,7 +124,7 @@ void LinkerScript::readAsNeeded() {
StringRef Tok = next();
if (Tok == ")")
return;
Symtab->addFile(createFile(openFile(Tok)));
Driver->addFile(Tok);
}
}
@@ -139,7 +138,7 @@ void LinkerScript::readGroup() {
readAsNeeded();
continue;
}
Symtab->addFile(createFile(openFile(Tok)));
Driver->addFile(Tok);
}
}
@@ -151,6 +150,6 @@ void LinkerScript::readOutputFormat() {
}
// Entry point. The other functions or classes are private to this file.
void lld::elf2::readLinkerScript(SymbolTable *Symtab, MemoryBufferRef MB) {
LinkerScript(Symtab, MB.getBuffer()).run();
void lld::elf2::readLinkerScript(MemoryBufferRef MB) {
LinkerScript(MB.getBuffer()).run();
}