llvm-project/lld/ELF/Driver.cpp
Rafael Espindola 4340aad144 Start adding support for creating shared libraries.
They are not fully functional yet, but this implements enough support for lld
itself to read them.

With that, delete the .so binary we were using for tests and start eating our
own dog food.

llvm-svn: 247487
2015-09-11 22:42:45 +00:00

123 lines
3.3 KiB
C++

//===- Driver.cpp ---------------------------------------------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "Driver.h"
#include "Config.h"
#include "Error.h"
#include "InputFiles.h"
#include "SymbolTable.h"
#include "Writer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/FileSystem.h"
using namespace llvm;
using namespace lld;
using namespace lld::elf2;
namespace lld {
namespace elf2 {
Configuration *Config;
void link(ArrayRef<const char *> Args) {
Configuration C;
Config = &C;
LinkerDriver().link(Args.slice(1));
}
}
}
// Opens a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
MemoryBufferRef LinkerDriver::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();
OwningMBs.push_back(std::move(MB)); // take ownership
return MBRef;
}
static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
using namespace llvm::sys::fs;
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);
}
void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
// Parse command line options.
opt::InputArgList Args = Parser.parse(ArgsArr);
// Handle -o
if (auto *Arg = Args.getLastArg(OPT_output))
Config->OutputFile = Arg->getValue();
if (Config->OutputFile.empty())
error("-o must be specified.");
// Handle -dynamic-linker
if (auto *Arg = Args.getLastArg(OPT_dynamic_linker))
Config->DynamicLinker = Arg->getValue();
std::vector<StringRef> RPaths;
for (auto *Arg : Args.filtered(OPT_rpath))
RPaths.push_back(Arg->getValue());
if (!RPaths.empty())
Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
if (Args.hasArg(OPT_shared))
Config->Shared = true;
// Create a list of input files.
std::vector<MemoryBufferRef> Inputs;
for (auto *Arg : Args.filtered(OPT_INPUT)) {
StringRef Path = Arg->getValue();
Inputs.push_back(openFile(Path));
}
if (Inputs.empty())
error("no input files.");
// Create a symbol table.
SymbolTable Symtab;
// Parse all input files and put all symbols to the symbol table.
// The symbol table will take care of name resolution.
for (MemoryBufferRef MB : Inputs) {
std::unique_ptr<InputFile> File = createFile(MB);
Symtab.addFile(std::move(File));
}
// Write the result.
const ELFFileBase *FirstObj = Symtab.getFirstELF();
switch (FirstObj->getELFKind()) {
case ELF32LEKind:
writeResult<object::ELF32LE>(&Symtab);
return;
case ELF32BEKind:
writeResult<object::ELF32BE>(&Symtab);
return;
case ELF64LEKind:
writeResult<object::ELF64LE>(&Symtab);
return;
case ELF64BEKind:
writeResult<object::ELF64BE>(&Symtab);
return;
}
}