diff options
Diffstat (limited to 'lib/ReaderWriter/ELF/X86_64')
20 files changed, 261 insertions, 342 deletions
diff --git a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt b/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt index a85d2b504630..36ea839aa674 100644 --- a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt +++ b/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt @@ -3,6 +3,7 @@ add_llvm_library(lldX86_64ELFTarget X86_64TargetHandler.cpp X86_64RelocationHandler.cpp X86_64RelocationPass.cpp + X86_64SectionChunks.cpp LINK_LIBS lldELF lldReaderWriter diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp index dbbb3ad3bc90..cb3e819aff6b 100644 --- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp +++ b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp @@ -14,14 +14,14 @@ using namespace lld; using namespace elf; std::unique_ptr<ELFLinkingContext> -ExampleLinkingContext::create(llvm::Triple triple) { +elf::createExampleLinkingContext(llvm::Triple triple) { if (triple.getVendorName() == "example") return llvm::make_unique<ExampleLinkingContext>(triple); return nullptr; } ExampleLinkingContext::ExampleLinkingContext(llvm::Triple triple) - : X86_64LinkingContext(triple, std::unique_ptr<TargetHandlerBase>( + : X86_64LinkingContext(triple, std::unique_ptr<TargetHandler>( new ExampleTargetHandler(*this))) { _outputELFType = llvm::ELF::ET_LOPROC; } diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp index b66b0d903f6a..89ec6671f3a0 100644 --- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp +++ b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp @@ -15,9 +15,8 @@ using namespace lld; using namespace elf; ExampleTargetHandler::ExampleTargetHandler(ExampleLinkingContext &c) - : X86_64TargetHandler(c), _exampleContext(c) {} + : X86_64TargetHandler(c), _ctx(c) {} std::unique_ptr<Writer> ExampleTargetHandler::getWriter() { - return std::unique_ptr<Writer>( - new X86_64ExecutableWriter(_exampleContext, *_x86_64TargetLayout)); + return llvm::make_unique<X86_64ExecutableWriter>(_ctx, *_targetLayout); } diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h index 19a642113359..46eade5864f9 100644 --- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h +++ b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h @@ -23,7 +23,7 @@ public: std::unique_ptr<Writer> getWriter() override; private: - ExampleLinkingContext &_exampleContext; + ExampleLinkingContext &_ctx; }; } // end namespace elf } // end namespace lld diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/Makefile b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/Makefile deleted file mode 100644 index 8f0b0fead1f6..000000000000 --- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lld/lib/ReaderWriter/ELF/X86_64/Makefile ----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLD_LEVEL := ../../../../.. -LIBRARYNAME := lldExampleSubTarget -USEDLIBS = lldX86_64ELFTarget.a -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF - -include $(LLD_LEVEL)/Makefile diff --git a/lib/ReaderWriter/ELF/X86_64/Makefile b/lib/ReaderWriter/ELF/X86_64/Makefile deleted file mode 100644 index dbeb4d227050..000000000000 --- a/lib/ReaderWriter/ELF/X86_64/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -##===- lld/lib/ReaderWriter/ELF/X86_64/Makefile ----------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LLD_LEVEL := ../../../.. -LIBRARYNAME := lldX86_64ELFTarget -USEDLIBS = lldCore.a - -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF -CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF/X86_64/ - -PARALLEL_DIRS := ExampleSubTarget - -include $(LLD_LEVEL)/Makefile diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h index b996186115b6..f84f85223bfb 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h +++ b/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h @@ -10,51 +10,33 @@ #define X86_64_DYNAMIC_LIBRARY_WRITER_H #include "DynamicLibraryWriter.h" -#include "X86_64ElfType.h" #include "X86_64LinkingContext.h" #include "X86_64TargetHandler.h" namespace lld { namespace elf { -class X86_64DynamicLibraryWriter : public DynamicLibraryWriter<X86_64ELFType> { +class X86_64DynamicLibraryWriter : public DynamicLibraryWriter<ELF64LE> { public: - X86_64DynamicLibraryWriter(X86_64LinkingContext &context, + X86_64DynamicLibraryWriter(X86_64LinkingContext &ctx, X86_64TargetLayout &layout); protected: // Add any runtime files and their atoms to the output - virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &); - - virtual void finalizeDefaultAtomValues() { - return DynamicLibraryWriter::finalizeDefaultAtomValues(); - } - - virtual void addDefaultAtoms() { - return DynamicLibraryWriter::addDefaultAtoms(); - } - -private: - class GOTFile : public SimpleFile { - public: - GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {} - llvm::BumpPtrAllocator _alloc; - }; - - std::unique_ptr<GOTFile> _gotFile; + void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override; }; X86_64DynamicLibraryWriter::X86_64DynamicLibraryWriter( - X86_64LinkingContext &context, X86_64TargetLayout &layout) - : DynamicLibraryWriter(context, layout), _gotFile(new GOTFile(context)) {} + X86_64LinkingContext &ctx, X86_64TargetLayout &layout) + : DynamicLibraryWriter(ctx, layout) {} -bool X86_64DynamicLibraryWriter::createImplicitFiles( +void X86_64DynamicLibraryWriter::createImplicitFiles( std::vector<std::unique_ptr<File>> &result) { DynamicLibraryWriter::createImplicitFiles(result); - _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile)); - _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile)); - result.push_back(std::move(_gotFile)); - return true; + auto gotFile = llvm::make_unique<SimpleFile>("GOTFile"); + gotFile->addAtom(*new (gotFile->allocator()) GlobalOffsetTableAtom(*gotFile)); + gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile)); + result.push_back(std::move(gotFile)); } } // namespace elf diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h b/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h deleted file mode 100644 index d43840a63e7e..000000000000 --- a/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h +++ /dev/null @@ -1,41 +0,0 @@ -//===- lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h ------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READER_WRITER_ELF_X86_64_ELF_FILE_H -#define LLD_READER_WRITER_ELF_X86_64_ELF_FILE_H - -#include "ELFReader.h" - -namespace lld { -namespace elf { - -class X86_64LinkingContext; - -template <class ELFT> class X86_64ELFFile : public ELFFile<ELFT> { -public: - X86_64ELFFile(std::unique_ptr<MemoryBuffer> mb, X86_64LinkingContext &ctx) - : ELFFile<ELFT>(std::move(mb), ctx) {} - - static ErrorOr<std::unique_ptr<X86_64ELFFile>> - create(std::unique_ptr<MemoryBuffer> mb, X86_64LinkingContext &ctx) { - return std::unique_ptr<X86_64ELFFile<ELFT>>( - new X86_64ELFFile<ELFT>(std::move(mb), ctx)); - } -}; - -template <class ELFT> class X86_64DynamicFile : public DynamicFile<ELFT> { -public: - X86_64DynamicFile(const X86_64LinkingContext &context, StringRef name) - : DynamicFile<ELFT>(context, name) {} -}; - -} // elf -} // lld - -#endif // LLD_READER_WRITER_ELF_X86_64_ELF_FILE_H diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h b/lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h deleted file mode 100644 index 9b1284c6dfa8..000000000000 --- a/lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h +++ /dev/null @@ -1,62 +0,0 @@ -//===- lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h ----------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READER_WRITER_X86_64_X86_64_ELF_READER_H -#define LLD_READER_WRITER_X86_64_X86_64_ELF_READER_H - -#include "ELFReader.h" -#include "X86_64ELFFile.h" - -namespace lld { -namespace elf { - -typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType; - -struct X86_64DynamicFileCreateELFTraits { - typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type; - - template <class ELFT> - static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, - X86_64LinkingContext &ctx) { - return lld::elf::X86_64DynamicFile<ELFT>::create(std::move(mb), ctx); - } -}; - -struct X86_64ELFFileCreateELFTraits { - typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type; - - template <class ELFT> - static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb, - X86_64LinkingContext &ctx) { - return lld::elf::X86_64ELFFile<ELFT>::create(std::move(mb), ctx); - } -}; - -class X86_64ELFObjectReader - : public ELFObjectReader<X86_64ELFType, X86_64ELFFileCreateELFTraits, - X86_64LinkingContext> { -public: - X86_64ELFObjectReader(X86_64LinkingContext &ctx) - : ELFObjectReader<X86_64ELFType, X86_64ELFFileCreateELFTraits, - X86_64LinkingContext>(ctx, llvm::ELF::EM_X86_64) {} -}; - -class X86_64ELFDSOReader - : public ELFDSOReader<X86_64ELFType, X86_64DynamicFileCreateELFTraits, - X86_64LinkingContext> { -public: - X86_64ELFDSOReader(X86_64LinkingContext &ctx) - : ELFDSOReader<X86_64ELFType, X86_64DynamicFileCreateELFTraits, - X86_64LinkingContext>(ctx, llvm::ELF::EM_X86_64) {} -}; - -} // namespace elf -} // namespace lld - -#endif // LLD_READER_WRITER_ELF_X86_64_X86_64_READER_H diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h b/lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h deleted file mode 100644 index 0b982e7754e2..000000000000 --- a/lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h +++ /dev/null @@ -1,21 +0,0 @@ -//===- lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h ------------------------===// -// -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_ELF_TYPE_H -#define LLD_READER_WRITER_ELF_X86_64_X86_64_ELF_TYPE_H - -#include "llvm/Object/ELF.h" - -namespace lld { -namespace elf { -typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType; -} -} - -#endif diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h b/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h index f549ed6dcfcb..930a2de2a9e8 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h +++ b/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h @@ -10,49 +10,45 @@ #define X86_64_EXECUTABLE_WRITER_H #include "ExecutableWriter.h" -#include "X86_64ElfType.h" #include "X86_64LinkingContext.h" namespace lld { namespace elf { -class X86_64ExecutableWriter : public ExecutableWriter<X86_64ELFType> { +class X86_64ExecutableWriter : public ExecutableWriter<ELF64LE> { public: - X86_64ExecutableWriter(X86_64LinkingContext &context, - X86_64TargetLayout &layout) - : ExecutableWriter(context, layout), _gotFile(new GOTFile(context)), - _context(context) {} + X86_64ExecutableWriter(X86_64LinkingContext &ctx, X86_64TargetLayout &layout) + : ExecutableWriter(ctx, layout), _targetLayout(layout) {} protected: // Add any runtime files and their atoms to the output - virtual bool - createImplicitFiles(std::vector<std::unique_ptr<File>> &result) { + void + createImplicitFiles(std::vector<std::unique_ptr<File>> &result) override { ExecutableWriter::createImplicitFiles(result); - _gotFile->addAtom(*new (_gotFile->_alloc) - GLOBAL_OFFSET_TABLEAtom(*_gotFile)); - if (_context.isDynamic()) - _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile)); - result.push_back(std::move(_gotFile)); - return true; + auto gotFile = llvm::make_unique<SimpleFile>("GOTFile"); + gotFile->addAtom(*new (gotFile->allocator()) + GlobalOffsetTableAtom(*gotFile)); + if (this->_ctx.isDynamic()) + gotFile->addAtom(*new (gotFile->allocator()) DynamicAtom(*gotFile)); + result.push_back(std::move(gotFile)); } - virtual void finalizeDefaultAtomValues() { - return ExecutableWriter::finalizeDefaultAtomValues(); + void buildDynamicSymbolTable(const File &file) override { + for (auto sec : this->_layout.sections()) { + if (auto section = dyn_cast<AtomSection<ELF64LE>>(sec)) { + for (const auto &atom : section->atoms()) { + if (_targetLayout.getGOTSection().hasGlobalGOTEntry(atom->_atom)) { + this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(), + atom->_virtualAddr, atom); + } + } + } + } + + ExecutableWriter<ELF64LE>::buildDynamicSymbolTable(file); } - virtual void addDefaultAtoms() { - return ExecutableWriter::addDefaultAtoms(); - } - -private: - class GOTFile : public SimpleFile { - public: - GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {} - llvm::BumpPtrAllocator _alloc; - }; - - std::unique_ptr<GOTFile> _gotFile; - X86_64LinkingContext &_context; + X86_64TargetLayout &_targetLayout; }; } // namespace elf diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp index 6a8ce8bd6496..0dcd6ac6fbed 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp +++ b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp @@ -12,10 +12,10 @@ #include "X86_64TargetHandler.h" using namespace lld; -using namespace elf; +using namespace lld::elf; X86_64LinkingContext::X86_64LinkingContext( - llvm::Triple triple, std::unique_ptr<TargetHandlerBase> handler) + llvm::Triple triple, std::unique_ptr<TargetHandler> handler) : ELFLinkingContext(triple, std::move(handler)) {} X86_64LinkingContext::X86_64LinkingContext(llvm::Triple triple) @@ -30,9 +30,21 @@ void X86_64LinkingContext::addPasses(PassManager &pm) { } std::unique_ptr<ELFLinkingContext> -X86_64LinkingContext::create(llvm::Triple triple) { +elf::createX86_64LinkingContext(llvm::Triple triple) { if (triple.getArch() == llvm::Triple::x86_64) - return std::unique_ptr<ELFLinkingContext>( - new elf::X86_64LinkingContext(triple)); + return llvm::make_unique<X86_64LinkingContext>(triple); return nullptr; } + +static const Registry::KindStrings kindStrings[] = { +#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name), +#include "llvm/Support/ELFRelocs/x86_64.def" +#undef ELF_RELOC + LLD_KIND_STRING_ENTRY(LLD_R_X86_64_GOTRELINDEX), + LLD_KIND_STRING_END +}; + +void X86_64LinkingContext::registerRelocationNames(Registry ®istry) { + registry.addKindTable(Reference::KindNamespace::ELF, + Reference::KindArch::x86_64, kindStrings); +} diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h index 2cc799a9c810..a5a7b3d21f4e 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h +++ b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h @@ -26,12 +26,15 @@ enum { class X86_64LinkingContext : public ELFLinkingContext { protected: - X86_64LinkingContext(llvm::Triple, std::unique_ptr<TargetHandlerBase>); + X86_64LinkingContext(llvm::Triple, std::unique_ptr<TargetHandler>); + public: static std::unique_ptr<ELFLinkingContext> create(llvm::Triple); + int getMachineType() const override { return llvm::ELF::EM_X86_64; } X86_64LinkingContext(llvm::Triple); void addPasses(PassManager &) override; + void registerRelocationNames(Registry &r) override; uint64_t getBaseAddress() const override { if (_baseAddress == 0) @@ -65,7 +68,7 @@ public: return false; } - virtual bool isPLTRelocation(const Reference &r) const override { + bool isPLTRelocation(const Reference &r) const override { if (r.kindNamespace() != Reference::KindNamespace::ELF) return false; assert(r.kindArch() == Reference::KindArch::x86_64); diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp index 8fd74f43bbd2..d56983d1e382 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp +++ b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp @@ -23,7 +23,7 @@ static void reloc64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { /// \brief R_X86_64_PC32 - word32: S + A - P static void relocPC32(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { - uint32_t result = (uint32_t)((S + A) - P); + uint32_t result = (uint32_t)(S + A - P); write32le(location, result + read32le(location)); } @@ -50,24 +50,24 @@ static void reloc16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { /// \brief R_X86_64_PC16 - word16: S + A - P static void relocPC16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) { - uint16_t result = (uint16_t)((S + A) - P); + uint16_t result = (uint16_t)(S + A - P); write16le(location, result | read16le(location)); // TODO: Check for overflow. } /// \brief R_X86_64_PC64 - word64: S + A - P static void relocPC64(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) { - int64_t result = (uint64_t)((S + A) - P); + int64_t result = (uint64_t)(S + A - P); write64le(location, result | read64le(location)); } std::error_code X86_64TargetRelocationHandler::applyRelocation( - ELFWriter &writer, llvm::FileOutputBuffer &buf, const lld::AtomLayout &atom, + ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom, const Reference &ref) const { uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset; - uint8_t *location = atomContent + ref.offsetInAtom(); - uint64_t targetVAddress = writer.addressOfAtom(ref.target()); - uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom(); + uint8_t *loc = atomContent + ref.offsetInAtom(); + uint64_t target = writer.addressOfAtom(ref.target()); + uint64_t reloc = atom._virtualAddr + ref.offsetInAtom(); if (ref.kindNamespace() != Reference::KindNamespace::ELF) return std::error_code(); @@ -76,38 +76,34 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation( case R_X86_64_NONE: break; case R_X86_64_64: - reloc64(location, relocVAddress, targetVAddress, ref.addend()); + reloc64(loc, reloc, target, ref.addend()); break; case R_X86_64_PC32: case R_X86_64_GOTPCREL: - relocPC32(location, relocVAddress, targetVAddress, ref.addend()); + relocPC32(loc, reloc, target, ref.addend()); break; case R_X86_64_32: - reloc32(location, relocVAddress, targetVAddress, ref.addend()); + reloc32(loc, reloc, target, ref.addend()); break; case R_X86_64_32S: - reloc32S(location, relocVAddress, targetVAddress, ref.addend()); + reloc32S(loc, reloc, target, ref.addend()); break; case R_X86_64_16: - reloc16(location, relocVAddress, targetVAddress, ref.addend()); + reloc16(loc, reloc, target, ref.addend()); break; case R_X86_64_PC16: - relocPC16(location, relocVAddress, targetVAddress, ref.addend()); + relocPC16(loc, reloc, target, ref.addend()); break; - case R_X86_64_TPOFF64: case R_X86_64_DTPOFF32: - case R_X86_64_TPOFF32: { - _tlsSize = _x86_64Layout.getTLSSize(); - if (ref.kindValue() == R_X86_64_TPOFF32 || - ref.kindValue() == R_X86_64_DTPOFF32) { - write32le(location, targetVAddress - _tlsSize); - } else { - write64le(location, targetVAddress - _tlsSize); - } + case R_X86_64_TPOFF32: + _tlsSize = _layout.getTLSSize(); + write32le(loc, target - _tlsSize); + break; + case R_X86_64_GOTTPOFF: + relocPC32(loc, reloc, target, ref.addend()); break; - } case R_X86_64_TLSGD: { - relocPC32(location, relocVAddress, targetVAddress, ref.addend()); + relocPC32(loc, reloc, target, ref.addend()); break; } case R_X86_64_TLSLD: { @@ -115,21 +111,20 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation( // next relocation is a PC32 to __tls_get_addr... static uint8_t instr[] = { 0x66, 0x66, 0x66, 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00 }; - std::memcpy(location - 3, instr, sizeof(instr)); + std::memcpy(loc - 3, instr, sizeof(instr)); break; } case R_X86_64_PC64: - relocPC64(location, relocVAddress, targetVAddress, ref.addend()); + relocPC64(loc, reloc, target, ref.addend()); break; case LLD_R_X86_64_GOTRELINDEX: { const DefinedAtom *target = cast<const DefinedAtom>(ref.target()); for (const Reference *r : *target) { if (r->kindValue() == R_X86_64_JUMP_SLOT) { uint32_t index; - if (!_x86_64Layout.getPLTRelocationTable()->getRelocationIndex(*r, - index)) + if (!_layout.getPLTRelocationTable()->getRelocationIndex(*r, index)) llvm_unreachable("Relocation doesn't exist"); - reloc32(location, 0, index, 0); + reloc32(loc, 0, index, 0); break; } } @@ -142,6 +137,7 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation( case R_X86_64_GLOB_DAT: case R_X86_64_DTPMOD64: case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: break; default: return make_unhandled_reloc_error(); diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h index 9e2c2171015d..26382804549b 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h +++ b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h @@ -10,27 +10,25 @@ #ifndef X86_64_RELOCATION_HANDLER_H #define X86_64_RELOCATION_HANDLER_H -#include "X86_64TargetHandler.h" +#include "lld/ReaderWriter/ELFLinkingContext.h" namespace lld { namespace elf { -typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType; - class X86_64TargetLayout; class X86_64TargetRelocationHandler final : public TargetRelocationHandler { public: X86_64TargetRelocationHandler(X86_64TargetLayout &layout) - : _tlsSize(0), _x86_64Layout(layout) {} + : _tlsSize(0), _layout(layout) {} std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &, - const lld::AtomLayout &, + const AtomLayout &, const Reference &) const override; private: // Cached size of the TLS segment. mutable uint64_t _tlsSize; - X86_64TargetLayout &_x86_64Layout; + X86_64TargetLayout &_layout; }; } // end namespace elf diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp index 0703927fd56c..a2f10dc08a4e 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp +++ b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp @@ -188,11 +188,12 @@ protected: return got->second; } - /// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to - /// the GOT. - void handleGOTTPOFF(const Reference &ref) { - const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target())); - const_cast<Reference &>(ref).setKindValue(R_X86_64_PC32); + /// \brief Create a TPOFF64 GOT entry. + std::error_code handleGOTTPOFF(const Reference &ref) { + if (isa<DefinedAtom>(ref.target())) { + const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target())); + } + return std::error_code(); } /// \brief Create a TLS GOT entry with DTPMOD64/DTPOFF64 dynamic relocations. @@ -243,9 +244,7 @@ protected: } public: - RelocationPass(const ELFLinkingContext &ctx) - : _file(ctx), _ctx(ctx), _null(nullptr), _PLT0(nullptr), _got0(nullptr), - _got1(nullptr) {} + RelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {} /// \brief Do the pass. /// @@ -255,45 +254,46 @@ public: /// /// After all references are handled, the atoms created during that are all /// added to mf. - void perform(std::unique_ptr<MutableFile> &mf) override { + std::error_code perform(SimpleFile &mf) override { ScopedTask task(getDefaultDomain(), "X86-64 GOT/PLT Pass"); // Process all references. - for (const auto &atom : mf->defined()) + for (const auto &atom : mf.defined()) for (const auto &ref : *atom) handleReference(*atom, *ref); // Add all created atoms to the link. uint64_t ordinal = 0; - if (_PLT0) { - _PLT0->setOrdinal(ordinal++); - mf->addAtom(*_PLT0); + if (_plt0) { + _plt0->setOrdinal(ordinal++); + mf.addAtom(*_plt0); } for (auto &plt : _pltVector) { plt->setOrdinal(ordinal++); - mf->addAtom(*plt); + mf.addAtom(*plt); } if (_null) { _null->setOrdinal(ordinal++); - mf->addAtom(*_null); + mf.addAtom(*_null); } - if (_PLT0) { + if (_plt0) { _got0->setOrdinal(ordinal++); _got1->setOrdinal(ordinal++); - mf->addAtom(*_got0); - mf->addAtom(*_got1); + mf.addAtom(*_got0); + mf.addAtom(*_got1); } for (auto &got : _gotVector) { got->setOrdinal(ordinal++); - mf->addAtom(*got); + mf.addAtom(*got); } for (auto &got : _tlsGotVector) { got->setOrdinal(ordinal++); - mf->addAtom(*got); + mf.addAtom(*got); } for (auto obj : _objectVector) { obj->setOrdinal(ordinal++); - mf->addAtom(*obj); + mf.addAtom(*obj); } + return std::error_code(); } protected: @@ -322,14 +322,14 @@ protected: std::vector<GOTAtom *> _tlsGotVector; /// \brief GOT entry that is always 0. Used for undefined weaks. - GOTAtom *_null; + GOTAtom *_null = nullptr; /// \brief The got and plt entries for .PLT0. This is used to call into the /// dynamic linker for symbol resolution. /// @{ - PLT0Atom *_PLT0; - GOTAtom *_got0; - GOTAtom *_got1; + PLT0Atom *_plt0 = nullptr; + GOTAtom *_got0 = nullptr; + GOTAtom *_got1 = nullptr; /// @} }; @@ -379,20 +379,20 @@ public: : RelocationPass(ctx) {} const PLT0Atom *getPLT0() { - if (_PLT0) - return _PLT0; + if (_plt0) + return _plt0; // Fill in the null entry. getNullGOT(); - _PLT0 = new (_file._alloc) X86_64PLT0Atom(_file); + _plt0 = new (_file._alloc) X86_64PLT0Atom(_file); _got0 = new (_file._alloc) X86_64GOTAtom(_file, ".got.plt"); _got1 = new (_file._alloc) X86_64GOTAtom(_file, ".got.plt"); - _PLT0->addReferenceELF_x86_64(R_X86_64_PC32, 2, _got0, -4); - _PLT0->addReferenceELF_x86_64(R_X86_64_PC32, 8, _got1, -4); + _plt0->addReferenceELF_x86_64(R_X86_64_PC32, 2, _got0, -4); + _plt0->addReferenceELF_x86_64(R_X86_64_PC32, 8, _got1, -4); #ifndef NDEBUG _got0->_name = "__got0"; _got1->_name = "__got1"; #endif - return _PLT0; + return _plt0; } const PLTAtom *getPLTEntry(const Atom *a) { diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp new file mode 100644 index 000000000000..28eb3e4244b6 --- /dev/null +++ b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp @@ -0,0 +1,37 @@ +//===- lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp --------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "X86_64SectionChunks.h" +#include "TargetLayout.h" + +namespace lld { +namespace elf { + +X86_64GOTSection::X86_64GOTSection(const ELFLinkingContext &ctx) + : AtomSection<ELF64LE>(ctx, ".got", DefinedAtom::typeGOT, DefinedAtom::permRW_, + TargetLayout<ELF64LE>::ORDER_GOT) { + this->_alignment = 8; +} + +const AtomLayout *X86_64GOTSection::appendAtom(const Atom *atom) { + const DefinedAtom *da = dyn_cast<DefinedAtom>(atom); + + for (const auto &r : *da) { + if (r->kindNamespace() != Reference::KindNamespace::ELF) + continue; + assert(r->kindArch() == Reference::KindArch::x86_64); + if (r->kindValue() == R_X86_64_TPOFF64) + _tlsMap[r->target()] = _tlsMap.size(); + } + + return AtomSection<ELF64LE>::appendAtom(atom); +} + +} // elf +} // lld diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h new file mode 100644 index 000000000000..5208491eee55 --- /dev/null +++ b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h @@ -0,0 +1,36 @@ +//===- lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h ----------------===// +// +// The LLVM Linker +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_SECTION_CHUNKS_H +#define LLD_READER_WRITER_ELF_X86_64_X86_64_SECTION_CHUNKS_H + +#include "TargetLayout.h" + +namespace lld { +namespace elf { + +class X86_64GOTSection : public AtomSection<ELF64LE> { +public: + X86_64GOTSection(const ELFLinkingContext &ctx); + + bool hasGlobalGOTEntry(const Atom *a) const { + return _tlsMap.count(a); + } + + const AtomLayout *appendAtom(const Atom *atom) override; + +private: + /// \brief Map TLS Atoms to their GOT entry index. + llvm::DenseMap<const Atom *, std::size_t> _tlsMap; +}; + +} // elf +} // lld + +#endif diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp index f35330eb25c0..599077ac33c5 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp +++ b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp @@ -16,37 +16,19 @@ using namespace lld; using namespace elf; -X86_64TargetHandler::X86_64TargetHandler(X86_64LinkingContext &context) - : _context(context), _x86_64TargetLayout(new X86_64TargetLayout(context)), - _x86_64RelocationHandler( - new X86_64TargetRelocationHandler(*_x86_64TargetLayout.get())) {} - -void X86_64TargetHandler::registerRelocationNames(Registry ®istry) { - registry.addKindTable(Reference::KindNamespace::ELF, - Reference::KindArch::x86_64, kindStrings); -} +X86_64TargetHandler::X86_64TargetHandler(X86_64LinkingContext &ctx) + : _ctx(ctx), _targetLayout(new X86_64TargetLayout(ctx)), + _relocationHandler(new X86_64TargetRelocationHandler(*_targetLayout)) {} std::unique_ptr<Writer> X86_64TargetHandler::getWriter() { - switch (this->_context.getOutputELFType()) { + switch (this->_ctx.getOutputELFType()) { case llvm::ELF::ET_EXEC: - return std::unique_ptr<Writer>( - new X86_64ExecutableWriter(_context, *_x86_64TargetLayout.get())); + return llvm::make_unique<X86_64ExecutableWriter>(_ctx, *_targetLayout); case llvm::ELF::ET_DYN: - return std::unique_ptr<Writer>( - new X86_64DynamicLibraryWriter(_context, *_x86_64TargetLayout.get())); + return llvm::make_unique<X86_64DynamicLibraryWriter>(_ctx, *_targetLayout); case llvm::ELF::ET_REL: llvm_unreachable("TODO: support -r mode"); default: llvm_unreachable("unsupported output type"); } } - -#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name), - -const Registry::KindStrings X86_64TargetHandler::kindStrings[] = { -#include "llvm/Support/ELFRelocs/x86_64.def" - LLD_KIND_STRING_ENTRY(LLD_R_X86_64_GOTRELINDEX), - LLD_KIND_STRING_END -}; - -#undef ELF_RELOC diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h index 57da7bca01e6..6e3e58f8aed6 100644 --- a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h +++ b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h @@ -10,57 +10,92 @@ #ifndef LLD_READER_WRITER_ELF_X86_64_X86_64_TARGET_HANDLER_H #define LLD_READER_WRITER_ELF_X86_64_X86_64_TARGET_HANDLER_H -#include "DefaultTargetHandler.h" +#include "ELFReader.h" #include "TargetLayout.h" -#include "X86_64ELFFile.h" -#include "X86_64ELFReader.h" #include "X86_64LinkingContext.h" #include "X86_64RelocationHandler.h" +#include "X86_64SectionChunks.h" #include "lld/Core/Simple.h" namespace lld { namespace elf { -class X86_64TargetLayout : public TargetLayout<X86_64ELFType> { + + +class X86_64TargetLayout : public TargetLayout<ELF64LE> { public: - X86_64TargetLayout(X86_64LinkingContext &context) - : TargetLayout(context) {} + X86_64TargetLayout(X86_64LinkingContext &ctx) : TargetLayout(ctx), + _gotSection(new (this->_allocator) X86_64GOTSection(ctx)) {} + + AtomSection<ELF64LE> * + createSection(StringRef name, int32_t type, + DefinedAtom::ContentPermissions permissions, + TargetLayout<ELF64LE>::SectionOrder order) override { + if (type == DefinedAtom::typeGOT && name == ".got") + return _gotSection; + return TargetLayout<ELF64LE>::createSection(name, type, permissions, order); + } void finalizeOutputSectionLayout() override { - sortOutputSectionByPriority(".init_array", ".init_array"); - sortOutputSectionByPriority(".fini_array", ".fini_array"); + sortOutputSectionByPriority<ELF64LE>(".init_array"); + sortOutputSectionByPriority<ELF64LE>(".fini_array"); } -}; -class X86_64TargetHandler - : public DefaultTargetHandler<X86_64ELFType> { -public: - X86_64TargetHandler(X86_64LinkingContext &context); + const X86_64GOTSection &getGOTSection() const { return *_gotSection; } - X86_64TargetLayout &getTargetLayout() override { - return *(_x86_64TargetLayout.get()); +private: + uint32_t getPriority(StringRef sectionName) const { + StringRef priority = sectionName.drop_front().rsplit('.').second; + uint32_t prio; + if (priority.getAsInteger(10, prio)) + return std::numeric_limits<uint32_t>::max(); + return prio; } - void registerRelocationNames(Registry ®istry) override; + template <typename T> void sortOutputSectionByPriority(StringRef prefix) { + OutputSection<T> *section = findOutputSection(prefix); + if (!section) + return; + auto sections = section->sections(); + std::sort(sections.begin(), sections.end(), + [&](Chunk<T> *lhs, Chunk<T> *rhs) { + Section<T> *lhsSection = dyn_cast<Section<T>>(lhs); + Section<T> *rhsSection = dyn_cast<Section<T>>(rhs); + if (!lhsSection || !rhsSection) + return false; + StringRef lhsName = lhsSection->inputSectionName(); + StringRef rhsName = rhsSection->inputSectionName(); + if (!lhsName.startswith(prefix) || !rhsName.startswith(prefix)) + return false; + return getPriority(lhsName) < getPriority(rhsName); + }); + } + +private: + X86_64GOTSection *_gotSection; +}; + +class X86_64TargetHandler : public TargetHandler { +public: + X86_64TargetHandler(X86_64LinkingContext &ctx); - const X86_64TargetRelocationHandler &getRelocationHandler() const override { - return *(_x86_64RelocationHandler.get()); + const TargetRelocationHandler &getRelocationHandler() const override { + return *_relocationHandler; } std::unique_ptr<Reader> getObjReader() override { - return std::unique_ptr<Reader>(new X86_64ELFObjectReader(_context)); + return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx); } std::unique_ptr<Reader> getDSOReader() override { - return std::unique_ptr<Reader>(new X86_64ELFDSOReader(_context)); + return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx); } std::unique_ptr<Writer> getWriter() override; protected: - static const Registry::KindStrings kindStrings[]; - X86_64LinkingContext &_context; - std::unique_ptr<X86_64TargetLayout> _x86_64TargetLayout; - std::unique_ptr<X86_64TargetRelocationHandler> _x86_64RelocationHandler; + X86_64LinkingContext &_ctx; + std::unique_ptr<X86_64TargetLayout> _targetLayout; + std::unique_ptr<X86_64TargetRelocationHandler> _relocationHandler; }; } // end namespace elf |