//===- 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" using namespace llvm; using namespace lld; using namespace lld::elf2; namespace lld { namespace elf2 { Configuration *Config; void link(ArrayRef Args) { auto C = make_unique(); Config = C.get(); 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> MBOrErr = MemoryBuffer::getFile(Path); error(MBOrErr, Twine("cannot open ") + Path); std::unique_ptr &MB = *MBOrErr; MemoryBufferRef MBRef = MB->getMemBufferRef(); OwningMBs.push_back(std::move(MB)); // take ownership return MBRef; } static std::unique_ptr createFile(MemoryBufferRef MB) { std::pair Type = object::getElfArchType(MB.getBuffer()); if (Type.second != ELF::ELFDATA2LSB && Type.second != ELF::ELFDATA2MSB) error("Invalid data encoding"); if (Type.first == ELF::ELFCLASS32) { if (Type.second == ELF::ELFDATA2LSB) return make_unique>(MB); return make_unique>(MB); } if (Type.first == ELF::ELFCLASS64) { if (Type.second == ELF::ELFDATA2LSB) return make_unique>(MB); return make_unique>(MB); } error("Invalid file class"); } void LinkerDriver::link(ArrayRef 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."); // Create a list of input files. std::vector 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 File = createFile(MB); Symtab.addFile(std::move(File)); } // Make sure we have resolved all symbols. Symtab.reportRemainingUndefines(); // Write the result. ObjectFileBase &FirstObj = *Symtab.ObjectFiles[0]; switch (FirstObj.kind()) { case InputFile::Object32LEKind: writeResult(&Symtab); return; case InputFile::Object32BEKind: writeResult(&Symtab); return; case InputFile::Object64LEKind: writeResult(&Symtab); return; case InputFile::Object64BEKind: writeResult(&Symtab); return; } }