forked from OSchip/llvm-project
parent
fa4513a178
commit
c8858b3469
|
@ -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)
|
|
@ -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 <vector>
|
||||
|
||||
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<uint8_t> rawContent() const {
|
||||
return ArrayRef<uint8_t>();
|
||||
}
|
||||
|
||||
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<uint8_t> rawContent() const {
|
||||
return ArrayRef<uint8_t>();
|
||||
}
|
||||
|
||||
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<DefinedAtom>(&atom))
|
||||
_definedAtoms._atoms.push_back(defAtom);
|
||||
else
|
||||
llvm_unreachable("atom has unknown definition kind");
|
||||
}
|
||||
|
||||
virtual DefinedAtomRange definedAtoms() {
|
||||
return range<std::vector<const DefinedAtom*>::iterator>(
|
||||
_definedAtoms._atoms.begin(), _definedAtoms._atoms.end());
|
||||
}
|
||||
|
||||
virtual const atom_collection<DefinedAtom> &defined() const {
|
||||
return _definedAtoms;
|
||||
}
|
||||
virtual const atom_collection<UndefinedAtom> &undefined() const {
|
||||
return _undefinedAtoms;
|
||||
}
|
||||
virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const {
|
||||
return _sharedLibraryAtoms;
|
||||
}
|
||||
virtual const atom_collection<AbsoluteAtom> &absolute() const {
|
||||
return _absoluteAtoms;
|
||||
}
|
||||
|
||||
private:
|
||||
atom_collection_vector<DefinedAtom> _definedAtoms;
|
||||
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
|
||||
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
|
||||
atom_collection_vector<AbsoluteAtom> _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<Reference*>(ref)->setKind(3); // pcrel32
|
||||
else
|
||||
const_cast<Reference*>(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_
|
|
@ -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 <vector>
|
||||
|
||||
#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<std::string>
|
||||
cmdLineInputFilePaths(llvm::cl::Positional,
|
||||
llvm::cl::desc("<input file>"));
|
||||
|
||||
llvm::cl::opt<std::string>
|
||||
cmdLineOutputFilePath("o",
|
||||
llvm::cl::desc("Specify output filename"),
|
||||
llvm::cl::value_desc("filename"));
|
||||
|
||||
llvm::cl::opt<bool> cmdLineDoStubsPass(
|
||||
"stubs-pass", llvm::cl::desc("Run pass to create stub atoms"));
|
||||
|
||||
llvm::cl::opt<bool>
|
||||
cmdLineDoGotPass("got-pass", llvm::cl::desc("Run pass to create GOT atoms"));
|
||||
|
||||
llvm::cl::opt<bool>
|
||||
cmdLineDoLayoutPass("layout-pass", llvm::cl::desc("Run pass to layout atoms"));
|
||||
|
||||
llvm::cl::opt<bool>
|
||||
cmdLineDoMergeStrings(
|
||||
"merge-strings",
|
||||
llvm::cl::desc("make common strings merge possible"));
|
||||
|
||||
llvm::cl::opt<bool> cmdLineUndefinesIsError(
|
||||
"undefines-are-errors",
|
||||
llvm::cl::desc("Any undefined symbols at end is an error"));
|
||||
|
||||
llvm::cl::opt<bool> cmdLineForceLoad(
|
||||
"force-load", llvm::cl::desc("force load all members of the archive"));
|
||||
|
||||
llvm::cl::opt<bool>
|
||||
cmdLineCommonsSearchArchives("commons-search-archives",
|
||||
llvm::cl::desc("Tentative definitions trigger archive search"));
|
||||
|
||||
llvm::cl::opt<bool>
|
||||
cmdLineDeadStrip("dead-strip",
|
||||
llvm::cl::desc("Remove unreachable code and data"));
|
||||
|
||||
llvm::cl::opt<bool>
|
||||
cmdLineGlobalsNotDeadStrip("keep-globals",
|
||||
llvm::cl::desc("All global symbols are roots for dead-strip"));
|
||||
|
||||
llvm::cl::opt<std::string>
|
||||
cmdLineEntryPoint("entry",
|
||||
llvm::cl::desc("Specify entry point symbol"),
|
||||
llvm::cl::value_desc("symbol"));
|
||||
|
||||
|
||||
enum WriteChoice {
|
||||
writeYAML, writePECOFF, writeELF
|
||||
};
|
||||
|
||||
llvm::cl::opt<WriteChoice>
|
||||
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<ReaderChoice>
|
||||
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<ArchChoice>
|
||||
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<endianChoice> 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<Pass>(new TestingStubsPass(*this)));
|
||||
if (_doGOT)
|
||||
pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
|
||||
if (_doLayout)
|
||||
pm.add(std::unique_ptr<Pass>(new LayoutPass()));
|
||||
}
|
||||
|
||||
virtual ErrorOr<int32_t> 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<std::string> 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<Reader &> getReader(const LinkerInput &input) const {
|
||||
llvm_unreachable("Unimplemented!");
|
||||
}
|
||||
|
||||
virtual ErrorOr<Writer &> 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<ELFTargetInfo> eti = ELFTargetInfo::create(targetTriple.getArch());
|
||||
std::unique_ptr<Writer> 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> 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<Reader&> {
|
||||
return *reader;
|
||||
});
|
||||
break;
|
||||
case readerELF:
|
||||
reader = createReaderELF(*eti,
|
||||
[&] (const LinkerInput &) -> ErrorOr<Reader&> {
|
||||
return *reader;
|
||||
});
|
||||
break;
|
||||
default:
|
||||
reader = createReaderYAML(tti);
|
||||
break;
|
||||
}
|
||||
|
||||
for (auto path : cmdLineInputFilePaths) {
|
||||
std::vector<std::unique_ptr<File>> 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<Writer> natWriter = createWriterNative(tti);
|
||||
if (error(natWriter->writeFile(mergedMasterFile, tmpNativePath.c_str())))
|
||||
return 1;
|
||||
|
||||
// read as native file
|
||||
std::unique_ptr<Reader> natReader = createReaderNative(tti);
|
||||
std::vector<std::unique_ptr<File>> 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;
|
||||
}
|
Loading…
Reference in New Issue