[lld] r242118 - Revert ELF port. Posting to mailing list.
Michael J. Spencer
bigcheesegs at gmail.com
Mon Jul 13 21:49:49 PDT 2015
Author: mspencer
Date: Mon Jul 13 23:49:48 2015
New Revision: 242118
URL: http://llvm.org/viewvc/llvm-project?rev=242118&view=rev
Log:
Revert ELF port. Posting to mailing list.
Removed:
lld/trunk/ELF/CMakeLists.txt
lld/trunk/ELF/Chunks.cpp
lld/trunk/ELF/Chunks.h
lld/trunk/ELF/Config.h
lld/trunk/ELF/Driver.cpp
lld/trunk/ELF/Driver.h
lld/trunk/ELF/DriverUtils.cpp
lld/trunk/ELF/Error.h
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputFiles.h
lld/trunk/ELF/Options.td
lld/trunk/ELF/README.md
lld/trunk/ELF/SymbolTable.cpp
lld/trunk/ELF/SymbolTable.h
lld/trunk/ELF/Symbols.cpp
lld/trunk/ELF/Symbols.h
lld/trunk/ELF/Writer.cpp
lld/trunk/ELF/Writer.h
lld/trunk/test/elfv2/basic.test
Modified:
lld/trunk/CMakeLists.txt
lld/trunk/include/lld/Driver/Driver.h
lld/trunk/lib/Driver/UniversalDriver.cpp
lld/trunk/tools/lld/CMakeLists.txt
lld/trunk/unittests/DriverTests/CMakeLists.txt
Modified: lld/trunk/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/CMakeLists.txt?rev=242118&r1=242117&r2=242118&view=diff
==============================================================================
--- lld/trunk/CMakeLists.txt (original)
+++ lld/trunk/CMakeLists.txt Mon Jul 13 23:49:48 2015
@@ -97,4 +97,3 @@ endif()
add_subdirectory(docs)
add_subdirectory(COFF)
-add_subdirectory(ELF)
Removed: lld/trunk/ELF/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/CMakeLists.txt?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/CMakeLists.txt (original)
+++ lld/trunk/ELF/CMakeLists.txt (removed)
@@ -1,23 +0,0 @@
-set(LLVM_TARGET_DEFINITIONS Options.td)
-tablegen(LLVM Options.inc -gen-opt-parser-defs)
-add_public_tablegen_target(ELFOptionsTableGen)
-
-add_llvm_library(lldELF2
- Chunks.cpp
- Driver.cpp
- DriverUtils.cpp
- InputFiles.cpp
- SymbolTable.cpp
- Symbols.cpp
- Writer.cpp
-
- LINK_COMPONENTS
- ${LLVM_TARGETS_TO_BUILD}
- Core
- LTO
- MC
- MCDisassembler
- Support
- )
-
-add_dependencies(lldELF2 ELFOptionsTableGen)
Removed: lld/trunk/ELF/Chunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.cpp?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Chunks.cpp (original)
+++ lld/trunk/ELF/Chunks.cpp (removed)
@@ -1,125 +0,0 @@
-//===- Chunks.cpp ---------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Chunks.h"
-#include "InputFiles.h"
-#include "Writer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace llvm::object;
-using namespace llvm::support::endian;
-using namespace llvm::ELF;
-
-using namespace lld;
-using namespace lld::elfv2;
-
-template <class ELFT>
-SectionChunk<ELFT>::SectionChunk(elfv2::ObjectFile<ELFT> *F, const Elf_Shdr *H,
- uint32_t SI)
- : File(F), Header(H), SectionIndex(SI) {
- // Initialize SectionName.
- SectionName = *File->getObj()->getSectionName(Header);
-
- Align = Header->sh_addralign;
-
- // When a new chunk is created, we don't if if it's going to make it
- // to the final output. Initially all sections are unmarked in terms
- // of garbage collection. The writer will call markLive() to mark
- // all reachable section chunks.
- Live = false;
-
- Root = true;
-}
-
-template <class ELFT> void SectionChunk<ELFT>::writeTo(uint8_t *Buf) {
- if (!hasData())
- return;
- // Copy section contents from source object file to output file.
- ArrayRef<uint8_t> Data = *File->getObj()->getSectionContents(Header);
- memcpy(Buf + FileOff, Data.data(), Data.size());
-
- // FIXME: Relocations
-}
-
-template <class ELFT> void SectionChunk<ELFT>::mark() {
- assert(!Live);
- Live = true;
-
- // Mark all symbols listed in the relocation table for this section.
- // FIXME: Relocations
-}
-
-template <class ELFT>
-void SectionChunk<ELFT>::applyReloc(uint8_t *Buf, const Elf_Rela *Rel) {
- // FIXME: Relocations
-}
-
-template <class ELFT>
-void SectionChunk<ELFT>::applyReloc(uint8_t *Buf, const Elf_Rel *Rel) {}
-
-template <class ELFT> bool SectionChunk<ELFT>::hasData() const {
- return Header->sh_type != SHT_NOBITS;
-}
-
-template <class ELFT> uint32_t SectionChunk<ELFT>::getFlags() const {
- return Header->sh_flags;
-}
-
-// Prints "Discarded <symbol>" for all external function symbols.
-template <class ELFT> void SectionChunk<ELFT>::printDiscardedMessage() {
- auto Obj = File->getObj();
-
- for (auto &&Sym : Obj->symbols()) {
- auto Sec = Obj->getSection(&Sym);
- if (Sec && *Sec != Header)
- continue;
- if (Sym.getType() != STT_FUNC)
- continue;
- if (auto Name = Obj->getStaticSymbolName(&Sym)) {
- llvm::outs() << "Discarded " << *Name << " from " << File->getShortName()
- << "\n";
- }
- }
-}
-
-template <class ELFT>
-const llvm::object::Elf_Shdr_Impl<ELFT> *SectionChunk<ELFT>::getSectionHdr() {
- return Header;
-}
-
-template <class ELFT>
-CommonChunk<ELFT>::CommonChunk(const Elf_Sym *S)
- : Sym(S) {
- // Alignment is a section attribute, but common symbols don't
- // belong to any section. How do we know common data alignments?
- // Needs investigating. For now, we set a large number as an alignment.
- Align = 16;
-}
-
-template <class ELFT> uint32_t CommonChunk<ELFT>::getFlags() const {
- return PF_R | PF_W;
-}
-
-namespace lld {
-namespace elfv2 {
-template class SectionChunk<llvm::object::ELF32LE>;
-template class SectionChunk<llvm::object::ELF32BE>;
-template class SectionChunk<llvm::object::ELF64LE>;
-template class SectionChunk<llvm::object::ELF64BE>;
-
-template class CommonChunk<llvm::object::ELF32LE>;
-template class CommonChunk<llvm::object::ELF32BE>;
-template class CommonChunk<llvm::object::ELF64LE>;
-template class CommonChunk<llvm::object::ELF64BE>;
-}
-}
Removed: lld/trunk/ELF/Chunks.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Chunks.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Chunks.h (original)
+++ lld/trunk/ELF/Chunks.h (removed)
@@ -1,152 +0,0 @@
-//===- Chunks.h -----------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_CHUNKS_H
-#define LLD_ELF_CHUNKS_H
-
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Object/ELF.h"
-#include <map>
-#include <vector>
-
-namespace lld {
-namespace elfv2 {
-
-class Defined;
-template <class ELFT> class ObjectFile;
-class OutputSection;
-
-// A Chunk represents a chunk of data that will occupy space in the
-// output (if the resolver chose that). It may or may not be backed by
-// a section of an input file. It could be linker-created data, or
-// doesn't even have actual data (if common or bss).
-class Chunk {
-public:
- virtual ~Chunk() = default;
-
- // Returns the size of this chunk (even if this is a common or BSS.)
- virtual size_t getSize() const = 0;
-
- // Write this chunk to a mmap'ed file, assuming Buf is pointing to
- // beginning of the file. Because this function may use VA values
- // of other chunks for relocations, you need to set them properly
- // before calling this function.
- virtual void writeTo(uint8_t *Buf) {}
-
- // The writer sets and uses the addresses.
- uint64_t getVA() { return VA; }
- uint64_t getFileOff() { return FileOff; }
- uint32_t getAlign() { return Align; }
- void setVA(uint64_t V) { VA = V; }
- void setFileOff(uint64_t V) { FileOff = V; }
-
- // Returns true if this has non-zero data. BSS chunks return
- // false. If false is returned, the space occupied by this chunk
- // will be filled with zeros.
- virtual bool hasData() const { return true; }
-
- // Returns readable/writable/executable bits.
- virtual uint32_t getFlags() const { return 0; }
-
- // Returns the section name if this is a section chunk.
- // It is illegal to call this function on non-section chunks.
- virtual StringRef getSectionName() const {
- llvm_unreachable("unimplemented getSectionName");
- }
-
- // Called if the garbage collector decides to not include this chunk
- // in a final output. It's supposed to print out a log message to stdout.
- // It is illegal to call this function on non-section chunks because
- // only section chunks are subject of garbage collection.
- virtual void printDiscardedMessage() {
- llvm_unreachable("unimplemented printDiscardedMessage");
- }
-
- // Used by the garbage collector.
- bool isRoot() { return Root; }
- bool isLive() { return Live; }
- void markLive() {
- if (!Live)
- mark();
- }
-
- // An output section has pointers to chunks in the section, and each
- // chunk has a back pointer to an output section.
- void setOutputSection(OutputSection *O) { Out = O; }
- OutputSection *getOutputSection() { return Out; }
-
-protected:
- // The VA of this chunk in the output. The writer sets a value.
- uint64_t VA = 0;
-
- // The offset from beginning of the output file. The writer sets a value.
- uint64_t FileOff = 0;
-
- // The output section for this chunk.
- OutputSection *Out = nullptr;
-
- // The alignment of this chunk. The writer uses the value.
- uint32_t Align = 1;
-
- // Used by the garbage collector.
- virtual void mark() {}
- bool Live = true;
- bool Root = false;
-};
-
-// A chunk corresponding a section of an input file.
-template <class ELFT> class SectionChunk : public Chunk {
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
- typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
- typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
-
-public:
- SectionChunk(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
- uint32_t SectionIndex);
- size_t getSize() const override { return Header->sh_size; }
- void writeTo(uint8_t *Buf) override;
- bool hasData() const override;
- uint32_t getFlags() const override;
- StringRef getSectionName() const override { return SectionName; }
- void printDiscardedMessage() override;
-
-private:
- void mark() override;
- const Elf_Shdr *getSectionHdr();
- void applyReloc(uint8_t *Buf, const Elf_Rela *Rel);
- void applyReloc(uint8_t *Buf, const Elf_Rel *Rel);
-
- // A file this chunk was created from.
- ObjectFile<ELFT> *File;
-
- const Elf_Shdr *Header;
- uint32_t SectionIndex;
- StringRef SectionName;
-};
-
-// A chunk for common symbols. Common chunks don't have actual data.
-template <class ELFT> class CommonChunk : public Chunk {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-public:
- CommonChunk(const Elf_Sym *Sym);
- size_t getSize() const override { return Sym->getValue(); }
- bool hasData() const override { return false; }
- uint32_t getFlags() const override;
- StringRef getSectionName() const override { return ".bss"; }
-
-private:
- const Elf_Sym *Sym;
-};
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Removed: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h (removed)
@@ -1,40 +0,0 @@
-//===- Config.h -----------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_CONFIG_H
-#define LLD_ELF_CONFIG_H
-
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Object/ELF.h"
-#include <set>
-#include <string>
-
-namespace lld {
-namespace elfv2 {
-
-using llvm::StringRef;
-
-class Configuration {
-public:
- int MachineArchitecture = llvm::ELF::EM_X86_64;
- bool Verbose = false;
- StringRef EntryName;
- std::string OutputFile;
- bool DoGC = true;
-
- // Symbols in this set are considered as live by the garbage collector.
- std::set<StringRef> GCRoots;
-};
-
-extern Configuration *Config;
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Removed: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp (removed)
@@ -1,229 +0,0 @@
-//===- Driver.cpp ---------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Config.h"
-#include "Driver.h"
-#include "InputFiles.h"
-#include "SymbolTable.h"
-#include "Writer.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/LibDriver/LibDriver.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/TargetSelect.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <memory>
-
-using namespace llvm;
-using llvm::sys::fs::file_magic;
-using llvm::sys::fs::identify_magic;
-
-using namespace lld;
-using namespace lld::elfv2;
-
-namespace lld {
-namespace elfv2 {
-Configuration *Config;
-LinkerDriver *Driver;
-
-bool link(llvm::ArrayRef<const char *> Args) {
- auto C = make_unique<Configuration>();
- Config = C.get();
- auto D = make_unique<LinkerDriver>();
- Driver = D.get();
- return Driver->link(Args);
-}
-}
-}
-
-// Drop directory components and replace extension with ".exe".
-static std::string getOutputPath(StringRef Path) {
- auto P = Path.find_last_of("\\/");
- StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);
- return (S.substr(0, S.rfind('.')) + ".exe").str();
-}
-
-// Opens a file. Path has to be resolved already.
-// Newly created memory buffers are owned by this driver.
-ErrorOr<MemoryBufferRef> LinkerDriver::openFile(StringRef Path) {
- auto MBOrErr = MemoryBuffer::getFile(Path);
- if (auto EC = MBOrErr.getError())
- return EC;
- std::unique_ptr<MemoryBuffer> MB = std::move(MBOrErr.get());
- MemoryBufferRef MBRef = MB->getMemBufferRef();
- OwningMBs.push_back(std::move(MB)); // take ownership
- return MBRef;
-}
-
-static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
- // File type is detected by contents, not by file extension.
- file_magic Magic = identify_magic(MB.getBuffer());
- if (Magic == file_magic::archive)
- return std::unique_ptr<InputFile>(new ArchiveFile(MB));
- if (Magic == file_magic::bitcode)
- return std::unique_ptr<InputFile>(new BitcodeFile(MB));
- if (Config->OutputFile == "")
- Config->OutputFile = getOutputPath(MB.getBufferIdentifier());
- return std::unique_ptr<InputFile>(new ObjectFile<llvm::object::ELF64LE>(MB));
-}
-
-// Find file from search paths. You can omit ".obj", this function takes
-// care of that. Note that the returned path is not guaranteed to exist.
-StringRef LinkerDriver::doFindFile(StringRef Filename) {
- bool hasPathSep = (Filename.find_first_of("/\\") != StringRef::npos);
- if (hasPathSep)
- return Filename;
- bool hasExt = (Filename.find('.') != StringRef::npos);
- for (StringRef Dir : SearchPaths) {
- SmallString<128> Path = Dir;
- llvm::sys::path::append(Path, Filename);
- if (llvm::sys::fs::exists(Path.str()))
- return Alloc.save(Path.str());
- if (!hasExt) {
- Path.append(".obj");
- if (llvm::sys::fs::exists(Path.str()))
- return Alloc.save(Path.str());
- }
- }
- return Filename;
-}
-
-// Resolves a file path. This never returns the same path
-// (in that case, it returns None).
-Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
- StringRef Path = doFindFile(Filename);
- bool Seen = !VisitedFiles.insert(Path.lower()).second;
- if (Seen)
- return None;
- return Path;
-}
-
-// Find library file from search path.
-StringRef LinkerDriver::doFindLib(StringRef Filename) {
- // Add ".lib" to Filename if that has no file extension.
- bool hasExt = (Filename.find('.') != StringRef::npos);
- if (!hasExt)
- Filename = Alloc.save(Filename + ".lib");
- return doFindFile(Filename);
-}
-
-// Resolves a library path. /nodefaultlib options are taken into
-// consideration. This never returns the same path (in that case,
-// it returns None).
-Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {
- StringRef Path = doFindLib(Filename);
- bool Seen = !VisitedFiles.insert(Path.lower()).second;
- if (Seen)
- return None;
- return Path;
-}
-
-bool LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
- // Needed for LTO.
- llvm::InitializeAllTargetInfos();
- llvm::InitializeAllTargets();
- llvm::InitializeAllTargetMCs();
- llvm::InitializeAllAsmParsers();
- llvm::InitializeAllAsmPrinters();
- llvm::InitializeAllDisassemblers();
-
- // Parse command line options.
- auto ArgsOrErr = Parser.parse(ArgsArr);
- if (auto EC = ArgsOrErr.getError()) {
- llvm::errs() << EC.message() << "\n";
- return false;
- }
- llvm::opt::InputArgList Args = std::move(ArgsOrErr.get());
-
- // Handle /help
- if (Args.hasArg(OPT_help)) {
- printHelp(ArgsArr[0]);
- return true;
- }
-
- if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end()) {
- llvm::errs() << "no input files.\n";
- return false;
- }
-
- // Construct search path list.
- SearchPaths.push_back("");
- for (auto *Arg : Args.filtered(OPT_L))
- SearchPaths.push_back(Arg->getValue());
-
- // Handle /out
- if (auto *Arg = Args.getLastArg(OPT_output))
- Config->OutputFile = Arg->getValue();
-
- // Handle /entry
- if (auto *Arg = Args.getLastArg(OPT_e))
- Config->EntryName = Arg->getValue();
-
- // Create a list of input files. Files can be given as arguments
- // for /defaultlib option.
- std::vector<StringRef> InputPaths;
- std::vector<MemoryBufferRef> Inputs;
- for (auto *Arg : Args.filtered(OPT_INPUT))
- if (Optional<StringRef> Path = findFile(Arg->getValue()))
- InputPaths.push_back(*Path);
-
- for (StringRef Path : InputPaths) {
- ErrorOr<MemoryBufferRef> MBOrErr = openFile(Path);
- if (auto EC = MBOrErr.getError()) {
- llvm::errs() << "cannot open " << Path << ": " << EC.message() << "\n";
- return false;
- }
- Inputs.push_back(MBOrErr.get());
- }
-
- // Create a symbol table.
- SymbolTable<llvm::object::ELF64LE> 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);
- if (Config->Verbose)
- llvm::outs() << "Reading " << File->getName() << "\n";
- if (auto EC = Symtab.addFile(std::move(File))) {
- llvm::errs() << MB.getBufferIdentifier() << ": " << EC.message() << "\n";
- return false;
- }
- }
-
- // Make sure we have resolved all symbols.
- if (Symtab.reportRemainingUndefines())
- return false;
-
- // Initialize a list of GC root.
- Config->GCRoots.insert(Config->EntryName);
-
- // Do LTO by compiling bitcode input files to a native ELF file
- // then link that file.
- if (auto EC = Symtab.addCombinedLTOObject()) {
- llvm::errs() << EC.message() << "\n";
- return false;
- }
-
- // Write the result.
- Writer<llvm::object::ELF64LE> Out(&Symtab);
- if (auto EC = Out.write(Config->OutputFile)) {
- llvm::errs() << EC.message() << "\n";
- return false;
- }
- return true;
-}
Removed: lld/trunk/ELF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Driver.h (original)
+++ lld/trunk/ELF/Driver.h (removed)
@@ -1,102 +0,0 @@
-//===- Driver.h -----------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_DRIVER_H
-#define LLD_ELF_DRIVER_H
-
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Support/StringSaver.h"
-#include <memory>
-#include <set>
-#include <system_error>
-#include <vector>
-
-namespace lld {
-namespace elfv2 {
-
-class LinkerDriver;
-extern LinkerDriver *Driver;
-
-using llvm::Optional;
-class InputFile;
-
-// Entry point of the ELF linker.
-bool link(llvm::ArrayRef<const char *> Args);
-
-class ArgParser {
-public:
- ArgParser() : Alloc(AllocAux) {}
- // Parses command line options.
- ErrorOr<llvm::opt::InputArgList> parse(llvm::ArrayRef<const char *> Args);
-
- // Tokenizes a given string and then parses as command line options.
- ErrorOr<llvm::opt::InputArgList> parse(StringRef S) {
- return parse(tokenize(S));
- }
-
-private:
- ErrorOr<llvm::opt::InputArgList> parse(std::vector<const char *> Argv);
-
- std::vector<const char *> tokenize(StringRef S);
-
- ErrorOr<std::vector<const char *>>
- replaceResponseFiles(std::vector<const char *>);
-
- llvm::BumpPtrAllocator AllocAux;
- llvm::BumpPtrStringSaver Alloc;
-};
-
-class LinkerDriver {
-public:
- LinkerDriver() : Alloc(AllocAux) {}
- bool link(llvm::ArrayRef<const char *> Args);
-
-private:
- llvm::BumpPtrAllocator AllocAux;
- llvm::BumpPtrStringSaver Alloc;
- ArgParser Parser;
-
- // Opens a file. Path has to be resolved already.
- ErrorOr<MemoryBufferRef> openFile(StringRef Path);
-
- // Searches a file from search paths.
- Optional<StringRef> findFile(StringRef Filename);
- Optional<StringRef> findLib(StringRef Filename);
- StringRef doFindFile(StringRef Filename);
- StringRef doFindLib(StringRef Filename);
-
- std::vector<StringRef> SearchPaths;
- std::set<std::string> VisitedFiles;
-
- // Driver is the owner of all opened files.
- // InputFiles have MemoryBufferRefs to them.
- std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
-};
-
-// Functions below this line are defined in DriverUtils.cpp.
-
-void printHelp(const char *Argv0);
-
-// Create enum with OPT_xxx values for each option in Options.td
-enum {
- OPT_INVALID = 0,
-#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,
-#include "Options.inc"
-#undef OPTION
-};
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Removed: lld/trunk/ELF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/DriverUtils.cpp?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/DriverUtils.cpp (original)
+++ lld/trunk/ELF/DriverUtils.cpp (removed)
@@ -1,121 +0,0 @@
-//===- DriverUtils.cpp ----------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file contains utility functions for the driver. Because there
-// are so many small functions, we created this separate file to make
-// Driver.cpp less cluttered.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Config.h"
-#include "Driver.h"
-#include "Error.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/ArgList.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-
-using namespace llvm;
-using llvm::cl::ExpandResponseFiles;
-using llvm::cl::TokenizeWindowsCommandLine;
-using llvm::sys::Process;
-
-using namespace lld;
-using namespace lld::elfv2;
-
-// Create OptTable
-
-// Create prefix string literals used in Options.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "Options.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in Options.td
-static const llvm::opt::OptTable::Info infoTable[] = {
-#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
- { \
- X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \
- OPT_##GROUP, OPT_##ALIAS, X6 \
- } \
- ,
-#include "Options.inc"
-#undef OPTION
-};
-
-class ELFOptTable : public llvm::opt::OptTable {
-public:
- ELFOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)) {}
-};
-
-// Parses a given list of options.
-ErrorOr<llvm::opt::InputArgList>
-ArgParser::parse(std::vector<const char *> Argv) {
- // First, replace respnose files (@<file>-style options).
- auto ArgvOrErr = replaceResponseFiles(Argv);
- if (auto EC = ArgvOrErr.getError()) {
- llvm::errs() << "error while reading response file: " << EC.message()
- << "\n";
- return EC;
- }
- Argv = std::move(ArgvOrErr.get());
-
- // Make InputArgList from string vectors.
- ELFOptTable Table;
- unsigned MissingIndex;
- unsigned MissingCount;
-
- llvm::opt::InputArgList Args =
- Table.ParseArgs(Argv, MissingIndex, MissingCount);
- if (MissingCount) {
- llvm::errs() << "missing arg value for \""
- << Args.getArgString(MissingIndex) << "\", expected "
- << MissingCount
- << (MissingCount == 1 ? " argument.\n" : " arguments.\n");
- return make_error_code(LLDError::InvalidOption);
- }
- for (auto *Arg : Args.filtered(OPT_UNKNOWN))
- llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
- return std::move(Args);
-}
-
-ErrorOr<llvm::opt::InputArgList>
-ArgParser::parse(llvm::ArrayRef<const char *> Args) {
- Args = Args.slice(1);
- std::vector<const char *> V(Args.begin(), Args.end());
- return parse(V);
-}
-
-std::vector<const char *> ArgParser::tokenize(StringRef S) {
- SmallVector<const char *, 16> Tokens;
- BumpPtrStringSaver Saver(AllocAux);
- llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
- return std::vector<const char *>(Tokens.begin(), Tokens.end());
-}
-
-// Creates a new command line by replacing options starting with '@'
-// character. '@<filename>' is replaced by the file's contents.
-ErrorOr<std::vector<const char *>>
-ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
- SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
- BumpPtrStringSaver Saver(AllocAux);
- ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);
- return std::vector<const char *>(Tokens.begin(), Tokens.end());
-}
-
-void lld::elfv2::printHelp(const char *Argv0) {
- ELFOptTable Table;
- Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false);
-}
Removed: lld/trunk/ELF/Error.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Error.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Error.h (original)
+++ lld/trunk/ELF/Error.h (removed)
@@ -1,54 +0,0 @@
-//===- Error.h ------------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_ERROR_H
-#define LLD_ELF_ERROR_H
-
-#include <string>
-#include <system_error>
-#include "llvm/Support/ErrorHandling.h"
-
-namespace lld {
-namespace elfv2 {
-
-enum class LLDError {
- InvalidOption = 1,
- InvalidFile,
- BrokenFile,
- DuplicateSymbols,
-};
-
-class LLDErrorCategory : public std::error_category {
-public:
- const char *name() const LLVM_NOEXCEPT override { return "lld"; }
-
- std::string message(int EV) const override {
- switch (static_cast<LLDError>(EV)) {
- case LLDError::InvalidOption:
- return "Invalid option";
- case LLDError::InvalidFile:
- return "Invalid file";
- case LLDError::BrokenFile:
- return "Broken file";
- case LLDError::DuplicateSymbols:
- return "Duplicate symbols";
- }
- llvm_unreachable("unknown error");
- }
-};
-
-inline std::error_code make_error_code(LLDError Err) {
- static LLDErrorCategory C;
- return std::error_code(static_cast<int>(Err), C);
-}
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Removed: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp (removed)
@@ -1,216 +0,0 @@
-//===- InputFiles.cpp -----------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Chunks.h"
-#include "Error.h"
-#include "InputFiles.h"
-#include "Writer.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/LTO/LTOModule.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm::ELF;
-using namespace llvm::object;
-using namespace llvm::support::endian;
-using llvm::RoundUpToAlignment;
-using llvm::sys::fs::identify_magic;
-using llvm::sys::fs::file_magic;
-
-using namespace lld;
-using namespace lld::elfv2;
-
-// Returns the last element of a path, which is supposed to be a filename.
-static StringRef getBasename(StringRef Path) {
- size_t Pos = Path.rfind('\\');
- if (Pos == StringRef::npos)
- return Path;
- return Path.substr(Pos + 1);
-}
-
-// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
-std::string InputFile::getShortName() {
- if (ParentName == "")
- return getName().lower();
- std::string Res =
- (getBasename(ParentName) + "(" + getBasename(getName()) + ")").str();
- return StringRef(Res).lower();
-}
-
-std::error_code ArchiveFile::parse() {
- // Parse a MemoryBufferRef as an archive file.
- auto ArchiveOrErr = Archive::create(MB);
- if (auto EC = ArchiveOrErr.getError())
- return EC;
- File = std::move(ArchiveOrErr.get());
-
- // Allocate a buffer for Lazy objects.
- size_t BufSize = File->getNumberOfSymbols() * sizeof(Lazy);
- Lazy *Buf = (Lazy *)Alloc.Allocate(BufSize, llvm::alignOf<Lazy>());
-
- // Read the symbol table to construct Lazy objects.
- uint32_t I = 0;
- for (const Archive::Symbol &Sym : File->symbols()) {
- SymbolBodies.push_back(new (&Buf[I++]) Lazy(this, Sym));
- }
- return std::error_code();
-}
-
-// Returns a buffer pointing to a member file containing a given symbol.
-ErrorOr<MemoryBufferRef> ArchiveFile::getMember(const Archive::Symbol *Sym) {
- auto ItOrErr = Sym->getMember();
- if (auto EC = ItOrErr.getError())
- return EC;
- Archive::child_iterator It = ItOrErr.get();
-
- // Return an empty buffer if we have already returned the same buffer.
- const char *StartAddr = It->getBuffer().data();
- auto Pair = Seen.insert(StartAddr);
- if (!Pair.second)
- return MemoryBufferRef();
- return It->getMemoryBufferRef();
-}
-
-template <class ELFT> std::error_code elfv2::ObjectFile<ELFT>::parse() {
- // Parse a memory buffer as a ELF file.
- std::error_code EC;
- ELFObj = llvm::make_unique<ELFFile<ELFT>>(MB.getBuffer(), EC);
-
- if (EC) {
- llvm::errs() << getName() << " is not an ELF file.\n";
- return EC;
- }
-
- // Read section and symbol tables.
- if ((EC = initializeChunks()))
- return EC;
- return initializeSymbols();
-}
-
-template <class ELFT>
-SymbolBody *elfv2::ObjectFile<ELFT>::getSymbolBody(uint32_t SymbolIndex) {
- return SparseSymbolBodies[SymbolIndex]->getReplacement();
-}
-
-static bool isIgnoredSectionType(unsigned Type) {
- switch (Type) {
- case SHT_NULL:
- case SHT_SYMTAB:
- case SHT_STRTAB:
- case SHT_RELA:
- case SHT_HASH:
- case SHT_DYNAMIC:
- case SHT_NOTE:
- case SHT_REL:
- case SHT_DYNSYM:
- case SHT_SYMTAB_SHNDX:
- return true;
- }
- return false;
-}
-
-template <class ELFT>
-std::error_code elfv2::ObjectFile<ELFT>::initializeChunks() {
- auto Size = ELFObj->getNumSections();
- Chunks.reserve(Size);
- SparseChunks.resize(Size);
- int I = 0;
- for (auto &&Sec : ELFObj->sections()) {
- if (isIgnoredSectionType(Sec.sh_type) || Sec.sh_addralign == 0) {
- ++I;
- continue;
- }
- auto *C = new (Alloc) SectionChunk<ELFT>(this, &Sec, I);
- Chunks.push_back(C);
- SparseChunks[I] = C;
- ++I;
- }
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code elfv2::ObjectFile<ELFT>::initializeSymbols() {
- auto Syms = ELFObj->symbols();
- Syms = typename ELFFile<ELFT>::Elf_Sym_Range(Syms.begin() + 1, Syms.end());
- auto NumSymbols = std::distance(Syms.begin(), Syms.end());
- SymbolBodies.reserve(NumSymbols + 1);
- SparseSymbolBodies.resize(NumSymbols + 1);
- int I = 1;
- for (auto &&Sym : Syms) {
- SymbolBody *Body = createSymbolBody(&Sym);
- if (Body) {
- SymbolBodies.push_back(Body);
- SparseSymbolBodies[I] = Body;
- }
- ++I;
- }
-
- return std::error_code();
-}
-
-template <class ELFT>
-SymbolBody *elfv2::ObjectFile<ELFT>::createSymbolBody(const Elf_Sym *Sym) {
- StringRef Name;
- if (Sym->isUndefined()) {
- Name = *ELFObj->getStaticSymbolName(Sym);
- return new (Alloc) Undefined(Name);
- }
- if (Sym->isCommon()) {
- Chunk *C = new (Alloc) CommonChunk<ELFT>(Sym);
- Chunks.push_back(C);
- return new (Alloc) DefinedRegular<ELFT>(ELFObj.get(), Sym, C);
- }
- if (Sym->isAbsolute()) {
- Name = *ELFObj->getStaticSymbolName(Sym);
- return new (Alloc) DefinedAbsolute(Name, Sym->getValue());
- }
- if (Chunk *C = SparseChunks[Sym->st_shndx])
- return new (Alloc) DefinedRegular<ELFT>(ELFObj.get(), Sym, C);
- return nullptr;
-}
-
-std::error_code BitcodeFile::parse() {
- std::string Err;
- M.reset(LTOModule::createFromBuffer(MB.getBufferStart(), MB.getBufferSize(),
- llvm::TargetOptions(), Err));
- if (!Err.empty()) {
- llvm::errs() << Err << '\n';
- return make_error_code(LLDError::BrokenFile);
- }
-
- for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) {
- lto_symbol_attributes Attrs = M->getSymbolAttributes(I);
- if ((Attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
- continue;
-
- StringRef SymName = M->getSymbolName(I);
- int SymbolDef = Attrs & LTO_SYMBOL_DEFINITION_MASK;
- if (SymbolDef == LTO_SYMBOL_DEFINITION_UNDEFINED) {
- SymbolBodies.push_back(new (Alloc) Undefined(SymName));
- } else {
- bool Replaceable = (SymbolDef == LTO_SYMBOL_DEFINITION_TENTATIVE ||
- (Attrs & LTO_SYMBOL_COMDAT));
- SymbolBodies.push_back(new (Alloc) DefinedBitcode(SymName, Replaceable));
- }
- }
-
- return std::error_code();
-}
-
-namespace lld {
-namespace elfv2 {
-template class elfv2::ObjectFile<llvm::object::ELF32LE>;
-template class elfv2::ObjectFile<llvm::object::ELF32BE>;
-template class elfv2::ObjectFile<llvm::object::ELF64LE>;
-template class elfv2::ObjectFile<llvm::object::ELF64BE>;
-}
-}
Removed: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h (removed)
@@ -1,158 +0,0 @@
-//===- InputFiles.h -------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_INPUT_FILES_H
-#define LLD_ELF_INPUT_FILES_H
-
-#include "Chunks.h"
-#include "Symbols.h"
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/LTO/LTOModule.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/StringSaver.h"
-#include <memory>
-#include <set>
-#include <vector>
-
-namespace lld {
-namespace elfv2 {
-
-using llvm::LTOModule;
-using llvm::object::Archive;
-using llvm::object::ELFFile;
-
-// The root class of input files.
-class InputFile {
-public:
- enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind };
- Kind kind() const { return FileKind; }
- virtual ~InputFile() {}
-
- // Returns the filename.
- StringRef getName() { return MB.getBufferIdentifier(); }
-
- // Returns symbols defined by this file.
- virtual std::vector<SymbolBody *> &getSymbols() = 0;
-
- // Reads a file (constructors don't do that). Returns an error if a
- // file is broken.
- virtual std::error_code parse() = 0;
-
- // Returns a short, human-friendly filename. If this is a member of
- // an archive file, a returned value includes parent's filename.
- // Used for logging or debugging.
- std::string getShortName();
-
- // Sets a parent filename if this file is created from an archive.
- void setParentName(StringRef N) { ParentName = N; }
-
-protected:
- explicit InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
- MemoryBufferRef MB;
-
-private:
- const Kind FileKind;
- StringRef ParentName;
-};
-
-// .lib or .a file.
-class ArchiveFile : public InputFile {
-public:
- explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
- static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
- std::error_code parse() override;
-
- // Returns a memory buffer for a given symbol. An empty memory buffer
- // is returned if we have already returned the same memory buffer.
- // (So that we don't instantiate same members more than once.)
- ErrorOr<MemoryBufferRef> getMember(const Archive::Symbol *Sym);
-
- // NB: All symbols returned by ArchiveFiles are of Lazy type.
- std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
-
-private:
- std::unique_ptr<Archive> File;
- std::string Filename;
- std::vector<SymbolBody *> SymbolBodies;
- std::set<const char *> Seen;
- llvm::MallocAllocator Alloc;
-};
-
-// .obj or .o file. This may be a member of an archive file.
-template <class ELFT> class ObjectFile : public InputFile {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-public:
- explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {}
- static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
- std::error_code parse() override;
- std::vector<Chunk *> &getChunks() { return Chunks; }
- std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
-
- // Returns a SymbolBody object for the SymbolIndex'th symbol in the
- // underlying object file.
- SymbolBody *getSymbolBody(uint32_t SymbolIndex);
-
- // Returns the underying ELF file.
- ELFFile<ELFT> *getObj() { return ELFObj.get(); }
-
-private:
- std::error_code initializeChunks();
- std::error_code initializeSymbols();
-
- SymbolBody *createSymbolBody(const Elf_Sym *Sym);
-
- std::unique_ptr<ELFFile<ELFT>> ELFObj;
- llvm::BumpPtrAllocator Alloc;
-
- // List of all chunks defined by this file. This includes both section
- // chunks and non-section chunks for common symbols.
- std::vector<Chunk *> Chunks;
-
- // This vector contains the same chunks as Chunks, but they are
- // indexed such that you can get a SectionChunk by section index.
- // Nonexistent section indices are filled with null pointers.
- // (Because section number is 1-based, the first slot is always a
- // null pointer.)
- std::vector<Chunk *> SparseChunks;
-
- // List of all symbols referenced or defined by this file.
- std::vector<SymbolBody *> SymbolBodies;
-
- // This vector contains the same symbols as SymbolBodies, but they
- // are indexed such that you can get a SymbolBody by symbol
- // index. Nonexistent indices (which are occupied by auxiliary
- // symbols in the real symbol table) are filled with null pointers.
- std::vector<SymbolBody *> SparseSymbolBodies;
-};
-
-// Used for LTO.
-class BitcodeFile : public InputFile {
-public:
- explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
- static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
- std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
-
- LTOModule *getModule() const { return M.get(); }
- LTOModule *releaseModule() { return M.release(); }
-
-private:
- std::error_code parse() override;
-
- std::vector<SymbolBody *> SymbolBodies;
- llvm::BumpPtrAllocator Alloc;
- std::unique_ptr<LTOModule> M;
-};
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Removed: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td (removed)
@@ -1,54 +0,0 @@
-include "llvm/Option/OptParser.td"
-
-//===----------------------------------------------------------------------===//
-/// Utility Functions
-//===----------------------------------------------------------------------===//
-// Single and multiple dash options combined
-multiclass smDash<string opt1, string opt2, string help> {
- // Option
- def "" : Separate<["-"], opt1>, HelpText<help>;
- def opt1_eq : Joined<["-"], opt1#"=">,
- Alias<!cast<Option>(opt1)>;
- // Compatibility aliases
- def opt2_dashdash : Separate<["--"], opt2>,
- Alias<!cast<Option>(opt1)>;
- def opt2_dashdash_eq : Joined<["--"], opt2#"=">,
- Alias<!cast<Option>(opt1)>;
-}
-
-// Support -<option>,-<option>=
-multiclass dashEq<string opt1, string opt2, string help> {
- // Option
- def "" : Separate<["-"], opt1>, HelpText<help>;
- // Compatibility aliases
- def opt2_eq : Joined<["-"], opt2#"=">,
- Alias<!cast<Option>(opt1)>;
-}
-
-// Support --<option>,--<option>=
-multiclass mDashEq<string opt1, string help> {
- // Option
- def "" : Separate<["--"], opt1>, HelpText<help>;
- // Compatibility aliases
- def opt2_eq : Joined<["--"], opt1#"=">,
- Alias<!cast<Option>(opt1)>;
-}
-
-def output : Separate<["-"], "o">, MetaVarName<"<path>">,
- HelpText<"Path to file to write output">;
-
-def L : Joined<["-"], "L">, MetaVarName<"<dir>">,
- HelpText<"Directory to search for libraries">;
-def l : Joined<["-"], "l">, MetaVarName<"<libName>">,
- HelpText<"Root name of library to use">;
-def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
- HelpText<"Retain the executable output file whenever"
- " it is still usable">;
-defm e : smDash<"e", "entry",
- "Name of entry point symbol">;
-
-//===----------------------------------------------------------------------===//
-/// Help
-//===----------------------------------------------------------------------===//
-def help : Flag<["--"], "help">,
- HelpText<"Display this help message">;
Removed: lld/trunk/ELF/README.md
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/README.md?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/README.md (original)
+++ lld/trunk/ELF/README.md (removed)
@@ -1,12 +0,0 @@
-The New ELF Linker
-==================
-This directory contains a port of the new PE/COFF linker for ELF.
-
-Overall Design
---------------
-See COFF/README.md for details on the design.
-
-Capabilities
-------------
-This linker can currently generate a valid ELF file that can be run on linux
-from a single input file.
Removed: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp (removed)
@@ -1,306 +0,0 @@
-//===- SymbolTable.cpp ----------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Config.h"
-#include "Driver.h"
-#include "Error.h"
-#include "SymbolTable.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/LTO/LTOCodeGenerator.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-
-using namespace lld;
-using namespace lld::elfv2;
-
-template <class ELFT> SymbolTable<ELFT>::SymbolTable() {
- if (!Config->EntryName.empty())
- resolve(new (Alloc) Undefined(Config->EntryName));
-}
-
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
- if (auto EC = File->parse())
- return EC;
- InputFile *FileP = File.release();
- if (auto *P = dyn_cast<ObjectFile<ELFT>>(FileP))
- return addObject(P);
- if (auto *P = dyn_cast<ArchiveFile>(FileP))
- return addArchive(P);
- if (auto *P = dyn_cast<BitcodeFile>(FileP))
- return addBitcode(P);
- llvm_unreachable("Unknown file");
-}
-
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::addObject(ObjectFile<ELFT> *File) {
- ObjectFiles.emplace_back(File);
- for (SymbolBody *Body : File->getSymbols())
- if (Body->isExternal())
- if (auto EC = resolve(Body))
- return EC;
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::addArchive(ArchiveFile *File) {
- ArchiveFiles.emplace_back(File);
- for (SymbolBody *Body : File->getSymbols())
- if (auto EC = resolve(Body))
- return EC;
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::addBitcode(BitcodeFile *File) {
- BitcodeFiles.emplace_back(File);
- for (SymbolBody *Body : File->getSymbols())
- if (Body->isExternal())
- if (auto EC = resolve(Body))
- return EC;
- return std::error_code();
-}
-
-template <class ELFT> bool SymbolTable<ELFT>::reportRemainingUndefines() {
- bool Ret = false;
- for (auto &I : Symtab) {
- Symbol *Sym = I.second;
- auto *Undef = dyn_cast<Undefined>(Sym->Body);
- if (!Undef)
- continue;
- if (SymbolBody *Alias = Undef->getWeakAlias()) {
- Sym->Body = Alias->getReplacement();
- if (!isa<Defined>(Sym->Body)) {
- // Aliases are yet another symbols pointed by other symbols
- // that could also remain undefined.
- llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";
- Ret = true;
- }
- continue;
- }
- llvm::errs() << "undefined symbol: " << Undef->getName() << "\n";
- Ret = true;
- }
- return Ret;
-}
-
-// This function resolves conflicts if there's an existing symbol with
-// the same name. Decisions are made based on symbol type.
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::resolve(SymbolBody *New) {
- // Find an existing Symbol or create and insert a new one.
- StringRef Name = New->getName();
- Symbol *&Sym = Symtab[Name];
- if (!Sym) {
- Sym = new (Alloc) Symbol(New);
- New->setBackref(Sym);
- return std::error_code();
- }
- New->setBackref(Sym);
-
- // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
- // equivalent (conflicting), or more preferable, respectively.
- SymbolBody *Existing = Sym->Body;
- int comp = Existing->compare(New);
- if (comp < 0)
- Sym->Body = New;
- if (comp == 0) {
- llvm::errs() << "duplicate symbol: " << Name << "\n";
- return make_error_code(LLDError::DuplicateSymbols);
- }
-
- // If we have an Undefined symbol for a Lazy symbol, we need
- // to read an archive member to replace the Lazy symbol with
- // a Defined symbol.
- if (isa<Undefined>(Existing) || isa<Undefined>(New))
- if (auto *B = dyn_cast<Lazy>(Sym->Body))
- return addMemberFile(B);
- return std::error_code();
-}
-
-// Reads an archive member file pointed by a given symbol.
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::addMemberFile(Lazy *Body) {
- auto FileOrErr = Body->getMember();
- if (auto EC = FileOrErr.getError())
- return EC;
- std::unique_ptr<InputFile> File = std::move(FileOrErr.get());
-
- // getMember returns an empty buffer if the member was already
- // read from the library.
- if (!File)
- return std::error_code();
- if (Config->Verbose)
- llvm::outs() << "Loaded " << File->getShortName() << " for "
- << Body->getName() << "\n";
- return addFile(std::move(File));
-}
-
-template <class ELFT> std::vector<Chunk *> SymbolTable<ELFT>::getChunks() {
- std::vector<Chunk *> Res;
- for (std::unique_ptr<ObjectFile<ELFT>> &File : ObjectFiles) {
- std::vector<Chunk *> &V = File->getChunks();
- Res.insert(Res.end(), V.begin(), V.end());
- }
- return Res;
-}
-
-template <class ELFT> Defined *SymbolTable<ELFT>::find(StringRef Name) {
- auto It = Symtab.find(Name);
- if (It == Symtab.end())
- return nullptr;
- if (auto *Def = dyn_cast<Defined>(It->second->Body))
- return Def;
- return nullptr;
-}
-
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::addUndefined(StringRef Name) {
- return resolve(new (Alloc) Undefined(Name));
-}
-
-// Resolve To, and make From an alias to To.
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::rename(StringRef From, StringRef To) {
- SymbolBody *Body = new (Alloc) Undefined(To);
- if (auto EC = resolve(Body))
- return EC;
- Symtab[From]->Body = Body->getReplacement();
- return std::error_code();
-}
-
-template <class ELFT> void SymbolTable<ELFT>::dump() {
- for (auto &P : Symtab) {
- Symbol *Ref = P.second;
- if (auto *Body = dyn_cast<Defined>(Ref->Body))
- llvm::dbgs() << Twine::utohexstr(Body->getVA()) << " " << Body->getName()
- << "\n";
- }
-}
-
-template <class ELFT>
-std::error_code SymbolTable<ELFT>::addCombinedLTOObject() {
- if (BitcodeFiles.empty())
- return std::error_code();
-
- // Create an object file and add it to the symbol table by replacing any
- // DefinedBitcode symbols with the definitions in the object file.
- LTOCodeGenerator CG;
- auto FileOrErr = createLTOObject(&CG);
- if (auto EC = FileOrErr.getError())
- return EC;
- ObjectFile<ELFT> *Obj = FileOrErr.get();
-
- for (SymbolBody *Body : Obj->getSymbols()) {
- if (!Body->isExternal())
- continue;
- // Find an existing Symbol. We should not see any new undefined symbols at
- // this point.
- StringRef Name = Body->getName();
- Symbol *&Sym = Symtab[Name];
- if (!Sym) {
- if (!isa<Defined>(Body)) {
- llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
- return make_error_code(LLDError::BrokenFile);
- }
- Sym = new (Alloc) Symbol(Body);
- Body->setBackref(Sym);
- continue;
- }
- Body->setBackref(Sym);
-
- if (isa<DefinedBitcode>(Sym->Body)) {
- // The symbol should now be defined.
- if (!isa<Defined>(Body)) {
- llvm::errs() << "LTO: undefined symbol: " << Name << '\n';
- return make_error_code(LLDError::BrokenFile);
- }
- Sym->Body = Body;
- } else {
- int comp = Sym->Body->compare(Body);
- if (comp < 0)
- Sym->Body = Body;
- if (comp == 0) {
- llvm::errs() << "LTO: unexpected duplicate symbol: " << Name << "\n";
- return make_error_code(LLDError::BrokenFile);
- }
- }
-
- // We may see new references to runtime library symbols such as __chkstk
- // here. These symbols must be wholly defined in non-bitcode files.
- if (auto *B = dyn_cast<Lazy>(Sym->Body)) {
- size_t NumBitcodeFiles = BitcodeFiles.size();
- if (auto EC = addMemberFile(B))
- return EC;
- if (BitcodeFiles.size() != NumBitcodeFiles) {
- llvm::errs()
- << "LTO: late loaded symbol created new bitcode reference: " << Name
- << "\n";
- return make_error_code(LLDError::BrokenFile);
- }
- }
- }
-
- // New runtime library symbol references may have created undefined
- // references.
- if (reportRemainingUndefines())
- return make_error_code(LLDError::BrokenFile);
- return std::error_code();
-}
-
-// Combine and compile bitcode files and then return the result
-// as a regular ELF object file.
-template <class ELFT>
-ErrorOr<ObjectFile<ELFT> *>
-SymbolTable<ELFT>::createLTOObject(LTOCodeGenerator *CG) {
- // All symbols referenced by non-bitcode objects must be preserved.
- for (std::unique_ptr<ObjectFile<ELFT>> &File : ObjectFiles)
- for (SymbolBody *Body : File->getSymbols())
- if (auto *S = dyn_cast<DefinedBitcode>(Body->getReplacement()))
- CG->addMustPreserveSymbol(S->getName());
-
- // Likewise for bitcode symbols which we initially resolved to non-bitcode.
- for (std::unique_ptr<BitcodeFile> &File : BitcodeFiles)
- for (SymbolBody *Body : File->getSymbols())
- if (isa<DefinedBitcode>(Body) &&
- !isa<DefinedBitcode>(Body->getReplacement()))
- CG->addMustPreserveSymbol(Body->getName());
-
- // Likewise for other symbols that must be preserved.
- for (StringRef Name : Config->GCRoots)
- if (isa<DefinedBitcode>(Symtab[Name]->Body))
- CG->addMustPreserveSymbol(Name);
-
- CG->setModule(BitcodeFiles[0]->releaseModule());
- for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
- CG->addModule(BitcodeFiles[I]->getModule());
-
- std::string ErrMsg;
- LTOMB = CG->compile(false, false, false, ErrMsg); // take MB ownership
- if (!LTOMB) {
- llvm::errs() << ErrMsg << '\n';
- return make_error_code(LLDError::BrokenFile);
- }
- auto Obj = new ObjectFile<ELFT>(LTOMB->getMemBufferRef());
- ObjectFiles.emplace_back(Obj);
- if (auto EC = Obj->parse())
- return EC;
- return Obj;
-}
-
-namespace lld {
-namespace elfv2 {
-template class SymbolTable<llvm::object::ELF32LE>;
-template class SymbolTable<llvm::object::ELF32BE>;
-template class SymbolTable<llvm::object::ELF64LE>;
-template class SymbolTable<llvm::object::ELF64BE>;
-}
-}
Removed: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h (removed)
@@ -1,88 +0,0 @@
-//===- SymbolTable.h ------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_SYMBOL_TABLE_H
-#define LLD_ELF_SYMBOL_TABLE_H
-
-#include "InputFiles.h"
-#include "llvm/Support/Allocator.h"
-#include <unordered_map>
-
-namespace llvm {
-struct LTOCodeGenerator;
-}
-
-namespace lld {
-namespace elfv2 {
-
-// SymbolTable is a bucket of all known symbols, including defined,
-// undefined, or lazy symbols (the last one is symbols in archive
-// files whose archive members are not yet loaded).
-//
-// We put all symbols of all files to a SymbolTable, and the
-// SymbolTable selects the "best" symbols if there are name
-// conflicts. For example, obviously, a defined symbol is better than
-// an undefined symbol. Or, if there's a conflict between a lazy and a
-// undefined, it'll read an archive member to read a real definition
-// to replace the lazy symbol. The logic is implemented in resolve().
-template <class ELFT> class SymbolTable {
-public:
- SymbolTable();
-
- std::error_code addFile(std::unique_ptr<InputFile> File);
-
- // Print an error message on undefined symbols.
- bool reportRemainingUndefines();
-
- // Returns a list of chunks of selected symbols.
- std::vector<Chunk *> getChunks();
-
- // Returns a symbol for a given name. It's not guaranteed that the
- // returned symbol actually has the same name (because of various
- // mechanisms to allow aliases, a name can be resolved to a
- // different symbol). Returns a nullptr if not found.
- Defined *find(StringRef Name);
-
- // Dump contents of the symbol table to stderr.
- void dump();
-
- // Build an ELF object representing the combined contents of BitcodeFiles
- // and add it to the symbol table. Called after all files are added and
- // before the writer writes results to a file.
- std::error_code addCombinedLTOObject();
-
- // The writer needs to infer the machine type from the object files.
- std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
-
- // Creates an Undefined symbol for a given name.
- std::error_code addUndefined(StringRef Name);
-
- // Rename From -> To in the symbol table.
- std::error_code rename(StringRef From, StringRef To);
-
-private:
- std::error_code addObject(ObjectFile<ELFT> *File);
- std::error_code addArchive(ArchiveFile *File);
- std::error_code addBitcode(BitcodeFile *File);
-
- std::error_code resolve(SymbolBody *Body);
- std::error_code addMemberFile(Lazy *Body);
- ErrorOr<ObjectFile<ELFT> *> createLTOObject(llvm::LTOCodeGenerator *CG);
-
- std::unordered_map<StringRef, Symbol *> Symtab;
- std::vector<std::unique_ptr<ArchiveFile>> ArchiveFiles;
- std::vector<std::unique_ptr<BitcodeFile>> BitcodeFiles;
- std::unique_ptr<MemoryBuffer> LTOMB;
- llvm::BumpPtrAllocator Alloc;
-};
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Removed: lld/trunk/ELF/Symbols.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.cpp?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Symbols.cpp (original)
+++ lld/trunk/ELF/Symbols.cpp (removed)
@@ -1,145 +0,0 @@
-//===- Symbols.cpp --------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Error.h"
-#include "InputFiles.h"
-#include "Symbols.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm::object;
-using llvm::sys::fs::identify_magic;
-using llvm::sys::fs::file_magic;
-
-using namespace lld;
-using namespace lld::elfv2;
-
-// Returns 1, 0 or -1 if this symbol should take precedence
-// over the Other, tie or lose, respectively.
-template <class ELFT> int DefinedRegular<ELFT>::compare(SymbolBody *Other) {
- if (Other->kind() < kind())
- return -Other->compare(this);
- auto *R = dyn_cast<DefinedRegular>(Other);
- if (!R)
- return 1;
-
- // Common symbols are weaker than other types of defined symbols.
- if (isCommon() && R->isCommon())
- return (getCommonSize() < R->getCommonSize()) ? -1 : 1;
- // TODO: we are not sure if regular defined symbol and common
- // symbols are allowed to have the same name.
- if (isCommon())
- return -1;
- if (R->isCommon())
- return 1;
- return 0;
-}
-
-int DefinedBitcode::compare(SymbolBody *Other) {
- assert(Other->kind() >= kind());
- if (!isa<Defined>(Other))
- return 1;
-
- if (auto *B = dyn_cast<DefinedBitcode>(Other)) {
- if (!Replaceable && !B->Replaceable)
- return 0;
- // Non-replaceable symbols win.
- return Replaceable ? -1 : 1;
- }
-
- // As an approximation, regular symbols win over bitcode symbols,
- // but we definitely have a conflict if the regular symbol is not
- // replaceable and neither is the bitcode symbol. We do not
- // replicate the rest of the symbol resolution logic here; symbol
- // resolution will be done accurately after lowering bitcode symbols
- // to regular symbols in addCombinedLTOObject().
- if (auto *R = dyn_cast<DefinedRegular<llvm::object::ELF64LE>>(Other)) {
- if (!R->isCommon() && !Replaceable)
- return 0;
- return -1;
- }
- return 0;
-}
-
-int Defined::compare(SymbolBody *Other) {
- if (Other->kind() < kind())
- return -Other->compare(this);
- if (isa<Defined>(Other))
- return 0;
- return 1;
-}
-
-int Lazy::compare(SymbolBody *Other) {
- if (Other->kind() < kind())
- return -Other->compare(this);
-
- // Undefined symbols with weak aliases will turn into defined
- // symbols if they remain undefined, so we don't need to resolve
- // such symbols.
- if (auto *U = dyn_cast<Undefined>(Other))
- if (U->getWeakAlias())
- return -1;
- return 1;
-}
-
-int Undefined::compare(SymbolBody *Other) {
- if (Other->kind() < kind())
- return -Other->compare(this);
- if (cast<Undefined>(Other)->getWeakAlias())
- return -1;
- return 1;
-}
-
-template <class ELFT> StringRef DefinedRegular<ELFT>::getName() {
- // DefinedSymbol's name is read lazily for a performance reason.
- // Non-external symbol names are never used by the linker
- // except for logging or debugging.
- // Their internal references are resolved not by name but by symbol index.
- // And because they are not external, no one can refer them by name.
- // Object files contain lots of non-external symbols, and creating
- // StringRefs for them (which involves lots of strlen() on the string table)
- // is a waste of time.
- if (Name.empty())
- Name = *File->getStaticSymbolName(Sym);
- return Name;
-}
-
-ErrorOr<std::unique_ptr<InputFile>> Lazy::getMember() {
- auto MBRefOrErr = File->getMember(&Sym);
- if (auto EC = MBRefOrErr.getError())
- return EC;
- MemoryBufferRef MBRef = MBRefOrErr.get();
-
- // getMember returns an empty buffer if the member was already
- // read from the library.
- if (MBRef.getBuffer().empty())
- return std::unique_ptr<InputFile>(nullptr);
-
- file_magic Magic = identify_magic(MBRef.getBuffer());
- if (Magic == file_magic::bitcode)
- return std::unique_ptr<InputFile>(new BitcodeFile(MBRef));
- if (Magic != file_magic::elf_relocatable) {
- llvm::errs() << File->getName() << ": unknown file type\n";
- return make_error_code(LLDError::InvalidFile);
- }
-
- std::unique_ptr<InputFile> Obj(new ObjectFile<llvm::object::ELF64LE>(MBRef));
- Obj->setParentName(File->getName());
- return std::move(Obj);
-}
-
-namespace lld {
-namespace elfv2 {
-template class DefinedRegular<llvm::object::ELF32LE>;
-template class DefinedRegular<llvm::object::ELF32BE>;
-template class DefinedRegular<llvm::object::ELF64LE>;
-template class DefinedRegular<llvm::object::ELF64BE>;
-}
-}
Removed: lld/trunk/ELF/Symbols.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Symbols.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Symbols.h (original)
+++ lld/trunk/ELF/Symbols.h (removed)
@@ -1,232 +0,0 @@
-//===- Symbols.h ----------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_SYMBOLS_H
-#define LLD_ELF_SYMBOLS_H
-
-#include "Chunks.h"
-#include "Config.h"
-#include "lld/Core/LLVM.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/ELF.h"
-#include <memory>
-#include <vector>
-
-namespace lld {
-namespace elfv2 {
-
-using llvm::object::Archive;
-using llvm::object::ELFFile;
-
-class ArchiveFile;
-class InputFile;
-class SymbolBody;
-
-// A real symbol object, SymbolBody, is usually accessed indirectly
-// through a Symbol. There's always one Symbol for each symbol name.
-// The resolver updates SymbolBody pointers as it resolves symbols.
-struct Symbol {
- explicit Symbol(SymbolBody *P) : Body(P) {}
- SymbolBody *Body;
-};
-
-// The base class for real symbol classes.
-class SymbolBody {
-public:
- enum Kind {
- DefinedFirst,
- DefinedBitcodeKind,
- DefinedAbsoluteKind,
- DefinedRegularKind,
- DefinedLast,
- LazyKind,
- UndefinedKind,
- };
-
- Kind kind() const { return SymbolKind; }
- virtual ~SymbolBody() {}
-
- // Returns true if this is an external symbol.
- virtual bool isExternal() { return true; }
-
- // Returns the symbol name.
- virtual StringRef getName() = 0;
-
- // A SymbolBody has a backreference to a Symbol. Originally they are
- // doubly-linked. A backreference will never change. But the pointer
- // in the Symbol may be mutated by the resolver. If you have a
- // pointer P to a SymbolBody and are not sure whether the resolver
- // has chosen the object among other objects having the same name,
- // you can access P->Backref->Body to get the resolver's result.
- void setBackref(Symbol *P) { Backref = P; }
- SymbolBody *getReplacement() { return Backref ? Backref->Body : this; }
-
- // Decides which symbol should "win" in the symbol table, this or
- // the Other. Returns 1 if this wins, -1 if the Other wins, or 0 if
- // they are duplicate (conflicting) symbols.
- virtual int compare(SymbolBody *Other) = 0;
-
-protected:
- SymbolBody(Kind K) : SymbolKind(K) {}
-
-private:
- const Kind SymbolKind;
- Symbol *Backref = nullptr;
-};
-
-// The base class for any defined symbols, including absolute symbols,
-// etc.
-class Defined : public SymbolBody {
-public:
- Defined(Kind K) : SymbolBody(K) {}
-
- static bool classof(const SymbolBody *S) {
- Kind K = S->kind();
- return DefinedFirst <= K && K <= DefinedLast;
- }
-
- // Returns the VA (virtual address) of this symbol. The
- // writer sets and uses VAs.
- virtual uint64_t getVA() = 0;
-
- // Returns the file offset of this symbol in the final executable.
- // The writer uses this information to apply relocations.
- virtual uint64_t getFileOff() = 0;
-
- // Called by the garbage collector. All Defined subclasses should
- // know how to call depending symbols' markLive functions.
- virtual void markLive() {}
-
- int compare(SymbolBody *Other) override;
-};
-
-// Regular defined symbols read from object file symbol tables.
-template <class ELFT> class DefinedRegular : public Defined {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
-
-public:
- DefinedRegular(ELFFile<ELFT> *F, const Elf_Sym *S, Chunk *C)
- : Defined(DefinedRegularKind), File(F), Sym(S), Data(C) {}
-
- static bool classof(const SymbolBody *S) {
- return S->kind() == DefinedRegularKind;
- }
-
- StringRef getName() override;
- uint64_t getVA() override { return Data->getVA() + Sym->getValue(); }
- bool isExternal() override { return Sym->isExternal(); }
- void markLive() override { Data->markLive(); }
- uint64_t getFileOff() override {
- return Data->getFileOff() + Sym->getValue();
- }
- int compare(SymbolBody *Other) override;
-
- // Returns true if this is a common symbol.
- bool isCommon() const { return Sym->isCommon(); }
- uint32_t getCommonSize() const { return Sym->st_size; }
-
-private:
- StringRef Name;
- ELFFile<ELFT> *File;
- const Elf_Sym *Sym;
- Chunk *Data;
-};
-
-// Absolute symbols.
-class DefinedAbsolute : public Defined {
-public:
- DefinedAbsolute(StringRef N, uint64_t VA)
- : Defined(DefinedAbsoluteKind), Name(N), VA(VA) {}
-
- static bool classof(const SymbolBody *S) {
- return S->kind() == DefinedAbsoluteKind;
- }
-
- StringRef getName() override { return Name; }
- uint64_t getVA() override { return VA; }
- uint64_t getFileOff() override { llvm_unreachable("internal error"); }
-
-private:
- StringRef Name;
- uint64_t VA;
-};
-
-// This class represents a symbol defined in an archive file. It is
-// created from an archive file header, and it knows how to load an
-// object file from an archive to replace itself with a defined
-// symbol. If the resolver finds both Undefined and Lazy for
-// the same name, it will ask the Lazy to load a file.
-class Lazy : public SymbolBody {
-public:
- Lazy(ArchiveFile *F, const Archive::Symbol S)
- : SymbolBody(LazyKind), Name(S.getName()), File(F), Sym(S) {}
-
- static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }
- StringRef getName() override { return Name; }
-
- // Returns an object file for this symbol, or a nullptr if the file
- // was already returned.
- ErrorOr<std::unique_ptr<InputFile>> getMember();
-
- int compare(SymbolBody *Other) override;
-
-private:
- StringRef Name;
- ArchiveFile *File;
- const Archive::Symbol Sym;
-};
-
-// Undefined symbols.
-class Undefined : public SymbolBody {
-public:
- explicit Undefined(StringRef N, SymbolBody **S = nullptr)
- : SymbolBody(UndefinedKind), Name(N), Alias(S) {}
-
- static bool classof(const SymbolBody *S) {
- return S->kind() == UndefinedKind;
- }
- StringRef getName() override { return Name; }
-
- // An undefined symbol can have a fallback symbol which gives an
- // undefined symbol a second chance if it would remain undefined.
- // If it remains undefined, it'll be replaced with whatever the
- // Alias pointer points to.
- SymbolBody *getWeakAlias() { return Alias ? *Alias : nullptr; }
-
- int compare(SymbolBody *Other) override;
-
-private:
- StringRef Name;
- SymbolBody **Alias;
-};
-
-class DefinedBitcode : public Defined {
-public:
- DefinedBitcode(StringRef N, bool R)
- : Defined(DefinedBitcodeKind), Name(N), Replaceable(R) {}
-
- static bool classof(const SymbolBody *S) {
- return S->kind() == DefinedBitcodeKind;
- }
-
- StringRef getName() override { return Name; }
- uint64_t getVA() override { llvm_unreachable("bitcode reached writer"); }
- uint64_t getFileOff() override { llvm_unreachable("bitcode reached writer"); }
- int compare(SymbolBody *Other) override;
-
-private:
- StringRef Name;
- bool Replaceable;
-};
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Removed: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp (removed)
@@ -1,241 +0,0 @@
-//===- Writer.cpp ---------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Config.h"
-#include "Writer.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cstdio>
-#include <functional>
-#include <unordered_map>
-#include <utility>
-
-#include "llvm/Support/raw_ostream.h"
-
-using namespace llvm;
-using namespace llvm::ELF;
-using namespace llvm::object;
-using namespace llvm::support;
-using namespace llvm::support::endian;
-
-static const int PageSize = 4096;
-
-struct SectionTraits {
- uint64_t Type;
- uint64_t Flags;
- StringRef Name;
-};
-
-bool operator==(const SectionTraits &A, const SectionTraits &B) {
- return A.Type == B.Type && A.Flags == B.Flags && A.Name == B.Name;
-}
-
-namespace std {
-template <> struct hash<SectionTraits> {
- size_t operator()(const SectionTraits &ST) const {
- return hash_combine(ST.Type, ST.Flags, ST.Name);
- }
-};
-}
-
-using namespace lld;
-using namespace lld::elfv2;
-
-// The main function of the writer.
-template <class ELFT>
-std::error_code Writer<ELFT>::write(StringRef OutputPath) {
- markLive();
- createSections();
- assignAddresses();
- removeEmptySections();
- if (auto EC = openFile(OutputPath))
- return EC;
- writeHeader();
- writeSections();
- return Buffer->commit();
-}
-
-void OutputSection::setVA(uint64_t VA) {
- Header.sh_addr = VA;
- for (Chunk *C : Chunks)
- C->setVA(C->getVA() + VA);
-}
-
-void OutputSection::setFileOffset(uint64_t Off) {
- if (Header.sh_size == 0)
- return;
- Header.sh_offset = Off;
- for (Chunk *C : Chunks)
- C->setFileOff(C->getFileOff() + Off);
-}
-
-void OutputSection::addChunk(Chunk *C) {
- Chunks.push_back(C);
- C->setOutputSection(this);
- uint64_t Off = Header.sh_size;
- Off = RoundUpToAlignment(Off, C->getAlign());
- C->setVA(Off);
- C->setFileOff(Off);
- Off += C->getSize();
- Header.sh_size = Off;
-}
-
-void OutputSection::addPermissions(uint32_t C) {
- // Header.Characteristics |= C & PermMask;
-}
-
-// Write the section header to a given buffer.
-void OutputSection::writeHeaderTo(uint8_t *Buf) {}
-
-// Set live bit on for each reachable chunk. Unmarked (unreachable)
-// COMDAT chunks will be ignored in the next step, so that they don't
-// come to the final output file.
-template <class ELFT> void Writer<ELFT>::markLive() {
- if (!Config->DoGC)
- return;
- for (StringRef Name : Config->GCRoots)
- cast<Defined>(Symtab->find(Name))->markLive();
- for (Chunk *C : Symtab->getChunks())
- if (C->isRoot())
- C->markLive();
-}
-
-static SectionTraits getChunkTraits(Chunk *C) {
- return {0, C->getFlags(), C->getSectionName()};
-}
-
-// Create output section objects and add them to OutputSections.
-template <class ELFT> void Writer<ELFT>::createSections() {
- std::unordered_map<SectionTraits, std::vector<Chunk *>> Map;
- for (Chunk *C : Symtab->getChunks()) {
- if (Config->DoGC && !C->isLive()) {
- if (Config->Verbose)
- C->printDiscardedMessage();
- continue;
- }
- Map[getChunkTraits(C)].push_back(C);
- }
-
- for (auto &P : Map) {
- auto Sec = new (CAlloc.Allocate())
- OutputSection(P.first.Name, OutputSections.size());
- OutputSections.push_back(Sec);
- for (Chunk *C : P.second) {
- Sec->addChunk(C);
- Sec->addPermissions(C->getFlags());
- }
- }
-}
-
-template <class ELFT> void Writer<ELFT>::removeEmptySections() {
- auto IsEmpty = [](OutputSection *S) { return S->getSize() == 0; };
- OutputSections.erase(
- std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),
- OutputSections.end());
-}
-
-// Visits all sections to assign incremental, non-overlapping RVAs and
-// file offsets.
-template <class ELFT> void Writer<ELFT>::assignAddresses() {
- SizeOfHeaders = RoundUpToAlignment(sizeof(Elf_Ehdr_Impl<ELFT>) +
- sizeof(Elf_Shdr_Impl<ELFT>) *
- OutputSections.size(),
- PageSize);
- uint64_t VA = 0x1000; // The first page is kept unmapped.
- uint64_t FileOff = SizeOfHeaders;
- for (OutputSection *Sec : OutputSections) {
- Sec->setVA(VA);
- Sec->setFileOffset(FileOff);
- VA += RoundUpToAlignment(Sec->getSize(), PageSize);
- FileOff += RoundUpToAlignment(Sec->getSize(), 8);
- }
- SizeOfImage = SizeOfHeaders + RoundUpToAlignment(VA - 0x1000, PageSize);
- FileSize = SizeOfHeaders + RoundUpToAlignment(FileOff - SizeOfHeaders, 8);
-}
-
-template <class ELFT> void Writer<ELFT>::writeHeader() {
- uint8_t *Buf = Buffer->getBufferStart();
- auto *EHdr = reinterpret_cast<Elf_Ehdr_Impl<ELFT> *>(Buf);
- EHdr->e_ident[EI_MAG0] = 0x7F;
- EHdr->e_ident[EI_MAG1] = 0x45;
- EHdr->e_ident[EI_MAG2] = 0x4C;
- EHdr->e_ident[EI_MAG3] = 0x46;
- EHdr->e_ident[EI_CLASS] = ELFCLASS64;
- EHdr->e_ident[EI_DATA] = ELFDATA2LSB;
- EHdr->e_ident[EI_VERSION] = EV_CURRENT;
- EHdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
-
- EHdr->e_type = ET_EXEC;
- EHdr->e_machine = EM_X86_64;
- EHdr->e_version = EV_CURRENT;
- EHdr->e_entry = 0x401000;
- EHdr->e_phoff = sizeof(Elf_Ehdr_Impl<ELFT>);
- EHdr->e_shoff = 0;
- EHdr->e_ehsize = sizeof(Elf_Ehdr_Impl<ELFT>);
- EHdr->e_phentsize = sizeof(Elf_Phdr_Impl<ELFT>);
- EHdr->e_phnum = 1;
- EHdr->e_shentsize = sizeof(Elf_Shdr_Impl<ELFT>);
- EHdr->e_shnum = 0;
- EHdr->e_shstrndx = 0;
-
- auto PHdrs = reinterpret_cast<Elf_Phdr_Impl<ELFT> *>(Buf + EHdr->e_phoff);
- PHdrs->p_type = PT_LOAD;
- PHdrs->p_flags = PF_R | PF_X;
- PHdrs->p_offset = 0x0000;
- PHdrs->p_vaddr = 0x400000;
- PHdrs->p_paddr = PHdrs->p_vaddr;
- PHdrs->p_filesz = FileSize;
- PHdrs->p_memsz = FileSize;
- PHdrs->p_align = 0x4000;
-}
-
-template <class ELFT> std::error_code Writer<ELFT>::openFile(StringRef Path) {
- if (auto EC = FileOutputBuffer::create(Path, FileSize, Buffer,
- FileOutputBuffer::F_executable)) {
- llvm::errs() << "failed to open " << Path << ": " << EC.message() << "\n";
- return EC;
- }
- return std::error_code();
-}
-
-// Write section contents to a mmap'ed file.
-template <class ELFT> void Writer<ELFT>::writeSections() {
- uint8_t *Buf = Buffer->getBufferStart();
- for (OutputSection *Sec : OutputSections) {
- // Fill gaps between functions in .text with nop instructions instead of
- // leaving as null bytes (which can be interpreted as ADD instructions).
- if (Sec->getPermissions() & PF_X)
- memset(Buf + Sec->getFileOff(), 0x90, Sec->getSize());
- for (Chunk *C : Sec->getChunks())
- C->writeTo(Buf);
- }
-}
-
-template <class ELFT> OutputSection *Writer<ELFT>::findSection(StringRef Name) {
- for (OutputSection *Sec : OutputSections)
- if (Sec->getName() == Name)
- return Sec;
- return nullptr;
-}
-
-namespace lld {
-namespace elfv2 {
-template class Writer<ELF32LE>;
-template class Writer<ELF32BE>;
-template class Writer<ELF64LE>;
-template class Writer<ELF64BE>;
-}
-}
Removed: lld/trunk/ELF/Writer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.h?rev=242117&view=auto
==============================================================================
--- lld/trunk/ELF/Writer.h (original)
+++ lld/trunk/ELF/Writer.h (removed)
@@ -1,91 +0,0 @@
-//===- Writer.h -----------------------------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_ELF_WRITER_H
-#define LLD_ELF_WRITER_H
-
-#include "InputFiles.h"
-#include "SymbolTable.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <memory>
-#include <vector>
-
-namespace lld {
-namespace elfv2 {
-
-// OutputSection represents a section in an output file. It's a
-// container of chunks. OutputSection and Chunk are 1:N relationship.
-// Chunks cannot belong to more than one OutputSections. The writer
-// creates multiple OutputSections and assign them unique,
-// non-overlapping file offsets and VAs.
-class OutputSection {
-public:
- OutputSection(StringRef N, uint32_t SI)
- : Name(N), SectionIndex(SI), Header({}) {}
- void setVA(uint64_t);
- void setFileOffset(uint64_t);
- void addChunk(Chunk *C);
- StringRef getName() { return Name; }
- uint64_t getSectionIndex() { return SectionIndex; }
- std::vector<Chunk *> &getChunks() { return Chunks; }
- void addPermissions(uint32_t C);
- uint32_t getPermissions() { return 0; }
- uint64_t getVA() { return Header.sh_addr; }
- uint64_t getFileOff() { return Header.sh_offset; }
- void writeHeaderTo(uint8_t *Buf);
-
- // Returns the size of the section in the output file.
- uint64_t getSize() { return Header.sh_size; }
-
- // Set offset into the string table storing this section name.
- // Used only when the name is longer than 8 bytes.
- void setStringTableOff(uint32_t V) { StringTableOff = V; }
-
-private:
- StringRef Name;
- uint32_t SectionIndex;
- llvm::ELF::Elf64_Shdr Header;
- uint32_t StringTableOff = 0;
- std::vector<Chunk *> Chunks;
-};
-
-// The writer writes a SymbolTable result to a file.
-template <class ELFT> class Writer {
-public:
- explicit Writer(SymbolTable<ELFT> *T) : Symtab(T) {}
- std::error_code write(StringRef Path);
-
-private:
- void markLive();
- void createSections();
- void assignAddresses();
- void removeEmptySections();
- std::error_code openFile(StringRef OutputPath);
- void writeHeader();
- void writeSections();
-
- OutputSection *findSection(StringRef Name);
-
- SymbolTable<ELFT> *Symtab;
- std::unique_ptr<llvm::FileOutputBuffer> Buffer;
- llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc;
- std::vector<OutputSection *> OutputSections;
-
- uint64_t FileSize;
- uint64_t SizeOfImage;
- uint64_t SizeOfHeaders;
-
- std::vector<std::unique_ptr<Chunk>> Chunks;
-};
-
-} // namespace elfv2
-} // namespace lld
-
-#endif
Modified: lld/trunk/include/lld/Driver/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/Driver.h?rev=242118&r1=242117&r2=242118&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/Driver.h (original)
+++ lld/trunk/include/lld/Driver/Driver.h Mon Jul 13 23:49:48 2015
@@ -146,10 +146,6 @@ namespace coff {
bool link(llvm::ArrayRef<const char *> args);
}
-namespace elfv2 {
-bool link(llvm::ArrayRef<const char *> args);
-}
-
/// Driver for lld unit tests
class CoreDriver : public Driver {
public:
Modified: lld/trunk/lib/Driver/UniversalDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/UniversalDriver.cpp?rev=242118&r1=242117&r2=242118&view=diff
==============================================================================
--- lld/trunk/lib/Driver/UniversalDriver.cpp (original)
+++ lld/trunk/lib/Driver/UniversalDriver.cpp Mon Jul 13 23:49:48 2015
@@ -69,7 +69,6 @@ public:
enum class Flavor {
invalid,
gnu_ld, // -flavor gnu
- gnu_ld2, // -flavor gnu2
win_link, // -flavor link
win_link2, // -flavor link2
darwin_ld, // -flavor darwin
@@ -86,7 +85,6 @@ struct ProgramNameParts {
static Flavor strToFlavor(StringRef str) {
return llvm::StringSwitch<Flavor>(str)
.Case("gnu", Flavor::gnu_ld)
- .Case("gnu2", Flavor::gnu_ld2)
.Case("link", Flavor::win_link)
.Case("lld-link", Flavor::win_link)
.Case("link2", Flavor::win_link2)
@@ -204,8 +202,6 @@ bool UniversalDriver::link(llvm::Mutable
switch (flavor) {
case Flavor::gnu_ld:
return GnuLdDriver::linkELF(args, diagnostics);
- case Flavor::gnu_ld2:
- return elfv2::link(args);
case Flavor::darwin_ld:
return DarwinLdDriver::linkMachO(args, diagnostics);
case Flavor::win_link:
Removed: lld/trunk/test/elfv2/basic.test
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/elfv2/basic.test?rev=242117&view=auto
==============================================================================
--- lld/trunk/test/elfv2/basic.test (original)
+++ lld/trunk/test/elfv2/basic.test (removed)
@@ -1,62 +0,0 @@
-# RUN: yaml2obj -format elf %s -o %t
-# RUN: lld -flavor gnu2 %t -e _start -o %t2
-# RUN: llvm-readobj -file-headers -program-headers %t2 | FileCheck %s
-
-FileHeader:
- Class: ELFCLASS64
- Data: ELFDATA2LSB
- OSABI: ELFOSABI_GNU
- Type: ET_REL
- Machine: EM_X86_64
-Sections:
- - Name: .text
- Type: SHT_PROGBITS
- Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
- AddressAlign: 0x0000000000000004
- Content: 5548C7C03C00000048C7C7010000000F05
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
-
-# CHECK: ElfHeader {
-# CHECK: Ident {
-# CHECK: Magic: (7F 45 4C 46)
-# CHECK: Class: 64-bit (0x2)
-# CHECK: DataEncoding: LittleEndian (0x1)
-# CHECK: FileVersion: 1
-# CHECK: OS/ABI: GNU/Linux (0x3)
-# CHECK: ABIVersion: 0
-# CHECK: Unused: (00 00 00 00 00 00 00)
-# CHECK: }
-# CHECK: Type: Executable (0x2)
-# CHECK: Machine: EM_X86_64 (0x3E)
-# CHECK: Version: 1
-# Entry: 0x401000
-# CHECK: ProgramHeaderOffset: 0x40
-# SectionHeaderOffset: 0x0
-# CHECK: Flags [ (0x0)
-# CHECK: ]
-# CHECK: HeaderSize: 64
-# CHECK: ProgramHeaderEntrySize: 56
-# ProgramHeaderCount: 1
-# CHECK: SectionHeaderEntrySize: 64
-# SectionHeaderCount: 0
-# StringTableSectionIndex: 0
-# CHECK: }
-# CHECK: ProgramHeaders [
-# CHECK: ProgramHeader {
-# CHECK: Type: PT_LOAD (0x1)
-# Offset: 0x0
-# VirtualAddress: 0x400000
-# PhysicalAddress: 0x400000
-# FileSize: 4128
-# MemSize: 4128
-# CHECK: Flags [ (0x5)
-# CHECK: PF_R (0x4)
-# CHECK: PF_X (0x1)
-# CHECK: ]
-# Alignment: 16384
-# CHECK: }
-# CHECK: ]
Modified: lld/trunk/tools/lld/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/tools/lld/CMakeLists.txt?rev=242118&r1=242117&r2=242118&view=diff
==============================================================================
--- lld/trunk/tools/lld/CMakeLists.txt (original)
+++ lld/trunk/tools/lld/CMakeLists.txt Mon Jul 13 23:49:48 2015
@@ -5,7 +5,6 @@ add_llvm_executable(lld
target_link_libraries(lld
lldDriver
lldCOFF
- lldELF2
LLVMSupport
)
Modified: lld/trunk/unittests/DriverTests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/CMakeLists.txt?rev=242118&r1=242117&r2=242118&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/CMakeLists.txt (original)
+++ lld/trunk/unittests/DriverTests/CMakeLists.txt Mon Jul 13 23:49:48 2015
@@ -10,7 +10,6 @@ target_link_libraries(DriverTests
lldDriver
lldCOFF
lldCore
- lldELF2
lldPECOFF
lldMachO
)
More information about the llvm-commits
mailing list