mirror of
https://github.com/intel/llvm.git
synced 2026-01-19 09:31:59 +08:00
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:
@@ -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())
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user