diff --git a/lld/tools/lld-core/CMakeLists.txt b/lld/tools/lld-core/CMakeLists.txt deleted file mode 100644 index 8b8a84ab92f4..000000000000 --- a/lld/tools/lld-core/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ - -add_lld_executable(lld-core - lld-core.cpp - ) - -target_link_libraries(lld-core - lldPasses - lldMachO - lldPECOFF - lldELF - lldNative - lldReaderWriter - lldYAML - lldCore - lldDriver - LLVMObject - LLVMSupport - ) - -install(TARGETS lld-core - RUNTIME DESTINATION bin) diff --git a/lld/tools/lld-core/TestingHelpers.hpp b/lld/tools/lld-core/TestingHelpers.hpp deleted file mode 100644 index 8b9c46602528..000000000000 --- a/lld/tools/lld-core/TestingHelpers.hpp +++ /dev/null @@ -1,351 +0,0 @@ -//===- tools/lld/TestingWriter.hpp - Linker Core Test Support -------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_TOOLS_TESTING_HELPERS_H_ -#define LLD_TOOLS_TESTING_HELPERS_H_ - -#include "lld/Core/Atom.h" -#include "lld/Core/LLVM.h" -#include "lld/Core/Pass.h" -#include "lld/Core/Resolver.h" -#include "lld/ReaderWriter/Writer.h" - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/system_error.h" - -#include - -using namespace lld; - -/// \brief Simple atom created by the stubs pass. -class TestingStubAtom : public DefinedAtom { -public: - TestingStubAtom(const File &F, const Atom&) : _file(F) { - static uint32_t lastOrdinal = 0; - _ordinal = lastOrdinal++; - } - - virtual const File &file() const { - return _file; - } - - virtual StringRef name() const { - return StringRef(); - } - - virtual uint64_t ordinal() const { - return _ordinal; - } - - virtual uint64_t size() const { - return 0; - } - - virtual Scope scope() const { - return DefinedAtom::scopeLinkageUnit; - } - - virtual Interposable interposable() const { - return DefinedAtom::interposeNo; - } - - virtual Merge merge() const { - return DefinedAtom::mergeNo; - } - - virtual ContentType contentType() const { - return DefinedAtom::typeStub; - } - - virtual Alignment alignment() const { - return Alignment(0, 0); - } - - virtual SectionChoice sectionChoice() const { - return DefinedAtom::sectionBasedOnContent; - } - - virtual StringRef customSectionName() const { - return StringRef(); - } - - virtual SectionPosition sectionPosition() const { - return sectionPositionAny; - } - - virtual DeadStripKind deadStrip() const { - return DefinedAtom::deadStripNormal; - } - - virtual ContentPermissions permissions() const { - return DefinedAtom::permR_X; - } - - virtual bool isThumb() const { - return false; - } - - virtual bool isAlias() const { - return false; - } - - virtual ArrayRef rawContent() const { - return ArrayRef(); - } - - virtual reference_iterator begin() const { - return reference_iterator(*this, nullptr); - } - - virtual reference_iterator end() const { - return reference_iterator(*this, nullptr); - } - - virtual const Reference *derefIterator(const void *iter) const { - return nullptr; - } - - virtual void incrementIterator(const void *&iter) const { - } - -private: - const File &_file; - uint32_t _ordinal; -}; - -/// \brief Simple atom created by the GOT pass. -class TestingGOTAtom : public DefinedAtom { -public: - TestingGOTAtom(const File &F, const Atom&) : _file(F) { - static uint32_t lastOrdinal = 0; - _ordinal = lastOrdinal++; - } - - virtual const File &file() const { - return _file; - } - - virtual StringRef name() const { - return StringRef(); - } - - virtual uint64_t ordinal() const { - return _ordinal; - } - - virtual uint64_t size() const { - return 0; - } - - virtual Scope scope() const { - return DefinedAtom::scopeLinkageUnit; - } - - virtual Interposable interposable() const { - return DefinedAtom::interposeNo; - } - - virtual Merge merge() const { - return DefinedAtom::mergeNo; - } - - virtual ContentType contentType() const { - return DefinedAtom::typeGOT; - } - - virtual Alignment alignment() const { - return Alignment(3, 0); - } - - virtual SectionChoice sectionChoice() const { - return DefinedAtom::sectionBasedOnContent; - } - - virtual StringRef customSectionName() const { - return StringRef(); - } - - virtual SectionPosition sectionPosition() const { - return sectionPositionAny; - } - - virtual DeadStripKind deadStrip() const { - return DefinedAtom::deadStripNormal; - } - - virtual ContentPermissions permissions() const { - return DefinedAtom::permRW_; - } - - virtual bool isThumb() const { - return false; - } - - virtual bool isAlias() const { - return false; - } - - virtual ArrayRef rawContent() const { - return ArrayRef(); - } - - virtual reference_iterator begin() const { - return reference_iterator(*this, nullptr); - } - - virtual reference_iterator end() const { - return reference_iterator(*this, nullptr); - } - - virtual const Reference *derefIterator(const void *iter) const { - return nullptr; - } - - virtual void incrementIterator(const void *&iter) const { - } - -private: - const File &_file; - uint32_t _ordinal; -}; - -class TestingPassFile : public MutableFile { -public: - TestingPassFile(const TargetInfo &ti) : MutableFile(ti, "Testing pass") {} - - virtual void addAtom(const Atom &atom) { - if (const DefinedAtom *defAtom = dyn_cast(&atom)) - _definedAtoms._atoms.push_back(defAtom); - else - llvm_unreachable("atom has unknown definition kind"); - } - - virtual DefinedAtomRange definedAtoms() { - return range::iterator>( - _definedAtoms._atoms.begin(), _definedAtoms._atoms.end()); - } - - virtual const atom_collection &defined() const { - return _definedAtoms; - } - virtual const atom_collection &undefined() const { - return _undefinedAtoms; - } - virtual const atom_collection &sharedLibrary() const { - return _sharedLibraryAtoms; - } - virtual const atom_collection &absolute() const { - return _absoluteAtoms; - } - -private: - atom_collection_vector _definedAtoms; - atom_collection_vector _undefinedAtoms; - atom_collection_vector _sharedLibraryAtoms; - atom_collection_vector _absoluteAtoms; -}; - -struct TestingKindMapping { - const char *string; - int32_t value; - bool isBranch; - bool isGotLoad; - bool isGotUse; -}; - -// -// Table of fixup kinds in YAML documents used for testing -// -const TestingKindMapping sKinds[] = { - {"in-group", -3, false, false, false}, - {"layout-after", -2, false, false, false}, - {"layout-before", -1, false, false, false}, - {"call32", 2, true, false, false}, - {"pcrel32", 3, false, false, false}, - {"gotLoad32", 7, false, true, true}, - {"gotUse32", 9, false, false, true}, - {"lea32wasGot", 8, false, false, false}, - {nullptr, 0, false, false, false} - }; - -class TestingStubsPass : public StubsPass { -public: - TestingStubsPass(const TargetInfo &ti) : _file(TestingPassFile(ti)) - {} - - virtual bool noTextRelocs() { - return true; - } - - virtual bool isCallSite(int32_t kind) { - for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { - if (kind == p->value) - return p->isBranch; - } - return false; - } - - virtual const DefinedAtom *getStub(const Atom &target) { - const DefinedAtom *result = new TestingStubAtom(_file, target); - _file.addAtom(*result); - return result; - } - - virtual void addStubAtoms(MutableFile &mergedFile) { - for (const DefinedAtom *stub : _file.defined() ) { - mergedFile.addAtom(*stub); - } - } - -private: - TestingPassFile _file; -}; - -class TestingGOTPass : public GOTPass { -public: - TestingGOTPass(const TargetInfo &ti) : _file(TestingPassFile(ti)) - {} - - virtual bool noTextRelocs() { - return true; - } - - virtual bool isGOTAccess(int32_t kind, bool &canBypassGOT) { - for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { - if (kind == p->value) { - canBypassGOT = p->isGotLoad; - return p->isGotUse || p->isGotLoad; - } - } - return false; - } - - virtual void updateReferenceToGOT(const Reference *ref, bool targetIsNowGOT) { - if (targetIsNowGOT) - const_cast(ref)->setKind(3); // pcrel32 - else - const_cast(ref)->setKind(8); // lea32wasGot - } - - virtual const DefinedAtom *makeGOTEntry(const Atom &target) { - return new TestingGOTAtom(_file, target); - } - -private: - TestingPassFile _file; -}; - -#endif // LLD_TOOLS_TESTING_HELPERS_H_ diff --git a/lld/tools/lld-core/lld-core.cpp b/lld/tools/lld-core/lld-core.cpp deleted file mode 100644 index 22388ef36bd8..000000000000 --- a/lld/tools/lld-core/lld-core.cpp +++ /dev/null @@ -1,359 +0,0 @@ -//===- tools/lld/lld-core.cpp - Linker Core Test Driver -----------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lld/Core/Atom.h" -#include "lld/Core/LLVM.h" -#include "lld/Core/Pass.h" -#include "lld/Core/PassManager.h" -#include "lld/Core/Resolver.h" -#include "lld/Passes/LayoutPass.h" -#include "lld/ReaderWriter/ELFTargetInfo.h" -#include "lld/ReaderWriter/MachOTargetInfo.h" -#include "lld/ReaderWriter/Reader.h" -#include "lld/ReaderWriter/ReaderArchive.h" -#include "lld/ReaderWriter/Writer.h" - -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/Triple.h" -#include "llvm/Support/ELF.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/system_error.h" - -#include - -#include "TestingHelpers.hpp" - -using namespace lld; - -static void error(Twine message) { - llvm::errs() << "lld-core: " << message << ".\n"; -} - -static bool error(error_code ec) { - if (ec) { - error(ec.message()); - return true; - } - return false; -} - - -llvm::cl::list -cmdLineInputFilePaths(llvm::cl::Positional, - llvm::cl::desc("")); - -llvm::cl::opt -cmdLineOutputFilePath("o", - llvm::cl::desc("Specify output filename"), - llvm::cl::value_desc("filename")); - -llvm::cl::opt cmdLineDoStubsPass( - "stubs-pass", llvm::cl::desc("Run pass to create stub atoms")); - -llvm::cl::opt -cmdLineDoGotPass("got-pass", llvm::cl::desc("Run pass to create GOT atoms")); - -llvm::cl::opt -cmdLineDoLayoutPass("layout-pass", llvm::cl::desc("Run pass to layout atoms")); - -llvm::cl::opt -cmdLineDoMergeStrings( - "merge-strings", - llvm::cl::desc("make common strings merge possible")); - -llvm::cl::opt cmdLineUndefinesIsError( - "undefines-are-errors", - llvm::cl::desc("Any undefined symbols at end is an error")); - -llvm::cl::opt cmdLineForceLoad( - "force-load", llvm::cl::desc("force load all members of the archive")); - -llvm::cl::opt -cmdLineCommonsSearchArchives("commons-search-archives", - llvm::cl::desc("Tentative definitions trigger archive search")); - -llvm::cl::opt -cmdLineDeadStrip("dead-strip", - llvm::cl::desc("Remove unreachable code and data")); - -llvm::cl::opt -cmdLineGlobalsNotDeadStrip("keep-globals", - llvm::cl::desc("All global symbols are roots for dead-strip")); - -llvm::cl::opt -cmdLineEntryPoint("entry", - llvm::cl::desc("Specify entry point symbol"), - llvm::cl::value_desc("symbol")); - - -enum WriteChoice { - writeYAML, writePECOFF, writeELF -}; - -llvm::cl::opt -writeSelected("writer", - llvm::cl::desc("Select writer"), - llvm::cl::values( - clEnumValN(writeYAML, "YAML", "link assuming YAML format"), - clEnumValN(writePECOFF, "PECOFF", "link as windows would"), - clEnumValN(writeELF, "ELF", "link as linux would"), - clEnumValEnd), - llvm::cl::init(writeYAML)); - -enum ReaderChoice { - readerYAML, readerMachO, readerPECOFF, readerELF -}; -llvm::cl::opt -readerSelected("reader", - llvm::cl::desc("Select reader"), - llvm::cl::values( - clEnumValN(readerYAML, "YAML", "read assuming YAML format"), - clEnumValN(readerMachO, "mach-o", "read as darwin would"), - clEnumValN(readerPECOFF, "PECOFF", "read as windows would"), - clEnumValN(readerELF, "ELF", "read as linux would"), - clEnumValEnd), - llvm::cl::init(readerYAML)); - -enum ArchChoice { - i386 = llvm::ELF::EM_386, - x86_64 = llvm::ELF::EM_X86_64, - hexagon = llvm::ELF::EM_HEXAGON, - ppc = llvm::ELF::EM_PPC -}; -llvm::cl::opt -archSelected("arch", - llvm::cl::desc("Select architecture, only valid with ELF output"), - llvm::cl::values( - clEnumValN(i386, "i386", - "output i386, EM_386 file"), - clEnumValN(x86_64, - "x86_64", "output x86_64, EM_X86_64 file"), - clEnumValN(hexagon, - "hexagon", "output Hexagon, EM_HEXAGON file"), - clEnumValN(ppc, - "ppc", "output PowerPC, EM_PPC file"), - clEnumValEnd), - llvm::cl::init(i386)); - - -enum endianChoice { - little, big -}; -llvm::cl::opt endianSelected( - "endian", llvm::cl::desc("Select endianness of ELF output"), - llvm::cl::values(clEnumValN(big, "big", "output big endian format"), - clEnumValN(little, "little", - "output little endian format"), clEnumValEnd)); - -class TestingTargetInfo : public TargetInfo { -public: - TestingTargetInfo(bool stubs, bool got, bool layout) - : _doStubs(stubs), _doGOT(got), _doLayout(layout) { - } - - llvm::Triple getTriple() const { return llvm::Triple("x86_64"); } - - virtual uint64_t getPageSize() const { return 0x1000; } - - virtual void addPasses(PassManager &pm) const { - if (_doStubs) - pm.add(std::unique_ptr(new TestingStubsPass(*this))); - if (_doGOT) - pm.add(std::unique_ptr(new TestingGOTPass(*this))); - if (_doLayout) - pm.add(std::unique_ptr(new LayoutPass())); - } - - virtual ErrorOr relocKindFromString(StringRef str) const { - // Try parsing as a number. - if (auto kind = TargetInfo::relocKindFromString(str)) - return kind; - for (const auto *kinds = sKinds; kinds->string; ++kinds) - if (str == kinds->string) - return kinds->value; - return llvm::make_error_code(llvm::errc::invalid_argument); - } - - virtual ErrorOr stringFromRelocKind(int32_t kind) const { - for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) { - if (kind == p->value) - return std::string(p->string); - } - return llvm::make_error_code(llvm::errc::invalid_argument); - } - - virtual ErrorOr getReader(const LinkerInput &input) const { - llvm_unreachable("Unimplemented!"); - } - - virtual ErrorOr getWriter() const { - llvm_unreachable("Unimplemented!"); - } - -private: - bool _doStubs; - bool _doGOT; - bool _doLayout; -}; - -int main(int argc, char *argv[]) { - // Print a stack trace if we signal out. - llvm::sys::PrintStackTraceOnErrorSignal(); - llvm::PrettyStackTraceProgram X(argc, argv); - llvm::llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - // parse options - llvm::cl::ParseCommandLineOptions(argc, argv); - - // if no input file specified, read from stdin - if (cmdLineInputFilePaths.empty()) - cmdLineInputFilePaths.emplace_back("-"); - - // if no output path specified, write to stdout - if (cmdLineOutputFilePath.empty()) - cmdLineOutputFilePath.assign("-"); -#if 0 - ELFLinkerOptions lo; - lo._noInhibitExec = !cmdLineUndefinesIsError; - lo._searchArchivesToOverrideTentativeDefinitions = - cmdLineCommonsSearchArchives; - lo._deadStrip = cmdLineDeadStrip; - lo._globalsAreDeadStripRoots = cmdLineGlobalsNotDeadStrip; - lo._forceLoadArchives = cmdLineForceLoad; - lo._entrySymbol = cmdLineEntryPoint; - lo._mergeCommonStrings = cmdLineDoMergeStrings; -#endif - - llvm::Triple targetTriple; - switch (archSelected) { - case i386: - targetTriple = llvm::Triple("i386"); - break; - case x86_64: - targetTriple = llvm::Triple("x86_64"); - break; - case hexagon: - targetTriple = llvm::Triple("hexagon"); - break; - case ppc: - targetTriple = llvm::Triple("powerpc"); - break; - } - TestingTargetInfo tti(cmdLineDoStubsPass, cmdLineDoGotPass, - cmdLineDoLayoutPass); - - std::unique_ptr eti = ELFTargetInfo::create(targetTriple.getArch()); - std::unique_ptr writer; - const TargetInfo *ti = 0; - switch ( writeSelected ) { - case writeYAML: - writer = createWriterYAML(tti); - ti = &tti; - break; - case writePECOFF: - writer = createWriterPECOFF(tti); - ti = &tti; - break; - case writeELF: - writer = createWriterELF(*eti); - ti = eti.get(); - break; - } - - // create object to mange input files - InputFiles inputFiles; - - // read input files into in-memory File objects - std::unique_ptr reader; - switch ( readerSelected ) { - case readerYAML: - reader = createReaderYAML(tti); - break; -#if 0 - case readerMachO: - reader = createReaderMachO(lld::readerOptionsMachO); - break; -#endif - case readerPECOFF: - reader = createReaderPECOFF(tti, - [&] (const LinkerInput &) -> ErrorOr { - return *reader; - }); - break; - case readerELF: - reader = createReaderELF(*eti, - [&] (const LinkerInput &) -> ErrorOr { - return *reader; - }); - break; - default: - reader = createReaderYAML(tti); - break; - } - - for (auto path : cmdLineInputFilePaths) { - std::vector> files; - if ( error(reader->readFile(path, files)) ) - return 1; - inputFiles.appendFiles(files); - } - - // given writer a chance to add files - writer->addFiles(inputFiles); - - // assign an ordinal to each file so sort() can preserve command line order - inputFiles.assignFileOrdinals(); - - // merge all atom graphs - Resolver resolver(tti, inputFiles); - resolver.resolve(); - MutableFile &mergedMasterFile = resolver.resultFile(); - - PassManager pm; - if (ti) - ti->addPasses(pm); - pm.runOnFile(mergedMasterFile); - - // showing yaml at this stage can help when debugging - const bool dumpIntermediateYAML = false; - if ( dumpIntermediateYAML ) - writer->writeFile(mergedMasterFile, "-"); - - // make unique temp file to put generated native object file - llvm::sys::Path tmpNativePath = llvm::sys::Path::GetTemporaryDirectory(); - if (tmpNativePath.createTemporaryFileOnDisk()) { - error("createTemporaryFileOnDisk() failed"); - return 1; - } - - // write as native file - std::unique_ptr natWriter = createWriterNative(tti); - if (error(natWriter->writeFile(mergedMasterFile, tmpNativePath.c_str()))) - return 1; - - // read as native file - std::unique_ptr natReader = createReaderNative(tti); - std::vector> readNativeFiles; - if (error(natReader->readFile(tmpNativePath.c_str(), readNativeFiles))) - return 1; - - // write new atom graph - const File *parsedNativeFile = readNativeFiles[0].get(); - if (error(writer->writeFile(*parsedNativeFile, cmdLineOutputFilePath))) - return 1; - - return 0; -}