summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter
diff options
context:
space:
mode:
Diffstat (limited to 'lld/lib/ReaderWriter')
-rw-r--r--lld/lib/ReaderWriter/CMakeLists.txt1
-rw-r--r--lld/lib/ReaderWriter/CoreTargetInfo.cpp395
-rw-r--r--lld/lib/ReaderWriter/ELF/Atoms.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultLayout.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp148
-rw-r--r--lld/lib/ReaderWriter/ELF/ExecutableAtoms.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/ExecutableWriter.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/File.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/HeaderChunks.h7
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h3
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp3
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp4
-rw-r--r--lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h10
-rw-r--r--lld/lib/ReaderWriter/ELF/OutputELFWriter.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp36
-rw-r--r--lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h8
-rw-r--r--lld/lib/ReaderWriter/ELF/Reader.cpp17
-rw-r--r--lld/lib/ReaderWriter/ELF/SectionChunks.h6
-rw-r--r--lld/lib/ReaderWriter/ELF/TargetHandler.h1
-rw-r--r--lld/lib/ReaderWriter/ELF/Writer.cpp86
-rw-r--r--lld/lib/ReaderWriter/ELF/Writer.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp36
-rw-r--r--lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h7
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp27
-rw-r--r--lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h14
-rw-r--r--lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp8
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOFormat.hpp6
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp247
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp18
-rw-r--r--lld/lib/ReaderWriter/MachO/ReferenceKinds.h3
-rw-r--r--lld/lib/ReaderWriter/MachO/StubsPass.hpp21
-rw-r--r--lld/lib/ReaderWriter/MachO/WriterMachO.cpp69
-rw-r--r--lld/lib/ReaderWriter/Native/ReaderNative.cpp4
-rw-r--r--lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp4
-rw-r--r--lld/lib/ReaderWriter/Reader.cpp4
-rw-r--r--lld/lib/ReaderWriter/ReaderArchive.cpp31
-rw-r--r--lld/lib/ReaderWriter/ReaderLinkerScript.cpp10
-rw-r--r--lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp40
39 files changed, 996 insertions, 294 deletions
diff --git a/lld/lib/ReaderWriter/CMakeLists.txt b/lld/lib/ReaderWriter/CMakeLists.txt
index 2ad3165ece6..fa3e71e8a37 100644
--- a/lld/lib/ReaderWriter/CMakeLists.txt
+++ b/lld/lib/ReaderWriter/CMakeLists.txt
@@ -6,6 +6,7 @@ add_subdirectory(Native)
add_subdirectory(PECOFF)
add_subdirectory(YAML)
add_lld_library(lldReaderWriter
+ CoreTargetInfo.cpp
LinkerScript.cpp
Reader.cpp
ReaderArchive.cpp
diff --git a/lld/lib/ReaderWriter/CoreTargetInfo.cpp b/lld/lib/ReaderWriter/CoreTargetInfo.cpp
new file mode 100644
index 00000000000..18da8378090
--- /dev/null
+++ b/lld/lib/ReaderWriter/CoreTargetInfo.cpp
@@ -0,0 +1,395 @@
+//===- lib/ReaderWriter/CoreTargetInfo.cpp --------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lld/ReaderWriter/CoreTargetInfo.h"
+
+#include "lld/Core/Pass.h"
+#include "lld/Core/PassManager.h"
+#include "lld/Passes/LayoutPass.h"
+
+#include "llvm/ADT/ArrayRef.h"
+
+
+using namespace lld;
+
+namespace {
+
+/// \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;
+};
+
+} // anonymous namespace
+
+
+CoreTargetInfo::CoreTargetInfo() {
+}
+
+
+void CoreTargetInfo::addPasses(PassManager &pm) const {
+ for (StringRef name : _passNames) {
+ if ( name.equals("layout") )
+ pm.add(std::unique_ptr<Pass>((new LayoutPass())));
+ else if ( name.equals("GOT") )
+ pm.add(std::unique_ptr<Pass>(new TestingGOTPass(*this)));
+ else if ( name.equals("stubs") )
+ pm.add(std::unique_ptr<Pass>(new TestingStubsPass(*this)));
+ else
+ llvm_unreachable("bad pass name");
+ }
+}
+
+
+error_code CoreTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
+ if (!_reader)
+ _reader = createReaderYAML(*this);
+ return _reader->parseFile(mb,result);
+}
+
+Writer &CoreTargetInfo::writer() const {
+ if (!_writer)
+ _writer = createWriterYAML(*this);
+ return *_writer;
+}
+
+
+ErrorOr<Reference::Kind>
+CoreTargetInfo::relocKindFromString(StringRef str) const {
+ for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
+ if (str.equals(p->string))
+ return p->value;
+ }
+ return make_error_code(yaml_reader_error::illegal_value);
+}
+
+ErrorOr<std::string>
+CoreTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ for (const TestingKindMapping *p = sKinds; p->string != nullptr; ++p) {
+ if (kind == p->value)
+ return std::string(p->string);
+ }
+ return make_error_code(yaml_reader_error::illegal_value);
+}
+
+
+
diff --git a/lld/lib/ReaderWriter/ELF/Atoms.h b/lld/lib/ReaderWriter/ELF/Atoms.h
index c5f66bcdedf..28501d9b231 100644
--- a/lld/lib/ReaderWriter/ELF/Atoms.h
+++ b/lld/lib/ReaderWriter/ELF/Atoms.h
@@ -512,7 +512,8 @@ public:
const Elf_Shdr *section, llvm::ArrayRef<uint8_t> contentData,
uint64_t offset)
: _owningFile(file), _sectionName(sectionName), _section(section),
- _contentData(contentData), _offset(offset) {}
+ _contentData(contentData), _offset(offset) {
+ }
virtual const class ELFFile<ELFT> &file() const {
return _owningFile;
diff --git a/lld/lib/ReaderWriter/ELF/DefaultLayout.h b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
index 73a4c163143..8c520ff4f7e 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultLayout.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultLayout.h
@@ -16,7 +16,6 @@
#include "SectionChunks.h"
#include "SegmentChunks.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/STDExtras.h"
#include "llvm/ADT/ArrayRef.h"
@@ -28,6 +27,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Format.h"
#include <map>
#include <tuple>
@@ -667,7 +667,6 @@ DefaultLayout<ELFT>::assignVirtualAddress() {
}
firstLoadSegment->prepend(_programHeader);
firstLoadSegment->prepend(_header);
-
bool newSegmentHeaderAdded = true;
while (true) {
for (auto si : _segments) {
diff --git a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h
index c6426724f25..c019df1baed 100644
--- a/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/DefaultTargetHandler.h
@@ -13,7 +13,6 @@
#include "DefaultLayout.h"
#include "TargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/ADT/Triple.h"
diff --git a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
index 3395609979c..338096d3a2c 100644
--- a/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFTargetInfo.cpp
@@ -12,41 +12,38 @@
#include "TargetHandler.h"
#include "Targets.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Passes/LayoutPass.h"
#include "lld/ReaderWriter/ReaderLinkerScript.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
namespace lld {
-ELFTargetInfo::ELFTargetInfo(const LinkerOptions &lo) : TargetInfo(lo) {}
-
-uint16_t ELFTargetInfo::getOutputType() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
- return llvm::ELF::ET_EXEC;
- case OutputKind::Relocatable:
- return llvm::ELF::ET_REL;
- case OutputKind::Shared:
- return llvm::ELF::ET_DYN;
- case OutputKind::Core:
- return llvm::ELF::ET_CORE;
- case OutputKind::SharedStubs:
- case OutputKind::DebugSymbols:
- case OutputKind::Bundle:
- case OutputKind::Preload:
- break;
- case OutputKind::Invalid:
- llvm_unreachable("Invalid output kind!");
- }
- llvm_unreachable("Unhandled OutputKind");
+ELFTargetInfo::ELFTargetInfo(llvm::Triple triple)
+ : _outputFileType(elf::ET_EXEC)
+ , _triple(triple)
+ , _baseAddress(0)
+ , _isStaticExecutable(false)
+ , _outputYAML(false)
+ , _noInhibitExec(false)
+ , _mergeCommonStrings(false)
+ , _runLayoutPass(true) {
+}
+
+bool ELFTargetInfo::is64Bits() const {
+ return getTriple().isArch64Bit();
+}
+
+bool ELFTargetInfo::isLittleEndian() const {
+ // TODO: Do this properly. It is not defined purely by arch.
+ return true;
}
void ELFTargetInfo::addPasses(PassManager &pm) const {
- pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+ if (_runLayoutPass)
+ pm.add(std::unique_ptr<Pass>(new LayoutPass()));
}
uint16_t ELFTargetInfo::getOutputMachine() const {
@@ -64,31 +61,63 @@ uint16_t ELFTargetInfo::getOutputMachine() const {
}
}
-ErrorOr<Reader &> ELFTargetInfo::getReader(const LinkerInput &input) const {
- DEBUG_WITH_TYPE("inputs", llvm::dbgs() << input.getPath() << "\n");
- auto buffer = input.getBuffer();
- if (!buffer)
- return error_code(buffer);
- auto magic = llvm::sys::fs::identify_magic(buffer->getBuffer());
- // Assume unknown file types are linker scripts.
- if (magic == llvm::sys::fs::file_magic::unknown) {
- if (!_linkerScriptReader)
- _linkerScriptReader.reset(new ReaderLinkerScript(
- *this,
- std::bind(&ELFTargetInfo::getReader, this, std::placeholders::_1)));
- return *_linkerScriptReader;
+bool ELFTargetInfo::validate(raw_ostream &diagnostics) {
+ if (_outputFileType == elf::ET_EXEC) {
+ if (_entrySymbolName.empty()) {
+ _entrySymbolName = "_start";
+ }
+ }
+
+ if (_inputFiles.empty()) {
+ diagnostics << "No input files\n";
+ return true;
+ }
+
+
+ return false;
+}
+
+
+bool ELFTargetInfo::isDynamic() const {
+ switch (_outputFileType) {
+ case llvm::ELF::ET_EXEC:
+ if (_isStaticExecutable)
+ return false;
+ else
+ return true;
+ case llvm::ELF::ET_DYN:
+ return true;
}
+ return false;
+}
- // Assume anything else is an ELF file.
+
+error_code ELFTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
if (!_elfReader)
- _elfReader = createReaderELF(*this, std::bind(&ELFTargetInfo::getReader,
- this, std::placeholders::_1));
- return *_elfReader;
+ _elfReader = createReaderELF(*this);
+ error_code ec = _elfReader->parseFile(mb, result);
+ if (ec) {
+ // Not an ELF file, check file extension to see if it might be yaml
+ StringRef path = mb->getBufferIdentifier();
+ if ( path.endswith(".objtxt") ) {
+ if (!_yamlReader)
+ _yamlReader = createReaderYAML(*this);
+ ec = _yamlReader->parseFile(mb, result);
+ }
+ if (ec) {
+ // Not a yaml file, assume it is a linkerscript
+ if (!_linkerScriptReader)
+ _linkerScriptReader.reset(new ReaderLinkerScript(*this));
+ ec = _linkerScriptReader->parseFile(mb, result);
+ }
+ }
+ return ec;
}
-ErrorOr<Writer &> ELFTargetInfo::getWriter() const {
+Writer &ELFTargetInfo::writer() const {
if (!_writer) {
- if (_options._outputYAML)
+ if (_outputYAML)
_writer = createWriterYAML(*this);
else
_writer = createWriterELF(*this);
@@ -96,27 +125,40 @@ ErrorOr<Writer &> ELFTargetInfo::getWriter() const {
return *_writer;
}
-std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(const LinkerOptions &lo) {
- switch (llvm::Triple(llvm::Triple::normalize(lo._target)).getArch()) {
+
+std::unique_ptr<ELFTargetInfo> ELFTargetInfo::create(llvm::Triple triple) {
+ switch (triple.getArch()) {
case llvm::Triple::x86:
- return std::unique_ptr<ELFTargetInfo>(new lld::elf::X86TargetInfo(lo));
+ return std::unique_ptr<ELFTargetInfo>(new lld::elf::X86TargetInfo(triple));
case llvm::Triple::x86_64:
return std::unique_ptr<
- ELFTargetInfo>(new lld::elf::X86_64TargetInfo(lo));
+ ELFTargetInfo>(new lld::elf::X86_64TargetInfo(triple));
case llvm::Triple::hexagon:
return std::unique_ptr<
- ELFTargetInfo>(new lld::elf::HexagonTargetInfo(lo));
+ ELFTargetInfo>(new lld::elf::HexagonTargetInfo(triple));
case llvm::Triple::ppc:
- return std::unique_ptr<ELFTargetInfo>(new lld::elf::PPCTargetInfo(lo));
+ return std::unique_ptr<ELFTargetInfo>(new lld::elf::PPCTargetInfo(triple));
default:
return std::unique_ptr<ELFTargetInfo>();
}
}
-StringRef ELFTargetInfo::getEntry() const {
- if (!_options._entrySymbol.empty())
- return _options._entrySymbol;
- return "_start";
+bool ELFTargetInfo::appendLibrary(StringRef libName) {
+ SmallString<128> fullPath;
+ for (StringRef dir : _inputSearchPaths) {
+ // FIXME: need to handle other extensions, like .so
+ fullPath.assign(dir);
+ llvm::sys::path::append(fullPath, Twine("lib") + libName + ".a");
+ StringRef pathref = fullPath.str();
+ unsigned pathlen = pathref.size();
+ if (llvm::sys::fs::exists(pathref)) {
+ char *x = _extraStrings.Allocate<char>(pathlen);
+ memcpy(x, pathref.data(), pathlen);
+ appendInputFile(StringRef(x,pathlen));
+ return false;
+ }
+ }
+ return true;
}
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h
index 4216cd5fb5b..d2ecbb2a903 100644
--- a/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h
+++ b/lld/lib/ReaderWriter/ELF/ExecutableAtoms.h
@@ -49,6 +49,7 @@ public:
/// \brief add an undefined atom
virtual void addUndefinedAtom(StringRef symbolName) {
+ assert(!symbolName.empty() && "UndefinedAtoms must have a name");
Elf_Sym *symbol = new (_allocator) Elf_Sym;
symbol->st_name = 0;
symbol->st_value = 0;
diff --git a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h
index fc0bde043b8..6bc283d701d 100644
--- a/lld/lib/ReaderWriter/ELF/ExecutableWriter.h
+++ b/lld/lib/ReaderWriter/ELF/ExecutableWriter.h
@@ -46,7 +46,7 @@ private:
/// absolute symbols
template<class ELFT>
void ExecutableWriter<ELFT>::addDefaultAtoms() {
- _runtimeFile.addUndefinedAtom(this->_targetInfo.getEntry());
+ _runtimeFile.addUndefinedAtom(this->_targetInfo.entrySymbolName());
_runtimeFile.addAbsoluteAtom("__bss_start");
_runtimeFile.addAbsoluteAtom("__bss_end");
_runtimeFile.addAbsoluteAtom("_end");
diff --git a/lld/lib/ReaderWriter/ELF/File.h b/lld/lib/ReaderWriter/ELF/File.h
index cbc2fff9895..a4c712420c9 100644
--- a/lld/lib/ReaderWriter/ELF/File.h
+++ b/lld/lib/ReaderWriter/ELF/File.h
@@ -143,7 +143,7 @@ public:
// Sections that have merge string property
std::vector<const Elf_Shdr *> mergeStringSections;
- bool doStringsMerge = _elfTargetInfo.getLinkerOptions()._mergeCommonStrings;
+ bool doStringsMerge = _elfTargetInfo.mergeCommonStrings();
// Handle: SHT_REL and SHT_RELA sections:
// Increment over the sections, when REL/RELA section types are found add
diff --git a/lld/lib/ReaderWriter/ELF/HeaderChunks.h b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
index fe8efddfb0d..64400dc26d0 100644
--- a/lld/lib/ReaderWriter/ELF/HeaderChunks.h
+++ b/lld/lib/ReaderWriter/ELF/HeaderChunks.h
@@ -18,6 +18,7 @@
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/Format.h"
/// \brief An Header represents the Elf[32/64]_Ehdr structure at the
/// start of an ELF executable file.
@@ -98,10 +99,10 @@ public:
FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
: _type(type)
, _flags(flags)
- , _flagsClear(flagsClear)
- {}
+ , _flagsClear(flagsClear) {
+ }
- bool operator()(const Elf_Phdr *j) const {
+ bool operator()(const llvm::object::Elf_Phdr_Impl<ELFT> *j) const {
return ((j->p_type == _type) &&
((j->p_flags & _flags) == _flags) &&
(!(j->p_flags & _flagsClear)));
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
index b0ee2e440e9..a02caa74595 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
@@ -29,7 +29,8 @@ typedef struct {
sizeof(insn_encodings_v4) / sizeof(Instruction))
/// \brief finds the scatter Bits that need to be used to apply relocations
-uint32_t findBitMask(uint32_t insn, Instruction *encodings, int32_t numInsns) {
+inline uint32_t
+findBitMask(uint32_t insn, Instruction *encodings, int32_t numInsns) {
for (int32_t i = 0; i < numInsns ; i++) {
if (((insn & 0xc000) == 0) && !(encodings[i].isDuplex))
continue;
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
index d7c15d410a3..cc928e6b379 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
@@ -212,8 +212,7 @@ public:
} // end anonymous namespace
void elf::HexagonTargetInfo::addPasses(PassManager &pm) const {
- if (_options._outputKind == OutputKind::DynamicExecutable ||
- _options._outputKind == OutputKind::Shared)
+ if (isDynamic())
pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
ELFTargetInfo::addPasses(pm);
}
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
index ddba886525d..49d91434fde 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.cpp
@@ -22,8 +22,8 @@ using namespace lld;
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
-ErrorOr<int32_t> elf::HexagonTargetInfo::relocKindFromString(
- StringRef str) const {
+ErrorOr<Reference::Kind>
+elf::HexagonTargetInfo::relocKindFromString(StringRef str) const {
int32_t ret = llvm::StringSwitch<int32_t>(str)
LLD_CASE(R_HEX_NONE)
LLD_CASE(R_HEX_B22_PCREL)
diff --git a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h
index ca8fb94d30d..82f4c6b5ce5 100644
--- a/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/Hexagon/HexagonTargetInfo.h
@@ -12,7 +12,6 @@
#include "HexagonTargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -23,15 +22,14 @@ namespace elf {
class HexagonTargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- HexagonTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ HexagonTargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler = std::unique_ptr<TargetHandlerBase>(
new HexagonTargetHandler(*this));
}
- virtual uint64_t getPageSize() const { return 0x1000; }
-
- virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const;
- virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const;
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
virtual void addPasses(PassManager &) const;
diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
index 2cc81dd1462..40f14bb5f03 100644
--- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
+++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
@@ -345,7 +345,7 @@ error_code OutputELFWriter<ELFT>::writeFile(const File &file, StringRef path) {
_Header->e_shnum(_shdrtab->numHeaders());
_Header->e_shstrndx(_shstrtab->ordinal());
uint64_t virtualAddr = 0;
- _layout->findAtomAddrByName(_targetInfo.getEntry(), virtualAddr);
+ _layout->findAtomAddrByName(_targetInfo.entrySymbolName(), virtualAddr);
_Header->e_entry(virtualAddr);
// HACK: We have to write out the header and program header here even though
diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp
index e69de29bb2d..337b02f4c2a 100644
--- a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.cpp
@@ -0,0 +1,36 @@
+#include "PPCTargetInfo.h"
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorOr.h"
+
+using namespace lld;
+
+#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
+
+ErrorOr<Reference::Kind> elf::PPCTargetInfo::relocKindFromString(
+ StringRef str) const {
+ int32_t ret = llvm::StringSwitch<int32_t>(str)
+ LLD_CASE(R_PPC_NONE)
+ LLD_CASE(R_PPC_ADDR32)
+ .Default(-1);
+
+ if (ret == -1)
+ return make_error_code(yaml_reader_error::illegal_value);
+ return ret;
+}
+
+#undef LLD_CASE
+
+#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
+
+ErrorOr<std::string>
+elf::PPCTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ switch (kind) {
+ LLD_CASE(R_PPC_NONE)
+ LLD_CASE(R_PPC_ADDR32)
+ }
+
+ return make_error_code(yaml_reader_error::illegal_value);
+}
diff --git a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h
index 97ba655d4ab..077767695c9 100644
--- a/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/PPC/PPCTargetInfo.h
@@ -12,7 +12,6 @@
#include "PPCTargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -22,14 +21,15 @@ namespace lld {
namespace elf {
class PPCTargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- PPCTargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ PPCTargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler = std::unique_ptr<TargetHandlerBase>(
new PPCTargetHandler(*this));
}
virtual bool isLittleEndian() const { return false; }
-
- virtual uint64_t getPageSize() const { return 0x1000; }
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
};
} // elf
diff --git a/lld/lib/ReaderWriter/ELF/Reader.cpp b/lld/lib/ReaderWriter/ELF/Reader.cpp
index be2fedb239b..cb6e9cde00f 100644
--- a/lld/lib/ReaderWriter/ELF/Reader.cpp
+++ b/lld/lib/ReaderWriter/ELF/Reader.cpp
@@ -78,12 +78,12 @@ namespace elf {
/// memory buffer for ELF class and bit width
class ELFReader : public Reader {
public:
- ELFReader(const ELFTargetInfo &ti, std::function<ReaderFunc> read)
- : lld::Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, read) {
+ ELFReader(const ELFTargetInfo &ti)
+ : lld::Reader(ti), _elfTargetInfo(ti), _readerArchive(ti, *this) {
}
- error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File> > &result) {
+ error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result) const {
using llvm::object::ELFType;
llvm::sys::LLVMFileType fileType =
llvm::sys::IdentifyFileType(mb->getBufferStart(),
@@ -112,10 +112,10 @@ public:
break;
}
case llvm::sys::Archive_FileType:
- ec = _readerArchive.parseFile(std::move(mb), result);
+ ec = _readerArchive.parseFile(mb, result);
break;
default:
- llvm_unreachable("not supported format");
+ return llvm::make_error_code(llvm::errc::executable_format_error);
break;
}
@@ -131,8 +131,7 @@ private:
};
} // end namespace elf
-std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &eti,
- std::function<ReaderFunc> read) {
- return std::unique_ptr<Reader>(new elf::ELFReader(eti, std::move(read)));
+std::unique_ptr<Reader> createReaderELF(const ELFTargetInfo &targetinfo) {
+ return std::unique_ptr<Reader>(new elf::ELFReader(targetinfo));
}
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/SectionChunks.h b/lld/lib/ReaderWriter/ELF/SectionChunks.h
index 2bca266fe2d..8237529629f 100644
--- a/lld/lib/ReaderWriter/ELF/SectionChunks.h
+++ b/lld/lib/ReaderWriter/ELF/SectionChunks.h
@@ -603,13 +603,13 @@ public:
/// \brief Get the symbol table index for an Atom. If it's not in the symbol
/// table, return STN_UNDEF.
uint32_t getSymbolTableIndex(const Atom *a) const {
- auto se = std::find_if(_symbolTable.begin(), _symbolTable.end(),
+ auto entry = std::find_if(_symbolTable.begin(), _symbolTable.end(),
[=](const SymbolEntry &se) {
return se._atom == a;
});
- if (se == _symbolTable.end())
+ if (entry == _symbolTable.end())
return STN_UNDEF;
- return std::distance(_symbolTable.begin(), se);
+ return std::distance(_symbolTable.begin(), entry);
}
virtual void finalize() { finalize(true); }
diff --git a/lld/lib/ReaderWriter/ELF/TargetHandler.h b/lld/lib/ReaderWriter/ELF/TargetHandler.h
index ebdb203c0da..ab30c3636e7 100644
--- a/lld/lib/ReaderWriter/ELF/TargetHandler.h
+++ b/lld/lib/ReaderWriter/ELF/TargetHandler.h
@@ -19,7 +19,6 @@
#include "Layout.h"
#include "lld/Core/InputFiles.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/LLVM.h"
#include "lld/Core/TargetInfo.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
diff --git a/lld/lib/ReaderWriter/ELF/Writer.cpp b/lld/lib/ReaderWriter/ELF/Writer.cpp
index 6e2744ea1f3..a174ef0c051 100644
--- a/lld/lib/ReaderWriter/ELF/Writer.cpp
+++ b/lld/lib/ReaderWriter/ELF/Writer.cpp
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/ELF/Writer.cpp ------------------------------------===//
+//===- lib/ReaderWriter/ELF/WriterELF.cpp ---------------------------------===//
//
// The LLVM Linker
//
@@ -6,53 +6,63 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-#include "ExecutableWriter.h"
+
+#include "lld/ReaderWriter/Writer.h"
+
#include "DynamicLibraryWriter.h"
+#include "ExecutableWriter.h"
+
using namespace llvm;
using namespace llvm::object;
-
namespace lld {
-std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &TI) {
+std::unique_ptr<Writer> createWriterELF(const ELFTargetInfo &info) {
using llvm::object::ELFType;
// Set the default layout to be the static executable layout
// We would set the layout to a dynamic executable layout
// if we came across any shared libraries in the process
- const LinkerOptions &options = TI.getLinkerOptions();
-
- if ((options._outputKind == OutputKind::StaticExecutable) ||
- (options._outputKind == OutputKind::DynamicExecutable)) {
- if (!TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::little, 4, false>>(TI));
- else if (TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::little, 8, true>>(TI));
- else if (!TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::big, 4, false>>(TI));
- else if (TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::ExecutableWriter<ELFType<support::big, 8, true>>(TI));
- llvm_unreachable("Invalid Options!");
- } else if (options._outputKind == OutputKind::Shared) {
- if (!TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::little, 4, false>>(TI));
- else if (TI.is64Bits() && TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::little, 8, true>>(TI));
- else if (!TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::big, 4, false>>(TI));
- else if (TI.is64Bits() && !TI.isLittleEndian())
- return std::unique_ptr<Writer>(new
- elf::DynamicLibraryWriter<ELFType<support::big, 8, true>>(TI));
- llvm_unreachable("Invalid Options!");
+ switch(info.getOutputType()) {
+ case llvm::ELF::ET_EXEC:
+ if (info.is64Bits()) {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::little, 8, true>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::big, 8, true>>(info));
+ } else {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::little, 4, false>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::ExecutableWriter<ELFType<support::big, 4, false>>(info));
+ }
+ break;
+ case llvm::ELF::ET_DYN:
+ if (info.is64Bits()) {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::little, 8, true>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::big, 8, true>>(info));
+ } else {
+ if (info.isLittleEndian())
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::little, 4, false>>(info));
+ else
+ return std::unique_ptr<Writer>(new
+ elf::DynamicLibraryWriter<ELFType<support::big, 4, false>>(info));
+ }
+ break;
+ case llvm::ELF::ET_REL:
+ llvm_unreachable("TODO: support -r mode");
+ default:
+ llvm_unreachable("unsupported output type");
}
- else
- llvm_unreachable("unsupported options");
-}
}
+
+} // namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/Writer.h b/lld/lib/ReaderWriter/ELF/Writer.h
index 7e67c31369d..20b330ed739 100644
--- a/lld/lib/ReaderWriter/ELF/Writer.h
+++ b/lld/lib/ReaderWriter/ELF/Writer.h
@@ -28,7 +28,7 @@ public:
virtual void buildChunks(const File &file) = 0;
/// \brief Writes the chunks into the output file specified by path
- virtual error_code writeFile(const File &File, StringRef path) = 0;
+ virtual error_code writeFile(const File &file, StringRef path) = 0;
/// \brief Get the virtual address of \p atom after layout.
virtual uint64_t addressOfAtom(const Atom *atom) = 0;
diff --git a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp
index e69de29bb2d..8a0737c5fc8 100644
--- a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.cpp
@@ -0,0 +1,36 @@
+#include "X86TargetInfo.h"
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorOr.h"
+
+using namespace lld;
+
+#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
+
+ErrorOr<Reference::Kind> elf::X86TargetInfo::relocKindFromString(
+ StringRef str) const {
+ int32_t ret = llvm::StringSwitch<int32_t>(str)
+ LLD_CASE(R_386_NONE)
+ LLD_CASE(R_386_PC32)
+ .Default(-1);
+
+ if (ret == -1)
+ return make_error_code(yaml_reader_error::illegal_value);
+ return ret;
+}
+
+#undef LLD_CASE
+
+#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
+
+ErrorOr<std::string>
+elf::X86TargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ switch (kind) {
+ LLD_CASE(R_386_NONE)
+ LLD_CASE(R_386_PC32)
+ }
+
+ return make_error_code(yaml_reader_error::illegal_value);
+}
diff --git a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h
index c66a42f78d6..00007afbdf0 100644
--- a/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/X86/X86TargetInfo.h
@@ -12,7 +12,6 @@
#include "X86TargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -22,12 +21,14 @@ namespace lld {
namespace elf {
class X86TargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- X86TargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ X86TargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler = std::unique_ptr<TargetHandlerBase>(
new X86TargetHandler(*this));
}
- virtual uint64_t getPageSize() const { return 0x1000; }
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
};
} // end namespace elf
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
index bb6236e109e..cad8dd2809f 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.cpp
@@ -399,18 +399,29 @@ public:
} // end anon namespace
void elf::X86_64TargetInfo::addPasses(PassManager &pm) const {
- if (_options._outputKind == OutputKind::StaticExecutable)
- pm.add(std::unique_ptr<Pass>(new StaticGOTPLTPass(*this)));
- else if (_options._outputKind == OutputKind::DynamicExecutable ||
- _options._outputKind == OutputKind::Shared)
+ switch (_outputFileType) {
+ case llvm::ELF::ET_EXEC:
+ if (_isStaticExecutable)
+ pm.add(std::unique_ptr<Pass>(new StaticGOTPLTPass(*this)));
+ else
+ pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
+ break;
+ case llvm::ELF::ET_DYN:
pm.add(std::unique_ptr<Pass>(new DynamicGOTPLTPass(*this)));
+ break;
+ case llvm::ELF::ET_REL:
+ break;
+ default:
+ llvm_unreachable("Unhandled output file type");
+ }
ELFTargetInfo::addPasses(pm);
}
+
#define LLD_CASE(name) .Case(#name, llvm::ELF::name)
-ErrorOr<int32_t> elf::X86_64TargetInfo::relocKindFromString(
- StringRef str) const {
+ErrorOr<Reference::Kind>
+elf::X86_64TargetInfo::relocKindFromString(StringRef str) const {
int32_t ret = llvm::StringSwitch<int32_t>(str)
LLD_CASE(R_X86_64_NONE)
LLD_CASE(R_X86_64_64)
@@ -462,8 +473,8 @@ ErrorOr<int32_t> elf::X86_64TargetInfo::relocKindFromString(
#define LLD_CASE(name) case llvm::ELF::name: return std::string(#name);
-ErrorOr<std::string> elf::X86_64TargetInfo::stringFromRelocKind(
- int32_t kind) const {
+ErrorOr<std::string>
+elf::X86_64TargetInfo::stringFromRelocKind(Reference::Kind kind) const {
switch (kind) {
LLD_CASE(R_X86_64_NONE)
LLD_CASE(R_X86_64_64)
diff --git a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h
index 11adab4ecfc..4c8afa065df 100644
--- a/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h
+++ b/lld/lib/ReaderWriter/ELF/X86_64/X86_64TargetInfo.h
@@ -12,7 +12,6 @@
#include "X86_64TargetHandler.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/ELFTargetInfo.h"
#include "llvm/Object/ELF.h"
@@ -29,19 +28,18 @@ enum {
class X86_64TargetInfo LLVM_FINAL : public ELFTargetInfo {
public:
- X86_64TargetInfo(const LinkerOptions &lo) : ELFTargetInfo(lo) {
+ X86_64TargetInfo(llvm::Triple triple)
+ : ELFTargetInfo(triple) {
_targetHandler =
std::unique_ptr<TargetHandlerBase>(new X86_64TargetHandler(*this));
}
- virtual uint64_t getPageSize() const { return 0x1000; }
-
virtual void addPasses(PassManager &) const;
virtual uint64_t getBaseAddress() const {
- if (_options._baseAddress == 0)
+ if (_baseAddress == 0)
return 0x400000;
- return _options._baseAddress;
+ return _baseAddress;
}
virtual bool isDynamicRelocation(const DefinedAtom &,
@@ -66,8 +64,8 @@ public:
}
}
- virtual ErrorOr<int32_t> relocKindFromString(StringRef str) const;
- virtual ErrorOr<std::string> stringFromRelocKind(int32_t kind) const;
+ virtual ErrorOr<Reference::Kind> relocKindFromString(StringRef str) const;
+ virtual ErrorOr<std::string> stringFromRelocKind(Reference::Kind kind) const;
};
} // end namespace elf
diff --git a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
index de8d5214e43..54dcb69de91 100644
--- a/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
+++ b/lld/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
@@ -29,13 +29,13 @@ namespace mach_o {
class CRuntimeFile : public SimpleFile {
public:
CRuntimeFile(const MachOTargetInfo &ti)
- : SimpleFile(ti, "C runtime"), _undefMain(*this, "_main") {
+ : SimpleFile(ti, "C runtime"), _undefMain(*this, ti.entrySymbolName()) {
// only main executables need _main
- if (ti.getLinkerOptions()._outputKind == OutputKind::StaticExecutable ||
- ti.getLinkerOptions()._outputKind == OutputKind::DynamicExecutable)
+ if (ti.outputFileType() == MH_EXECUTE) {
this->addAtom(_undefMain);
+ }
}
-
+
private:
SimpleUndefinedAtom _undefMain;
};
diff --git a/lld/lib/ReaderWriter/MachO/MachOFormat.hpp b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
index 2010a7f87da..41b432a16ec 100644
--- a/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
+++ b/lld/lib/ReaderWriter/MachO/MachOFormat.hpp
@@ -40,12 +40,14 @@ enum {
CPU_SUBTYPE_X86_ALL = 0x00000003,
CPU_SUBTYPE_X86_64_ALL = 0x00000003,
CPU_SUBTYPE_ARM_V6 = 0x00000006,
- CPU_SUBTYPE_ARM_V7 = 0x00000009
+ CPU_SUBTYPE_ARM_V7 = 0x00000009,
+ CPU_SUBTYPE_ARM_V7S = 0x0000000B
};
enum {
MH_OBJECT = 0x1,
MH_EXECUTE = 0x2,
+ MH_PRELOAD = 0x5,
MH_DYLIB = 0x6,
MH_DYLINKER = 0x7,
MH_BUNDLE = 0x8,
@@ -494,7 +496,7 @@ public:
// in-memory matches on-disk, so copy first fields followed by path
::memcpy(to, (uint8_t*)&cmd, 24);
::memcpy(&to[24], _loadPath.data(), _loadPath.size());
- ::memset(&to[12+_loadPath.size()], 0, cmdsize-(12+_loadPath.size()));
+ ::memset(&to[24+_loadPath.size()], 0, cmdsize-(24+_loadPath.size()));
}
}
diff --git a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
index 0b2d0772294..f60f32ea43c 100644
--- a/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachOTargetInfo.cpp
@@ -10,83 +10,244 @@
#include "lld/ReaderWriter/MachOTargetInfo.h"
#include "GOTPass.hpp"
#include "StubsPass.hpp"
+#include "ReferenceKinds.h"
+#include "MachOFormat.hpp"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/PassManager.h"
+#include "lld/ReaderWriter/Reader.h"
+#include "lld/ReaderWriter/Writer.h"
#include "lld/Passes/LayoutPass.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/Support/MachO.h"
+
+using lld::mach_o::KindHandler;
+
namespace lld {
+
+
+MachOTargetInfo::PackedVersion::PackedVersion(StringRef str) {
+ if (parse(str, *this))
+ llvm_unreachable("bad version string");
+}
+
+/// Construct 32-bit PackedVersion from string "X.Y.Z" where
+/// bits are xxxx.yy.zz. Largest number is 65535.255.255
+bool MachOTargetInfo::PackedVersion::parse(StringRef str,
+ MachOTargetInfo::PackedVersion &result) {
+ result._value = 0;
+
+ if (str.empty())
+ return false;
+
+ SmallVector<StringRef, 3> parts;
+ llvm::SplitString(str, parts, ".");
+
+ unsigned long long num;
+ if (llvm::getAsUnsignedInteger(parts[0], 10, num))
+ return true;
+ if (num > 65535)
+ return true;
+ result._value = num << 16;
+
+ if (parts.size() > 1) {
+ if (llvm::getAsUnsignedInteger(parts[1], 10, num))
+ return true;
+ if (num > 255)
+ return true;
+ result._value |= (num << 8);
+ }
+
+ if (parts.size() > 2) {
+ if (llvm::getAsUnsignedInteger(parts[2], 10, num))
+ return true;
+ if (num > 255)
+ return true;
+ result._value |= num;
+ }
+
+ return false;
+}
+
+bool MachOTargetInfo::PackedVersion::operator<(
+ const PackedVersion &rhs) const {
+ return _value < rhs._value;
+}
+
+bool MachOTargetInfo::PackedVersion::operator>=(
+ const PackedVersion &rhs) const {
+ return _value >= rhs._value;
+}
+
+bool MachOTargetInfo::PackedVersion::operator==(
+ const PackedVersion &rhs) const {
+ return _value == rhs._value;
+}
+
+
+MachOTargetInfo::MachOTargetInfo()
+ : _outputFileType(mach_o::MH_EXECUTE)
+ , _outputFileTypeStatic(false)
+ , _arch(arch_unknown)
+ , _os(OS::macOSX)
+ , _osMinVersion("0.0")
+ , _pageZeroSize(0x1000)
+ , _kindHandler(nullptr) {
+}
+
+
+MachOTargetInfo::~MachOTargetInfo() {
+}
+
uint32_t MachOTargetInfo::getCPUType() const {
- switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- return llvm::MachO::CPUTypeI386;
- case llvm::Triple::x86_64:
- return llvm::MachO::CPUTypeX86_64;
- case llvm::Triple::arm:
- return llvm::MachO::CPUTypeARM;
- default:
+ switch (_arch) {
+ case MachOTargetInfo::arch_x86:
+ return mach_o::CPU_TYPE_I386;
+ case MachOTargetInfo::arch_x86_64:
+ return mach_o::CPU_TYPE_X86_64;
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
+ return mach_o::CPU_TYPE_ARM;
+ case MachOTargetInfo::arch_unknown:
llvm_unreachable("Unknown arch type");
}
}
uint32_t MachOTargetInfo::getCPUSubType() const {
- switch (getTriple().getArch()) {
- case llvm::Triple::x86:
- return llvm::MachO::CPUSubType_I386_ALL;
- case llvm::Triple::x86_64:
- return llvm::MachO::CPUSubType_X86_64_ALL;
- case llvm::Triple::arm:
- return llvm::MachO::CPUSubType_ARM_ALL;
- default:
+ switch (_arch) {
+ case MachOTargetInfo::arch_x86:
+ return mach_o::CPU_SUBTYPE_X86_ALL;
+ case MachOTargetInfo::arch_x86_64:
+ return mach_o::CPU_SUBTYPE_X86_64_ALL;
+ case MachOTargetInfo::arch_armv6:
+ return mach_o::CPU_SUBTYPE_ARM_V6;
+ case MachOTargetInfo::arch_armv7:
+ return mach_o::CPU_SUBTYPE_ARM_V7;
+ case MachOTargetInfo::arch_armv7s:
+ return mach_o::CPU_SUBTYPE_ARM_V7S;
+ case MachOTargetInfo::arch_unknown:
llvm_unreachable("Unknown arch type");
}
}
-bool MachOTargetInfo::addEntryPointLoadCommand() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
+
+bool MachOTargetInfo::outputTypeHasEntry() const {
+ switch (_outputFileType) {
+ case mach_o::MH_EXECUTE:
+ case mach_o::MH_DYLINKER:
+ case mach_o::MH_PRELOAD:
return true;
default:
return false;
}
}
+
+bool MachOTargetInfo::minOS(StringRef mac, StringRef iOS) const {
+ switch (_os) {
+ case OS::macOSX:
+ return (_osMinVersion >= PackedVersion(mac));
+ case OS::iOS:
+ case OS::iOS_simulator:
+ return (_osMinVersion >= PackedVersion(iOS));
+ }
+ llvm_unreachable("target not configured for iOS or MacOSX");
+}
+
+bool MachOTargetInfo::addEntryPointLoadCommand() const {
+ if ((_outputFileType == mach_o::MH_EXECUTE) && !_outputFileTypeStatic) {
+ return minOS("10.8", "6.0");
+ }
+ return false;
+}
+
bool MachOTargetInfo::addUnixThreadLoadCommand() const {
- switch (_options._outputKind) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
+ switch (_outputFileType) {
+ case mach_o::MH_EXECUTE:
+ if (_outputFileTypeStatic)
+ return true;
+ else
+ return !minOS("10.8", "6.0");
+ break;
+ case mach_o::MH_DYLINKER:
+ case mach_o::MH_PRELOAD:
return true;
default:
return false;
}
}
-class GenericMachOTargetInfo LLVM_FINAL : public MachOTargetInfo {
-public:
- GenericMachOTargetInfo(const LinkerOptions &lo) : MachOTargetInfo(lo) {}
+bool MachOTargetInfo::validate(raw_ostream &diagnostics) {
+ if ((_outputFileType == mach_o::MH_EXECUTE) && _entrySymbolName.empty()) {
+ if (_outputFileTypeStatic) {
+ _entrySymbolName = "start";
+ }
+ else {
+ // If targeting newer OS, use _main
+ if (addEntryPointLoadCommand())
+ _entrySymbolName = "_main";
- virtual uint64_t getPageSize() const { return 0x1000; }
- virtual uint64_t getPageZeroSize() const { return getPageSize(); }
-
- virtual StringRef getEntry() const {
- if (!_options._entrySymbol.empty())
- return _options._entrySymbol;
- return "_main";
+ // If targeting older OS, use start (in crt1.o)
+ if (addUnixThreadLoadCommand())
+ _entrySymbolName = "start";
+ }
}
- virtual void addPasses(PassManager &pm) const {
- pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
- pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
- pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+ return false;
+}
+
+bool MachOTargetInfo::setOS(OS os, StringRef minOSVersion) {
+ _os = os;
+ return PackedVersion::parse(minOSVersion, _osMinVersion);
+}
+
+void MachOTargetInfo::addPasses(PassManager &pm) const {
+ pm.add(std::unique_ptr<Pass>(new mach_o::GOTPass));
+ pm.add(std::unique_ptr<Pass>(new mach_o::StubsPass(*this)));
+ pm.add(std::unique_ptr<Pass>(new LayoutPass()));
+}
+
+
+
+error_code MachOTargetInfo::parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
+// if (!_machoReader)
+// _machoReader = createReaderMachO(*this);
+// error_code ec = _machoReader->parseFile(mb,result);
+// if (ec) {
+ if (!_yamlReader)
+ _yamlReader = createReaderYAML(*this);
+ return _yamlReader->parseFile(mb,result);
+// }
+
+ return error_code::success();
+}
+
+
+Writer &MachOTargetInfo::writer() const {
+ if (!_writer) {
+ _writer = createWriterMachO(*this);
}
-};
+ return *_writer;
+}
+
+KindHandler &MachOTargetInfo::kindHandler() const {
+ if (!_kindHandler)
+ _kindHandler = KindHandler::create(_arch);
+ return *_kindHandler;
+}
-std::unique_ptr<MachOTargetInfo>
-MachOTargetInfo::create(const LinkerOptions &lo) {
- return std::unique_ptr<MachOTargetInfo>(new GenericMachOTargetInfo(lo));
+ErrorOr<Reference::Kind>
+MachOTargetInfo::relocKindFromString(StringRef str) const {
+ return kindHandler().stringToKind(str);
+ }
+
+ErrorOr<std::string>
+MachOTargetInfo::stringFromRelocKind(Reference::Kind kind) const {
+ return std::string(kindHandler().kindToString(kind));
}
+
+
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
index d2fb6177f4f..d2ad3a23b67 100644
--- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.cpp
@@ -10,6 +10,7 @@
#include "ReferenceKinds.h"
+
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
@@ -29,14 +30,17 @@ KindHandler::KindHandler() {
KindHandler::~KindHandler() {
}
-KindHandler *KindHandler::makeHandler(llvm::Triple::ArchType arch) {
+std::unique_ptr<mach_o::KindHandler> KindHandler::create(
+ MachOTargetInfo::Arch arch) {
switch( arch ) {
- case llvm::Triple::x86_64:
- return new KindHandler_x86_64();
- case llvm::Triple::x86:
- return new KindHandler_x86();
- case llvm::Triple::arm:
- return new KindHandler_arm();
+ case MachOTargetInfo::arch_x86_64:
+ return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86_64());
+ case MachOTargetInfo::arch_x86:
+ return std::unique_ptr<mach_o::KindHandler>(new KindHandler_x86());
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
+ return std::unique_ptr<mach_o::KindHandler>(new KindHandler_arm());
default:
llvm_unreachable("Unknown arch");
}
diff --git a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
index 1fce85ff4e9..a9bf0e658c8 100644
--- a/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
+++ b/lld/lib/ReaderWriter/MachO/ReferenceKinds.h
@@ -10,6 +10,7 @@
#include "lld/Core/LLVM.h"
#include "lld/Core/Reference.h"
+#include "lld/ReaderWriter/MachOTargetInfo.h"
#include "llvm/ADT/Triple.h"
@@ -29,7 +30,7 @@ class KindHandler {
public:
typedef Reference::Kind Kind;
- static KindHandler *makeHandler(llvm::Triple::ArchType arch);
+ static std::unique_ptr<mach_o::KindHandler> create(MachOTargetInfo::Arch);
virtual ~KindHandler();
virtual Kind stringToKind(StringRef str) = 0;
virtual StringRef kindToString(Kind) = 0;
diff --git a/lld/lib/ReaderWriter/MachO/StubsPass.hpp b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
index 64524945625..558fe13e91c 100644
--- a/lld/lib/ReaderWriter/MachO/StubsPass.hpp
+++ b/lld/lib/ReaderWriter/MachO/StubsPass.hpp
@@ -13,7 +13,6 @@
#include "llvm/ADT/DenseMap.h"
#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/Reference.h"
@@ -31,7 +30,7 @@ class StubsPass : public lld::StubsPass {
public:
StubsPass(const MachOTargetInfo &ti)
: _targetInfo(ti)
- , _kindHandler(KindHandler::makeHandler(_targetInfo.getTriple().getArch()))
+ , _kindHandler(_targetInfo.kindHandler())
, _file(ti)
, _helperCommonAtom(nullptr)
, _helperCacheAtom(nullptr)
@@ -39,11 +38,11 @@ public:
}
virtual bool noTextRelocs() {
- return !_targetInfo.getLinkerOptions()._textRelocations;
+ return true;
}
virtual bool isCallSite(int32_t kind) {
- return _kindHandler->isCallSite(kind);
+ return _kindHandler.isCallSite(kind);
}
virtual const DefinedAtom* getStub(const Atom& target) {
@@ -60,15 +59,17 @@ public:
}
const DefinedAtom* makeStub(const Atom& target) {
- switch (_targetInfo.getTriple().getArch()) {
- case llvm::Triple::x86_64:
+ switch (_targetInfo.arch()) {
+ case MachOTargetInfo::arch_x86_64:
return makeStub_x86_64(target);
- case llvm::Triple::x86:
+ case MachOTargetInfo::arch_x86:
return makeStub_x86(target);
- case llvm::Triple::arm:
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
return makeStub_arm(target);
default:
- llvm_unreachable("Unknown arch");
+ llvm_unreachable("Unknown mach-o arch");
}
}
@@ -153,7 +154,7 @@ private:
};
const MachOTargetInfo &_targetInfo;
- KindHandler *_kindHandler;
+ mach_o::KindHandler &_kindHandler;
File _file;
llvm::DenseMap<const Atom*, const DefinedAtom*> _targetToStub;
std::vector<const DefinedAtom*> _lazyPointers;
diff --git a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
index b0e5fd290e4..e91a3d945c9 100644
--- a/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
+++ b/lld/lib/ReaderWriter/MachO/WriterMachO.cpp
@@ -28,7 +28,6 @@
#include "lld/Core/DefinedAtom.h"
#include "lld/Core/File.h"
#include "lld/Core/InputFiles.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/Core/Reference.h"
#include "lld/Core/SharedLibraryAtom.h"
#include "lld/ReaderWriter/MachOTargetInfo.h"
@@ -155,7 +154,6 @@ public:
uint64_t loadCommandsSize();
private:
- uint32_t filetype(OutputKind);
uint32_t magic(uint32_t cpuType);
mach_header _mh;
@@ -350,7 +348,7 @@ public:
uint64_t *segStartAddr, uint64_t *segEndAddr);
const std::vector<Chunk*> chunks() { return _chunks; }
- KindHandler *kindHandler() { return _referenceKindHandler; }
+ mach_o::KindHandler &kindHandler() { return _referenceKindHandler; }
bool use64BitMachO() const;
@@ -372,7 +370,7 @@ private:
typedef llvm::DenseMap<const Atom*, uint64_t> AtomToAddress;
const MachOTargetInfo &_targetInfo;
- KindHandler *_referenceKindHandler;
+ mach_o::KindHandler &_referenceKindHandler;
CRuntimeFile _cRuntimeFile;
LoadCommandsChunk *_loadCommandsChunk;
LoadCommandPaddingChunk *_paddingChunk;
@@ -580,7 +578,7 @@ void SectionChunk::write(uint8_t *chunkBuffer) {
if ( ref->target() != nullptr )
targetAddress = _writer.addressOfAtom(ref->target());
uint64_t fixupAddress = _writer.addressOfAtom(atomInfo.atom) + offset;
- _writer.kindHandler()->applyFixup(ref->kind(), ref->addend(),
+ _writer.kindHandler().applyFixup(ref->kind(), ref->addend(),
&atomContent[offset], fixupAddress, targetAddress);
}
}
@@ -596,7 +594,7 @@ MachHeaderChunk::MachHeaderChunk(const MachOTargetInfo &ti, const File &file) {
_mh.magic = this->magic(ti.getCPUType());
_mh.cputype = ti.getCPUType();
_mh.cpusubtype = ti.getCPUSubType();
- _mh.filetype = this->filetype(ti.getLinkerOptions()._outputKind);
+ _mh.filetype = ti.outputFileType();
_mh.ncmds = 0;
_mh.sizeofcmds = 0;
_mh.flags = 0;
@@ -638,30 +636,6 @@ uint32_t MachHeaderChunk::magic(uint32_t cpuType) {
return 0;
}
-uint32_t MachHeaderChunk::filetype(OutputKind kind) {
- switch ( kind ) {
- case OutputKind::StaticExecutable:
- case OutputKind::DynamicExecutable:
- return MH_EXECUTE;
- case OutputKind::Relocatable:
- return MH_OBJECT;
- case OutputKind::Shared:
- return MH_DYLIB;
- case OutputKind::SharedStubs:
- return MH_DYLIB_STUB;
- case OutputKind::Bundle:
- return MH_BUNDLE;
- case OutputKind::Preload:
- case OutputKind::DebugSymbols:
- case OutputKind::Core:
- break;
- case OutputKind::Invalid:
- llvm_unreachable("Invalid output kind!");
- }
- llvm_unreachable("file OutputKind not supported");
- return 0;
-}
-
//===----------------------------------------------------------------------===//
@@ -719,7 +693,7 @@ uint32_t LoadCommandsChunk::permissionsFromSections(
void LoadCommandsChunk::computeSize(const lld::File &file) {
const bool is64 = _writer.use64BitMachO();
// Main executables have a __PAGEZERO segment.
- uint64_t pageZeroSize = _targetInfo.getPageZeroSize();
+ uint64_t pageZeroSize = _targetInfo.pageZeroSize();
if ( pageZeroSize != 0 ) {
assert(is64 || (pageZeroSize < 0xFFFFFFFF));
segment_command* pzSegCmd = new segment_command(0, is64);
@@ -1032,7 +1006,7 @@ void BindingInfoChunk::computeSize(const lld::File &file,
const SharedLibraryAtom *shlTarget
= dyn_cast<SharedLibraryAtom>(target);
if ( shlTarget != nullptr ) {
- assert(_writer.kindHandler()->isPointer(ref->kind()));
+ assert(_writer.kindHandler().isPointer(ref->kind()));
targetName = shlTarget->name();
ordinal = 1; // FIXME
}
@@ -1099,14 +1073,14 @@ const char* LazyBindingInfoChunk::info() {
void LazyBindingInfoChunk::updateHelper(const DefinedAtom *lazyPointerAtom,
uint32_t offset) {
for (const Reference *ref : *lazyPointerAtom ) {
- if ( ! _writer.kindHandler()->isPointer(ref->kind() ) )
+ if ( ! _writer.kindHandler().isPointer(ref->kind() ) )
continue;
const Atom *targ = ref->target();
const DefinedAtom *helperAtom = dyn_cast<DefinedAtom>(targ);
assert(helperAtom != nullptr);
// Found helper atom. Search it for Reference that is lazy immediate value.
for (const Reference *href : *helperAtom ) {
- if ( _writer.kindHandler()->isLazyImmediate(href->kind()) ) {
+ if ( _writer.kindHandler().isLazyImmediate(href->kind()) ) {
(const_cast<Reference*>(href))->setAddend(offset);
return;
}
@@ -1156,7 +1130,7 @@ void LazyBindingInfoChunk::computeSize(const lld::File &file,
int flags = 0;
StringRef name;
for (const Reference *ref : *lazyPointerAtom ) {
- if ( _writer.kindHandler()->isLazyTarget(ref->kind()) ) {
+ if ( _writer.kindHandler().isLazyTarget(ref->kind()) ) {
const Atom *shlib = ref->target();
assert(shlib != nullptr);
name = shlib->name();
@@ -1301,7 +1275,7 @@ uint32_t SymbolStringsChunk::stringIndex(StringRef str) {
MachOWriter::MachOWriter(const MachOTargetInfo &ti)
: _targetInfo(ti),
- _referenceKindHandler(KindHandler::makeHandler(ti.getTriple().getArch())),
+ _referenceKindHandler(ti.kindHandler()),
_cRuntimeFile(ti),
_bindingInfo(nullptr), _lazyBindingInfo(nullptr),
_symbolTableChunk(nullptr), _stringsChunk(nullptr), _entryAtom(nullptr),
@@ -1392,17 +1366,14 @@ void MachOWriter::addLinkEditChunk(LinkEditChunk *chunk) {
void MachOWriter::buildAtomToAddressMap() {
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
<< "assign atom addresses:\n");
- const bool lookForEntry = _targetInfo.getLinkerOptions()._outputKind ==
- OutputKind::StaticExecutable ||
- _targetInfo.getLinkerOptions()._outputKind ==
- OutputKind::DynamicExecutable;
+ const bool lookForEntry = _targetInfo.outputTypeHasEntry();
for (SectionChunk *chunk : _sectionChunks ) {
for (const SectionChunk::AtomInfo &info : chunk->atoms() ) {
_atomToAddress[info.atom] = chunk->address() + info.offsetInSection;
if ( lookForEntry
&& (info.atom->contentType() == DefinedAtom::typeCode)
&& (info.atom->size() != 0)
- && info.atom->name() == _targetInfo.getEntry()) {
+ && info.atom->name() == _targetInfo.entrySymbolName()) {
_entryAtom = info.atom;
}
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
@@ -1425,7 +1396,7 @@ void MachOWriter::assignFileOffsets() {
DEBUG_WITH_TYPE("WriterMachO-layout", llvm::dbgs()
<< "assign file offsets:\n");
uint64_t offset = 0;
- uint64_t address = _targetInfo.getPageZeroSize();
+ uint64_t address = _targetInfo.pageZeroSize();
for ( Chunk *chunk : _chunks ) {
if ( chunk->segmentName().equals("__LINKEDIT") ) {
_linkEditStartOffset = Chunk::alignTo(offset, 12);
@@ -1463,7 +1434,7 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
const uint64_t kInvalidAddress = (uint64_t)(-1);
StringRef lastSegName("__TEXT");
*segIndex = 0;
- if ( _targetInfo.getPageZeroSize() != 0 ) {
+ if ( _targetInfo.pageZeroSize() != 0 ) {
*segIndex = 1;
}
*segStartAddr = kInvalidAddress;
@@ -1487,7 +1458,17 @@ void MachOWriter::findSegment(StringRef segmentName, uint32_t *segIndex,
}
bool MachOWriter::use64BitMachO() const {
- return _targetInfo.getTriple().isArch64Bit();
+ switch (_targetInfo.arch()) {
+ case MachOTargetInfo::arch_x86_64:
+ return true;
+ case MachOTargetInfo::arch_x86:
+ case MachOTargetInfo::arch_armv6:
+ case MachOTargetInfo::arch_armv7:
+ case MachOTargetInfo::arch_armv7s:
+ return false;
+ default:
+ llvm_unreachable("Unknown mach-o arch");
+ }
}
diff --git a/lld/lib/ReaderWriter/Native/ReaderNative.cpp b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
index 1255a22ee27..ac3cf3bfe41 100644
--- a/lld/lib/ReaderWriter/Native/ReaderNative.cpp
+++ b/lld/lib/ReaderWriter/Native/ReaderNative.cpp
@@ -916,8 +916,8 @@ public:
: lld::Reader(ti) {}
virtual error_code parseFile(
- std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<lld::File> > &result) {
+ std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<lld::File> > &result) const {
return File::make(_targetInfo, mb, mb->getBufferIdentifier(), result);
}
};
diff --git a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
index 9b33dafccbc..b752a794117 100644
--- a/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ b/lld/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
@@ -369,8 +369,8 @@ class ReaderCOFF : public Reader {
public:
ReaderCOFF(const TargetInfo &ti) : Reader(ti) {}
- error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File> > &result) {
+ error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result) const {
llvm::error_code ec;
std::unique_ptr<File> f(new FileCOFF(_targetInfo, std::move(mb), ec));
if (ec) {
diff --git a/lld/lib/ReaderWriter/Reader.cpp b/lld/lib/ReaderWriter/Reader.cpp
index 17ee4f3023d..9f08ed27436 100644
--- a/lld/lib/ReaderWriter/Reader.cpp
+++ b/lld/lib/ReaderWriter/Reader.cpp
@@ -19,12 +19,12 @@ Reader::~Reader() {
}
error_code Reader::readFile(StringRef path,
- std::vector<std::unique_ptr<File>> &result) {
+ std::vector<std::unique_ptr<File>> &result) const {
OwningPtr<llvm::MemoryBuffer> opmb;
if (error_code ec = llvm::MemoryBuffer::getFileOrSTDIN(path, opmb))
return ec;
std::unique_ptr<MemoryBuffer> mb(opmb.take());
- return this->parseFile(std::move(mb), result);
+ return this->parseFile(mb, result);
}
} // end namespace lld
diff --git a/lld/lib/ReaderWriter/ReaderArchive.cpp b/lld/lib/ReaderWriter/ReaderArchive.cpp
index 370348b8990..d3287dd429d 100644
--- a/lld/lib/ReaderWriter/ReaderArchive.cpp
+++ b/lld/lib/ReaderWriter/ReaderArchive.cpp
@@ -10,7 +10,6 @@
#include "lld/ReaderWriter/ReaderArchive.h"
#include "lld/Core/ArchiveLibraryFile.h"
-#include "lld/Core/LinkerOptions.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/Object/ObjectFile.h"
@@ -46,8 +45,10 @@ public:
OwningPtr<MemoryBuffer> buff;
if (ci->getMemoryBuffer(buff, true))
return nullptr;
- LinkerInput li(std::unique_ptr<MemoryBuffer>(buff.take()));
- if (_getReader(li)->parseFile(li.takeBuffer(), result))
+ std::unique_ptr<MemoryBuffer> mb(buff.take());
+ if (_targetInfo.logInputFiles())
+ llvm::outs() << buff->getBufferIdentifier() << "\n";
+ if (_targetInfo.parseFile(mb, result))
return nullptr;
assert(result.size() == 1);
@@ -121,8 +122,7 @@ protected:
}
private:
- std::function<ErrorOr<Reader&> (const LinkerInput &)> _getReader;
- std::unique_ptr<llvm::object::Archive> _archive;
+ std::unique_ptr<llvm::object::Archive> _archive;
atom_collection_vector<DefinedAtom> _definedAtoms;
atom_collection_vector<UndefinedAtom> _undefinedAtoms;
atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
@@ -132,10 +132,8 @@ private:
public:
/// only subclasses of ArchiveLibraryFile can be instantiated
FileArchive(const TargetInfo &ti,
- std::function<ErrorOr<Reader &>(const LinkerInput &)> getReader,
std::unique_ptr<llvm::MemoryBuffer> mb, error_code &ec)
- : ArchiveLibraryFile(ti, mb->getBufferIdentifier()),
- _getReader(getReader) {
+ : ArchiveLibraryFile(ti, mb->getBufferIdentifier()) {
std::unique_ptr<llvm::object::Archive> archive_obj(
new llvm::object::Archive(mb.release(), ec));
if (ec)
@@ -155,16 +153,17 @@ public:
}
}
- std::unordered_map<StringRef, llvm::object::Archive::child_iterator> _symbolMemberMap;
+ std::unordered_map<StringRef,
+ llvm::object::Archive::child_iterator> _symbolMemberMap;
}; // class FileArchive
// Returns a vector of Files that are contained in the archive file
// pointed to by the MemoryBuffer
-error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
- std::vector<std::unique_ptr<File>> &result){
+error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
error_code ec;
- if (_options._forceLoadArchives) {
+ if (_targetInfo.forceLoadAllArchives()) {
_archive.reset(new llvm::object::Archive(mb.release(), ec));
if (ec)
return ec;
@@ -174,13 +173,15 @@ error_code ReaderArchive::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
OwningPtr<MemoryBuffer> buff;
if ((ec = mf->getMemoryBuffer(buff, true)))
return ec;
- LinkerInput li(std::unique_ptr<MemoryBuffer>(buff.take()));
- if ((ec = _getReader(li)->parseFile(li.takeBuffer(), result)))
+ std::unique_ptr<MemoryBuffer> mbc(buff.take());
+ if (_targetInfo.logInputFiles())
+ llvm::outs() << buff->getBufferIdentifier() << "\n";
+ if ((ec = _targetInfo.parseFile(mbc, result)))
return ec;
}
} else {
std::unique_ptr<File> f;
- f.reset(new FileArchive(_targetInfo, _getReader, std::move(mb), ec));
+ f.reset(new FileArchive(_targetInfo, std::move(mb), ec));
if (ec)
return ec;
diff --git a/lld/lib/ReaderWriter/ReaderLinkerScript.cpp b/lld/lib/ReaderWriter/ReaderLinkerScript.cpp
index 4beb32a3bc6..646f97e7f46 100644
--- a/lld/lib/ReaderWriter/ReaderLinkerScript.cpp
+++ b/lld/lib/ReaderWriter/ReaderLinkerScript.cpp
@@ -11,7 +11,6 @@
#include "lld/Core/Error.h"
#include "lld/Core/File.h"
-#include "lld/Core/LinkerOptions.h"
#include "lld/ReaderWriter/LinkerScript.h"
using namespace lld;
@@ -81,8 +80,8 @@ private:
namespace lld {
error_code
-ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
- std::vector<std::unique_ptr<File> > &result) {
+ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File> > &result) const {
auto lsf = LinkerScriptFile::create(_targetInfo, std::move(mb));
if (!lsf)
return lsf;
@@ -91,10 +90,7 @@ ReaderLinkerScript::parseFile(std::unique_ptr<llvm::MemoryBuffer> mb,
for (const auto &c : ls->_commands) {
if (auto group = dyn_cast<Group>(c))
for (const auto &path : group->getPaths()) {
- auto reader = _getReader(LinkerInput(path._path));
- if (!reader)
- return reader;
- if (error_code ec = reader->readFile(path._path, result))
+ if (error_code ec = _targetInfo.readFile(path._path, result))
return ec;
}
}
diff --git a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index c2945f719f7..5100d3a1547 100644
--- a/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -288,16 +288,44 @@ struct ScalarTraits<RefKind> {
llvm::raw_ostream &out) {
assert(ctxt != nullptr);
ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt);
- auto relocStr = info->_targetInfo.stringFromRelocKind(value);
- out << (relocStr ? *relocStr : "<unknown>");
- }
+ switch (value) {
+ case lld::Reference::kindLayoutAfter:
+ out << "layout-after";
+ break;
+ case lld::Reference::kindLayoutBefore:
+ out << "layout-before";
+ break;
+ case lld::Reference::kindInGroup:
+ out << "in-group";
+ break;
+ default:
+ if (auto relocStr = info->_targetInfo.stringFromRelocKind(value))
+ out << *relocStr;
+ else
+ out << "<unknown>";
+ break;
+ }
+ }
static StringRef input(StringRef scalar, void *ctxt, RefKind &value) {
assert(ctxt != nullptr);
ContextInfo *info = reinterpret_cast<ContextInfo*>(ctxt);
auto relocKind = info->_targetInfo.relocKindFromString(scalar);
- if (!relocKind)
+ if (!relocKind) {
+ if (scalar.equals("layout-after")) {
+ value = lld::Reference::kindLayoutAfter;
+ return StringRef();
+ }
+ if (scalar.equals("layout-before")) {
+ value = lld::Reference::kindLayoutBefore;
+ return StringRef();
+ }
+ if (scalar.equals("in-group")) {
+ value = lld::Reference::kindInGroup;
+ return StringRef();
+ }
return "Invalid relocation kind";
+ }
value = *relocKind;
return StringRef();
}
@@ -1314,8 +1342,8 @@ class ReaderYAML : public Reader {
public:
ReaderYAML(const TargetInfo &ti) : Reader(ti) {}
- error_code parseFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File>> &result) {
+ error_code parseFile(std::unique_ptr<MemoryBuffer> &mb,
+ std::vector<std::unique_ptr<File>> &result) const {
// Note: we do not take ownership of the MemoryBuffer. That is
// because yaml may produce multiple File objects, so there is no
// *one* File to take ownership. Therefore, the yaml File objects
OpenPOWER on IntegriCloud