diff options
Diffstat (limited to 'lld/lib/ReaderWriter')
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 |